From 33f88fa5e0ad2a9686990df2987ef73a0ae062fa Mon Sep 17 00:00:00 2001 From: shimon Date: Wed, 22 Oct 2025 16:35:48 +0300 Subject: [PATCH 01/77] Refactor authorization handling across multiple modules to use the new getAuthorization() method. Update CHANGES.md to reflect the change in usage worker authorization. Adjust composer.json to specify the correct version for utopia-php/database. Update plugin-api-version in composer.lock. --- CHANGES.md | 2 +- app/cli.php | 29 ++-- app/controllers/api/account.php | 80 +++++----- app/controllers/api/avatars.php | 12 +- app/controllers/api/graphql.php | 5 +- app/controllers/api/messaging.php | 41 +++-- app/controllers/api/migrations.php | 8 +- app/controllers/api/project.php | 6 +- app/controllers/api/storage.php | 151 ++++++++---------- app/controllers/api/teams.php | 42 ++--- app/controllers/api/users.php | 2 +- app/controllers/api/vcs.php | 38 ++--- app/controllers/general.php | 37 ++--- app/controllers/shared/api.php | 45 +++--- app/controllers/shared/api/auth.php | 7 +- app/http.php | 21 ++- app/init/database/filters.php | 14 +- app/init/resources.php | 55 ++++--- app/realtime.php | 22 +-- app/worker.php | 39 +++-- composer.json | 2 +- composer.lock | 96 ++++++++--- src/Appwrite/Auth/Auth.php | 4 +- src/Appwrite/Databases/TransactionState.php | 4 +- src/Appwrite/Migration/Migration.php | 5 +- .../Platform/Modules/Compute/Base.php | 6 +- .../Modules/Console/Http/Resources/Get.php | 2 +- .../Collections/Attributes/Action.php | 6 +- .../Collections/Attributes/Delete.php | 2 +- .../Databases/Collections/Attributes/Get.php | 2 +- .../Attributes/Relationship/Create.php | 2 +- .../Collections/Attributes/XList.php | 2 +- .../Http/Databases/Collections/Create.php | 2 +- .../Http/Databases/Collections/Delete.php | 2 +- .../Collections/Documents/Action.php | 2 +- .../Documents/Attribute/Decrement.php | 10 +- .../Documents/Attribute/Increment.php | 10 +- .../Collections/Documents/Create.php | 34 ++-- .../Collections/Documents/Delete.php | 12 +- .../Databases/Collections/Documents/Get.php | 8 +- .../Collections/Documents/Logs/XList.php | 2 +- .../Collections/Documents/Update.php | 20 +-- .../Collections/Documents/Upsert.php | 20 +-- .../Databases/Collections/Documents/XList.php | 10 +- .../Http/Databases/Collections/Get.php | 2 +- .../Databases/Collections/Indexes/Create.php | 2 +- .../Databases/Collections/Indexes/Delete.php | 2 +- .../Databases/Collections/Indexes/Get.php | 2 +- .../Databases/Collections/Indexes/XList.php | 4 +- .../Http/Databases/Collections/Logs/XList.php | 2 +- .../Http/Databases/Collections/Update.php | 2 +- .../Http/Databases/Collections/Usage/Get.php | 2 +- .../Http/Databases/Collections/XList.php | 2 +- .../Http/Databases/Transactions/Create.php | 2 +- .../Transactions/Operations/Create.php | 24 +-- .../Http/Databases/Transactions/Update.php | 30 ++-- .../Databases/Http/Databases/Usage/Get.php | 2 +- .../Databases/Http/Databases/Usage/XList.php | 2 +- .../Functions/Http/Executions/Create.php | 22 ++- .../Functions/Http/Executions/Delete.php | 2 +- .../Modules/Functions/Http/Executions/Get.php | 6 +- .../Functions/Http/Executions/XList.php | 6 +- .../Functions/Http/Functions/Create.php | 4 +- .../Functions/Http/Functions/Delete.php | 2 +- .../Http/Functions/Deployment/Update.php | 6 +- .../Functions/Http/Functions/Update.php | 2 +- .../Modules/Functions/Http/Usage/Get.php | 2 +- .../Modules/Functions/Http/Usage/XList.php | 2 +- .../Functions/Http/Variables/Create.php | 2 +- .../Functions/Http/Variables/Delete.php | 2 +- .../Functions/Http/Variables/Update.php | 2 +- .../Modules/Functions/Workers/Builds.php | 10 +- .../Modules/Sites/Http/Deployments/Create.php | 4 +- .../Http/Deployments/Duplicate/Create.php | 2 +- .../Http/Deployments/Template/Create.php | 2 +- .../Sites/Http/Sites/Deployment/Update.php | 4 +- .../Platform/Modules/Sites/Http/Usage/Get.php | 2 +- .../Modules/Sites/Http/Usage/XList.php | 2 +- .../Http/Tokens/Buckets/Files/Action.php | 16 +- .../Http/Tokens/Buckets/Files/Create.php | 9 +- src/Appwrite/Platform/Tasks/Migrate.php | 2 +- src/Appwrite/Platform/Tasks/ScheduleBase.php | 2 +- .../Platform/Tasks/StatsResources.php | 6 +- src/Appwrite/Platform/Workers/Deletes.php | 4 +- src/Appwrite/Utopia/Request.php | 9 +- src/Appwrite/Utopia/Request/Filters/V20.php | 4 +- src/Appwrite/Utopia/Response.php | 9 +- .../DatabasesPermissionsGuestTest.php | 22 ++- .../DatabasesPermissionsGuestTest.php | 23 ++- tests/unit/Auth/AuthTest.php | 31 ++-- .../unit/Messaging/MessagingChannelsTest.php | 15 +- 91 files changed, 688 insertions(+), 551 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index bc903e4b31..1ca2410aec 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1155,7 +1155,7 @@ * Bump console to version 3.2.7 [#7148](https://github.com/appwrite/appwrite/pull/7148) * Chore update database to 0.45.2 [#7138](https://github.com/appwrite/appwrite/pull/7138) * Implement queue thresholds for the health API [#7123](https://github.com/appwrite/appwrite/pull/7123) -* Add Authorization::skip to the usage worker [#7124](https://github.com/appwrite/appwrite/pull/7124) +* Add Authorization->skip to the usage worker [#7124](https://github.com/appwrite/appwrite/pull/7124) ## Bug fixes * fix: use queueForDeletes in git installation delete endpoint [#7140](https://github.com/appwrite/appwrite/pull/7140) diff --git a/app/cli.php b/app/cli.php index 71b6464cb9..08726c2d4d 100644 --- a/app/cli.php +++ b/app/cli.php @@ -40,8 +40,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) { @@ -59,7 +57,12 @@ CLI::setResource('pools', function (Registry $register) { return $register->get('pools'); }, ['register']); -CLI::setResource('dbForPlatform', function ($pools, $cache) { +CLI::setResource('authorization', function () { + $authorization = new Authorization(); + return $authorization; +}, []); + +CLI::setResource('dbForPlatform', function ($pools, $cache, $authorization) { $sleep = 3; $maxAttempts = 5; $attempts = 0; @@ -73,6 +76,7 @@ CLI::setResource('dbForPlatform', function ($pools, $cache) { $dbForPlatform = new Database($adapter, $cache); $dbForPlatform + ->setAuthorization($authorization) ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console'); @@ -97,7 +101,7 @@ CLI::setResource('dbForPlatform', function ($pools, $cache) { } return $dbForPlatform; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); CLI::setResource('console', function () { return new Document(Config::getParam('console')); @@ -108,10 +112,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; } @@ -129,11 +133,13 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform if (\in_array($dsn->getHost(), $sharedTables)) { $database + ->setAuthorization($authorization) ->setSharedTables(true) ->setTenant((int)$project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database + ->setAuthorization($authorization) ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getSequence()); @@ -149,11 +155,13 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform if (\in_array($dsn->getHost(), $sharedTables)) { $database + ->setAuthorization($authorization) ->setSharedTables(true) ->setTenant((int)$project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database + ->setAuthorization($authorization) ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getSequence()); @@ -165,12 +173,12 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform 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; @@ -180,6 +188,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) @@ -192,7 +201,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/controllers/api/account.php b/app/controllers/api/account.php index 5563fc6a59..aeeff76dff 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -173,7 +173,7 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, Doc $createSession = function (string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails) { /** @var Utopia\Database\Document $user */ - $userFromRequest = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); + $userFromRequest = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('users', $userId)); if ($userFromRequest->isEmpty()) { throw new Exception(Exception::USER_INVALID_TOKEN); @@ -219,7 +219,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res $detector->getDevice() )); - Authorization::setRole(Role::user($user->getId())->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); $session = $dbForProject->createDocument('sessions', $session ->setAttribute('$permissions', [ @@ -228,7 +228,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res Permission::delete(Role::user($user->getId())), ])); - Authorization::skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId())); + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId())); $dbForProject->purgeCachedDocument('users', $user->getId()); // Magic URL + Email OTP @@ -403,9 +403,9 @@ App::post('/v1/account') 'accessedAt' => DateTime::now(), ]); $user->removeAttribute('$sequence'); - $user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -431,9 +431,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()); + $dbForProject->getAuthorization()->removeRole(Role::guests()->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); + $dbForProject->getAuthorization()->addRole(Role::users()->toString()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -937,7 +937,7 @@ App::post('/v1/account/sessions/email') $detector->getDevice() )); - Authorization::setRole(Role::user($user->getId())->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); // Re-hash if not using recommended algo if ($user->getAttribute('hash') !== Auth::DEFAULT_ALGO) { @@ -1074,7 +1074,7 @@ App::post('/v1/account/sessions/anonymous') 'accessedAt' => DateTime::now(), ]); $user->removeAttribute('$sequence'); - Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $dbForProject->getAuthorization()-> skip(fn () => $dbForProject->createDocument('users', $user)); // Create session token $duration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; @@ -1100,7 +1100,7 @@ App::post('/v1/account/sessions/anonymous') $detector->getDevice() )); - Authorization::setRole(Role::user($user->getId())->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); $session = $dbForProject->createDocument('sessions', $session->setAttribute('$permissions', [ Permission::read(Role::user($user->getId())), @@ -1606,7 +1606,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'accessedAt' => DateTime::now(), ]); $user->removeAttribute('$sequence'); - $userDoc = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $userDoc = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('users', $user)); $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), @@ -1625,8 +1625,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } } - Authorization::setRole(Role::user($user->getId())->toString()); - Authorization::setRole(Role::users()->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); + $dbForProject->getAuthorization()->addRole(Role::users()->toString()); if (false === $user->getAttribute('status')) { // Account is blocked $failureRedirect(Exception::USER_BLOCKED); // User is in status blocked @@ -1685,7 +1685,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $dbForProject->updateDocument('users', $user->getId(), $user); - Authorization::setRole(Role::user($user->getId())->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); $state['success'] = URLParser::parse($state['success']); $query = URLParser::parseQuery($state['success']['query']); @@ -1707,7 +1707,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -1996,7 +1996,7 @@ App::post('/v1/account/tokens/magic-url') ]); $user->removeAttribute('$sequence'); - Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('users', $user)); } $tokenSecret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_MAGIC_URL); @@ -2013,7 +2013,7 @@ App::post('/v1/account/tokens/magic-url') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2244,9 +2244,9 @@ App::post('/v1/account/tokens/email') ]); $user->removeAttribute('$sequence'); - $user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -2284,7 +2284,7 @@ App::post('/v1/account/tokens/email') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2591,9 +2591,9 @@ App::post('/v1/account/tokens/phone') ]); $user->removeAttribute('$sequence'); - Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ + $target = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), @@ -2639,7 +2639,7 @@ App::post('/v1/account/tokens/phone') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -3063,7 +3063,7 @@ App::patch('/v1/account/email') ->setAttribute('passwordUpdate', DateTime::now()); } - $target = Authorization::skip(fn () => $dbForProject->findOne('targets', [ + $target = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->findOne('targets', [ Query::equal('identifier', [$email]), ])); @@ -3079,7 +3079,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))); + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $email))); } $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Duplicate) { @@ -3134,7 +3134,7 @@ App::patch('/v1/account/phone') $hooks->trigger('passwordValidator', [$dbForProject, $project, $password, &$user, false]); - $target = Authorization::skip(fn () => $dbForProject->findOne('targets', [ + $target = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->findOne('targets', [ Query::equal('identifier', [$phone]), ])); @@ -3165,7 +3165,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))); + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('targets', $oldTarget->getId(), $oldTarget->setAttribute('identifier', $phone))); } $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Duplicate $th) { @@ -3335,7 +3335,7 @@ App::post('/v1/account/recovery') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($profile->getId())->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($profile->getId())->toString()); $recovery = $dbForProject->createDocument('tokens', $recovery ->setAttribute('$permissions', [ @@ -3491,7 +3491,7 @@ App::put('/v1/account/recovery') throw new Exception(Exception::USER_INVALID_TOKEN); } - Authorization::setRole(Role::user($profile->getId())->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($profile->getId())->toString()); $newPassword = Auth::passwordHash($password, Auth::DEFAULT_ALGO, Auth::DEFAULT_ALGO_OPTIONS); @@ -3618,7 +3618,7 @@ App::post('/v1/account/verifications/email') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); $verification = $dbForProject->createDocument('tokens', $verification ->setAttribute('$permissions', [ @@ -3803,7 +3803,7 @@ App::put('/v1/account/verifications/email') ->inject('queueForEvents') ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { - $profile = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); + $profile = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('users', $userId)); if ($profile->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); @@ -3816,7 +3816,7 @@ App::put('/v1/account/verifications/email') throw new Exception(Exception::USER_INVALID_TOKEN); } - Authorization::setRole(Role::user($profile->getId())->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($profile->getId())->toString()); $profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('emailVerification', true)); @@ -3914,7 +3914,7 @@ App::post('/v1/account/verifications/phone') 'ip' => $request->getIP(), ]); - Authorization::setRole(Role::user($user->getId())->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); $verification = $dbForProject->createDocument('tokens', $verification ->setAttribute('$permissions', [ @@ -4021,7 +4021,7 @@ App::put('/v1/account/verifications/phone') ->inject('queueForEvents') ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { - $profile = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); + $profile = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('users', $userId)); if ($profile->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); @@ -4033,7 +4033,7 @@ App::put('/v1/account/verifications/phone') throw new Exception(Exception::USER_INVALID_TOKEN); } - Authorization::setRole(Role::user($profile->getId())->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($profile->getId())->toString()); $profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('phoneVerification', true)); @@ -5024,9 +5024,9 @@ App::post('/v1/account/targets/push') ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject) { $targetId = $targetId == 'unique()' ? ID::unique() : $targetId; - $provider = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); + $provider = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('providers', $providerId)); - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('targets', $targetId)); if (!$target->isEmpty()) { throw new Exception(Exception::USER_TARGET_ALREADY_EXISTS); @@ -5103,7 +5103,7 @@ App::put('/v1/account/targets/:targetId/push') ->inject('dbForProject') ->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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('targets', $targetId)); if ($target->isEmpty()) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); @@ -5167,7 +5167,7 @@ App::delete('/v1/account/targets/:targetId/push') ->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)); + $target = $dbForProject->getAuthorization()->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 90364d997e..64f13c1981 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -69,7 +69,7 @@ $avatarCallback = function (string $type, string $code, int $width, int $height, $getUserGitHub = function (string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger) { try { - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); @@ -120,7 +120,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)); + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('sessions', $gitHubSession->getId(), $gitHubSession)); $dbForProject->purgeCachedDocument('users', $user->getId()); } catch (Throwable $err) { @@ -128,7 +128,7 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro do { $previousAccessToken = $gitHubSession->getAttribute('providerAccessToken'); - $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); $gitHubSession = new Document(); @@ -658,7 +658,7 @@ App::get('/v1/cards/cloud') ->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)); + $user = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -865,7 +865,7 @@ App::get('/v1/cards/cloud-back') ->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)); + $user = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -943,7 +943,7 @@ App::get('/v1/cards/cloud-og') ->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)); + $user = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); diff --git a/app/controllers/api/graphql.php b/app/controllers/api/graphql.php index 482b38d698..d0480225da 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'] - && !(Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles())) + && !(Auth::isPrivilegedUser($authorization->getRoles()) || Auth::isAppUser($authorization->getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index dbc384f3c4..6029f7642e 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -35,7 +35,7 @@ use Utopia\Database\Exception\Order as OrderException; 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; @@ -1013,7 +1013,7 @@ App::get('/v1/messaging/providers') } $providerId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); + $cursorDocument = $dbForProject->getAuthorization()->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."); @@ -2320,7 +2320,7 @@ App::get('/v1/messaging/topics') } $topicId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $cursorDocument = $dbForProject->getAuthorization()->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."); @@ -2599,25 +2599,22 @@ App::post('/v1/messaging/topics/:topicId/subscribers') ->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 = $dbForProject->getAuthorization()->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 (!$dbForProject->getAuthorization()->isValid(new Input('subscribe', $topic->getAttribute('subscribe')))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } - $target = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId)); + $target = $dbForProject->getAuthorization()->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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); $subscriber = new Document([ '$id' => $subscriberId, @@ -2650,7 +2647,7 @@ App::post('/v1/messaging/topics/:topicId/subscribers') default => throw new Exception(Exception::TARGET_PROVIDER_INVALID_TYPE), }; - Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute( + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->increaseDocumentAttribute( 'topics', $topicId, $totalAttribute, @@ -2706,7 +2703,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') $queries[] = Query::search('search', $search); } - $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $topic = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -2729,7 +2726,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') } $subscriberId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('subscribers', $subscriberId)); + $cursorDocument = $dbForProject->getAuthorization()->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."); @@ -2745,8 +2742,8 @@ App::get('/v1/messaging/topics/:topicId/subscribers') $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'))); + $target = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); + $user = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); return $subscriber ->setAttribute('target', $target) @@ -2882,7 +2879,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId') ->inject('dbForProject') ->inject('response') ->action(function (string $topicId, string $subscriberId, Database $dbForProject, Response $response) { - $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $topic = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -2894,8 +2891,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); + $user = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); $subscriber ->setAttribute('target', $target) @@ -2933,7 +2930,7 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId') ->inject('dbForProject') ->inject('response') ->action(function (string $topicId, string $subscriberId, Event $queueForEvents, Database $dbForProject, Response $response) { - $topic = Authorization::skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $topic = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -2956,7 +2953,7 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId') default => throw new Exception(Exception::TARGET_PROVIDER_INVALID_TYPE), }; - Authorization::skip(fn () => $dbForProject->decreaseDocumentAttribute( + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->decreaseDocumentAttribute( 'topics', $topicId, $totalAttribute, @@ -3539,7 +3536,7 @@ App::get('/v1/messaging/messages') } $messageId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('messages', $messageId)); + $cursorDocument = $dbForProject->getAuthorization()->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 4a968e63f2..4f88adf616 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -339,12 +339,12 @@ App::post('/v1/migrations/csv') ->inject('queueForEvents') ->inject('queueForMigrations') ->action(function (string $bucketId, string $fileId, string $resourceId, bool $internalFile, Response $response, Database $dbForProject, Database $dbForPlatform, Document $project, Device $deviceForFiles, Device $deviceForImports, Event $queueForEvents, Migration $queueForMigrations) { - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForPlatform->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForPlatform->getAuthorization()->getRoles()); if ($internalFile && !$isPrivilegedUser) { throw new Exception(Exception::USER_UNAUTHORIZED); } - $bucket = Authorization::skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) { + $bucket = $dbForPlatform->getAuthorization()->skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) { if ($internalFile) { return $dbForPlatform->getDocument('buckets', 'default'); } @@ -355,7 +355,7 @@ App::post('/v1/migrations/csv') 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 = $dbForPlatform->getAuthorization()->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); } diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 390e88637a..554d2defec 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -101,7 +101,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) { + $dbForProject->getAuthorization()->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; @@ -285,7 +285,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->sum('stats', 'value', [ Query::equal('metric', [METRIC_AUTH_METHOD_PHONE]), Query::equal('period', ['1d']), Query::greaterThanEqual('time', $firstDay), @@ -293,7 +293,7 @@ App::get('/v1/project/usage') ])); // This estimate is only for paid SMS usage - $authPhoneMetrics = Authorization::skip(fn () => $dbForProject->find('stats', [ + $authPhoneMetrics = $dbForProject->getAuthorization()->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/storage.php b/app/controllers/api/storage.php index 8bc383cabd..ebccc9c321 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -31,7 +31,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\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; @@ -428,18 +428,17 @@ App::post('/v1/storage/buckets/:bucketId/files') ->inject('deviceForLocal') ->action(function (string $bucketId, string $fileId, mixed $file, ?array $permissions, Request $request, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, string $mode, Device $deviceForFiles, Device $deviceForLocal) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $validator = new Authorization(Database::PERMISSION_CREATE); - if (!$validator->isValid($bucket->getCreate())) { - throw new Exception(Exception::USER_UNAUTHORIZED); + if (!$dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } $allowedPermissions = [ @@ -462,7 +461,7 @@ App::post('/v1/storage/buckets/:bucketId/files') } // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); + $roles = $dbForProject->getAuthorization()->getRoles(); if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -475,7 +474,7 @@ App::post('/v1/storage/buckets/:bucketId/files') $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$dbForProject->getAuthorization()->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -695,11 +694,10 @@ App::post('/v1/storage/buckets/:bucketId/files') * 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(Database::PERMISSION_CREATE); - if (!$validator->isValid($bucket->getCreate())) { - throw new Exception(Exception::USER_UNAUTHORIZED); + if (!$dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } } else { if ($file->isEmpty()) { @@ -738,13 +736,12 @@ App::post('/v1/storage/buckets/:bucketId/files') * 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(Database::PERMISSION_CREATE); - if (!$validator->isValid($bucket->getCreate())) { - throw new Exception(Exception::USER_UNAUTHORIZED); + if (!$dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } - + try { - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -789,20 +786,19 @@ App::get('/v1/storage/buckets/:bucketId/files') ->inject('dbForProject') ->inject('mode') ->action(function (string $bucketId, array $queries, string $search, Response $response, Database $dbForProject, string $mode) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->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 = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } $queries = Query::parseQueries($queries); @@ -831,7 +827,7 @@ App::get('/v1/storage/buckets/:bucketId/files') if ($fileSecurity && !$valid) { $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $cursorDocument = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($cursorDocument->isEmpty()) { @@ -848,8 +844,8 @@ App::get('/v1/storage/buckets/:bucketId/files') $files = $dbForProject->find('bucket_' . $bucket->getSequence(), $queries); $total = $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT); } else { - $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); - $total = Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)); + $files = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); + $total = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -890,26 +886,25 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId') ->inject('dbForProject') ->inject('mode') ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, string $mode) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->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 = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } if ($fileSecurity && !$valid) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { @@ -972,10 +967,10 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') } /* @type Document $bucket */ - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -983,17 +978,16 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $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 = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { @@ -1115,11 +1109,11 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; //Do not update transformedAt if it's a console user - if (!Auth::isPrivilegedUser(Authorization::getRoles())) { + if (!Auth::isPrivilegedUser($dbForProject->getAuthorization()->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)); + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); } } @@ -1164,10 +1158,10 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') ->inject('deviceForFiles') ->action(function (string $bucketId, string $fileId, ?string $token, Request $request, Response $response, Database $dbForProject, string $mode, Document $resourceToken, Device $deviceForFiles) { /* @type Document $bucket */ - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -1175,8 +1169,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') $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 = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -1185,7 +1178,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { @@ -1325,10 +1318,10 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') ->inject('deviceForFiles') ->action(function (string $bucketId, string $fileId, ?string $token, Response $response, Request $request, Database $dbForProject, string $mode, Document $resourceToken, Device $deviceForFiles) { /* @type Document $bucket */ - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -1336,8 +1329,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $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 = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -1346,7 +1338,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { @@ -1479,7 +1471,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') ->inject('mode') ->inject('deviceForFiles') ->action(function (string $bucketId, string $fileId, string $jwt, Response $response, Request $request, Database $dbForProject, Document $project, string $mode, Device $deviceForFiles) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); $decoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); @@ -1497,14 +1489,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') throw new Exception(Exception::USER_UNAUTHORIZED); } - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); 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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -1652,24 +1644,23 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') ->inject('queueForEvents') ->action(function (string $bucketId, string $fileId, ?string $name, ?array $permissions, Response $response, Database $dbForProject, Document $user, string $mode, Event $queueForEvents) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->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 = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } // Read permission should not be required for update - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -1683,7 +1674,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') ]); // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); + $roles = $dbForProject->getAuthorization()->getRoles(); if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles) && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -1696,7 +1687,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$dbForProject->getAuthorization()->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -1717,7 +1708,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') if ($fileSecurity && !$valid) { $file = $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file); } else { - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -1766,32 +1757,32 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') ->inject('deviceForFiles') ->inject('queueForDeletes') ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, Event $queueForEvents, string $mode, Device $deviceForFiles, Delete $queueForDeletes) { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->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 = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_DELETE, $bucket->getDelete())); if (!$fileSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED); } // Read permission should not be required for delete - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $dbForProject->getAuthorization()->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); + $validFile = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_DELETE, $file->getDelete())); + if ($fileSecurity && !$valid && !$validFile) { + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } $deviceDeleted = false; @@ -1815,7 +1806,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') if ($fileSecurity && !$valid) { $deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId)); + $deleted = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -1872,7 +1863,7 @@ App::get('/v1/storage/usage') ]; $total = []; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) { + $dbForProject->getAuthorization()->skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), @@ -1968,7 +1959,7 @@ App::get('/v1/storage/:bucketId/usage') str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED), ]; - Authorization::skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) { + $dbForProject->getAuthorization()->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/app/controllers/api/teams.php b/app/controllers/api/teams.php index 7398e451b5..eb70282ff4 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -85,13 +85,13 @@ App::post('/v1/teams') ->inject('queueForEvents') ->action(function (string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - $isAppUser = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAppUser = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); $teamId = $teamId == 'unique()' ? ID::unique() : $teamId; try { - $team = Authorization::skip(fn () => $dbForProject->createDocument('teams', new Document([ + $team = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('teams', new Document([ '$id' => $teamId, '$permissions' => [ Permission::read(Role::team($teamId)), @@ -494,8 +494,8 @@ App::post('/v1/teams/:teamId/memberships') ->inject('queueForStatsUsage') ->inject('plan') ->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) { - $isAppUser = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAppUser = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); $url = htmlentities($url); if (empty($url)) { @@ -566,7 +566,7 @@ App::post('/v1/teams/:teamId/memberships') try { $userId = ID::unique(); - $invitee = Authorization::skip(fn () => $dbForProject->createDocument('users', new Document([ + $invitee = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('users', new Document([ '$id' => $userId, '$permissions' => [ Permission::read(Role::any()), @@ -602,7 +602,7 @@ App::post('/v1/teams/:teamId/memberships') } } - $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); + $isOwner = $dbForProject->getAuthorization()->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'); @@ -638,11 +638,11 @@ App::post('/v1/teams/:teamId/memberships') ]); $membership = ($isPrivilegedUser || $isAppUser) ? - Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) : + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('memberships', $membership)) : $dbForProject->createDocument('memberships', $membership); if ($isPrivilegedUser || $isAppUser) { - Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); } } elseif ($membership->getAttribute('confirm') === false) { @@ -655,7 +655,7 @@ App::post('/v1/teams/:teamId/memberships') } $membership = ($isPrivilegedUser || $isAppUser) ? - Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : $dbForProject->updateDocument('memberships', $membership->getId(), $membership); } else { throw new Exception(Exception::MEMBERSHIP_ALREADY_CONFIRMED); @@ -911,7 +911,7 @@ App::get('/v1/teams/:teamId/memberships') 'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true, ]; - $roles = Authorization::getRoles(); + $roles = $dbForProject->getAuthorization()->getRoles(); $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); @@ -1002,7 +1002,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') 'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true, ]; - $roles = Authorization::getRoles(); + $roles = $dbForProject->getAuthorization()->getRoles(); $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); @@ -1099,9 +1099,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') throw new Exception(Exception::USER_NOT_FOUND); } - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - $isAppUser = Auth::isAppUser(Authorization::getRoles()); - $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAppUser = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isOwner = $dbForProject->getAuthorization()->hasRole('team:' . $team->getId() . '/owner'); if ($project->getId() === 'console') { // Quick check: fetch up to 2 owners to determine if only one exists @@ -1194,7 +1194,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('teams', $teamId)); if ($team->isEmpty()) { throw new Exception(Exception::TEAM_NOT_FOUND); @@ -1230,11 +1230,11 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->setAttribute('confirm', true) ; - Authorization::skip(fn () => $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('emailVerification', true))); + $dbForProject->getAuthorization()->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()); + $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); $detector = new Detector($request->getUserAgent('UNKNOWN')); $record = $geodb->get($request->getIP()); @@ -1262,7 +1262,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $session = $dbForProject->createDocument('sessions', $session); - Authorization::setRole(Role::user($userId)->toString()); + $dbForProject->getAuthorization()->addRole(Role::user($userId)->toString()); if (!Config::getParam('domainVerification')) { $response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); @@ -1295,7 +1295,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $dbForProject->purgeCachedDocument('users', $user->getId()); - Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); $queueForEvents ->setParam('userId', $user->getId()) @@ -1398,7 +1398,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)); + $dbForProject->getAuthorization()->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 5498a33bf5..9c7cd75817 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -2629,7 +2629,7 @@ App::get('/v1/users/usage') METRIC_SESSIONS, ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $dbForProject->getAuthorization()->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 5bda9961f3..564f6e5493 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -73,12 +73,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } $projectId = $repository->getAttribute('projectId'); - $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = $dbForPlatform->getAuthorization()->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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId)); $resourceInternalId = $resource->getSequence(); $deploymentId = ID::unique(); @@ -127,7 +127,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = ''; if (!empty($providerPullRequestId) && $resource->getAttribute('providerSilentMode', false) === false) { - $latestComment = Authorization::skip(fn () => $dbForPlatform->findOne('vcsComments', [ + $latestComment = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->findOne('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerPullRequestId', [$providerPullRequestId]), Query::orderDesc('$createdAt'), @@ -177,7 +177,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId if (!empty($latestCommentId)) { $teamId = $project->getAttribute('teamId', ''); - $latestComment = Authorization::skip(fn () => $dbForPlatform->createDocument('vcsComments', new Document([ + $latestComment = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->createDocument('vcsComments', new Document([ '$id' => ID::unique(), '$permissions' => [ Permission::read(Role::team(ID::custom($teamId))), @@ -198,7 +198,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } } } elseif (!empty($providerBranch)) { - $latestComments = Authorization::skip(fn () => $dbForPlatform->find('vcsComments', [ + $latestComments = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->find('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerBranch', [$providerBranch]), Query::orderDesc('$createdAt'), @@ -280,7 +280,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $commands[] = $resource->getAttribute('commands', ''); } - $deployment = Authorization::skip(fn () => $dbForProject->createDocument('deployments', new Document([ + $deployment = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('deployments', new Document([ '$id' => $deploymentId, '$permissions' => [ Permission::read(Role::any()), @@ -320,7 +320,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)); + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource)); if ($resource->getCollection() === 'sites') { $projectId = $project->getId(); @@ -330,7 +330,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = ID::unique() . "." . $sitesDomain; $ruleId = md5($domain); $previewRuleId = $ruleId; - Authorization::skip( + $dbForProject->getAuthorization()->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -363,7 +363,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { - Authorization::skip( + $dbForProject->getAuthorization()->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -394,7 +394,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = "commit-" . substr($providerCommitHash, 0, 16) . ".{$sitesDomain}"; $ruleId = md5($domain); try { - Authorization::skip( + $dbForProject->getAuthorization()->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -446,7 +446,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 = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('rules', $previewRuleId)); $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $previewUrl = !empty($rule) ? ("{$protocol}://" . $rule->getAttribute('domain', '')) : ''; @@ -1345,7 +1345,7 @@ 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 = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::limit(100), ])); @@ -1365,13 +1365,13 @@ App::post('/v1/vcs/github/events') ]); foreach ($installations as $installation) { - $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $dbForPlatform->getAuthorization()->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())); + $dbForProject->getAuthorization()->skip(fn () => $dbForPlatform->deleteDocument('repositories', $repository->getId())); } $dbForPlatform->deleteDocument('installations', $installation->getId()); @@ -1403,7 +1403,7 @@ App::post('/v1/vcs/github/events') $providerCommitAuthor = $commitDetails["commitAuthor"] ?? ''; $providerCommitMessage = $commitDetails["commitMessage"] ?? ''; - $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); @@ -1417,7 +1417,7 @@ App::post('/v1/vcs/github/events') $external = $parsedPayload["external"] ?? true; if ($external) { - $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); @@ -1428,7 +1428,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 = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); } } } @@ -1624,7 +1624,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor throw new Exception(Exception::INSTALLATION_NOT_FOUND); } - $repository = Authorization::skip(fn () => $dbForPlatform->getDocument('repositories', $repositoryId, [ + $repository = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('repositories', $repositoryId, [ Query::equal('projectInternalId', [$project->getSequence()]) ])); @@ -1641,7 +1641,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 = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); $githubAppId = System::getEnv('_APP_VCS_GITHUB_APP_ID'); diff --git a/app/controllers/general.php b/app/controllers/general.php index 07de95a38f..b6452abd7f 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -65,9 +65,9 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw // TODO: @christyjacob remove once we migrate the rules in 1.7.x if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { - $rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($host))); + $rule = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('rules', md5($host))); } else { - $rule = Authorization::skip( + $rule = $dbForPlatform->getAuthorization()->skip( fn () => $dbForPlatform->find('rules', [ Query::equal('domain', [$host]), Query::limit(1) @@ -108,7 +108,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $projectId = $rule->getAttribute('projectId'); - $project = Authorization::skip( + $project = $dbForPlatform->getAuthorization()->skip( fn () => $dbForPlatform->getDocument('projects', $projectId) ); @@ -116,7 +116,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)); + $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } /** @@ -155,7 +155,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 = $dbForProject->getAuthorization()->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 @@ -169,15 +169,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)); + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('functions', $resourceId)) : + $dbForProject->getAuthorization()->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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('deployments', $activeDeploymentId)); } if ($deployment->getAttribute('resourceType', '') === 'functions') { @@ -196,8 +196,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', ''))); + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) : + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('sites', $deployment->getAttribute('resourceId', ''))); $isPreview = $type === 'function' ? false : ($rule->getAttribute('trigger', '') !== 'manual'); @@ -239,7 +239,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 = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if (!$user->isEmpty() && $user->getAttribute('status', false)) { $userExists = true; } @@ -252,7 +252,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $membershipExists = false; - $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); if (!$project->isEmpty() && isset($user)) { $teamId = $project->getAttribute('teamId', ''); $membership = $user->find('teamId', $teamId, 'memberships'); @@ -919,7 +919,7 @@ App::init() } elseif (str_starts_with($request->getURI(), '/.well-known/acme-challenge')) { Console::warning('Skipping SSL certificates generation on ACME challenge.'); } else { - Authorization::disable(); + $dbForPlatform->getAuthorization()->disable(); $envDomain = System::getEnv('_APP_DOMAIN', ''); $mainDomain = null; @@ -989,7 +989,7 @@ App::init() } $domains[$domain->get()] = true; - Authorization::reset(); // ensure authorization is re-enabled + $dbForPlatform->getAuthorization()->reset(); // ensure authorization is re-enabled } Config::setParam('domains', $domains); } @@ -1174,7 +1174,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, Authorization $authorization) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); @@ -1256,7 +1257,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 (!Auth::isPrivilegedUser(Authorization::getRoles())) { + if (!Auth::isPrivilegedUser($authorization->getRoles())) { $fileSize = 0; $file = $request->getFiles('file'); if (!empty($file)) { @@ -1318,7 +1319,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)) { @@ -1580,7 +1581,7 @@ App::get('/v1/ping') ->setAttribute('pingCount', $pingCount) ->setAttribute('pingedAt', $pingedAt); - Authorization::skip(function () use ($dbForPlatform, $project) { + $dbForPlatform->getAuthorization()->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 959ee77b7d..113b665925 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -28,7 +28,7 @@ use Utopia\Database\Database; 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; @@ -249,7 +249,7 @@ App::init() if ($apiKey->getRole() === Auth::USER_ROLE_APPS) { // Disable authorization checks for API keys - Authorization::setDefaultStatus(false); + $dbForPlatform->getAuthorization()->setDefaultStatus(false); $user = new Document([ '$id' => '', @@ -322,14 +322,14 @@ App::init() $scopes = \array_merge($scopes, $roles[$role]['scopes']); } - Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users. + $dbForPlatform->getAuthorization()->setDefaultStatus(false); // Cancel security segmentation for admin users. } $scopes = \array_unique($scopes); - Authorization::setRole($role); - foreach (Auth::getRoles($user) as $authRole) { - Authorization::setRole($authRole); + $dbForPlatform->getAuthorization()->addRole($role); + foreach (Auth::getRoles($user, $dbForPlatform->getAuthorization()) as $authRole) { + $dbForPlatform->getAuthorization()->addRole($authRole); } // Update project last activity @@ -337,7 +337,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)); + $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } } @@ -372,7 +372,7 @@ App::init() if ( array_key_exists($namespace, $project->getAttribute('services', [])) && !$project->getAttribute('services', [])[$namespace] - && !(Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles())) + && !(Auth::isPrivilegedUser($dbForPlatform->getAuthorization()->getRoles()) || Auth::isAppUser($dbForPlatform->getAuthorization()->getRoles())) ) { throw new Exception(Exception::GENERAL_SERVICE_DISABLED); } @@ -439,7 +439,7 @@ App::init() if ( array_key_exists('rest', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['rest'] - && !(Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles())) + && !(Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()) || Auth::isAppUser($dbForProject->getAuthorization() ->getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -469,7 +469,7 @@ App::init() $closestLimit = null; - $roles = Authorization::getRoles(); + $roles = $dbForProject->getAuthorization()->getRoles(); $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); @@ -569,10 +569,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 && !Auth::isPrivilegedUser(Authorization::getRoles()); + $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); $key = $request->cacheIdentifier(); - $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); + $cacheLog = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('cache', $key)); $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) ); @@ -585,18 +585,17 @@ App::init() if ($type === 'bucket' && (!$isImageTransformation || !$isDisabled)) { $bucketId = $parts[1] ?? null; - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAppUser && !$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 = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -607,7 +606,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { @@ -618,11 +617,11 @@ App::init() throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } //Do not update transformedAt if it's a console user - if (!Auth::isPrivilegedUser(Authorization::getRoles())) { + if (!Auth::isPrivilegedUser($dbForProject->getAuthorization()->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)); + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); } } } @@ -844,11 +843,11 @@ App::shutdown() $key = $request->cacheIdentifier(); $signature = md5($data['payload']); - $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); + $cacheLog = $dbForProject->getAuthorization()->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([ + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('cache', new Document([ '$id' => $key, 'resource' => $resource, 'resourceType' => $resourceType, @@ -858,7 +857,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)); + $dbForProject->getAuthorization()->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']); } @@ -870,7 +869,7 @@ App::shutdown() } if ($project->getId() !== 'console') { - if (!Auth::isPrivilegedUser(Authorization::getRoles())) { + if (!Auth::isPrivilegedUser($dbForProject->getAuthorization()->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 ecabc641ec..0e3c89c19a 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 = Auth::isPrivilegedUser(Authorization::getRoles()); - $isAppUser = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAppUser = Auth::isAppUser($authorization->getRoles()); if ($isAppUser || $isPrivilegedUser) { // Skip limits for app and console devs return; diff --git a/app/http.php b/app/http.php index 1bd3e97e69..0f65bb6606 100644 --- a/app/http.php +++ b/app/http.php @@ -318,9 +318,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 ($dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) { Console::info(" └── Creating screenshots bucket..."); - Authorization::skip(fn () => $dbForPlatform->createDocument('buckets', new Document([ + $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->createDocument('buckets', new Document([ '$id' => ID::custom('screenshots'), '$collection' => ID::custom('buckets'), 'name' => 'Screenshots', @@ -335,7 +335,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'search' => 'buckets Screenshots', ]))); - $bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); + $bucket = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); Console::info(" └── Creating files collection for screenshots bucket..."); $files = $collections['buckets']['files'] ?? []; @@ -363,7 +363,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)); + $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes)); } }); @@ -454,8 +454,13 @@ $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) { @@ -497,7 +502,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', $authorization->getRoles()); $sdk = $route->getLabel("sdk", false); @@ -573,7 +578,7 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) { } $results = []; try { - $results = Authorization::skip(fn () => $dbForPlatform->find('rules', $queries)); + $results = $dbForPlatform->getAuthorization()->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 c4cfd1ac81..1e2f458724 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -176,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), ])); @@ -189,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), @@ -203,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), @@ -217,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), @@ -231,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), @@ -331,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) @@ -345,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 f91d18f698..2d5d8059a6 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -200,9 +200,9 @@ App::setResource('platforms', function (Request $request, Document $console, Doc // Safe if rule with same project ID exists if (!empty($origin)) { if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { - $rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($origin ?? ''))); + $rule = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('rules', md5($origin ?? ''))); } else { - $rule = Authorization::skip( + $rule = $dbForPlatform->getAuthorization()->skip( fn () => $dbForPlatform->find('rules', [ Query::equal('domain', [$origin]), Query::limit(1) @@ -232,9 +232,10 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons /** @var Utopia\Database\Document $project */ /** @var Utopia\Database\Database $dbForProject */ /** @var Utopia\Database\Database $dbForPlatform */ + /** @var Utopia\Database\Authorization $authorization */ /** @var string $mode */ - Authorization::setDefaultStatus(true); + $dbForPlatform->getAuthorization()->setDefaultStatus(true); Auth::setCookieName('a_session_' . $project->getId()); @@ -349,7 +350,7 @@ App::setResource('project', function ($dbForPlatform, $request, $console) { return $console; } - $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + $project = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); return $project; }, ['dbForPlatform', 'request', 'console']); @@ -379,7 +380,11 @@ App::setResource('console', function () { return new Document(Config::getParam('console')); }, []); -App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project) { +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; } @@ -395,6 +400,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) @@ -415,13 +421,14 @@ 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) { +App::setResource('dbForPlatform', function (Group $pools, Cache $cache, Authorization $authorization) { $adapter = new DatabasePool($pools->get('console')); $database = new Database($adapter, $cache); $database + ->setAuthorization($authorization) ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console') @@ -429,12 +436,12 @@ App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); 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; } @@ -446,8 +453,9 @@ 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) @@ -481,12 +489,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; @@ -496,6 +504,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) @@ -508,7 +517,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) { return $database; }; -}, ['pools', 'cache']); +}, ['pools', 'cache', 'authorization']); App::setResource('telemetry', fn () => new NoTelemetry()); @@ -713,7 +722,7 @@ App::setResource('schema', function ($utopia, $dbForProject) { }; $attributes = function (int $limit, int $offset) use ($dbForProject) { - $attrs = Authorization::skip(fn () => $dbForProject->find('attributes', [ + $attrs = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->find('attributes', [ Query::limit($limit), Query::offset($offset), ])); @@ -852,7 +861,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)); + $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } @@ -869,7 +878,7 @@ 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 = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } } @@ -886,7 +895,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 = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('projects', $pid)); $teamInternalId = $p->getAttribute('teamInternalId', ''); } elseif ($path === '/v1/projects') { $teamId = $request->getParam('teamId', ''); @@ -895,7 +904,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A return new Document([]); } - $team = Authorization::skip(fn () => $dbForPlatform->getDocument('teams', $teamId)); + $team = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('teams', $teamId)); return $team; } } @@ -904,7 +913,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A return new Document([]); } - $team = Authorization::skip(function () use ($dbForPlatform, $teamInternalId) { + $team = $dbForPlatform->getAuthorization()->skip(function () use ($dbForPlatform, $teamInternalId) { return $dbForPlatform->findOne('teams', [ Query::equal('$sequence', [$teamInternalId]), ]); @@ -966,7 +975,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { return new Document([]); } - $token = Authorization::skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId)); + $token = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId)); if ($token->isEmpty()) { return new Document([]); @@ -995,7 +1004,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)); + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token)); } return new Document([ diff --git a/app/realtime.php b/app/realtime.php index e18ab8e10d..e70b0a152d 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -28,7 +28,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; @@ -299,7 +298,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})..."); @@ -329,7 +328,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"); } @@ -360,7 +359,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)), ])); @@ -454,12 +453,12 @@ $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); $user = $database->getDocument('users', $userId); - $roles = Auth::getRoles($user); + $roles = $consoleDatabase->getAuthorization()->getRoles($user); $channels = $realtime->connections[$connection]['channels']; $realtime->unsubscribe($connection); @@ -515,6 +514,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, try { /** @var Document $project */ $project = $app->getResource('project'); + $authorization = $app->getResource('authorization'); /* * Project Check @@ -526,7 +526,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, if ( array_key_exists('realtime', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['realtime'] - && !(Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles())) + && !(Auth::isPrivilegedUser($authorization->getRoles()) || Auth::isAppUser($authorization->getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -563,7 +563,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, throw new Exception(Exception::REALTIME_POLICY_VIOLATION, $originValidator->getDescription()); } - $roles = Auth::getRoles($user); + $roles = Auth::getRoles($user, $authorization); $channels = Realtime::convertChannels($request->getQuery('channels', []), $user->getId()); @@ -637,8 +637,8 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re $database = getConsoleDB(); if ($projectId !== 'console') { - $project = Authorization::skip(fn () => $database->getDocument('projects', $projectId)); - $database = getProjectDB($project); + $project = $database->getAuthorization()->skip(fn () => $database->getDocument('projects', $projectId)); + $database = getProjectDB($project, $database->getAuthorization()); } else { $project = null; } @@ -692,7 +692,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Session is not valid.'); } - $roles = Auth::getRoles($user); + $roles = Auth::getRoles($user, $database->getAuthorization()); $channels = Realtime::convertChannels(array_flip($realtime->connections[$connection]['channels']), $user->getId()); $realtime->subscribe($realtime->connections[$connection]['projectId'], $connection, $roles, $channels); diff --git a/app/worker.php b/app/worker.php index bf0a6583ec..c5dcb14a1e 100644 --- a/app/worker.php +++ b/app/worker.php @@ -45,19 +45,24 @@ 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(); + 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->setAuthorization($authorization); return $dbForPlatform; -}, ['cache', 'register']); +}, ['cache', 'register', 'authorization']); Server::setResource('project', function (Message $message, Database $dbForPlatform) { $payload = $message->getPayload() ?? []; @@ -70,7 +75,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; } @@ -91,11 +96,13 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, if (\in_array($dsn->getHost(), $sharedTables)) { $database + ->setAuthorization($authorization) ->setSharedTables(true) ->setTenant((int)$project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database + ->setAuthorization($authorization) ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getSequence()); @@ -104,12 +111,12 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, $database->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,11 +135,13 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf if (\in_array($dsn->getHost(), $sharedTables)) { $database + ->setAuthorization($authorization) ->setSharedTables(true) ->setTenant((int)$project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database + ->setAuthorization($authorization) ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getSequence()); @@ -150,11 +159,13 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf if (\in_array($dsn->getHost(), $sharedTables)) { $database + ->setAuthorization($authorization) ->setSharedTables(true) ->setTenant((int)$project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database + ->setAuthorization($authorization) ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getSequence()); @@ -164,11 +175,11 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf 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; @@ -178,6 +189,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) @@ -190,7 +202,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 @@ -478,7 +490,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) { @@ -494,7 +507,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 bb843fd771..6f408a72f7 100644 --- a/composer.json +++ b/composer.json @@ -52,7 +52,7 @@ "utopia-php/cache": "0.13.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "3.*", + "utopia-php/database": "dev-feat-authorization-instance as 3.0.2", "utopia-php/detector": "0.1.*", "utopia-php/domains": "0.8.*", "utopia-php/dns": "0.3.*", diff --git a/composer.lock b/composer.lock index c4a8b67561..68c88b9c73 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "407c1717bfef580d733ff2bbb232ec8a", + "content-hash": "f27ea68014d28d445baa355466cdb7a9", "packages": [ { "name": "adhocore/jwt", @@ -3791,17 +3791,65 @@ "time": "2020-10-24T09:49:09+00:00" }, { - "name": "utopia-php/database", - "version": "3.0.2", + "name": "utopia-php/console", + "version": "0.0.1", "source": { "type": "git", - "url": "https://github.com/utopia-php/database.git", - "reference": "b92554e2e7b3b00f0f0acb2b53c6a11e1349b81e" + "url": "https://github.com/utopia-php/console.git", + "reference": "f77104e4a888fa9cb3e08f32955ec09479ab7a92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/b92554e2e7b3b00f0f0acb2b53c6a11e1349b81e", - "reference": "b92554e2e7b3b00f0f0acb2b53c6a11e1349b81e", + "url": "https://api.github.com/repos/utopia-php/console/zipball/f77104e4a888fa9cb3e08f32955ec09479ab7a92", + "reference": "f77104e4a888fa9cb3e08f32955ec09479ab7a92", + "shasum": "" + }, + "require": { + "php": ">=7.4" + }, + "require-dev": { + "laravel/pint": "1.2.*", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.3", + "squizlabs/php_codesniffer": "^3.6", + "swoole/ide-helper": "4.8.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Console helpers for logging, prompting, and executing commands", + "keywords": [ + "cli", + "console", + "php", + "terminal", + "utopia" + ], + "support": { + "issues": "https://github.com/utopia-php/console/issues", + "source": "https://github.com/utopia-php/console/tree/0.0.1" + }, + "time": "2025-10-20T14:41:36+00:00" + }, + { + "name": "utopia-php/database", + "version": "dev-feat-authorization-instance", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/database.git", + "reference": "4088c1002bbc837fd9299987cce5d460ded210d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/database/zipball/4088c1002bbc837fd9299987cce5d460ded210d1", + "reference": "4088c1002bbc837fd9299987cce5d460ded210d1", "shasum": "" }, "require": { @@ -3844,9 +3892,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/3.0.2" + "source": "https://github.com/utopia-php/database/tree/feat-authorization-instance" }, - "time": "2025-10-20T23:58:56+00:00" + "time": "2025-10-20T13:53:53+00:00" }, { "name": "utopia-php/detector", @@ -4346,16 +4394,16 @@ }, { "name": "utopia-php/migration", - "version": "1.2.2", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "e0b6687620dd67fe2b96eb4419e8243577b11c8f" + "reference": "b6985b235ab64f07a6b88569e20cf9b2df7d838c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/e0b6687620dd67fe2b96eb4419e8243577b11c8f", - "reference": "e0b6687620dd67fe2b96eb4419e8243577b11c8f", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/b6985b235ab64f07a6b88569e20cf9b2df7d838c", + "reference": "b6985b235ab64f07a6b88569e20cf9b2df7d838c", "shasum": "" }, "require": { @@ -4363,9 +4411,9 @@ "ext-curl": "*", "ext-openssl": "*", "php": ">=8.1", + "utopia-php/console": "0.0.*", "utopia-php/database": "3.*", "utopia-php/dsn": "0.2.*", - "utopia-php/framework": "0.33.*", "utopia-php/storage": "0.18.*" }, "require-dev": { @@ -4373,7 +4421,6 @@ "laravel/pint": "1.*", "phpstan/phpstan": "1.*", "phpunit/phpunit": "11.*", - "utopia-php/cli": "0.16.*", "vlucas/phpdotenv": "5.*" }, "type": "library", @@ -4396,9 +4443,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/1.2.2" + "source": "https://github.com/utopia-php/migration/tree/1.3.1" }, - "time": "2025-10-20T10:12:11+00:00" + "time": "2025-10-21T08:13:54+00:00" }, { "name": "utopia-php/mongo", @@ -8736,9 +8783,18 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/database", + "version": "dev-feat-authorization-instance", + "alias": "3.0.2", + "alias_normalized": "3.0.2.0" + } + ], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "utopia-php/database": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8762,5 +8818,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.2.0" } diff --git a/src/Appwrite/Auth/Auth.php b/src/Appwrite/Auth/Auth.php index 9af5045fa4..b6676a2843 100644 --- a/src/Appwrite/Auth/Auth.php +++ b/src/Appwrite/Auth/Auth.php @@ -453,11 +453,11 @@ class Auth * @param Document $user * @return array */ - public static function getRoles(Document $user): array + public static function getRoles(Document $user, Authorization $authorization): array { $roles = []; - if (!self::isPrivilegedUser(Authorization::getRoles()) && !self::isAppUser(Authorization::getRoles())) { + if (!self::isPrivilegedUser($authorization->getRoles()) && !self::isAppUser($authorization->getRoles())) { if ($user->getId()) { $roles[] = Role::user($user->getId())->toString(); $roles[] = Role::users()->toString(); diff --git a/src/Appwrite/Databases/TransactionState.php b/src/Appwrite/Databases/TransactionState.php index 23dc6fc2e9..123e2f767f 100644 --- a/src/Appwrite/Databases/TransactionState.php +++ b/src/Appwrite/Databases/TransactionState.php @@ -342,12 +342,12 @@ class TransactionState */ private function getTransactionState(string $transactionId): array { - $transaction = Authorization::skip(fn () => $this->dbForProject->getDocument('transactions', $transactionId)); + $transaction = $this->dbForProject->getAuthorization()->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->dbForProject->getAuthorization()->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 2d82b9c486..f338b2ab29 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -99,8 +99,6 @@ abstract class Migration public function __construct() { - Authorization::disable(); - Authorization::setDefaultStatus(false); $this->collections = Config::getParam('collections', []); @@ -135,6 +133,9 @@ abstract class Migration $this->dbForPlatform = $dbForPlatform; $this->getProjectDB = $getProjectDB; + $this->dbForPlatform->getAuthorization()->disable(); + $this->dbForPlatform->getAuthorization()->setDefaultStatus(false); + return $this; } diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 92805fbaf8..168ee7fc79 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -205,7 +205,7 @@ class Base extends Action // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); - Authorization::skip( + $dbForProject->getAuthorization()->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -231,7 +231,7 @@ class Base extends Action $domain = "commit-" . substr($commitDetails['commitHash'], 0, 16) . ".{$sitesDomain}"; $ruleId = md5($domain); try { - Authorization::skip( + $dbForProject->getAuthorization()->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -268,7 +268,7 @@ class Base extends Action $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { - Authorization::skip( + $dbForProject->getAuthorization()->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php index b67a42adb1..3bb49e7142 100644 --- a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -124,7 +124,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 = $dbForPlatform->getAuthorization()->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 48124e2a11..9e014fd083 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 @@ -310,7 +310,7 @@ abstract class Action extends UtopiaAction throw new Exception($this->getSpatialTypeNotSupportedException()); } - $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $db = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); @@ -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 = !$dbForProject->getAuthorization()->skip(fn () => $dbForProject ->findOne('database_' . $db->getSequence() . '_collection_' . $collection->getSequence())) ->isEmpty(); @@ -474,7 +474,7 @@ abstract class Action extends UtopiaAction 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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); 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 eb51044323..d106b00293 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 @@ -72,7 +72,7 @@ class Delete extends Action 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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } 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 91fa3582f7..8528d6d2cd 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 @@ -73,7 +73,7 @@ class Get extends Action public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } 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 75471b826c..3a451d3839 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 @@ -90,7 +90,7 @@ class Create extends Action $key ??= $relatedCollectionId; $twoWayKey ??= $collectionId; - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index 6daa180df9..60e05420a4 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 @@ -67,7 +67,7 @@ class XList extends Action public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject): void { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } 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 b810ce602f..9b71c80337 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -82,7 +82,7 @@ class Create extends Action 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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); 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 d124a47289..e1c4122942 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php @@ -69,7 +69,7 @@ class Delete extends Action 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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } 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 3da89f352c..cda3f0371f 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 @@ -297,7 +297,7 @@ abstract class Action extends AppwriteAction $relatedCollectionId = $relationship->getAttribute('relatedCollection'); if (!isset($collectionsCache[$relatedCollectionId])) { - $relatedCollectionDoc = Authorization::skip( + $relatedCollectionDoc = $dbForProject->getAuthorization()->skip( fn () => $dbForProject->getDocument( 'database_' . $database->getSequence(), $relatedCollectionId 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 0b3d0e9fb4..4e41784b59 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 @@ -89,15 +89,15 @@ class Decrement extends 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 { - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException()); } @@ -105,7 +105,7 @@ class Decrement extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $dbForProject->getAuthorization()->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 ef64099fa8..3b47a3f14c 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 @@ -89,15 +89,15 @@ class Increment extends 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 { - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception($this->getParentNotFoundException()); } @@ -105,7 +105,7 @@ class Increment extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $dbForProject->getAuthorization()->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 521190d3dc..d53bf44922 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 @@ -23,7 +23,7 @@ use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; -use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -177,19 +177,19 @@ class Create extends Action $documents = [$data]; } - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); if ($isBulk && !$isAPIKey && !$isPrivilegedUser) { throw new Exception(Exception::GENERAL_UNAUTHORIZED_SCOPE); } - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException()); } @@ -246,8 +246,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 (!$dbForProject->getAuthorization()->hasRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $dbForProject->getAuthorization()->getRoles()) . ')'); } } } @@ -262,17 +262,17 @@ class Create extends Action $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 = $dbForProject->getAuthorization()->isValid(new Input($permission, $collection->getPermissionsByType($permission))); + if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$validCollection) { + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } if ($permission === Database::PERMISSION_UPDATE) { - $valid = $valid || $validator->isValid($document->getUpdate()); + $validDocument= $dbForProject->getAuthorization()->isValid(new Input($permission, $document->getUpdate())); + $valid = $validCollection || $validDocument; if ($documentSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } } @@ -297,7 +297,7 @@ class Create extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( + $relatedCollection = $dbForProject->getAuthorization()->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -313,7 +313,7 @@ class Create extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $current = Authorization::skip( + $current = $dbForProject->getAuthorization()->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId()) ); @@ -368,7 +368,7 @@ class Create extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND); @@ -503,4 +503,4 @@ class Create extends Action $this->getResponseModel() ); } -} +} \ No newline at end of file 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 a4cef59e5f..e213687b54 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 @@ -98,16 +98,16 @@ class Delete extends Action TransactionState $transactionState, array $plan ): void { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException()); @@ -120,7 +120,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($document->isEmpty()) { @@ -130,7 +130,7 @@ class Delete extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND); 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 3d8cd9198c..43dee6083d 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 @@ -74,15 +74,15 @@ class Get extends Action public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void { - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException()); 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 241b0c4ede..a4ac205a2d 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 @@ -78,7 +78,7 @@ class XList extends Action public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): void { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } 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 552c51a5fb..faf7b7db3b 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 @@ -97,16 +97,16 @@ class Update extends Action throw new Exception($this->getMissingPayloadException()); } - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException()); @@ -120,7 +120,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($document->isEmpty()) { @@ -135,7 +135,7 @@ class Update extends Action ]); // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); + $roles = $dbForProject->getAuthorization()->getRoles(); if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -148,7 +148,7 @@ class Update extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$dbForProject->getAuthorization()->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -190,7 +190,7 @@ class Update extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( + $relatedCollection = $dbForProject->getAuthorization()->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -207,7 +207,7 @@ class Update extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( + $oldDocument = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); @@ -245,7 +245,7 @@ class Update extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND); 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 f113a99c7a..50e4e840fc 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 @@ -105,15 +105,15 @@ class Upsert extends Action throw new Exception($this->getMissingPayloadException()); } - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException()); } @@ -134,7 +134,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($oldDocument->isEmpty()) { if (!empty($user->getId())) { @@ -150,7 +150,7 @@ class Upsert extends Action } // Users can only manage their own roles, API keys and Admin users can manage any - $roles = Authorization::getRoles(); + $roles = $dbForProject->getAuthorization()->getRoles(); if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -163,7 +163,7 @@ class Upsert extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$dbForProject->getAuthorization()->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -200,7 +200,7 @@ class Upsert extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = Authorization::skip( + $relatedCollection = $dbForProject->getAuthorization()->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -217,7 +217,7 @@ class Upsert extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( + $oldDocument = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); @@ -254,7 +254,7 @@ class Upsert extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index a30fed47ed..26866ac33d 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 @@ -76,15 +76,15 @@ class XList extends Action public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void { - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException()); } @@ -112,7 +112,7 @@ class XList extends Action $documentId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); + $cursorDocument = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); if ($cursorDocument->isEmpty()) { $type = ucfirst($this->getContext()); 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 89739570c7..18509da214 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php @@ -62,7 +62,7 @@ class Get extends Action public function action(string $databaseId, string $collectionId, UtopiaResponse $response, Database $dbForProject): void { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); 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 9fb438d577..c3e7e66b2e 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 @@ -84,7 +84,7 @@ class Create extends 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 { - $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $db = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); 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 2bccfdfb52..dbe6e48dd3 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 @@ -75,7 +75,7 @@ class Delete extends Action 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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); 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 3d118d1922..e703ad03b3 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 @@ -64,7 +64,7 @@ class Get extends Action public function action(string $databaseId, string $collectionId, string $key, UtopiaResponse $response, Database $dbForProject): void { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index 60e52f883a..f8ee258698 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 @@ -70,7 +70,7 @@ class XList extends Action public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject): void { /** @var Document $database */ - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); @@ -110,7 +110,7 @@ class XList extends Action } $indexId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [ + $cursorDocument = $dbForProject->getAuthorization()->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 b202120bad..f6046cc468 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 @@ -77,7 +77,7 @@ class XList extends Action public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): void { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); 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 49870002ce..42fdbfb7f1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php @@ -75,7 +75,7 @@ class Update extends Action 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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } 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 9cf7b85267..3ec9dafe5c 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 @@ -83,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) { + $dbForProject->getAuthorization()->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 b4cc5470d9..59d0540224 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -70,7 +70,7 @@ class XList extends Action public function action(string $databaseId, array $queries, string $search, UtopiaResponse $response, Database $dbForProject): void { - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); 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 c4c5bf8b51..ebe06661f5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php @@ -73,7 +73,7 @@ class Create extends Action } } - $transaction = Authorization::skip(fn () => $dbForProject->createDocument('transactions', new Document([ + $transaction = $dbForProject->getAuthorization()->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 bd94c1c7eb..66f86045fe 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 @@ -17,7 +17,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\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; @@ -72,12 +72,12 @@ class Create extends Action throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Operations array cannot be empty'); } - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); // API keys and admins can read any transaction, regular users need permissions $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND); @@ -113,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']] ??= $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $operation['databaseId'])); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } $collection = $collections[$operation[$this->getGroupId()]] ??= - Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $operation[$this->getGroupId()])); + $dbForProject->getAuthorization()->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); @@ -165,8 +165,10 @@ 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 = $dbForProject->getAuthorization()->isValid( + new input($permissionType, $collection->getPermissionsByType($permissionType)) + ); $documentValid = false; if ($document !== null && !$document->isEmpty() && $documentSecurity) { if ($permissionType === Database::PERMISSION_UPDATE) { @@ -189,7 +191,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 = $dbForProject->getAuthorization()->getRoles(); foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); @@ -201,7 +203,7 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!Authorization::isRole($role)) { + if (!$dbForProject->getAuthorization()->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -230,7 +232,7 @@ class Create extends Action } } - $transaction = Authorization::skip(fn () => $dbForProject->withTransaction(function () use ($dbForProject, $transactionId, $staged, $existing, $operations) { + $transaction = $dbForProject->getAuthorization()->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 6e2bd63827..ec43cfa87f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php @@ -111,11 +111,11 @@ class Update extends Action throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Cannot commit and rollback at the same time'); } - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); $transaction = ($isAPIKey || $isPrivilegedUser) - ? Authorization::skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) + ? $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) : $dbForProject->getDocument('transactions', $transactionId); if ($transaction->isEmpty()) { throw new Exception(Exception::TRANSACTION_NOT_FOUND); @@ -138,11 +138,11 @@ class Update extends Action try { $dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, $queueForEvents, $queueForStatsUsage, $queueForRealtime, $queueForFunctions, $queueForWebhooks) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'committing', ]))); - $operations = Authorization::skip(fn () => $dbForProject->find('transactionLogs', [ + $operations = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->find('transactionLogs', [ Query::equal('transactionInternalId', [$transaction->getSequence()]), Query::orderAsc(), Query::limit(PHP_INT_MAX), @@ -218,7 +218,7 @@ class Update extends Action } } - $transaction = Authorization::skip(fn () => $dbForProject->updateDocument( + $transaction = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument( 'transactions', $transactionId, new Document(['status' => 'committed']) @@ -230,32 +230,32 @@ class Update extends Action }); } catch (NotFoundException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::DOCUMENT_NOT_FOUND, previous: $e); } catch (DuplicateException|ConflictException $e) { - Authorization::skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $dbForProject->getAuthorization()->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([ + $dbForProject->getAuthorization()->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([ + $dbForProject->getAuthorization()->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([ + $dbForProject->getAuthorization()->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([ + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', ]))); throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); @@ -283,11 +283,11 @@ class Update extends Action $data = $data->getArrayCopy(); } - $database = Authorization::skip(fn () => $dbForProject->findOne('databases', [ + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->findOne('databases', [ Query::equal('$sequence', [$databaseInternalId]) ])); - $collection = Authorization::skip(fn () => $dbForProject->findOne('database_' . $databaseInternalId, [ + $collection = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->findOne('database_' . $databaseInternalId, [ Query::equal('$sequence', [$collectionInternalId]) ])); @@ -379,7 +379,7 @@ class Update extends Action } if ($rollback) { - $transaction = Authorization::skip(fn () => $dbForProject->updateDocument( + $transaction = $dbForProject->getAuthorization()->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 c9de9d5217..112892d39d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php @@ -81,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) { + $dbForProject->getAuthorization()->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..4c0515c02b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php @@ -74,7 +74,7 @@ class XList extends Action METRIC_DATABASES_OPERATIONS_WRITES, ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $dbForProject->getAuthorization()->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/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index 69af3b7d04..a05dfbd2a4 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -26,7 +26,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\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -152,10 +152,10 @@ class Create extends Base throw new Exception($validator->getDescription(), 400); } - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRole); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); @@ -171,7 +171,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 = $dbForProject->getAuthorization()->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'); @@ -185,10 +185,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 (!$dbForProject->getAuthorization()->isValid(new Input('execute', $function->getAttribute('execute')))) { // Check if user has write access to execute function + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } $jwt = ''; // initialize @@ -286,7 +284,7 @@ class Create extends Base if ($async) { if (is_null($scheduledAt)) { - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('executions', $execution)); $queueForFunctions ->setType('http') ->setExecution($execution) @@ -327,7 +325,7 @@ class Create extends Base ->setAttribute('scheduleInternalId', $schedule->getSequence()) ->setAttribute('scheduledAt', $scheduledAt); - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('executions', $execution)); } return $response @@ -480,7 +478,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 = $dbForProject->getAuthorization()->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 666cb8310c..fbe53218d3 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php @@ -108,7 +108,7 @@ class Delete extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('active', false); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $dbForPlatform->getAuthorization()->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 42d78f8ca8..e0f90e5f00 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php @@ -61,10 +61,10 @@ class Get extends Base Response $response, Database $dbForProject ) { - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->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 46a41e6517..b4fe89e5ce 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -67,10 +67,10 @@ class XList extends Base Response $response, Database $dbForProject ) { - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->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 932f515fc1..0f137a42c0 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php @@ -237,7 +237,7 @@ class Create extends Base throw new Exception(Exception::FUNCTION_ALREADY_EXISTS); } - $schedule = Authorization::skip( + $schedule = $dbForProject->getAuthorization()->skip( fn () => $dbForPlatform->createDocument('schedules', new Document([ 'region' => $project->getAttribute('region'), 'resourceType' => SCHEDULE_RESOURCE_TYPE_FUNCTION, @@ -365,7 +365,7 @@ class Create extends Base // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); - $rule = Authorization::skip( + $rule = $dbForPlatform->getAuthorization()->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 72d5589252..8462e649a2 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php @@ -87,7 +87,7 @@ class Delete extends Base $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('active', false); - Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $dbForPlatform->getAuthorization()->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 8846329d27..7d521caa9c 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -101,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)); + $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queries = [ Query::equal('trigger', ['manual']), @@ -112,12 +112,12 @@ class Update extends Base Query::equal('projectInternalId', [$project->getSequence()]) ]; - Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { + $dbForPlatform->getAuthorization()->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)); + $dbForPlatform->getAuthorization()->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 aaff953af0..cce896713c 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php @@ -282,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)); + $dbForPlatform->getAuthorization()->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..c2ea423c31 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php @@ -83,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) { + $dbForProject->getAuthorization()->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..877e014dfb 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php @@ -75,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) { + $dbForProject->getAuthorization()->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 815d364dad..4c1141e1a7 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php @@ -119,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)); + $dbForPlatform->getAuthorization()->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 35f9618edb..bc85063a26 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php @@ -92,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)); + $dbForPlatform->getAuthorization()->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 639b1c74d5..b571a63709 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php @@ -109,7 +109,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)); + $dbForPlatform->getAuthorization()->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 d6385c1f40..cff0073523 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -916,7 +916,7 @@ class Builds extends Action ->trigger(); try { - $rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ + $rule = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal("projectInternalId", [$project->getSequence()]), Query::equal("type", ["deployment"]), Query::equal('deploymentInternalId', [$deployment->getSequence()]), @@ -930,7 +930,7 @@ class Builds extends Action $client->setTimeout(\intval($resource->getAttribute('timeout', '15'))); $client->addHeader('content-type', FetchClient::CONTENT_TYPE_APPLICATION_JSON); - $bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); + $bucket = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); $configs = [ 'screenshotLight' => [ @@ -1052,7 +1052,7 @@ class Builds extends Action 'metadata' => ['content_type' => $mimeType], ]); - Authorization::skip(fn () => $dbForPlatform->createDocument('bucket_' . $bucket->getSequence(), $file)); + $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->createDocument('bucket_' . $bucket->getSequence(), $file)); $deployment->setAttribute($key, $fileId); } @@ -1275,7 +1275,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->getAuthorization()->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); } Console::info('Deployment action finished'); @@ -1570,7 +1570,7 @@ class Builds extends Action default => throw new \Exception('Invalid resource type') }; - $rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ + $rule = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->findOne('rules', [ Query::equal("projectInternalId", [$project->getSequence()]), Query::equal("type", ["deployment"]), Query::equal("deploymentInternalId", [$deployment->getSequence()]), diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index 65a0fcf143..5f7e442bdd 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php @@ -274,7 +274,7 @@ class Create extends Action // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); - Authorization::skip( + $dbForPlatform->getAuthorization()->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -339,7 +339,7 @@ class Create extends Action $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $domain = ID::unique() . "." . $sitesDomain; $ruleId = md5($domain); - Authorization::skip( + $dbForPlatform->getAuthorization()->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), 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 065dd13e88..721d55bdf1 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php @@ -146,7 +146,7 @@ class Create extends Action // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); - Authorization::skip( + $dbForPlatform->getAuthorization()->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 dc90045b0c..f7dc9a3c43 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php @@ -176,7 +176,7 @@ class Create extends Base // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); - Authorization::skip( + $dbForPlatform->getAuthorization()->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), 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 bb6bd4f632..7abfb02689 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -104,12 +104,12 @@ class Update extends Base Query::equal('projectInternalId', [$project->getSequence()]) ]; - Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { + $dbForPlatform->getAuthorization()->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)); + $dbForPlatform->getAuthorization()->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..3864a6328f 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php @@ -91,7 +91,7 @@ class Get extends Base ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $dbForProject->getAuthorization()->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..eec1b321c6 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php @@ -78,7 +78,7 @@ class XList extends Base METRIC_SITES_OUTBOUND, ]; - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + $dbForProject->getAuthorization()->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 5708f1b83b..17984a1725 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 @@ -5,33 +5,31 @@ namespace Appwrite\Platform\Modules\Tokens\Http\Tokens\Buckets\Files; use Appwrite\Auth\Auth; use Appwrite\Extend\Exception; 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 { - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->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 (!$dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead()))){ + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->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 = $dbForProject->getAuthorization()->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 fe7a0187e9..57bf7cf1a9 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 @@ -13,7 +13,7 @@ use Appwrite\Utopia\Response; 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; @@ -78,11 +78,10 @@ class Create extends Action ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $bucketId, $fileId); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $validator = new Authorization(Database::PERMISSION_UPDATE); - $bucketPermission = $validator->isValid($bucket->getUpdate()); - + $bucketPermission = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); + if ($fileSecurity) { - $filePermission = $validator->isValid($file->getUpdate()); + $filePermission = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_UPDATE, $file->getUpdate())); if (!$bucketPermission && !$filePermission) { throw new Exception(Exception::USER_UNAUTHORIZED); } diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index 3e35c1c1fa..721a1f4039 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -48,7 +48,7 @@ class Migrate extends Action callable $getProjectDB, Registry $register, ): void { - Authorization::disable(); + $dbForPlatform->getAuthorization()->disable(); if (!\array_key_exists($version, Migration::$versions)) { Console::error("No migration found for version $version."); diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index e9a0e1d333..f696dbd790 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -62,7 +62,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->getAuthorization()->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 b64dd61f86..102a25df62 100644 --- a/src/Appwrite/Platform/Tasks/StatsResources.php +++ b/src/Appwrite/Platform/Tasks/StatsResources.php @@ -61,9 +61,9 @@ 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) { + $dbForPlatform->getAuthorization()->disable(); + $dbForPlatform->getAuthorization()->setDefaultStatus(false); $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 331a2668a3..8769e2f56b 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -954,14 +954,14 @@ class Deletes extends Action } Console::info("Deleting screenshots for deployment " . $deployment->getId()); - $bucket = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); + $bucket = $dbForPlatform->getAuthorization()->skip(fn () => $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->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $id)); if ($file->isEmpty()) { Console::error('Failed to get deployment screenshot: ' . $id); diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index 558f0cdf09..75f0744098 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -210,7 +210,7 @@ class Request extends UtopiaRequest { $forwardedUserAgent = $this->getHeader('x-forwarded-user-agent'); if (!empty($forwardedUserAgent)) { - $roles = Authorization::getRoles(); + $roles = $this->authorization->getRoles(); $isAppUser = Auth::isAppUser($roles); if ($isAppUser) { @@ -233,4 +233,11 @@ class Request extends UtopiaRequest ksort($params); return md5($this->getURI() . '*' . serialize($params) . '*' . APP_CACHE_BUSTER); } + + private Authorization $authorization; + + public function setAuthorization(Authorization $authorization): void + { + $this->authorization = $authorization; + } } diff --git a/src/Appwrite/Utopia/Request/Filters/V20.php b/src/Appwrite/Utopia/Request/Filters/V20.php index 3783a61947..8f500c9380 100644 --- a/src/Appwrite/Utopia/Request/Filters/V20.php +++ b/src/Appwrite/Utopia/Request/Filters/V20.php @@ -139,7 +139,7 @@ class V20 extends Filter } try { - $database = Authorization::skip(fn () => $dbForProject->getDocument( + $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument( 'databases', $databaseId )); @@ -151,7 +151,7 @@ class V20 extends Filter } try { - $collection = Authorization::skip(fn () => $dbForProject->getDocument( + $collection = $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 b391f0ea72..099bf7fd44 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -809,7 +809,7 @@ class Response extends SwooleResponse } if ($rule['sensitive']) { - $roles = Authorization::getRoles(); + $roles = $this->authorization->getRoles(); $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); @@ -977,4 +977,11 @@ class Response extends SwooleResponse self::$showSensitive = false; } } + + private Authorization $authorization; + + 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..26e11ff0b9 100644 --- a/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php @@ -17,6 +17,16 @@ class DatabasesPermissionsGuestTest extends Scope use SideClient; use DatabasesPermissionsScope; +private $authorization; + +public function getAuthorization(): Authorization +{ + if (isset($this->authorization)) { + return $this->authorization; + } + return new Authorization(); +} + public function createCollection(): array { $database = $this->client->call(Client::METHOD_POST, '/databases', array_merge([ @@ -111,8 +121,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 +144,7 @@ class DatabasesPermissionsGuestTest extends Scope } foreach ($roles as $role) { - Authorization::setRole($role); + $this->getAuthorization()->addRole($role); } } @@ -145,8 +155,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 +232,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..20a91c6717 100644 --- a/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php @@ -17,6 +17,17 @@ class DatabasesPermissionsGuestTest extends Scope use SideClient; use DatabasesPermissionsScope; + private $authorization; + + public function getAuthorization(): Authorization + { + if (isset($this->authorization)) { + return $this->authorization; + } + return new Authorization(); + } + + public function createTable(): array { $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ @@ -111,8 +122,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 +145,7 @@ class DatabasesPermissionsGuestTest extends Scope } foreach ($roles as $role) { - Authorization::setRole($role); + $this->getAuthorization()->addRole($role); } } @@ -145,8 +156,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 +233,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/unit/Auth/AuthTest.php b/tests/unit/Auth/AuthTest.php index 705da42879..4fef733457 100644 --- a/tests/unit/Auth/AuthTest.php +++ b/tests/unit/Auth/AuthTest.php @@ -13,13 +13,24 @@ use Utopia\Database\Validator\Roles; class AuthTest extends TestCase { + private $authorization; + + public function getAuthorization(): Authorization + { + if (isset($this->authorization)) { + return $this->authorization; + } + return new 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 testCookieName(): void @@ -347,7 +358,7 @@ class AuthTest extends TestCase '$id' => '' ]); - $roles = Auth::getRoles($user); + $roles = Auth::getRoles($user, new Authorization()); $this->assertCount(1, $roles); $this->assertContains(Role::guests()->toString(), $roles); } @@ -383,7 +394,7 @@ class AuthTest extends TestCase ] ]); - $roles = Auth::getRoles($user); + $roles = Auth::getRoles($user, $this->getAuthorization()); $this->assertCount(13, $roles); $this->assertContains(Role::users()->toString(), $roles); @@ -404,21 +415,21 @@ class AuthTest extends TestCase $user['emailVerification'] = false; $user['phoneVerification'] = false; - $roles = Auth::getRoles($user); + $roles = Auth::getRoles($user, $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 = Auth::getRoles($user); + $roles = Auth::getRoles($user, $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(Auth::USER_ROLE_OWNER); + $this->getAuthorization()->addRole(Auth::USER_ROLE_OWNER); $user = new Document([ '$id' => ID::custom('123'), 'emailVerification' => true, @@ -444,7 +455,7 @@ class AuthTest extends TestCase ] ]); - $roles = Auth::getRoles($user); + $roles = Auth::getRoles($user, $this->getAuthorization()); $this->assertCount(7, $roles); $this->assertNotContains(Role::users()->toString(), $roles); @@ -462,7 +473,7 @@ class AuthTest extends TestCase public function testAppUserRoles(): void { - Authorization::setRole(Auth::USER_ROLE_APPS); + $this->getAuthorization()->addRole(Auth::USER_ROLE_APPS); $user = new Document([ '$id' => ID::custom('123'), 'memberships' => [ @@ -486,7 +497,7 @@ class AuthTest extends TestCase ] ]); - $roles = Auth::getRoles($user); + $roles = Auth::getRoles($user, $this->getAuthorization()); $this->assertCount(7, $roles); $this->assertNotContains(Role::users()->toString(), $roles); diff --git a/tests/unit/Messaging/MessagingChannelsTest.php b/tests/unit/Messaging/MessagingChannelsTest.php index 8ba0374093..54784edada 100644 --- a/tests/unit/Messaging/MessagingChannelsTest.php +++ b/tests/unit/Messaging/MessagingChannelsTest.php @@ -8,6 +8,7 @@ use PHPUnit\Framework\TestCase; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; class MessagingChannelsTest extends TestCase { @@ -34,6 +35,16 @@ class MessagingChannelsTest extends TestCase 'functions.1', ]; + private $authorization; + + public function getAuthorization(): Authorization + { + if (isset($this->authorization)) { + return $this->authorization; + } + return new Authorization(); + } + public function setUp(): void { /** @@ -66,7 +77,7 @@ class MessagingChannelsTest extends TestCase ] ]); - $roles = Auth::getRoles($user); + $roles = Auth::getRoles($user, $this->getAuthorization()); $parsedChannels = Realtime::convertChannels([0 => $channel], $user->getId()); @@ -90,7 +101,7 @@ class MessagingChannelsTest extends TestCase '$id' => '' ]); - $roles = Auth::getRoles($user); + $roles = Auth::getRoles($user, $this->getAuthorization()); $parsedChannels = Realtime::convertChannels([0 => $channel], $user->getId()); From 8b3b07a710e328d670dce67391475b2b7fda698e Mon Sep 17 00:00:00 2001 From: shimon Date: Wed, 22 Oct 2025 16:40:00 +0300 Subject: [PATCH 02/77] linter --- app/controllers/api/account.php | 3 +-- app/controllers/api/avatars.php | 1 - app/controllers/api/migrations.php | 1 - app/controllers/api/project.php | 1 - app/controllers/api/storage.php | 2 +- app/controllers/api/teams.php | 1 - app/controllers/api/users.php | 1 - app/controllers/api/vcs.php | 1 - app/controllers/shared/api.php | 2 +- app/http.php | 1 - app/init/database/filters.php | 1 - src/Appwrite/Databases/TransactionState.php | 3 +-- src/Appwrite/Migration/Migration.php | 1 - src/Appwrite/Platform/Modules/Compute/Base.php | 1 - .../Modules/Console/Http/Resources/Get.php | 1 - .../Databases/Collections/Attributes/Action.php | 1 - .../Databases/Collections/Attributes/Delete.php | 1 - .../Http/Databases/Collections/Attributes/Get.php | 1 - .../Collections/Attributes/Relationship/Create.php | 1 - .../Databases/Collections/Attributes/XList.php | 1 - .../Http/Databases/Collections/Create.php | 1 - .../Http/Databases/Collections/Delete.php | 1 - .../Databases/Collections/Documents/Action.php | 1 - .../Collections/Documents/Attribute/Decrement.php | 1 - .../Collections/Documents/Attribute/Increment.php | 1 - .../Databases/Collections/Documents/Create.php | 4 ++-- .../Databases/Collections/Documents/Delete.php | 1 - .../Http/Databases/Collections/Documents/Get.php | 1 - .../Databases/Collections/Documents/Logs/XList.php | 1 - .../Databases/Collections/Documents/Update.php | 1 - .../Databases/Collections/Documents/Upsert.php | 1 - .../Http/Databases/Collections/Documents/XList.php | 1 - .../Databases/Http/Databases/Collections/Get.php | 1 - .../Http/Databases/Collections/Indexes/Create.php | 1 - .../Http/Databases/Collections/Indexes/Delete.php | 1 - .../Http/Databases/Collections/Indexes/Get.php | 1 - .../Http/Databases/Collections/Indexes/XList.php | 1 - .../Http/Databases/Collections/Logs/XList.php | 1 - .../Http/Databases/Collections/Update.php | 1 - .../Http/Databases/Collections/Usage/Get.php | 1 - .../Databases/Http/Databases/Collections/XList.php | 1 - .../Http/Databases/Transactions/Create.php | 1 - .../Databases/Transactions/Operations/Create.php | 2 +- .../Modules/Databases/Http/Databases/Usage/Get.php | 1 - .../Databases/Http/Databases/Usage/XList.php | 1 - .../Modules/Functions/Http/Executions/Delete.php | 1 - .../Modules/Functions/Http/Executions/Get.php | 1 - .../Modules/Functions/Http/Executions/XList.php | 1 - .../Modules/Functions/Http/Functions/Create.php | 1 - .../Modules/Functions/Http/Functions/Delete.php | 1 - .../Functions/Http/Functions/Deployment/Update.php | 1 - .../Modules/Functions/Http/Functions/Update.php | 1 - .../Platform/Modules/Functions/Http/Usage/Get.php | 1 - .../Modules/Functions/Http/Usage/XList.php | 1 - .../Modules/Functions/Http/Variables/Create.php | 1 - .../Modules/Functions/Http/Variables/Delete.php | 1 - .../Modules/Functions/Http/Variables/Update.php | 1 - .../Modules/Sites/Http/Deployments/Create.php | 1 - .../Sites/Http/Deployments/Duplicate/Create.php | 1 - .../Sites/Http/Deployments/Template/Create.php | 1 - .../Modules/Sites/Http/Sites/Deployment/Update.php | 1 - .../Platform/Modules/Sites/Http/Usage/Get.php | 1 - .../Platform/Modules/Sites/Http/Usage/XList.php | 1 - .../Tokens/Http/Tokens/Buckets/Files/Action.php | 2 +- .../Tokens/Http/Tokens/Buckets/Files/Create.php | 2 +- src/Appwrite/Platform/Tasks/Migrate.php | 1 - src/Appwrite/Platform/Tasks/ScheduleBase.php | 1 - src/Appwrite/Platform/Tasks/StatsResources.php | 1 - src/Appwrite/Platform/Workers/Deletes.php | 1 - src/Appwrite/Utopia/Request.php | 2 +- src/Appwrite/Utopia/Request/Filters/V20.php | 1 - src/Appwrite/Utopia/Response.php | 2 +- .../Permissions/DatabasesPermissionsGuestTest.php | 14 +++++++------- 73 files changed, 18 insertions(+), 82 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index aeeff76dff..8dfe4b51b7 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -51,7 +51,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\Queries; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\Query\Limit; @@ -228,7 +227,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res Permission::delete(Role::user($user->getId())), ])); - $dbForProject->getAuthorization()->skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId())); + $dbForProject->getAuthorization()->skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId())); $dbForProject->purgeCachedDocument('users', $user->getId()); // Magic URL + Email OTP diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index 64f13c1981..4952a763fc 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -16,7 +16,6 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Domains\Domain; use Utopia\Fetch\Client; diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 4f88adf616..f370580a79 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -19,7 +19,6 @@ use Utopia\Database\Exception\Order as OrderException; 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\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Migration\Resource; diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 554d2defec..061711c96a 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -14,7 +14,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\Datetime as DateTimeValidator; use Utopia\Database\Validator\UID; use Utopia\Validator\Boolean; diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index ebccc9c321..ab003bedf1 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -739,7 +739,7 @@ App::post('/v1/storage/buckets/:bucketId/files') if (!$dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } - + try { $file = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } catch (NotFoundException) { diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index eb70282ff4..5843cebeca 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -41,7 +41,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\Key; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Cursor; diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 9c7cd75817..d7b4b56806 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -43,7 +43,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\Queries; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\Query\Limit; diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 564f6e5493..354c89999b 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.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\Database\Validator\Query\Cursor; use Utopia\Detector\Detection\Framework\Astro; use Utopia\Detector\Detection\Framework\Flutter; diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 113b665925..f9109c3be3 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -328,7 +328,7 @@ App::init() $scopes = \array_unique($scopes); $dbForPlatform->getAuthorization()->addRole($role); - foreach (Auth::getRoles($user, $dbForPlatform->getAuthorization()) as $authRole) { + foreach (Auth::getRoles($user, $dbForPlatform->getAuthorization()) as $authRole) { $dbForPlatform->getAuthorization()->addRole($authRole); } diff --git a/app/http.php b/app/http.php index 0f65bb6606..629d1d21b7 100644 --- a/app/http.php +++ b/app/http.php @@ -25,7 +25,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; diff --git a/app/init/database/filters.php b/app/init/database/filters.php index 1e2f458724..c065bf0d82 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( diff --git a/src/Appwrite/Databases/TransactionState.php b/src/Appwrite/Databases/TransactionState.php index 123e2f767f..44ba62c4a4 100644 --- a/src/Appwrite/Databases/TransactionState.php +++ b/src/Appwrite/Databases/TransactionState.php @@ -7,7 +7,6 @@ use Utopia\Database\Document; use Utopia\Database\Exception; use Utopia\Database\Exception\Timeout; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; /** * Service for managing transaction state and providing transaction-aware document operations @@ -347,7 +346,7 @@ class TransactionState return []; } - $operations =$this->dbForProject->getAuthorization()->skip(fn () => $this->dbForProject->find('transactionLogs', [ + $operations = $this->dbForProject->getAuthorization()->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 f338b2ab29..142c828ac5 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -13,7 +13,6 @@ use Utopia\Database\Exception\Limit; use Utopia\Database\Exception\Structure; use Utopia\Database\Helpers\ID; use Utopia\Database\PDO; -use Utopia\Database\Validator\Authorization; abstract class Migration { diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 168ee7fc79..f90d615cac 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -11,7 +11,6 @@ use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; -use Utopia\Database\Validator\Authorization; use Utopia\Swoole\Request; use Utopia\System\System; use Utopia\VCS\Adapter\Git\GitHub; diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php index 3bb49e7142..2abe4e0957 100644 --- a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -10,7 +10,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Domains\Domain as Domain; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; 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 9e014fd083..5b41c42200 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 @@ -17,7 +17,6 @@ use Utopia\Database\Exception\Relationship as RelationshipException; use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Exception\Truncate as TruncateException; use Utopia\Database\Helpers\ID; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Structure; use Utopia\Platform\Action as UtopiaAction; use Utopia\Swoole\Response as SwooleResponse; 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 d106b00293..ec8005993c 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 @@ -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\IndexDependency as IndexDependencyValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; 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 8528d6d2cd..158184e336 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 @@ -9,7 +9,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; 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 3a451d3839..a502c2012b 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 @@ -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; 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 60e05420a4..e632f6397e 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 @@ -14,7 +14,6 @@ use Utopia\Database\Document; 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\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; 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 9b71c80337..8a9088382d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -19,7 +19,6 @@ use Utopia\Database\Exception\Limit as LimitException; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; 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 e1c4122942..a9eebbc9d6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.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\UID; use Utopia\Swoole\Response as SwooleResponse; 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 cda3f0371f..bbf62b2e83 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 @@ -7,7 +7,6 @@ use Appwrite\Extend\Exception; use Appwrite\Platform\Action as AppwriteAction; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Validator\Authorization; abstract class Action extends AppwriteAction { 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 4e41784b59..9f92a707f8 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 @@ -21,7 +21,6 @@ use Utopia\Database\Exception\Limit as LimitException; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Exception\Type as TypeException; use Utopia\Database\Helpers\ID; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; 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 3b47a3f14c..b97a937e58 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 @@ -21,7 +21,6 @@ use Utopia\Database\Exception\Limit as LimitException; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Exception\Type as TypeException; use Utopia\Database\Helpers\ID; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; 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 d53bf44922..5a5e3f223b 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 @@ -269,7 +269,7 @@ class Create extends Action } if ($permission === Database::PERMISSION_UPDATE) { - $validDocument= $dbForProject->getAuthorization()->isValid(new Input($permission, $document->getUpdate())); + $validDocument = $dbForProject->getAuthorization()->isValid(new Input($permission, $document->getUpdate())); $valid = $validCollection || $validDocument; if ($documentSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); @@ -503,4 +503,4 @@ class Create extends Action $this->getResponseModel() ); } -} \ No newline at end of file +} 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 e213687b54..325072f97e 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 @@ -18,7 +18,6 @@ use Utopia\Database\Document; use Utopia\Database\Exception\Conflict as ConflictException; use Utopia\Database\Exception\Restricted as RestrictedException; use Utopia\Database\Helpers\ID; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; 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 43dee6083d..93f66ed989 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 @@ -15,7 +15,6 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; 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 a4ac205a2d..6c38a03ea2 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 @@ -18,7 +18,6 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Limit; use Utopia\Database\Validator\Query\Offset; 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 faf7b7db3b..a969585b6c 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 @@ -22,7 +22,6 @@ use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; 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 50e4e840fc..6cf2f646eb 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 @@ -23,7 +23,6 @@ use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; 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 26866ac33d..dbb30fcc1b 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 @@ -17,7 +17,6 @@ use Utopia\Database\Document; 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\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; 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 18509da214..9d4183d75f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php @@ -10,7 +10,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\UID; use Utopia\Swoole\Response as SwooleResponse; 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 c3e7e66b2e..7c0d61b588 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 @@ -16,7 +16,6 @@ use Utopia\Database\Document; use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Index as IndexValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; 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 dbe6e48dd3..cc6ed66466 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 @@ -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; 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 e703ad03b3..01b186b2c9 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 @@ -10,7 +10,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; 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 f8ee258698..7828b91221 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 @@ -15,7 +15,6 @@ use Utopia\Database\Document; 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\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; 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 f6046cc468..a7f24e7c2b 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 @@ -18,7 +18,6 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Limit; use Utopia\Database\Validator\Query\Offset; 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 42fdbfb7f1..116b8cdccf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Helpers\Permission; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; 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 3ec9dafe5c..9ade789cb9 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 @@ -14,7 +14,6 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\WhiteList; 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 59d0540224..43b4d59255 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -15,7 +15,6 @@ use Utopia\Database\Document; 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\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; 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 ebe06661f5..cd01a03ca4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php @@ -12,7 +12,6 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; -use Utopia\Database\Validator\Authorization; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Range; 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 66f86045fe..aa3926817e 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 @@ -165,7 +165,7 @@ class Create extends Action // For individual operations, enforce permissions unless using API key/admin if (!$isAPIKey && !$isPrivilegedUser) { $documentSecurity = $collection->getAttribute('documentSecurity', false); - + $collectionValid = $dbForProject->getAuthorization()->isValid( new input($permissionType, $collection->getPermissionsByType($permissionType)) ); 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 112892d39d..f75506e5cf 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php @@ -13,7 +13,6 @@ use Utopia\Config\Config; 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\Action; use Utopia\Swoole\Response as SwooleResponse; 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 4c0515c02b..5927f98a02 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php @@ -12,7 +12,6 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\WhiteList; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php index fbe53218d3..c9dffc82b8 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php @@ -13,7 +13,6 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php index e0f90e5f00..1f11976b8a 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php @@ -10,7 +10,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php index b4fe89e5ce..3cd07b6cea 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -15,7 +15,6 @@ use Utopia\Database\Document; 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\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php index 0f137a42c0..7ca0cb74c8 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php @@ -27,7 +27,6 @@ use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Roles; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php index 8462e649a2..5b87031fa0 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php @@ -13,7 +13,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\DateTime; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; 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 7d521caa9c..c1851e3eb3 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -13,7 +13,6 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php index cce896713c..fd19f89afb 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php @@ -22,7 +22,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\Roles; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php index c2ea423c31..501b6bb468 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php @@ -12,7 +12,6 @@ use Utopia\Config\Config; 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\Action; use Utopia\Platform\Scope\HTTP; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php index 877e014dfb..2b8308a75a 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php @@ -11,7 +11,6 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\WhiteList; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php index 4c1141e1a7..4aedbdabc5 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php @@ -15,7 +15,6 @@ use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php index bc85063a26..ecbdf3e13b 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\DateTime; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php index b571a63709..d83af69a0b 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php @@ -11,7 +11,6 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Exception\Duplicate as DuplicateException; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index 5f7e442bdd..9e3812bb1c 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/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; 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 721d55bdf1..4a3b7c804f 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php @@ -12,7 +12,6 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; 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 f7dc9a3c43..5888040476 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/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; 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 7abfb02689..d89014f7d8 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -12,7 +12,6 @@ use Appwrite\Utopia\Response; 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\Action; use Utopia\Platform\Scope\HTTP; diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php index 3864a6328f..ca1ef5d9f3 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php @@ -12,7 +12,6 @@ use Utopia\Config\Config; 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\Action; use Utopia\Platform\Scope\HTTP; diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php index eec1b321c6..f29ca2bec3 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php @@ -11,7 +11,6 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\WhiteList; 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 17984a1725..709a12a957 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 @@ -21,7 +21,7 @@ class Action extends UtopiaAction throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - if (!$dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead()))){ + if (!$dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead()))) { throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } 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 57bf7cf1a9..e0f51308d4 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 @@ -79,7 +79,7 @@ class Create extends Action $fileSecurity = $bucket->getAttribute('fileSecurity', false); $bucketPermission = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); - + if ($fileSecurity) { $filePermission = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_UPDATE, $file->getUpdate())); if (!$bucketPermission && !$filePermission) { diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index 721a1f4039..4bab864653 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -9,7 +9,6 @@ use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Exception; -use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Registry\Registry; use Utopia\Validator\Text; diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index f696dbd790..4e8a5beb76 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -9,7 +9,6 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Queue\Broker\Pool as BrokerPool; use Utopia\System\System; diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php index 102a25df62..345c855920 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; /** diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 8769e2f56b..ee0587fad4 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -24,7 +24,6 @@ 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; diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index 75f0744098..a3820f4f1f 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -239,5 +239,5 @@ class Request extends UtopiaRequest public function setAuthorization(Authorization $authorization): void { $this->authorization = $authorization; - } + } } diff --git a/src/Appwrite/Utopia/Request/Filters/V20.php b/src/Appwrite/Utopia/Request/Filters/V20.php index 8f500c9380..0bc1ed4f1f 100644 --- a/src/Appwrite/Utopia/Request/Filters/V20.php +++ b/src/Appwrite/Utopia/Request/Filters/V20.php @@ -8,7 +8,6 @@ use Utopia\Database\Database; use Utopia\Database\Exception\NotFound; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; class V20 extends Filter { diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 099bf7fd44..83ab451c74 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -983,5 +983,5 @@ class Response extends SwooleResponse 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 26e11ff0b9..60c4421853 100644 --- a/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php @@ -17,15 +17,15 @@ class DatabasesPermissionsGuestTest extends Scope use SideClient; use DatabasesPermissionsScope; -private $authorization; + private $authorization; -public function getAuthorization(): Authorization -{ - if (isset($this->authorization)) { - return $this->authorization; + public function getAuthorization(): Authorization + { + if (isset($this->authorization)) { + return $this->authorization; + } + return new Authorization(); } - return new Authorization(); -} public function createCollection(): array { From 25403ea35eff5e48f731c38a3e9344e71b5419c8 Mon Sep 17 00:00:00 2001 From: shimon Date: Wed, 22 Oct 2025 16:43:49 +0300 Subject: [PATCH 03/77] composer.lock --- composer.lock | 99 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 73 insertions(+), 26 deletions(-) diff --git a/composer.lock b/composer.lock index 68c88b9c73..4a212ef6f7 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": "f27ea68014d28d445baa355466cdb7a9", + "content-hash": "a2f032a3d278c7f493ea4d87d6908258", "packages": [ { "name": "adhocore/jwt", @@ -3999,21 +3999,22 @@ }, { "name": "utopia-php/domains", - "version": "0.8.4", + "version": "0.9.1", "source": { "type": "git", "url": "https://github.com/utopia-php/domains.git", - "reference": "316a76b0fcbc7f82e40be466c22c19acb243ee22" + "reference": "99b4ec95d5d6b7a5c990a66c56412212d9af37e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/domains/zipball/316a76b0fcbc7f82e40be466c22c19acb243ee22", - "reference": "316a76b0fcbc7f82e40be466c22c19acb243ee22", + "url": "https://api.github.com/repos/utopia-php/domains/zipball/99b4ec95d5d6b7a5c990a66c56412212d9af37e7", + "reference": "99b4ec95d5d6b7a5c990a66c56412212d9af37e7", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/framework": "0.33.*" + "utopia-php/cache": "0.13.*", + "utopia-php/validators": "0.0.*" }, "require-dev": { "laravel/pint": "1.2.*", @@ -4054,9 +4055,9 @@ ], "support": { "issues": "https://github.com/utopia-php/domains/issues", - "source": "https://github.com/utopia-php/domains/tree/0.8.4" + "source": "https://github.com/utopia-php/domains/tree/0.9.1" }, - "time": "2025-10-17T11:31:56+00:00" + "time": "2025-10-21T14:52:27+00:00" }, { "name": "utopia-php/dsn", @@ -4394,16 +4395,16 @@ }, { "name": "utopia-php/migration", - "version": "1.3.1", + "version": "1.3.2", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "b6985b235ab64f07a6b88569e20cf9b2df7d838c" + "reference": "f5c1d2cae764290766a4c2d1546c1d51de95b67f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/b6985b235ab64f07a6b88569e20cf9b2df7d838c", - "reference": "b6985b235ab64f07a6b88569e20cf9b2df7d838c", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/f5c1d2cae764290766a4c2d1546c1d51de95b67f", + "reference": "f5c1d2cae764290766a4c2d1546c1d51de95b67f", "shasum": "" }, "require": { @@ -4443,9 +4444,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/1.3.1" + "source": "https://github.com/utopia-php/migration/tree/1.3.2" }, - "time": "2025-10-21T08:13:54+00:00" + "time": "2025-10-22T12:30:47+00:00" }, { "name": "utopia-php/mongo", @@ -5046,6 +5047,52 @@ }, "time": "2025-03-17T11:57:52+00:00" }, + { + "name": "utopia-php/validators", + "version": "0.0.2", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/validators.git", + "reference": "894210695c5d35fa248fb65f7fe7237b6ff4fb0b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/validators/zipball/894210695c5d35fa248fb65f7fe7237b6ff4fb0b", + "reference": "894210695c5d35fa248fb65f7fe7237b6ff4fb0b", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-xdebug": "*", + "laravel/pint": "^1.2", + "phpstan/phpstan": "1.*", + "phpunit/phpunit": "^9.5.25" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A lightweight collection of reusable validators for Utopia projects", + "keywords": [ + "php", + "utopia", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/utopia-php/validators/issues", + "source": "https://github.com/utopia-php/validators/tree/0.0.2" + }, + "time": "2025-10-20T21:52:28+00:00" + }, { "name": "utopia-php/vcs", "version": "0.11.0", @@ -5271,16 +5318,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.4.5", + "version": "1.4.7", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "0c4f514bf861f42555dae781f394fefeb27ff521" + "reference": "a61c8be551e10f4970bf46f75a54e4b0385c550d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/0c4f514bf861f42555dae781f394fefeb27ff521", - "reference": "0c4f514bf861f42555dae781f394fefeb27ff521", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/a61c8be551e10f4970bf46f75a54e4b0385c550d", + "reference": "a61c8be551e10f4970bf46f75a54e4b0385c550d", "shasum": "" }, "require": { @@ -5316,9 +5363,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/1.4.5" + "source": "https://github.com/appwrite/sdk-generator/tree/1.4.7" }, - "time": "2025-10-21T04:59:59+00:00" + "time": "2025-10-22T06:03:44+00:00" }, { "name": "doctrine/annotations", @@ -5795,16 +5842,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.6.1", + "version": "v5.6.2", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2" + "reference": "3a454ca033b9e06b63282ce19562e892747449bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", - "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3a454ca033b9e06b63282ce19562e892747449bb", + "reference": "3a454ca033b9e06b63282ce19562e892747449bb", "shasum": "" }, "require": { @@ -5847,9 +5894,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.2" }, - "time": "2025-08-13T20:13:15+00:00" + "time": "2025-10-21T19:32:17+00:00" }, { "name": "phar-io/manifest", From 6ed2000478300582f5c79b317e666005e059c1a0 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 27 Oct 2025 12:09:23 +0200 Subject: [PATCH 04/77] Update composer.lock and refactor authorization handling in CLI and worker modules. Adjust Docker configuration to include database source path. Modify error handling in general controller and enhance permission setting in document creation. Fix privileged user role retrieval in function execution. Ensure consistent authorization usage across various resources. --- app/cli.php | 10 +++--- app/controllers/general.php | 2 +- app/init/resources.php | 4 ++- app/worker.php | 16 ++++----- composer.lock | 34 +++++++++---------- docker-compose.yml | 1 + .../Collections/Documents/Create.php | 2 +- .../Functions/Http/Executions/Create.php | 2 +- 8 files changed, 35 insertions(+), 36 deletions(-) diff --git a/app/cli.php b/app/cli.php index 08726c2d4d..d30e870c30 100644 --- a/app/cli.php +++ b/app/cli.php @@ -59,6 +59,7 @@ CLI::setResource('pools', function (Registry $register) { CLI::setResource('authorization', function () { $authorization = new Authorization(); + $authorization->disable(); return $authorization; }, []); @@ -133,13 +134,11 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform if (\in_array($dsn->getHost(), $sharedTables)) { $database - ->setAuthorization($authorization) ->setSharedTables(true) ->setTenant((int)$project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database - ->setAuthorization($authorization) ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getSequence()); @@ -150,18 +149,17 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform $adapter = new DatabasePool($pools->get($dsn->getHost())); $database = new Database($adapter, $cache); + $database->setAuthorization($authorization); $databases[$dsn->getHost()] = $database; $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); if (\in_array($dsn->getHost(), $sharedTables)) { $database - ->setAuthorization($authorization) ->setSharedTables(true) ->setTenant((int)$project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database - ->setAuthorization($authorization) ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getSequence()); @@ -186,9 +184,9 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorizatio $adapter = new DatabasePool($pools->get('logs')); $database = new Database($adapter, $cache); - + $database->setAuthorization($authorization); + $database - ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_TASK) diff --git a/app/controllers/general.php b/app/controllers/general.php index b6452abd7f..332f0c1d15 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1175,7 +1175,7 @@ App::error() ->inject('queueForStatsUsage') ->inject('devKey') ->inject('authorization') - ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage, Authorization $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); diff --git a/app/init/resources.php b/app/init/resources.php index 2d5d8059a6..e85b18d80a 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -424,9 +424,10 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform }, ['pools', 'dbForPlatform', 'cache', 'project', 'authorization']); App::setResource('dbForPlatform', function (Group $pools, Cache $cache, Authorization $authorization) { + $adapter = new DatabasePool($pools->get('console')); $database = new Database($adapter, $cache); - + $database ->setAuthorization($authorization) ->setNamespace('_console') @@ -484,6 +485,7 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform $adapter = new DatabasePool($pools->get($dsn->getHost())); $database = new Database($adapter, $cache); + $database->setAuthorization($authorization); $databases[$dsn->getHost()] = $database; $configure($database); diff --git a/app/worker.php b/app/worker.php index c5dcb14a1e..211b4ebfa6 100644 --- a/app/worker.php +++ b/app/worker.php @@ -51,6 +51,7 @@ Server::setResource('register', fn () => $register); Server::setResource('authorization', function () { $authorization = new Authorization(); + $authorization->disable(); return $authorization; }, []); @@ -58,8 +59,9 @@ Server::setResource('dbForPlatform', function (Cache $cache, Registry $register, $pools = $register->get('pools'); $adapter = new DatabasePool($pools->get('console')); $dbForPlatform = new Database($adapter, $cache); - $dbForPlatform->setNamespace('_console'); $dbForPlatform->setAuthorization($authorization); + $dbForPlatform->setNamespace('_console'); + return $dbForPlatform; }, ['cache', 'register', 'authorization']); @@ -91,18 +93,16 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, $adapter = new DatabasePool($pools->get($dsn->getHost())); $database = new Database($adapter, $cache); - + $database->setAuthorization($authorization); $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); if (\in_array($dsn->getHost(), $sharedTables)) { $database - ->setAuthorization($authorization) ->setSharedTables(true) ->setTenant((int)$project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database - ->setAuthorization($authorization) ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getSequence()); @@ -130,18 +130,16 @@ 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)) { $database - ->setAuthorization($authorization) ->setSharedTables(true) ->setTenant((int)$project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database - ->setAuthorization($authorization) ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getSequence()); @@ -151,7 +149,9 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf } $adapter = new DatabasePool($pools->get($dsn->getHost())); + $adapter->setAuthorization($authorization); $database = new Database($adapter, $cache); + $database->setAuthorization($authorization); $databases[$dsn->getHost()] = $database; @@ -159,13 +159,11 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf if (\in_array($dsn->getHost(), $sharedTables)) { $database - ->setAuthorization($authorization) ->setSharedTables(true) ->setTenant((int)$project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database - ->setAuthorization($authorization) ->setSharedTables(false) ->setTenant(null) ->setNamespace('_' . $project->getSequence()); diff --git a/composer.lock b/composer.lock index 4a212ef6f7..1b06775fe8 100644 --- a/composer.lock +++ b/composer.lock @@ -3844,12 +3844,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "4088c1002bbc837fd9299987cce5d460ded210d1" + "reference": "22123ad30782be131ecad4e9298b843d8daf387b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/4088c1002bbc837fd9299987cce5d460ded210d1", - "reference": "4088c1002bbc837fd9299987cce5d460ded210d1", + "url": "https://api.github.com/repos/utopia-php/database/zipball/22123ad30782be131ecad4e9298b843d8daf387b", + "reference": "22123ad30782be131ecad4e9298b843d8daf387b", "shasum": "" }, "require": { @@ -3894,7 +3894,7 @@ "issues": "https://github.com/utopia-php/database/issues", "source": "https://github.com/utopia-php/database/tree/feat-authorization-instance" }, - "time": "2025-10-20T13:53:53+00:00" + "time": "2025-10-27T08:34:29+00:00" }, { "name": "utopia-php/detector", @@ -5318,16 +5318,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.4.7", + "version": "1.4.12", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "a61c8be551e10f4970bf46f75a54e4b0385c550d" + "reference": "efda55836d19b8d5f36ac0df33c83b48af0aa8fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/a61c8be551e10f4970bf46f75a54e4b0385c550d", - "reference": "a61c8be551e10f4970bf46f75a54e4b0385c550d", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/efda55836d19b8d5f36ac0df33c83b48af0aa8fd", + "reference": "efda55836d19b8d5f36ac0df33c83b48af0aa8fd", "shasum": "" }, "require": { @@ -5363,9 +5363,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/1.4.7" + "source": "https://github.com/appwrite/sdk-generator/tree/1.4.12" }, - "time": "2025-10-22T06:03:44+00:00" + "time": "2025-10-25T05:39:48+00:00" }, { "name": "doctrine/annotations", @@ -6069,16 +6069,16 @@ }, { "name": "phpbench/phpbench", - "version": "1.4.1", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/phpbench/phpbench.git", - "reference": "78cd98a9aa34e0f8f80ca01972a8b88d2c30194b" + "reference": "bb61ae6c54b3d58642be154eb09f4e73c3511018" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpbench/phpbench/zipball/78cd98a9aa34e0f8f80ca01972a8b88d2c30194b", - "reference": "78cd98a9aa34e0f8f80ca01972a8b88d2c30194b", + "url": "https://api.github.com/repos/phpbench/phpbench/zipball/bb61ae6c54b3d58642be154eb09f4e73c3511018", + "reference": "bb61ae6c54b3d58642be154eb09f4e73c3511018", "shasum": "" }, "require": { @@ -6105,7 +6105,7 @@ "ergebnis/composer-normalize": "^2.39", "friendsofphp/php-cs-fixer": "^3.0", "jangregor/phpstan-prophecy": "^1.0", - "phpspec/prophecy": "dev-master", + "phpspec/prophecy": "^1.22", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.0", "phpstan/phpstan-phpunit": "^1.0", @@ -6155,7 +6155,7 @@ ], "support": { "issues": "https://github.com/phpbench/phpbench/issues", - "source": "https://github.com/phpbench/phpbench/tree/1.4.1" + "source": "https://github.com/phpbench/phpbench/tree/1.4.2" }, "funding": [ { @@ -6163,7 +6163,7 @@ "type": "github" } ], - "time": "2025-03-12T08:01:40+00:00" + "time": "2025-10-26T14:21:59+00:00" }, { "name": "phpstan/phpstan", diff --git a/docker-compose.yml b/docker-compose.yml index b72f12a116..38685354c1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -89,6 +89,7 @@ services: - ./public:/usr/src/code/public - ./src:/usr/src/code/src - ./dev:/usr/src/code/dev + - ./vendor/utopia-php/database/src:/usr/src/code/vendor/utopia-php/database/src depends_on: - mariadb - redis 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 5a5e3f223b..bc23a0e130 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 @@ -203,7 +203,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) { $allowedPermissions = [ Database::PERMISSION_READ, Database::PERMISSION_UPDATE, diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index a05dfbd2a4..572736f975 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -155,7 +155,7 @@ class Create extends Base $function = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('functions', $functionId)); $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRole); + $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); From 30d58e6371dbf23a29d7a7cd62b739ab4cd4b72f Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 27 Oct 2025 16:14:04 +0200 Subject: [PATCH 05/77] Update composer dependencies for utopia-php/audit and utopia-php/database, reflecting new versioning and aliases. Refactor document validation in Create operation to utilize the new authorization method for better security handling. --- composer.json | 2 +- composer.lock | 35 +++++++++++-------- .../Transactions/Operations/Create.php | 7 ++-- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/composer.json b/composer.json index f030d0aabf..5225e67d52 100644 --- a/composer.json +++ b/composer.json @@ -48,7 +48,7 @@ "appwrite/php-clamav": "2.0.*", "utopia-php/abuse": "1.*", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "1.*", + "utopia-php/audit": "dev-feat-auth-single-instance as 1.1.0", "utopia-php/cache": "0.13.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", diff --git a/composer.lock b/composer.lock index 1b06775fe8..5785529265 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": "a2f032a3d278c7f493ea4d87d6908258", + "content-hash": "d7f36b787ff2fe013d9b866c3823f6d4", "packages": [ { "name": "adhocore/jwt", @@ -3547,21 +3547,21 @@ }, { "name": "utopia-php/audit", - "version": "1.0.2", + "version": "dev-feat-auth-single-instance", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "8c17065c2473d4ca799f65585ca74eb53e1be211" + "reference": "b74a6f8213b444e0af6ce0714ec85ea2859b3508" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/8c17065c2473d4ca799f65585ca74eb53e1be211", - "reference": "8c17065c2473d4ca799f65585ca74eb53e1be211", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/b74a6f8213b444e0af6ce0714ec85ea2859b3508", + "reference": "b74a6f8213b444e0af6ce0714ec85ea2859b3508", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "*" + "utopia-php/database": "dev-feat-authorization-instance as 3.0.2" }, "require-dev": { "laravel/pint": "1.*", @@ -3588,9 +3588,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/1.0.2" + "source": "https://github.com/utopia-php/audit/tree/feat-auth-single-instance" }, - "time": "2025-10-20T07:14:26+00:00" + "time": "2025-10-27T13:39:14+00:00" }, { "name": "utopia-php/cache", @@ -5318,16 +5318,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.4.12", + "version": "1.4.14", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "efda55836d19b8d5f36ac0df33c83b48af0aa8fd" + "reference": "b9405ccaeac5619c76558a82b7bfeb440b665b9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/efda55836d19b8d5f36ac0df33c83b48af0aa8fd", - "reference": "efda55836d19b8d5f36ac0df33c83b48af0aa8fd", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/b9405ccaeac5619c76558a82b7bfeb440b665b9f", + "reference": "b9405ccaeac5619c76558a82b7bfeb440b665b9f", "shasum": "" }, "require": { @@ -5363,9 +5363,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/1.4.12" + "source": "https://github.com/appwrite/sdk-generator/tree/1.4.14" }, - "time": "2025-10-25T05:39:48+00:00" + "time": "2025-10-27T11:17:01+00:00" }, { "name": "doctrine/annotations", @@ -8831,6 +8831,12 @@ } ], "aliases": [ + { + "package": "utopia-php/audit", + "version": "dev-feat-auth-single-instance", + "alias": "1.1.0", + "alias_normalized": "1.1.0.0" + }, { "package": "utopia-php/database", "version": "dev-feat-authorization-instance", @@ -8840,6 +8846,7 @@ ], "minimum-stability": "stable", "stability-flags": { + "utopia-php/audit": 20, "utopia-php/database": 20 }, "prefer-stable": false, 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 aa3926817e..bea26a2983 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 @@ -172,9 +172,12 @@ class Create extends Action $documentValid = false; if ($document !== null && !$document->isEmpty() && $documentSecurity) { if ($permissionType === Database::PERMISSION_UPDATE) { - $documentValid = $validator->isValid($document->getUpdate()); + $documentValid = $dbForProject->getAuthorization()->isValid( + new input(Database::PERMISSION_UPDATE, $document->getUpdate())); } elseif ($permissionType === Database::PERMISSION_DELETE) { - $documentValid = $validator->isValid($document->getDelete()); + $documentValid = $dbForProject->getAuthorization()->isValid( + new input(Database::PERMISSION_DELETE, $document->getDelete()) + ); } } From ecd6880fe0bb7285db7992ec8fe49d5c0f61b3b1 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 27 Oct 2025 16:20:07 +0200 Subject: [PATCH 06/77] composer.lock --- composer.lock | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/composer.lock b/composer.lock index 4a212ef6f7..ced7e9d96c 100644 --- a/composer.lock +++ b/composer.lock @@ -3844,12 +3844,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "4088c1002bbc837fd9299987cce5d460ded210d1" + "reference": "22123ad30782be131ecad4e9298b843d8daf387b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/4088c1002bbc837fd9299987cce5d460ded210d1", - "reference": "4088c1002bbc837fd9299987cce5d460ded210d1", + "url": "https://api.github.com/repos/utopia-php/database/zipball/22123ad30782be131ecad4e9298b843d8daf387b", + "reference": "22123ad30782be131ecad4e9298b843d8daf387b", "shasum": "" }, "require": { @@ -3894,7 +3894,7 @@ "issues": "https://github.com/utopia-php/database/issues", "source": "https://github.com/utopia-php/database/tree/feat-authorization-instance" }, - "time": "2025-10-20T13:53:53+00:00" + "time": "2025-10-27T08:34:29+00:00" }, { "name": "utopia-php/detector", @@ -5318,16 +5318,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.4.7", + "version": "1.4.14", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "a61c8be551e10f4970bf46f75a54e4b0385c550d" + "reference": "b9405ccaeac5619c76558a82b7bfeb440b665b9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/a61c8be551e10f4970bf46f75a54e4b0385c550d", - "reference": "a61c8be551e10f4970bf46f75a54e4b0385c550d", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/b9405ccaeac5619c76558a82b7bfeb440b665b9f", + "reference": "b9405ccaeac5619c76558a82b7bfeb440b665b9f", "shasum": "" }, "require": { @@ -5363,9 +5363,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/1.4.7" + "source": "https://github.com/appwrite/sdk-generator/tree/1.4.14" }, - "time": "2025-10-22T06:03:44+00:00" + "time": "2025-10-27T11:17:01+00:00" }, { "name": "doctrine/annotations", @@ -6069,16 +6069,16 @@ }, { "name": "phpbench/phpbench", - "version": "1.4.1", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/phpbench/phpbench.git", - "reference": "78cd98a9aa34e0f8f80ca01972a8b88d2c30194b" + "reference": "bb61ae6c54b3d58642be154eb09f4e73c3511018" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpbench/phpbench/zipball/78cd98a9aa34e0f8f80ca01972a8b88d2c30194b", - "reference": "78cd98a9aa34e0f8f80ca01972a8b88d2c30194b", + "url": "https://api.github.com/repos/phpbench/phpbench/zipball/bb61ae6c54b3d58642be154eb09f4e73c3511018", + "reference": "bb61ae6c54b3d58642be154eb09f4e73c3511018", "shasum": "" }, "require": { @@ -6105,7 +6105,7 @@ "ergebnis/composer-normalize": "^2.39", "friendsofphp/php-cs-fixer": "^3.0", "jangregor/phpstan-prophecy": "^1.0", - "phpspec/prophecy": "dev-master", + "phpspec/prophecy": "^1.22", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.0", "phpstan/phpstan-phpunit": "^1.0", @@ -6155,7 +6155,7 @@ ], "support": { "issues": "https://github.com/phpbench/phpbench/issues", - "source": "https://github.com/phpbench/phpbench/tree/1.4.1" + "source": "https://github.com/phpbench/phpbench/tree/1.4.2" }, "funding": [ { @@ -6163,7 +6163,7 @@ "type": "github" } ], - "time": "2025-03-12T08:01:40+00:00" + "time": "2025-10-26T14:21:59+00:00" }, { "name": "phpstan/phpstan", From d7cc3895cba6620c8bf98ca8627a7fb4768ac9e2 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 27 Oct 2025 19:23:55 +0200 Subject: [PATCH 07/77] Update composer.lock to reflect version changes for utopia-php/detector, remove unused registers.php file, and clean up whitespace in cli.php and worker.php. Refactor database resource initialization in resources.php for consistency. --- app/cli.php | 2 +- app/init/registers.php | 342 ------------------ app/init/resources.php | 4 +- app/worker.php | 2 +- composer.lock | 14 +- .../Transactions/Operations/Create.php | 3 +- 6 files changed, 13 insertions(+), 354 deletions(-) delete mode 100644 app/init/registers.php diff --git a/app/cli.php b/app/cli.php index d30e870c30..a70a718948 100644 --- a/app/cli.php +++ b/app/cli.php @@ -185,7 +185,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorizatio $adapter = new DatabasePool($pools->get('logs')); $database = new Database($adapter, $cache); $database->setAuthorization($authorization); - + $database ->setSharedTables(true) ->setNamespace('logsV1') diff --git a/app/init/registers.php b/app/init/registers.php deleted file mode 100644 index 3dc0e22dba..0000000000 --- a/app/init/registers.php +++ /dev/null @@ -1,342 +0,0 @@ -set('logger', function () { - // Register error logger - $providerName = System::getEnv('_APP_LOGGING_PROVIDER', ''); - $providerConfig = System::getEnv('_APP_LOGGING_CONFIG', ''); - - if (empty($providerConfig)) { - return; - } - - try { - $loggingProvider = new DSN($providerConfig ?? ''); - - $providerName = $loggingProvider->getScheme(); - $providerConfig = match ($providerName) { - 'sentry' => ['key' => $loggingProvider->getPassword(), 'projectId' => $loggingProvider->getUser() ?? '', 'host' => 'https://' . $loggingProvider->getHost()], - 'logowl' => ['ticket' => $loggingProvider->getUser() ?? '', 'host' => $loggingProvider->getHost()], - default => ['key' => $loggingProvider->getHost()], - }; - } catch (Throwable $th) { - // Fallback for older Appwrite versions up to 1.5.x that use _APP_LOGGING_PROVIDER and _APP_LOGGING_CONFIG environment variables - Console::warning('Using deprecated logging configuration. Please update your configuration to use DSN format.' . $th->getMessage()); - $configChunks = \explode(";", $providerConfig); - - $providerConfig = match ($providerName) { - 'sentry' => [ 'key' => $configChunks[0], 'projectId' => $configChunks[1] ?? '', 'host' => '',], - 'logowl' => ['ticket' => $configChunks[0] ?? '', 'host' => ''], - default => ['key' => $providerConfig], - }; - } - - if (empty($providerName) || empty($providerConfig)) { - return; - } - - if (!Logger::hasProvider($providerName)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, "Logging provider not supported. Logging is disabled"); - } - - try { - $adapter = match ($providerName) { - 'sentry' => new Sentry($providerConfig['projectId'], $providerConfig['key'], $providerConfig['host']), - 'logowl' => new LogOwl($providerConfig['ticket'], $providerConfig['host']), - 'raygun' => new Raygun($providerConfig['key']), - 'appsignal' => new AppSignal($providerConfig['key']), - default => null - }; - } catch (Throwable $th) { - $adapter = null; - } - - if ($adapter === null) { - Console::error("Logging provider not supported. Logging is disabled"); - return; - } - - return new Logger($adapter); -}); - -$register->set('pools', function () { - $group = new Group(); - - $fallbackForDB = 'db_main=' . AppwriteURL::unparse([ - 'scheme' => 'mariadb', - 'host' => System::getEnv('_APP_DB_HOST', 'mariadb'), - 'port' => System::getEnv('_APP_DB_PORT', '3306'), - 'user' => System::getEnv('_APP_DB_USER', ''), - 'pass' => System::getEnv('_APP_DB_PASS', ''), - 'path' => System::getEnv('_APP_DB_SCHEMA', ''), - ]); - $fallbackForRedis = 'redis_main=' . AppwriteURL::unparse([ - 'scheme' => 'redis', - 'host' => System::getEnv('_APP_REDIS_HOST', 'redis'), - 'port' => System::getEnv('_APP_REDIS_PORT', '6379'), - 'user' => System::getEnv('_APP_REDIS_USER', ''), - 'pass' => System::getEnv('_APP_REDIS_PASS', ''), - ]); - - $connections = [ - 'console' => [ - 'type' => 'database', - 'dsns' => $fallbackForDB, - 'multiple' => false, - 'schemes' => ['mariadb', 'mysql'], - ], - 'database' => [ - 'type' => 'database', - 'dsns' => $fallbackForDB, - 'multiple' => true, - 'schemes' => ['mariadb', 'mysql'], - ], - 'logs' => [ - 'type' => 'database', - 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_LOGS', $fallbackForDB), - 'multiple' => false, - 'schemes' => ['mariadb', 'mysql'], - ], - 'publisher' => [ - 'type' => 'publisher', - 'dsns' => $fallbackForRedis, - 'multiple' => false, - 'schemes' => ['redis'], - ], - 'consumer' => [ - 'type' => 'consumer', - 'dsns' => $fallbackForRedis, - 'multiple' => false, - 'schemes' => ['redis'], - ], - 'pubsub' => [ - 'type' => 'pubsub', - 'dsns' => $fallbackForRedis, - 'multiple' => false, - 'schemes' => ['redis'], - ], - 'cache' => [ - 'type' => 'cache', - 'dsns' => $fallbackForRedis, - 'multiple' => true, - 'schemes' => ['redis'], - ], - ]; - - $maxConnections = System::getEnv('_APP_CONNECTIONS_MAX', 151); - $instanceConnections = $maxConnections / System::getEnv('_APP_POOL_CLIENTS', 14); - - $multiprocessing = System::getEnv('_APP_SERVER_MULTIPROCESS', 'disabled') === 'enabled'; - - if ($multiprocessing) { - $workerCount = intval(System::getEnv('_APP_CPU_NUM', swoole_cpu_num())) * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); - } else { - $workerCount = 1; - } - - if ($workerCount > $instanceConnections) { - throw new \Exception('Pool size is too small. Increase the number of allowed database connections or decrease the number of workers.', 500); - } - - $poolSize = (int)($instanceConnections / $workerCount); - - foreach ($connections as $key => $connection) { - $type = $connection['type'] ?? ''; - $multiple = $connection['multiple'] ?? false; - $schemes = $connection['schemes'] ?? []; - $config = []; - $dsns = explode(',', $connection['dsns'] ?? ''); - foreach ($dsns as &$dsn) { - $dsn = explode('=', $dsn); - $name = ($multiple) ? $key . '_' . $dsn[0] : $key; - $dsn = $dsn[1] ?? ''; - $config[] = $name; - if (empty($dsn)) { - //throw new Exception(Exception::GENERAL_SERVER_ERROR, "Missing value for DSN connection in {$key}"); - continue; - } - - $dsn = new DSN($dsn); - $dsnHost = $dsn->getHost(); - $dsnPort = $dsn->getPort(); - $dsnUser = $dsn->getUser(); - $dsnPass = $dsn->getPassword(); - $dsnScheme = $dsn->getScheme(); - $dsnDatabase = $dsn->getPath(); - - if (!in_array($dsnScheme, $schemes)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid console database scheme"); - } - - /** - * Get Resource - * - * Creation could be reused across connection types like database, cache, queue, etc. - * - * Resource assignment to an adapter will happen below. - */ - $resource = match ($dsnScheme) { - 'mysql', - 'mariadb' => function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) { - return new PDOProxy(function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) { - return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, [ - \PDO::ATTR_TIMEOUT => 3, // Seconds - \PDO::ATTR_PERSISTENT => false, - \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC, - \PDO::ATTR_EMULATE_PREPARES => true, - \PDO::ATTR_STRINGIFY_FETCHES => true - ]); - }); - }, - 'redis' => function () use ($dsnHost, $dsnPort, $dsnPass) { - $redis = new \Redis(); - @$redis->pconnect($dsnHost, (int)$dsnPort); - if ($dsnPass) { - $redis->auth($dsnPass); - } - $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); - - return $redis; - }, - default => throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Invalid scheme'), - }; - - $pool = new Pool($name, $poolSize, function () use ($type, $resource, $dsn) { - // Get Adapter - switch ($type) { - case 'database': - $adapter = match ($dsn->getScheme()) { - 'mariadb' => new MariaDB($resource()), - 'mysql' => new MySQL($resource()), - default => null - }; - - $adapter->setDatabase($dsn->getPath()); - return $adapter; - case 'pubsub': - return match ($dsn->getScheme()) { - 'redis' => new PubSub($resource()), - default => null - }; - case 'publisher': - case 'consumer': - return match ($dsn->getScheme()) { - 'redis' => new Queue\Broker\Redis(new Queue\Connection\Redis($dsn->getHost(), $dsn->getPort())), - default => null - }; - case 'cache': - return match ($dsn->getScheme()) { - 'redis' => new RedisCache($resource()), - default => null - }; - default: - throw new Exception(Exception::GENERAL_SERVER_ERROR, "Server error: Missing adapter implementation."); - } - }); - - $group->add($pool); - } - - Config::setParam('pools-' . $key, $config); - } - - return $group; -}); - -$register->set('db', function () { - // This is usually for our workers or CLI commands scope - $dbHost = System::getEnv('_APP_DB_HOST', ''); - $dbPort = System::getEnv('_APP_DB_PORT', ''); - $dbUser = System::getEnv('_APP_DB_USER', ''); - $dbPass = System::getEnv('_APP_DB_PASS', ''); - $dbScheme = System::getEnv('_APP_DB_SCHEMA', ''); - - return new PDO( - "mysql:host={$dbHost};port={$dbPort};dbname={$dbScheme};charset=utf8mb4", - $dbUser, - $dbPass, - SQL::getPDOAttributes() - ); -}); - -$register->set('smtp', function () { - $mail = new PHPMailer(true); - - $mail->isSMTP(); - - $username = System::getEnv('_APP_SMTP_USERNAME'); - $password = System::getEnv('_APP_SMTP_PASSWORD'); - - $mail->XMailer = 'Appwrite Mailer'; - $mail->Host = System::getEnv('_APP_SMTP_HOST', 'smtp'); - $mail->Port = System::getEnv('_APP_SMTP_PORT', 25); - $mail->SMTPAuth = !empty($username) && !empty($password); - $mail->Username = $username; - $mail->Password = $password; - $mail->SMTPSecure = System::getEnv('_APP_SMTP_SECURE', ''); - $mail->SMTPAutoTLS = false; - $mail->CharSet = 'UTF-8'; - - $from = \urldecode(System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server')); - $email = System::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM); - - $mail->setFrom($email, $from); - $mail->addReplyTo($email, $from); - - $mail->isHTML(true); - - return $mail; -}); -$register->set('geodb', function () { - return new Reader(__DIR__ . '/../assets/dbip/dbip-country-lite-2024-09.mmdb'); -}); -$register->set('passwordsDictionary', function () { - $content = \file_get_contents(__DIR__ . '/../assets/security/10k-common-passwords'); - $content = explode("\n", $content); - $content = array_flip($content); - return $content; -}); -$register->set('promiseAdapter', function () { - return new Swoole(); -}); -$register->set('hooks', function () { - return new Hooks(); -}); diff --git a/app/init/resources.php b/app/init/resources.php index e85b18d80a..183c83adf4 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -424,10 +424,10 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform }, ['pools', 'dbForPlatform', 'cache', 'project', 'authorization']); App::setResource('dbForPlatform', function (Group $pools, Cache $cache, Authorization $authorization) { - + $adapter = new DatabasePool($pools->get('console')); $database = new Database($adapter, $cache); - + $database ->setAuthorization($authorization) ->setNamespace('_console') diff --git a/app/worker.php b/app/worker.php index 211b4ebfa6..b88d96e3c2 100644 --- a/app/worker.php +++ b/app/worker.php @@ -61,7 +61,7 @@ Server::setResource('dbForPlatform', function (Cache $cache, Registry $register, $dbForPlatform = new Database($adapter, $cache); $dbForPlatform->setAuthorization($authorization); $dbForPlatform->setNamespace('_console'); - + return $dbForPlatform; }, ['cache', 'register', 'authorization']); diff --git a/composer.lock b/composer.lock index 3884b242f1..edb7cb5bf6 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": "d7f36b787ff2fe013d9b866c3823f6d4", + "content-hash": "48764fa55a13051632675cd4a0f7a6fc", "packages": [ { "name": "adhocore/jwt", @@ -3898,16 +3898,16 @@ }, { "name": "utopia-php/detector", - "version": "0.2.0", + "version": "0.1.5", "source": { "type": "git", "url": "https://github.com/utopia-php/detector.git", - "reference": "795ed56169af833fd6a4ea58a6c747e05ccc7ba6" + "reference": "b5d6ba51352485b524589bc0ee8d07a9efafe718" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/detector/zipball/795ed56169af833fd6a4ea58a6c747e05ccc7ba6", - "reference": "795ed56169af833fd6a4ea58a6c747e05ccc7ba6", + "url": "https://api.github.com/repos/utopia-php/detector/zipball/b5d6ba51352485b524589bc0ee8d07a9efafe718", + "reference": "b5d6ba51352485b524589bc0ee8d07a9efafe718", "shasum": "" }, "require": { @@ -3937,9 +3937,9 @@ ], "support": { "issues": "https://github.com/utopia-php/detector/issues", - "source": "https://github.com/utopia-php/detector/tree/0.2.0" + "source": "https://github.com/utopia-php/detector/tree/0.1.5" }, - "time": "2025-10-21T13:57:30+00:00" + "time": "2025-05-19T11:01:28+00:00" }, { "name": "utopia-php/dns", 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 bea26a2983..389cf19c4a 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 @@ -173,7 +173,8 @@ class Create extends Action if ($document !== null && !$document->isEmpty() && $documentSecurity) { if ($permissionType === Database::PERMISSION_UPDATE) { $documentValid = $dbForProject->getAuthorization()->isValid( - new input(Database::PERMISSION_UPDATE, $document->getUpdate())); + new input(Database::PERMISSION_UPDATE, $document->getUpdate()) + ); } elseif ($permissionType === Database::PERMISSION_DELETE) { $documentValid = $dbForProject->getAuthorization()->isValid( new input(Database::PERMISSION_DELETE, $document->getDelete()) From 681fa198c9bf2a3dffb48f3dcf2f34074c4b5164 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 27 Oct 2025 19:27:16 +0200 Subject: [PATCH 08/77] composer.lock --- composer.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/composer.lock b/composer.lock index 5785529265..edb7cb5bf6 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": "d7f36b787ff2fe013d9b866c3823f6d4", + "content-hash": "48764fa55a13051632675cd4a0f7a6fc", "packages": [ { "name": "adhocore/jwt", @@ -4344,16 +4344,16 @@ }, { "name": "utopia-php/messaging", - "version": "0.19.0", + "version": "0.20.0", "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "0b866d54e70c792a3c4f5ca9c12a6d358a31f4b8" + "reference": "6c5be4588d97e3732a1907ecb13cd8a098eade96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/0b866d54e70c792a3c4f5ca9c12a6d358a31f4b8", - "reference": "0b866d54e70c792a3c4f5ca9c12a6d358a31f4b8", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/6c5be4588d97e3732a1907ecb13cd8a098eade96", + "reference": "6c5be4588d97e3732a1907ecb13cd8a098eade96", "shasum": "" }, "require": { @@ -4389,9 +4389,9 @@ ], "support": { "issues": "https://github.com/utopia-php/messaging/issues", - "source": "https://github.com/utopia-php/messaging/tree/0.19.0" + "source": "https://github.com/utopia-php/messaging/tree/0.20.0" }, - "time": "2025-10-14T11:46:49+00:00" + "time": "2025-10-22T04:27:37+00:00" }, { "name": "utopia-php/migration", @@ -5095,16 +5095,16 @@ }, { "name": "utopia-php/vcs", - "version": "0.11.0", + "version": "0.12.0", "source": { "type": "git", "url": "https://github.com/utopia-php/vcs.git", - "reference": "0e665eaa7d906168525bf6aac50b6bcc3e4fe528" + "reference": "28457cf347972c4ec95d3ca77776a4921364a665" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/vcs/zipball/0e665eaa7d906168525bf6aac50b6bcc3e4fe528", - "reference": "0e665eaa7d906168525bf6aac50b6bcc3e4fe528", + "url": "https://api.github.com/repos/utopia-php/vcs/zipball/28457cf347972c4ec95d3ca77776a4921364a665", + "reference": "28457cf347972c4ec95d3ca77776a4921364a665", "shasum": "" }, "require": { @@ -5138,9 +5138,9 @@ ], "support": { "issues": "https://github.com/utopia-php/vcs/issues", - "source": "https://github.com/utopia-php/vcs/tree/0.11.0" + "source": "https://github.com/utopia-php/vcs/tree/0.12.0" }, - "time": "2025-07-23T13:54:58+00:00" + "time": "2025-10-22T12:58:29+00:00" }, { "name": "utopia-php/websocket", From 26f61c18552cae9155e693bdbf7096d081848e03 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 27 Oct 2025 19:34:49 +0200 Subject: [PATCH 09/77] add back registers.php --- app/init/registers.php | 342 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 342 insertions(+) create mode 100644 app/init/registers.php diff --git a/app/init/registers.php b/app/init/registers.php new file mode 100644 index 0000000000..c64335c09a --- /dev/null +++ b/app/init/registers.php @@ -0,0 +1,342 @@ +set('logger', function () { + // Register error logger + $providerName = System::getEnv('_APP_LOGGING_PROVIDER', ''); + $providerConfig = System::getEnv('_APP_LOGGING_CONFIG', ''); + + if (empty($providerConfig)) { + return; + } + + try { + $loggingProvider = new DSN($providerConfig ?? ''); + + $providerName = $loggingProvider->getScheme(); + $providerConfig = match ($providerName) { + 'sentry' => ['key' => $loggingProvider->getPassword(), 'projectId' => $loggingProvider->getUser() ?? '', 'host' => 'https://' . $loggingProvider->getHost()], + 'logowl' => ['ticket' => $loggingProvider->getUser() ?? '', 'host' => $loggingProvider->getHost()], + default => ['key' => $loggingProvider->getHost()], + }; + } catch (Throwable $th) { + // Fallback for older Appwrite versions up to 1.5.x that use _APP_LOGGING_PROVIDER and _APP_LOGGING_CONFIG environment variables + Console::warning('Using deprecated logging configuration. Please update your configuration to use DSN format.' . $th->getMessage()); + $configChunks = \explode(";", $providerConfig); + + $providerConfig = match ($providerName) { + 'sentry' => [ 'key' => $configChunks[0], 'projectId' => $configChunks[1] ?? '', 'host' => '',], + 'logowl' => ['ticket' => $configChunks[0] ?? '', 'host' => ''], + default => ['key' => $providerConfig], + }; + } + + if (empty($providerName) || empty($providerConfig)) { + return; + } + + if (!Logger::hasProvider($providerName)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, "Logging provider not supported. Logging is disabled"); + } + + try { + $adapter = match ($providerName) { + 'sentry' => new Sentry($providerConfig['projectId'], $providerConfig['key'], $providerConfig['host']), + 'logowl' => new LogOwl($providerConfig['ticket'], $providerConfig['host']), + 'raygun' => new Raygun($providerConfig['key']), + 'appsignal' => new AppSignal($providerConfig['key']), + default => null + }; + } catch (Throwable $th) { + $adapter = null; + } + + if ($adapter === null) { + Console::error("Logging provider not supported. Logging is disabled"); + return; + } + + return new Logger($adapter); +}); + +$register->set('pools', function () { + $group = new Group(); + + $fallbackForDB = 'db_main=' . AppwriteURL::unparse([ + 'scheme' => 'mariadb', + 'host' => System::getEnv('_APP_DB_HOST', 'mariadb'), + 'port' => System::getEnv('_APP_DB_PORT', '3306'), + 'user' => System::getEnv('_APP_DB_USER', ''), + 'pass' => System::getEnv('_APP_DB_PASS', ''), + 'path' => System::getEnv('_APP_DB_SCHEMA', ''), + ]); + $fallbackForRedis = 'redis_main=' . AppwriteURL::unparse([ + 'scheme' => 'redis', + 'host' => System::getEnv('_APP_REDIS_HOST', 'redis'), + 'port' => System::getEnv('_APP_REDIS_PORT', '6379'), + 'user' => System::getEnv('_APP_REDIS_USER', ''), + 'pass' => System::getEnv('_APP_REDIS_PASS', ''), + ]); + + $connections = [ + 'console' => [ + 'type' => 'database', + 'dsns' => $fallbackForDB, + 'multiple' => false, + 'schemes' => ['mariadb', 'mysql'], + ], + 'database' => [ + 'type' => 'database', + 'dsns' => $fallbackForDB, + 'multiple' => true, + 'schemes' => ['mariadb', 'mysql'], + ], + 'logs' => [ + 'type' => 'database', + 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_LOGS', $fallbackForDB), + 'multiple' => false, + 'schemes' => ['mariadb', 'mysql'], + ], + 'publisher' => [ + 'type' => 'publisher', + 'dsns' => $fallbackForRedis, + 'multiple' => false, + 'schemes' => ['redis'], + ], + 'consumer' => [ + 'type' => 'consumer', + 'dsns' => $fallbackForRedis, + 'multiple' => false, + 'schemes' => ['redis'], + ], + 'pubsub' => [ + 'type' => 'pubsub', + 'dsns' => $fallbackForRedis, + 'multiple' => false, + 'schemes' => ['redis'], + ], + 'cache' => [ + 'type' => 'cache', + 'dsns' => $fallbackForRedis, + 'multiple' => true, + 'schemes' => ['redis'], + ], + ]; + + $maxConnections = System::getEnv('_APP_CONNECTIONS_MAX', 151); + $instanceConnections = $maxConnections / System::getEnv('_APP_POOL_CLIENTS', 14); + + $multiprocessing = System::getEnv('_APP_SERVER_MULTIPROCESS', 'disabled') === 'enabled'; + + if ($multiprocessing) { + $workerCount = intval(System::getEnv('_APP_CPU_NUM', swoole_cpu_num())) * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); + } else { + $workerCount = 1; + } + + if ($workerCount > $instanceConnections) { + throw new \Exception('Pool size is too small. Increase the number of allowed database connections or decrease the number of workers.', 500); + } + + $poolSize = (int)($instanceConnections / $workerCount); + + foreach ($connections as $key => $connection) { + $type = $connection['type'] ?? ''; + $multiple = $connection['multiple'] ?? false; + $schemes = $connection['schemes'] ?? []; + $config = []; + $dsns = explode(',', $connection['dsns'] ?? ''); + foreach ($dsns as &$dsn) { + $dsn = explode('=', $dsn); + $name = ($multiple) ? $key . '_' . $dsn[0] : $key; + $dsn = $dsn[1] ?? ''; + $config[] = $name; + if (empty($dsn)) { + //throw new Exception(Exception::GENERAL_SERVER_ERROR, "Missing value for DSN connection in {$key}"); + continue; + } + + $dsn = new DSN($dsn); + $dsnHost = $dsn->getHost(); + $dsnPort = $dsn->getPort(); + $dsnUser = $dsn->getUser(); + $dsnPass = $dsn->getPassword(); + $dsnScheme = $dsn->getScheme(); + $dsnDatabase = $dsn->getPath(); + + if (!in_array($dsnScheme, $schemes)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid console database scheme"); + } + + /** + * Get Resource + * + * Creation could be reused across connection types like database, cache, queue, etc. + * + * Resource assignment to an adapter will happen below. + */ + $resource = match ($dsnScheme) { + 'mysql', + 'mariadb' => function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) { + return new PDOProxy(function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) { + return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, [ + \PDO::ATTR_TIMEOUT => 3, // Seconds + \PDO::ATTR_PERSISTENT => false, + \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC, + \PDO::ATTR_EMULATE_PREPARES => true, + \PDO::ATTR_STRINGIFY_FETCHES => true + ]); + }); + }, + 'redis' => function () use ($dsnHost, $dsnPort, $dsnPass) { + $redis = new \Redis(); + @$redis->pconnect($dsnHost, (int)$dsnPort); + if ($dsnPass) { + $redis->auth($dsnPass); + } + $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); + + return $redis; + }, + default => throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Invalid scheme'), + }; + + $pool = new Pool($name, $poolSize, function () use ($type, $resource, $dsn) { + // Get Adapter + switch ($type) { + case 'database': + $adapter = match ($dsn->getScheme()) { + 'mariadb' => new MariaDB($resource()), + 'mysql' => new MySQL($resource()), + default => null + }; + + $adapter->setDatabase($dsn->getPath()); + return $adapter; + case 'pubsub': + return match ($dsn->getScheme()) { + 'redis' => new PubSub($resource()), + default => null + }; + case 'publisher': + case 'consumer': + return match ($dsn->getScheme()) { + 'redis' => new Queue\Broker\Redis(new Queue\Connection\Redis($dsn->getHost(), $dsn->getPort())), + default => null + }; + case 'cache': + return match ($dsn->getScheme()) { + 'redis' => new RedisCache($resource()), + default => null + }; + default: + throw new Exception(Exception::GENERAL_SERVER_ERROR, "Server error: Missing adapter implementation."); + } + }); + + $group->add($pool); + } + + Config::setParam('pools-' . $key, $config); + } + + return $group; +}); + +$register->set('db', function () { + // This is usually for our workers or CLI commands scope + $dbHost = System::getEnv('_APP_DB_HOST', ''); + $dbPort = System::getEnv('_APP_DB_PORT', ''); + $dbUser = System::getEnv('_APP_DB_USER', ''); + $dbPass = System::getEnv('_APP_DB_PASS', ''); + $dbScheme = System::getEnv('_APP_DB_SCHEMA', ''); + + return new PDO( + "mysql:host={$dbHost};port={$dbPort};dbname={$dbScheme};charset=utf8mb4", + $dbUser, + $dbPass, + SQL::getPDOAttributes() + ); +}); + +$register->set('smtp', function () { + $mail = new PHPMailer(true); + + $mail->isSMTP(); + + $username = System::getEnv('_APP_SMTP_USERNAME'); + $password = System::getEnv('_APP_SMTP_PASSWORD'); + + $mail->XMailer = 'Appwrite Mailer'; + $mail->Host = System::getEnv('_APP_SMTP_HOST', 'smtp'); + $mail->Port = System::getEnv('_APP_SMTP_PORT', 25); + $mail->SMTPAuth = !empty($username) && !empty($password); + $mail->Username = $username; + $mail->Password = $password; + $mail->SMTPSecure = System::getEnv('_APP_SMTP_SECURE', ''); + $mail->SMTPAutoTLS = false; + $mail->CharSet = 'UTF-8'; + + $from = \urldecode(System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server')); + $email = System::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM); + + $mail->setFrom($email, $from); + $mail->addReplyTo($email, $from); + + $mail->isHTML(true); + + return $mail; +}); +$register->set('geodb', function () { + return new Reader(__DIR__ . '/../assets/dbip/dbip-country-lite-2024-09.mmdb'); +}); +$register->set('passwordsDictionary', function () { + $content = \file_get_contents(__DIR__ . '/../assets/security/10k-common-passwords'); + $content = explode("\n", $content); + $content = array_flip($content); + return $content; +}); +$register->set('promiseAdapter', function () { + return new Swoole(); +}); +$register->set('hooks', function () { + return new Hooks(); +}); \ No newline at end of file From fbaffa980a4aaea288918c27dc54c4b239bb79f2 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 27 Oct 2025 20:46:58 +0200 Subject: [PATCH 10/77] linter --- app/init/registers.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/init/registers.php b/app/init/registers.php index c64335c09a..3dc0e22dba 100644 --- a/app/init/registers.php +++ b/app/init/registers.php @@ -339,4 +339,4 @@ $register->set('promiseAdapter', function () { }); $register->set('hooks', function () { return new Hooks(); -}); \ No newline at end of file +}); From e769cf4e487a8f9a52dd9c52c422c8a52405acd2 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 27 Oct 2025 21:23:03 +0200 Subject: [PATCH 11/77] Remove vendor path for utopia-php/database in docker-compose.yml --- docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 1e437356c5..2d2c04ddfd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -89,7 +89,6 @@ services: - ./public:/usr/src/code/public - ./src:/usr/src/code/src - ./dev:/usr/src/code/dev - - ./vendor/utopia-php/database/src:/usr/src/code/vendor/utopia-php/database/src depends_on: - mariadb - redis From 462634d311c4707fe7f3a12b53e72834d95a808b Mon Sep 17 00:00:00 2001 From: shimon Date: Tue, 28 Oct 2025 09:09:54 +0200 Subject: [PATCH 12/77] Update dependencies in composer.json and composer.lock; upgrade utopia-php/detector to version 0.2.*, and utopia-php/migration to version 1.3.3. Modify exception messages in storage API for better clarity on authorization failures. Adjust test assertions to reflect updated error messages. --- app/controllers/api/storage.php | 16 ++++---- composer.json | 2 +- composer.lock | 38 +++++++++---------- .../Transactions/Operations/Create.php | 6 +-- tests/e2e/Services/Tokens/TokensBase.php | 8 ++-- 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index ab003bedf1..1224bdd46e 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -991,7 +991,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } if ($file->isEmpty()) { @@ -1171,7 +1171,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') $fileSecurity = $bucket->getAttribute('fileSecurity', false); $valid = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } if ($fileSecurity && !$valid && !$isToken) { @@ -1182,7 +1182,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } if ($file->isEmpty()) { @@ -1331,7 +1331,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $fileSecurity = $bucket->getAttribute('fileSecurity', false); $valid = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } if ($fileSecurity && !$valid && !$isToken) { @@ -1342,7 +1342,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') } if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } if ($file->isEmpty()) { @@ -1478,7 +1478,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') try { $decoded = $decoder->decode($jwt); } catch (JWTException) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } if ( @@ -1486,7 +1486,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') $decoded['bucketId'] !== $bucketId || $decoded['fileId'] !== $fileId ) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); @@ -1769,7 +1769,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') $fileSecurity = $bucket->getAttribute('fileSecurity', false); $valid = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_DELETE, $bucket->getDelete())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED); + throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } // Read permission should not be required for delete diff --git a/composer.json b/composer.json index d53ce2314a..e9b0cebd4d 100644 --- a/composer.json +++ b/composer.json @@ -53,7 +53,7 @@ "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", "utopia-php/database": "dev-feat-authorization-instance as 3.0.2", - "utopia-php/detector": "0.1.*", + "utopia-php/detector": "0.2.*", "utopia-php/domains": "0.9.*", "utopia-php/dns": "0.3.*", "utopia-php/dsn": "0.2.1", diff --git a/composer.lock b/composer.lock index edb7cb5bf6..10664cac37 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": "48764fa55a13051632675cd4a0f7a6fc", + "content-hash": "e84237cbb00cc2f2edfa7650cc19c940", "packages": [ { "name": "adhocore/jwt", @@ -3898,16 +3898,16 @@ }, { "name": "utopia-php/detector", - "version": "0.1.5", + "version": "0.2.1", "source": { "type": "git", "url": "https://github.com/utopia-php/detector.git", - "reference": "b5d6ba51352485b524589bc0ee8d07a9efafe718" + "reference": "89f96e864220de13800cf398a1f1686a85401eaa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/detector/zipball/b5d6ba51352485b524589bc0ee8d07a9efafe718", - "reference": "b5d6ba51352485b524589bc0ee8d07a9efafe718", + "url": "https://api.github.com/repos/utopia-php/detector/zipball/89f96e864220de13800cf398a1f1686a85401eaa", + "reference": "89f96e864220de13800cf398a1f1686a85401eaa", "shasum": "" }, "require": { @@ -3937,9 +3937,9 @@ ], "support": { "issues": "https://github.com/utopia-php/detector/issues", - "source": "https://github.com/utopia-php/detector/tree/0.1.5" + "source": "https://github.com/utopia-php/detector/tree/0.2.1" }, - "time": "2025-05-19T11:01:28+00:00" + "time": "2025-10-27T13:38:33+00:00" }, { "name": "utopia-php/dns", @@ -4395,16 +4395,16 @@ }, { "name": "utopia-php/migration", - "version": "1.3.2", + "version": "1.3.3", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "f5c1d2cae764290766a4c2d1546c1d51de95b67f" + "reference": "731b3a963c58c30e0b2368695d57a7e8fcb7455c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/f5c1d2cae764290766a4c2d1546c1d51de95b67f", - "reference": "f5c1d2cae764290766a4c2d1546c1d51de95b67f", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/731b3a963c58c30e0b2368695d57a7e8fcb7455c", + "reference": "731b3a963c58c30e0b2368695d57a7e8fcb7455c", "shasum": "" }, "require": { @@ -4444,9 +4444,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/1.3.2" + "source": "https://github.com/utopia-php/migration/tree/1.3.3" }, - "time": "2025-10-22T12:30:47+00:00" + "time": "2025-10-28T04:02:08+00:00" }, { "name": "utopia-php/mongo", @@ -5318,16 +5318,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.4.14", + "version": "1.4.15", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "b9405ccaeac5619c76558a82b7bfeb440b665b9f" + "reference": "b4a2fd9e92903c2e156f17fc5dafe102e6cfdfda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/b9405ccaeac5619c76558a82b7bfeb440b665b9f", - "reference": "b9405ccaeac5619c76558a82b7bfeb440b665b9f", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/b4a2fd9e92903c2e156f17fc5dafe102e6cfdfda", + "reference": "b4a2fd9e92903c2e156f17fc5dafe102e6cfdfda", "shasum": "" }, "require": { @@ -5363,9 +5363,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/1.4.14" + "source": "https://github.com/appwrite/sdk-generator/tree/1.4.15" }, - "time": "2025-10-27T11:17:01+00:00" + "time": "2025-10-28T04:52:59+00:00" }, { "name": "doctrine/annotations", 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 389cf19c4a..1e90d7f2b5 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 @@ -167,17 +167,17 @@ class Create extends Action $documentSecurity = $collection->getAttribute('documentSecurity', false); $collectionValid = $dbForProject->getAuthorization()->isValid( - new input($permissionType, $collection->getPermissionsByType($permissionType)) + new Input($permissionType, $collection->getPermissionsByType($permissionType)) ); $documentValid = false; if ($document !== null && !$document->isEmpty() && $documentSecurity) { if ($permissionType === Database::PERMISSION_UPDATE) { $documentValid = $dbForProject->getAuthorization()->isValid( - new input(Database::PERMISSION_UPDATE, $document->getUpdate()) + new Input(Database::PERMISSION_UPDATE, $document->getUpdate()) ); } elseif ($permissionType === Database::PERMISSION_DELETE) { $documentValid = $dbForProject->getAuthorization()->isValid( - new input(Database::PERMISSION_DELETE, $document->getDelete()) + new Input(Database::PERMISSION_DELETE, $document->getDelete()) ); } } 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; } From 4aaaa460b2e241e7e9e2e4fcebf3dbcbc493976f Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 28 Oct 2025 14:13:38 +0530 Subject: [PATCH 13/77] feat: per bucket image transformations flag --- app/config/collections/common.php | 11 ++++ app/config/errors.php | 5 ++ app/controllers/api/storage.php | 19 ++++-- app/controllers/shared/api.php | 4 ++ src/Appwrite/Extend/Exception.php | 1 + src/Appwrite/Migration/Version/V23.php | 10 +++ .../Database/Validator/Queries/Buckets.php | 3 +- src/Appwrite/Utopia/Response/Model/Bucket.php | 6 ++ .../Storage/StorageConsoleClientTest.php | 53 ++++++++++++++++ .../Storage/StorageCustomClientTest.php | 61 +++++++++++++++++++ 10 files changed, 167 insertions(+), 6 deletions(-) diff --git a/app/config/collections/common.php b/app/config/collections/common.php index 6de7eb224b..add08931d1 100644 --- a/app/config/collections/common.php +++ b/app/config/collections/common.php @@ -1527,6 +1527,17 @@ return [ 'required' => true, 'array' => false, ], + [ + '$id' => ID::custom('transformations'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + 'default' => true, + ], [ '$id' => ID::custom('search'), 'type' => Database::VAR_STRING, diff --git a/app/config/errors.php b/app/config/errors.php index 2e18f05797..e9c3894f53 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -522,6 +522,11 @@ return [ 'description' => 'The requested file is not publicly readable.', 'code' => 403, ], + Exception::STORAGE_BUCKET_TRANSFORMATIONS_DISABLED => [ + 'name' => Exception::STORAGE_BUCKET_TRANSFORMATIONS_DISABLED, + 'description' => 'Image transformations are disabled for the requested bucket.', + 'code' => 403, + ], /** Tokens */ Exception::TOKEN_NOT_FOUND => [ diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 8bc383cabd..5494509c89 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -85,10 +85,11 @@ App::post('/v1/storage/buckets') ->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD], true), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true) ->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true) + ->param('transformations', true, new Boolean(true), 'Are image transformations enabled?', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, int $maximumFileSize, array $allowedFileExtensions, ?string $compression, ?bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, int $maximumFileSize, array $allowedFileExtensions, ?string $compression, ?bool $encryption, bool $antivirus, bool $transformations, Response $response, Database $dbForProject, Event $queueForEvents) { $bucketId = $bucketId === 'unique()' ? ID::unique() : $bucketId; @@ -141,6 +142,7 @@ App::post('/v1/storage/buckets') 'compression' => $compression, 'encryption' => $encryption, 'antivirus' => $antivirus, + 'transformations' => $transformations, 'search' => implode(' ', [$bucketId, $name]), ])); @@ -297,10 +299,11 @@ App::put('/v1/storage/buckets/:bucketId') ->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD], true), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true) ->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true) + ->param('transformations', true, new Boolean(true), 'Are image transformations enabled?', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, ?int $maximumFileSize, array $allowedFileExtensions, ?string $compression, ?bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, ?int $maximumFileSize, array $allowedFileExtensions, ?string $compression, ?bool $encryption, bool $antivirus, bool $transformations, Response $response, Database $dbForProject, Event $queueForEvents) { $bucket = $dbForProject->getDocument('buckets', $bucketId); if ($bucket->isEmpty()) { @@ -314,6 +317,7 @@ App::put('/v1/storage/buckets/:bucketId') $encryption ??= $bucket->getAttribute('encryption', true); $antivirus ??= $bucket->getAttribute('antivirus', true); $compression ??= $bucket->getAttribute('compression', Compression::NONE); + $transformations ??= $bucket->getAttribute('transformations', true); // Map aggregate permissions into the multiple permissions they represent. $permissions = Permission::aggregate($permissions); @@ -327,7 +331,8 @@ App::put('/v1/storage/buckets/:bucketId') ->setAttribute('enabled', $enabled) ->setAttribute('encryption', $encryption) ->setAttribute('compression', $compression) - ->setAttribute('antivirus', $antivirus)); + ->setAttribute('antivirus', $antivirus) + ->setAttribute('transformations', $transformations)); $dbForProject->updateCollection('bucket_' . $bucket->getSequence(), $permissions, $fileSecurity); @@ -974,13 +979,17 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') /* @type Document $bucket */ $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isAppUser = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAppUser && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } + if (!$bucket->getAttribute('transformations', true) && !$isAppUser && !$isPrivilegedUser) { + throw new Exception(Exception::STORAGE_BUCKET_TRANSFORMATIONS_DISABLED); + } + $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 959ee77b7d..b9f56f8494 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -594,6 +594,10 @@ App::init() throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } + if (!$bucket->getAttribute('transformations', true) && !$isAppUser && !$isPrivilegedUser) { + throw new Exception(Exception::STORAGE_BUCKET_TRANSFORMATIONS_DISABLED); + } + $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 6f8744568a..5ecc54b86a 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -150,6 +150,7 @@ class Exception extends \Exception public const string STORAGE_INVALID_RANGE = 'storage_invalid_range'; public const string STORAGE_INVALID_APPWRITE_ID = 'storage_invalid_appwrite_id'; public const string STORAGE_FILE_NOT_PUBLIC = 'storage_file_not_public'; + public const string STORAGE_BUCKET_TRANSFORMATIONS_DISABLED = 'storage_bucket_transformations_disabled'; /** VCS */ public const string INSTALLATION_NOT_FOUND = 'installation_not_found'; diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index 7a6d58d59f..fd6973a71e 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -136,6 +136,16 @@ class V23 extends Migration break; } } + + try { + $this->createAttributeFromCollection( + $this->dbForPlatform, + 'buckets', + 'transformations', + ); + } catch (Throwable $th) { + Console::warning("'transformations' from 'buckets': {$th->getMessage()}"); + } } /** diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php b/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php index c4d187520f..ee320a969f 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php @@ -10,7 +10,8 @@ class Buckets extends Base 'fileSecurity', 'maximumFileSize', 'encryption', - 'antivirus' + 'antivirus', + 'transformations', ]; /** diff --git a/src/Appwrite/Utopia/Response/Model/Bucket.php b/src/Appwrite/Utopia/Response/Model/Bucket.php index f5261c026e..f51c8b6527 100644 --- a/src/Appwrite/Utopia/Response/Model/Bucket.php +++ b/src/Appwrite/Utopia/Response/Model/Bucket.php @@ -86,6 +86,12 @@ class Bucket extends Model 'default' => true, 'example' => false, ]) + ->addRule('transformations', [ + 'type' => self::TYPE_BOOLEAN, + 'description' => 'Image transformations are enabled.', + 'default' => true, + 'example' => false, + ]) ; } diff --git a/tests/e2e/Services/Storage/StorageConsoleClientTest.php b/tests/e2e/Services/Storage/StorageConsoleClientTest.php index bbb14fb136..c913816c56 100644 --- a/tests/e2e/Services/Storage/StorageConsoleClientTest.php +++ b/tests/e2e/Services/Storage/StorageConsoleClientTest.php @@ -2,6 +2,7 @@ namespace Tests\E2E\Services\Storage; +use CURLFile; use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; @@ -107,4 +108,56 @@ class StorageConsoleClientTest extends Scope $this->assertIsArray($response['body']['imageTransformations']); $this->assertIsNumeric($response['body']['imageTransformationsTotal']); } + public function testCreateBucketTransformationsDisabledConsole(): void + { + // Create a bucket with default settings + $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'bucketId' => ID::unique(), + 'name' => 'Test Console Bucket Transformations Disabled', + ]); + $this->assertEquals(201, $bucket['headers']['status-code']); + + // Create a file in the bucket + $file = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucket['body']['$id'] . '/files', array_merge([ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'fileId' => ID::unique(), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'transformations.png'), + ]); + $this->assertEquals(201, $file['headers']['status-code']); + + // Try to get the file preview + $preview = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucket['body']['$id'] . '/files/' . $file['body']['$id'] . '/preview', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(200, $preview['headers']['status-code']); + + // Update the bucket to disable transformations + $bucket = $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . $bucket['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Test Bucket Transformations Disabled', + 'transformations' => false, + ]); + + // Try to get the file preview again + $preview = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucket['body']['$id'] . '/files/' . $file['body']['$id'] . '/preview', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(200, $preview['headers']['status-code']); // Returns 200 since image transformations are not counted for console requests + + // Delete the bucket + $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucket['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(200, $bucket['headers']['status-code']); + } } diff --git a/tests/e2e/Services/Storage/StorageCustomClientTest.php b/tests/e2e/Services/Storage/StorageCustomClientTest.php index c723fba50a..71d33165dc 100644 --- a/tests/e2e/Services/Storage/StorageCustomClientTest.php +++ b/tests/e2e/Services/Storage/StorageCustomClientTest.php @@ -1386,4 +1386,65 @@ class StorageCustomClientTest extends Scope $this->assertStringContainsString('users', $file['body']['message']); $this->assertStringContainsString('user:' . $this->getUser()['$id'], $file['body']['message']); } + + public function testCreateBucketTransformationsDisabled(): void + { + // Create a bucket with default settings + $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 Transformations Disabled', + 'permissions' => [ + Permission::read(Role::any()) + ], + ]); + $this->assertEquals(201, $bucket['headers']['status-code']); + + // Create a file in the bucket + $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->assertEquals(201, $file['headers']['status-code']); + + // Try to get the file preview + $preview = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucket['body']['$id'] . '/files/' . $file['body']['$id'] . '/preview', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]); + $this->assertEquals(200, $preview['headers']['status-code']); + + // Update the bucket to disable transformations + $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 Transformations Disabled', + 'transformations' => false, + ]); + + // Try to get the file preview again + $preview = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucket['body']['$id'] . '/files/' . $file['body']['$id'] . '/preview', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]); + $this->assertEquals(403, $preview['headers']['status-code']); + $this->assertStringContainsString('Image transformations are disabled for the requested bucket.', $preview['body']['message']); + + // Delete the bucket + $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(200, $bucket['headers']['status-code']); + } } From cc6319a2c72b993b62fa1284a7ba8af6131d2c8a Mon Sep 17 00:00:00 2001 From: shimon Date: Tue, 28 Oct 2025 11:09:20 +0200 Subject: [PATCH 14/77] singletone fix --- .../TablesDB/Permissions/DatabasesPermissionsGuestTest.php | 4 +++- tests/unit/Auth/AuthTest.php | 6 ++++-- tests/unit/Messaging/MessagingChannelsTest.php | 5 ++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php index 20a91c6717..dde765cfeb 100644 --- a/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php @@ -24,7 +24,9 @@ class DatabasesPermissionsGuestTest extends Scope if (isset($this->authorization)) { return $this->authorization; } - return new Authorization(); + + $this->authorization = new Authorization(); + return $this->authorization; } diff --git a/tests/unit/Auth/AuthTest.php b/tests/unit/Auth/AuthTest.php index 4fef733457..910d10d2ba 100644 --- a/tests/unit/Auth/AuthTest.php +++ b/tests/unit/Auth/AuthTest.php @@ -20,14 +20,16 @@ class AuthTest extends TestCase if (isset($this->authorization)) { return $this->authorization; } - return new Authorization(); + + $this->authorization = new Authorization(); + return $this->authorization; } /** * Reset Roles */ - public function tearDown(): void + public function setUp(): void { $this->getAuthorization()->cleanRoles(); $this->getAuthorization()->addRole(Role::any()->toString()); diff --git a/tests/unit/Messaging/MessagingChannelsTest.php b/tests/unit/Messaging/MessagingChannelsTest.php index 54784edada..b6410205a3 100644 --- a/tests/unit/Messaging/MessagingChannelsTest.php +++ b/tests/unit/Messaging/MessagingChannelsTest.php @@ -35,6 +35,7 @@ class MessagingChannelsTest extends TestCase 'functions.1', ]; + private $authorization; public function getAuthorization(): Authorization @@ -42,7 +43,9 @@ class MessagingChannelsTest extends TestCase if (isset($this->authorization)) { return $this->authorization; } - return new Authorization(); + + $this->authorization = new Authorization(); + return $this->authorization; } public function setUp(): void From 68524067cf4c1664d0621558f508fa4fbd4e937b Mon Sep 17 00:00:00 2001 From: shimon Date: Tue, 28 Oct 2025 11:29:14 +0200 Subject: [PATCH 15/77] migrations tests fix --- app/controllers/api/migrations.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 294704f7cc..1ea21f9bb5 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -1,5 +1,6 @@ inject('deviceForMigrations') ->inject('queueForEvents') ->inject('queueForMigrations') - ->action(function (string $bucketId, string $fileId, string $resourceId, bool $internalFile, Response $response, Database $dbForProject, Database $dbForPlatform, Document $project, Device $deviceForFiles, Device $deviceForImports, Event $queueForEvents, Migration $queueForMigrations) { + ->action(function (string $bucketId, string $fileId, string $resourceId, bool $internalFile, Response $response, Database $dbForProject, Database $dbForPlatform, Document $project, Device $deviceForFiles, Device $deviceForMigrations, Event $queueForEvents, Migration $queueForMigrations) { $isAPIKey = Auth::isAppUser($dbForPlatform->getAuthorization()->getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser($dbForPlatform->getAuthorization()->getRoles()); if ($internalFile && !$isPrivilegedUser) { @@ -497,7 +499,7 @@ App::post('/v1/migrations/csv/exports') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); if ($bucket->isEmpty()) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -510,12 +512,12 @@ App::post('/v1/migrations/csv/exports') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $dbForProject->getAuthorization()->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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } From 1546add5d559c77ad02a5a659db56cab0e09557c Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 28 Oct 2025 15:05:14 +0530 Subject: [PATCH 16/77] add to both dbs --- src/Appwrite/Migration/Version/V23.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index fd6973a71e..82acf40149 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -143,6 +143,16 @@ class V23 extends Migration 'buckets', 'transformations', ); + } catch (Throwable $th) { + Console::warning("(platform) 'transformations' from 'buckets': {$th->getMessage()}"); + } + + try { + $this->createAttributeFromCollection( + $this->dbForProject, + 'buckets', + 'transformations', + ); } catch (Throwable $th) { Console::warning("'transformations' from 'buckets': {$th->getMessage()}"); } From 3f710ddc704d3f3567946e8ec6f967155f18b9df Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 28 Oct 2025 15:06:43 +0530 Subject: [PATCH 17/77] fix: test --- tests/e2e/Services/Storage/StorageConsoleClientTest.php | 4 ++-- tests/e2e/Services/Storage/StorageCustomClientTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/e2e/Services/Storage/StorageConsoleClientTest.php b/tests/e2e/Services/Storage/StorageConsoleClientTest.php index c913816c56..5c618d6357 100644 --- a/tests/e2e/Services/Storage/StorageConsoleClientTest.php +++ b/tests/e2e/Services/Storage/StorageConsoleClientTest.php @@ -154,10 +154,10 @@ class StorageConsoleClientTest extends Scope $this->assertEquals(200, $preview['headers']['status-code']); // Returns 200 since image transformations are not counted for console requests // Delete the bucket - $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucket['body']['$id'], array_merge([ + $response = $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucket['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(200, $bucket['headers']['status-code']); + $this->assertEquals(204, $response['headers']['status-code']); } } diff --git a/tests/e2e/Services/Storage/StorageCustomClientTest.php b/tests/e2e/Services/Storage/StorageCustomClientTest.php index 71d33165dc..ec9f0d0cc7 100644 --- a/tests/e2e/Services/Storage/StorageCustomClientTest.php +++ b/tests/e2e/Services/Storage/StorageCustomClientTest.php @@ -1440,11 +1440,11 @@ class StorageCustomClientTest extends Scope $this->assertStringContainsString('Image transformations are disabled for the requested bucket.', $preview['body']['message']); // Delete the bucket - $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucket['body']['$id'], [ + $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(200, $bucket['headers']['status-code']); + $this->assertEquals(204, $response['headers']['status-code']); } } From 7b1e163c7761bfa636ae470710a2628b7b6951a3 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 28 Oct 2025 15:07:24 +0530 Subject: [PATCH 18/77] move to check --- src/Appwrite/Migration/Version/V23.php | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index 82acf40149..9d724bac0a 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -132,6 +132,14 @@ class V23 extends Migration } $this->dbForProject->purgeCachedCollection($id); break; + case 'buckets': + try { + $this->createAttributeFromCollection($this->dbForProject, $id, 'transformations'); + } catch (Throwable $th) { + Console::warning("'transformations' from {$id}: {$th->getMessage()}"); + } + $this->dbForProject->purgeCachedCollection($id); + break; default: break; } @@ -146,16 +154,6 @@ class V23 extends Migration } catch (Throwable $th) { Console::warning("(platform) 'transformations' from 'buckets': {$th->getMessage()}"); } - - try { - $this->createAttributeFromCollection( - $this->dbForProject, - 'buckets', - 'transformations', - ); - } catch (Throwable $th) { - Console::warning("'transformations' from 'buckets': {$th->getMessage()}"); - } } /** From 0bfbae4cdd2325b2e4dae3aeae1dc5b6ce76e628 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 28 Oct 2025 15:09:11 +0530 Subject: [PATCH 19/77] add to both dbs --- src/Appwrite/Migration/Version/V23.php | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index 9d724bac0a..07091050d0 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -135,6 +135,7 @@ class V23 extends Migration case 'buckets': try { $this->createAttributeFromCollection($this->dbForProject, $id, 'transformations'); + $this->createAttributeFromCollection($this->dbForPlatform, $id, 'transformations'); } catch (Throwable $th) { Console::warning("'transformations' from {$id}: {$th->getMessage()}"); } @@ -144,16 +145,6 @@ class V23 extends Migration break; } } - - try { - $this->createAttributeFromCollection( - $this->dbForPlatform, - 'buckets', - 'transformations', - ); - } catch (Throwable $th) { - Console::warning("(platform) 'transformations' from 'buckets': {$th->getMessage()}"); - } } /** From ca861119f9bbd6e00f76d63a7ae8e7c1ca61db3f Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 28 Oct 2025 15:10:51 +0530 Subject: [PATCH 20/77] keep in same --- src/Appwrite/Migration/Version/V23.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index 07091050d0..bed744700a 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -135,7 +135,6 @@ class V23 extends Migration case 'buckets': try { $this->createAttributeFromCollection($this->dbForProject, $id, 'transformations'); - $this->createAttributeFromCollection($this->dbForPlatform, $id, 'transformations'); } catch (Throwable $th) { Console::warning("'transformations' from {$id}: {$th->getMessage()}"); } From 9e79d883a06d05dab122bf32986b6128339cf36c Mon Sep 17 00:00:00 2001 From: shimon Date: Tue, 28 Oct 2025 14:16:26 +0200 Subject: [PATCH 21/77] Refactor authorization retrieval in realtime and update imports in migration files; clean up whitespace in tests --- app/realtime.php | 3 +-- .../TablesDB/Permissions/DatabasesPermissionsGuestTest.php | 4 ++-- tests/unit/Auth/AuthTest.php | 2 +- tests/unit/Messaging/MessagingChannelsTest.php | 6 +++--- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app/realtime.php b/app/realtime.php index e70b0a152d..75aa625348 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -457,8 +457,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $database = getProjectDB($project); $user = $database->getDocument('users', $userId); - - $roles = $consoleDatabase->getAuthorization()->getRoles($user); + $roles = Auth::getRoles($user, $database->getAuthorization()); $channels = $realtime->connections[$connection]['channels']; $realtime->unsubscribe($connection); diff --git a/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php index dde765cfeb..84cb4bce3a 100644 --- a/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/TablesDB/Permissions/DatabasesPermissionsGuestTest.php @@ -24,9 +24,9 @@ class DatabasesPermissionsGuestTest extends Scope if (isset($this->authorization)) { return $this->authorization; } - + $this->authorization = new Authorization(); - return $this->authorization; + return $this->authorization; } diff --git a/tests/unit/Auth/AuthTest.php b/tests/unit/Auth/AuthTest.php index 910d10d2ba..06e128003a 100644 --- a/tests/unit/Auth/AuthTest.php +++ b/tests/unit/Auth/AuthTest.php @@ -20,7 +20,7 @@ class AuthTest extends TestCase if (isset($this->authorization)) { return $this->authorization; } - + $this->authorization = new Authorization(); return $this->authorization; } diff --git a/tests/unit/Messaging/MessagingChannelsTest.php b/tests/unit/Messaging/MessagingChannelsTest.php index b6410205a3..8fb7f3f666 100644 --- a/tests/unit/Messaging/MessagingChannelsTest.php +++ b/tests/unit/Messaging/MessagingChannelsTest.php @@ -35,7 +35,7 @@ class MessagingChannelsTest extends TestCase 'functions.1', ]; - + private $authorization; public function getAuthorization(): Authorization @@ -43,9 +43,9 @@ class MessagingChannelsTest extends TestCase if (isset($this->authorization)) { return $this->authorization; } - + $this->authorization = new Authorization(); - return $this->authorization; + return $this->authorization; } public function setUp(): void From 0e22b06f0a18a2b794b1f37ca2ebae00179db397 Mon Sep 17 00:00:00 2001 From: shimon Date: Tue, 28 Oct 2025 15:01:08 +0200 Subject: [PATCH 22/77] linter --- app/controllers/api/migrations.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 1ea21f9bb5..db1b867a4b 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -19,8 +19,8 @@ use Utopia\Database\Exception\Order as OrderException; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; -use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\Queries\Documents; +use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Migration\Resource; use Utopia\Migration\Sources\Appwrite; From 145b8846287678b5bd02a0ada10d07a39e54e016 Mon Sep 17 00:00:00 2001 From: shimon Date: Tue, 28 Oct 2025 15:07:26 +0200 Subject: [PATCH 23/77] compose.lock --- composer.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/composer.lock b/composer.lock index 9c732c33ee..aa76cd45d5 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": "e84237cbb00cc2f2edfa7650cc19c940", + "content-hash": "6a0ff41b0f382016b899d52307df5983", "packages": [ { "name": "adhocore/jwt", @@ -7872,16 +7872,16 @@ }, { "name": "symfony/console", - "version": "v7.3.4", + "version": "v7.3.5", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db" + "reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/2b9c5fafbac0399a20a2e82429e2bd735dcfb7db", - "reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db", + "url": "https://api.github.com/repos/symfony/console/zipball/cdb80fa5869653c83cfe1a9084a673b6daf57ea7", + "reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7", "shasum": "" }, "require": { @@ -7946,7 +7946,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.4" + "source": "https://github.com/symfony/console/tree/v7.3.5" }, "funding": [ { @@ -7966,7 +7966,7 @@ "type": "tidelift" } ], - "time": "2025-09-22T15:31:00+00:00" + "time": "2025-10-14T15:46:26+00:00" }, { "name": "symfony/filesystem", @@ -8040,16 +8040,16 @@ }, { "name": "symfony/finder", - "version": "v7.3.2", + "version": "v7.3.5", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe" + "reference": "9f696d2f1e340484b4683f7853b273abff94421f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe", - "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe", + "url": "https://api.github.com/repos/symfony/finder/zipball/9f696d2f1e340484b4683f7853b273abff94421f", + "reference": "9f696d2f1e340484b4683f7853b273abff94421f", "shasum": "" }, "require": { @@ -8084,7 +8084,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.3.2" + "source": "https://github.com/symfony/finder/tree/v7.3.5" }, "funding": [ { @@ -8104,7 +8104,7 @@ "type": "tidelift" } ], - "time": "2025-07-15T13:41:35+00:00" + "time": "2025-10-15T18:45:57+00:00" }, { "name": "symfony/options-resolver", From a6d1f46133c4610adecb976eb3d8d046b4aa3512 Mon Sep 17 00:00:00 2001 From: shimon Date: Wed, 29 Oct 2025 10:38:09 +0200 Subject: [PATCH 24/77] addressing comments --- app/controllers/api/account.php | 4 +-- app/http.php | 3 +-- composer.lock | 26 +++++++++---------- .../Collections/Documents/Create.php | 8 ++++-- src/Appwrite/Utopia/Request.php | 4 +-- src/Appwrite/Utopia/Response.php | 4 +-- .../DatabasesPermissionsGuestTest.php | 5 +++- tests/unit/Auth/AuthTest.php | 1 + 8 files changed, 31 insertions(+), 24 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 8dfe4b51b7..da7e4c6ff1 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1995,7 +1995,7 @@ App::post('/v1/account/tokens/magic-url') ]); $user->removeAttribute('$sequence'); - $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('users', $user)); } $tokenSecret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_MAGIC_URL); @@ -2590,7 +2590,7 @@ App::post('/v1/account/tokens/phone') ]); $user->removeAttribute('$sequence'); - $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('users', $user)); try { $target = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('targets', new Document([ '$permissions' => [ diff --git a/app/http.php b/app/http.php index 629d1d21b7..5ca72c45ed 100644 --- a/app/http.php +++ b/app/http.php @@ -457,7 +457,6 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool $request->setAuthorization($authorization); $response->setAuthorization($authorization); - $authorization->cleanRoles(); $authorization->addRole(Role::any()->toString()); @@ -501,7 +500,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); diff --git a/composer.lock b/composer.lock index aa76cd45d5..93a4d68546 100644 --- a/composer.lock +++ b/composer.lock @@ -4108,16 +4108,16 @@ }, { "name": "utopia-php/emails", - "version": "0.6.1", + "version": "0.6.2", "source": { "type": "git", "url": "https://github.com/utopia-php/emails.git", - "reference": "0de8896f369b6aa1f14df338645048f95a8439e3" + "reference": "9c4c40cf7c03c2e9e21364566f9b192d03ea93c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/emails/zipball/0de8896f369b6aa1f14df338645048f95a8439e3", - "reference": "0de8896f369b6aa1f14df338645048f95a8439e3", + "url": "https://api.github.com/repos/utopia-php/emails/zipball/9c4c40cf7c03c2e9e21364566f9b192d03ea93c9", + "reference": "9c4c40cf7c03c2e9e21364566f9b192d03ea93c9", "shasum": "" }, "require": { @@ -4125,7 +4125,7 @@ "utopia-php/cli": "^0.15", "utopia-php/domains": "^0.9", "utopia-php/fetch": "^0.4", - "utopia-php/validators": "^0.0.1" + "utopia-php/validators": "^0.0.2" }, "require-dev": { "laravel/pint": "1.25.*", @@ -4162,9 +4162,9 @@ ], "support": { "issues": "https://github.com/utopia-php/emails/issues", - "source": "https://github.com/utopia-php/emails/tree/0.6.1" + "source": "https://github.com/utopia-php/emails/tree/0.6.2" }, - "time": "2025-10-28T07:29:58+00:00" + "time": "2025-10-28T16:08:17+00:00" }, { "name": "utopia-php/fetch", @@ -5109,16 +5109,16 @@ }, { "name": "utopia-php/validators", - "version": "0.0.1", + "version": "0.0.2", "source": { "type": "git", "url": "https://github.com/utopia-php/validators.git", - "reference": "69d1afa5df2f052535764520609e91b491708db2" + "reference": "894210695c5d35fa248fb65f7fe7237b6ff4fb0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/validators/zipball/69d1afa5df2f052535764520609e91b491708db2", - "reference": "69d1afa5df2f052535764520609e91b491708db2", + "url": "https://api.github.com/repos/utopia-php/validators/zipball/894210695c5d35fa248fb65f7fe7237b6ff4fb0b", + "reference": "894210695c5d35fa248fb65f7fe7237b6ff4fb0b", "shasum": "" }, "require": { @@ -5149,9 +5149,9 @@ ], "support": { "issues": "https://github.com/utopia-php/validators/issues", - "source": "https://github.com/utopia-php/validators/tree/0.0.1" + "source": "https://github.com/utopia-php/validators/tree/0.0.2" }, - "time": "2025-10-20T15:08:50+00:00" + "time": "2025-10-20T21:52:28+00:00" }, { "name": "utopia-php/vcs", 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 bc23a0e130..011a9f5a52 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 @@ -263,13 +263,17 @@ class Create extends Action $documentSecurity = $collection->getAttribute('documentSecurity', false); - $validCollection = $dbForProject->getAuthorization()->isValid(new Input($permission, $collection->getPermissionsByType($permission))); + $validCollection = $dbForProject->getAuthorization()->isValid( + new Input($permission, $collection->getPermissionsByType($permission)) + ); if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$validCollection) { throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); } if ($permission === Database::PERMISSION_UPDATE) { - $validDocument = $dbForProject->getAuthorization()->isValid(new Input($permission, $document->getUpdate())); + $validDocument = $dbForProject->getAuthorization()->isValid( + new Input($permission, $document->getUpdate()) + ); $valid = $validCollection || $validDocument; if ($documentSecurity && !$valid) { throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index a3820f4f1f..76d87e2012 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -210,7 +210,7 @@ class Request extends UtopiaRequest { $forwardedUserAgent = $this->getHeader('x-forwarded-user-agent'); if (!empty($forwardedUserAgent)) { - $roles = $this->authorization->getRoles(); + $roles = $this->authorization->getRoles() ?? []; $isAppUser = Auth::isAppUser($roles); if ($isAppUser) { @@ -234,7 +234,7 @@ class Request extends UtopiaRequest return md5($this->getURI() . '*' . serialize($params) . '*' . APP_CACHE_BUSTER); } - private Authorization $authorization; + private ?Authorization $authorization = null; public function setAuthorization(Authorization $authorization): void { diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 83ab451c74..c92d49ade8 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -809,7 +809,7 @@ class Response extends SwooleResponse } if ($rule['sensitive']) { - $roles = $this->authorization->getRoles(); + $roles = $this->authorization->getRoles() ?? []; $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); @@ -978,7 +978,7 @@ class Response extends SwooleResponse } } - private Authorization $authorization; + private ?Authorization $authorization = null; public function setAuthorization(Authorization $authorization): void { diff --git a/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php index 60c4421853..0c9854160e 100644 --- a/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/Legacy/Permissions/DatabasesPermissionsGuestTest.php @@ -24,7 +24,10 @@ class DatabasesPermissionsGuestTest extends Scope if (isset($this->authorization)) { return $this->authorization; } - return new Authorization(); + + $this->authorization = new Authorization(); + + return $this->authorization; } public function createCollection(): array diff --git a/tests/unit/Auth/AuthTest.php b/tests/unit/Auth/AuthTest.php index 06e128003a..5e883bf924 100644 --- a/tests/unit/Auth/AuthTest.php +++ b/tests/unit/Auth/AuthTest.php @@ -22,6 +22,7 @@ class AuthTest extends TestCase } $this->authorization = new Authorization(); + return $this->authorization; } From 9503507011f63515ed4725230cfcba980d4663dd Mon Sep 17 00:00:00 2001 From: Shimon Newman Date: Wed, 29 Oct 2025 11:20:49 +0200 Subject: [PATCH 25/77] Update src/Appwrite/Utopia/Response.php Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- src/Appwrite/Utopia/Response.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index c92d49ade8..da614a5a6a 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -809,7 +809,7 @@ class Response extends SwooleResponse } if ($rule['sensitive']) { - $roles = $this->authorization->getRoles() ?? []; + $roles = $this->authorization?->getRoles() ?? []; $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); From 111b2abeeb641c9a6cadc5c7c03bbef85707511b Mon Sep 17 00:00:00 2001 From: Shimon Newman Date: Wed, 29 Oct 2025 20:19:49 +0200 Subject: [PATCH 26/77] Update app/cli.php Co-authored-by: Jake Barnby --- app/cli.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/cli.php b/app/cli.php index a70a718948..449f1b444d 100644 --- a/app/cli.php +++ b/app/cli.php @@ -60,7 +60,7 @@ CLI::setResource('pools', function (Registry $register) { CLI::setResource('authorization', function () { $authorization = new Authorization(); $authorization->disable(); - return $authorization; + return $authorization; }, []); CLI::setResource('dbForPlatform', function ($pools, $cache, $authorization) { From 5c2828bc78aa6e2c5cb483089227f0cf4cc1d083 Mon Sep 17 00:00:00 2001 From: shimon Date: Wed, 29 Oct 2025 20:21:41 +0200 Subject: [PATCH 27/77] Refactor authorization handling across multiple modules to use a single instance of the Authorization class. --- app/cli.php | 3 +- app/controllers/api/account.php | 140 +++++++------ app/controllers/api/avatars.php | 30 +-- app/controllers/api/messaging.php | 62 +++--- app/controllers/api/migrations.php | 20 +- app/controllers/api/project.php | 10 +- app/controllers/api/storage.php | 186 ++++++++++-------- app/controllers/api/teams.php | 64 +++--- app/controllers/api/users.php | 6 +- app/controllers/api/vcs.php | 61 +++--- .../Modules/Console/Http/Resources/Get.php | 7 +- .../Collections/Attributes/Delete.php | 6 +- .../Databases/Collections/Attributes/Get.php | 6 +- .../Attributes/Relationship/Create.php | 6 +- .../Collections/Attributes/XList.php | 6 +- .../Http/Databases/Collections/Create.php | 6 +- .../Http/Databases/Collections/Delete.php | 6 +- .../Collections/Documents/Action.php | 4 +- .../Documents/Attribute/Decrement.php | 14 +- .../Documents/Attribute/Increment.php | 14 +- .../Collections/Documents/Create.php | 30 +-- .../Collections/Documents/Delete.php | 17 +- .../Databases/Collections/Documents/Get.php | 12 +- .../Collections/Documents/Logs/XList.php | 6 +- .../Collections/Documents/Update.php | 24 +-- .../Collections/Documents/Upsert.php | 24 +-- .../Databases/Collections/Documents/XList.php | 14 +- .../Http/Databases/Collections/Get.php | 6 +- .../Databases/Collections/Indexes/Create.php | 6 +- .../Databases/Collections/Indexes/Delete.php | 6 +- .../Databases/Collections/Indexes/Get.php | 6 +- .../Databases/Collections/Indexes/XList.php | 8 +- .../Http/Databases/Collections/Logs/XList.php | 6 +- .../Http/Databases/Collections/Update.php | 6 +- .../Http/Databases/Collections/Usage/Get.php | 6 +- .../Http/Databases/Collections/XList.php | 6 +- .../Http/Databases/Transactions/Create.php | 6 +- .../Transactions/Operations/Create.php | 26 +-- .../Http/Databases/Transactions/Update.php | 33 ++-- .../Databases/Http/Databases/Usage/Get.php | 6 +- .../Databases/Http/Databases/Usage/XList.php | 6 +- .../Functions/Http/Executions/Create.php | 23 ++- .../Functions/Http/Executions/Delete.php | 7 +- .../Modules/Functions/Http/Executions/Get.php | 11 +- .../Functions/Http/Executions/XList.php | 11 +- .../Functions/Http/Functions/Create.php | 9 +- .../Functions/Http/Functions/Delete.php | 7 +- .../Http/Functions/Deployment/Update.php | 11 +- .../Functions/Http/Functions/Update.php | 7 +- .../Modules/Functions/Http/Usage/Get.php | 6 +- .../Modules/Functions/Http/Usage/XList.php | 6 +- .../Functions/Http/Variables/Create.php | 7 +- .../Functions/Http/Variables/Delete.php | 7 +- .../Functions/Http/Variables/Update.php | 7 +- .../Modules/Sites/Http/Deployments/Create.php | 9 +- .../Http/Deployments/Duplicate/Create.php | 7 +- .../Http/Deployments/Template/Create.php | 7 +- .../Sites/Http/Sites/Deployment/Update.php | 9 +- .../Platform/Modules/Sites/Http/Usage/Get.php | 7 +- .../Modules/Sites/Http/Usage/XList.php | 6 +- .../Http/Tokens/Buckets/Files/Create.php | 8 +- src/Appwrite/Platform/Tasks/Migrate.php | 5 +- .../Platform/Tasks/StatsResources.php | 10 +- 63 files changed, 647 insertions(+), 457 deletions(-) diff --git a/app/cli.php b/app/cli.php index a70a718948..d2e335b795 100644 --- a/app/cli.php +++ b/app/cli.php @@ -149,7 +149,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform $adapter = new DatabasePool($pools->get($dsn->getHost())); $database = new Database($adapter, $cache); - $database->setAuthorization($authorization); + $databases[$dsn->getHost()] = $database; $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); @@ -166,6 +166,7 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform } $database + ->setAuthorization($authorization) ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()); diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index da7e4c6ff1..ca6ac52cd4 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -51,6 +51,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\Queries; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\Query\Limit; @@ -169,10 +170,10 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, Doc ; -$createSession = function (string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails) { +$createSession = function (string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Authorization $authorization) { /** @var Utopia\Database\Document $user */ - $userFromRequest = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('users', $userId)); + $userFromRequest = $authorization->skip(fn () => $dbForProject->getDocument('users', $userId)); if ($userFromRequest->isEmpty()) { throw new Exception(Exception::USER_INVALID_TOKEN); @@ -218,7 +219,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res $detector->getDevice() )); - $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $session = $dbForProject->createDocument('sessions', $session ->setAttribute('$permissions', [ @@ -227,7 +228,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res Permission::delete(Role::user($user->getId())), ])); - $dbForProject->getAuthorization()->skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId())); + $authorization->skip(fn () => $dbForProject->deleteDocument('tokens', $verifiedToken->getId())); $dbForProject->purgeCachedDocument('users', $user->getId()); // Magic URL + Email OTP @@ -323,8 +324,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()) { @@ -402,9 +404,9 @@ App::post('/v1/account') 'accessedAt' => DateTime::now(), ]); $user->removeAttribute('$sequence'); - $user = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = $dbForProject->getAuthorization()->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())), @@ -430,9 +432,9 @@ App::post('/v1/account') throw new Exception(Exception::USER_ALREADY_EXISTS); } - $dbForProject->getAuthorization()->removeRole(Role::guests()->toString()); - $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); - $dbForProject->getAuthorization()->addRole(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) @@ -893,7 +895,8 @@ App::post('/v1/account/sessions/email') ->inject('queueForEvents') ->inject('queueForMails') ->inject('hooks') - ->action(function (string $email, string $password, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks) { + ->inject('authorization') + ->action(function (string $email, string $password, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks, Authorization $authorization) { $email = \strtolower($email); $protocol = $request->getProtocol(); @@ -936,7 +939,7 @@ App::post('/v1/account/sessions/email') $detector->getDevice() )); - $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); // Re-hash if not using recommended algo if ($user->getAttribute('hash') !== Auth::DEFAULT_ALGO) { @@ -1028,7 +1031,8 @@ App::post('/v1/account/sessions/anonymous') ->inject('dbForProject') ->inject('geodb') ->inject('queueForEvents') - ->action(function (Request $request, Response $response, Locale $locale, Document $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents) { + ->inject('authorization') + ->action(function (Request $request, Response $response, Locale $locale, Document $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents, Authorization $authorization) { $protocol = $request->getProtocol(); if ('console' === $project->getId()) { @@ -1073,7 +1077,7 @@ App::post('/v1/account/sessions/anonymous') 'accessedAt' => DateTime::now(), ]); $user->removeAttribute('$sequence'); - $dbForProject->getAuthorization()-> skip(fn () => $dbForProject->createDocument('users', $user)); + $authorization-> skip(fn () => $dbForProject->createDocument('users', $user)); // Create session token $duration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; @@ -1099,7 +1103,7 @@ App::post('/v1/account/sessions/anonymous') $detector->getDevice() )); - $dbForProject->getAuthorization()->addRole(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())), @@ -1172,6 +1176,7 @@ App::post('/v1/account/sessions/token') ->inject('geodb') ->inject('queueForEvents') ->inject('queueForMails') + ->inject('authorization') ->action($createSession); App::get('/v1/account/sessions/oauth2/:provider') @@ -1364,7 +1369,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') ->inject('dbForProject') ->inject('geodb') ->inject('queueForEvents') - ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, array $platforms, Document $devKey, Document $user, Database $dbForProject, Reader $geodb, Event $queueForEvents) use ($oauthDefaultSuccess) { + ->inject('authorization') + ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, array $platforms, Document $devKey, Document $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Authorization $authorization) use ($oauthDefaultSuccess) { $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $port = $request->getPort(); $callbackBase = $protocol . '://' . $request->getHostname(); @@ -1605,7 +1611,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'accessedAt' => DateTime::now(), ]); $user->removeAttribute('$sequence'); - $userDoc = $dbForProject->getAuthorization()->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())), @@ -1624,8 +1630,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } } - $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); - $dbForProject->getAuthorization()->addRole(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 @@ -1684,7 +1690,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $dbForProject->updateDocument('users', $user->getId(), $user); - $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $state['success'] = URLParser::parse($state['success']); $query = URLParser::parseQuery($state['success']['query']); @@ -1706,7 +1712,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'ip' => $request->getIP(), ]); - $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -1933,7 +1939,8 @@ App::post('/v1/account/tokens/magic-url') ->inject('locale') ->inject('queueForEvents') ->inject('queueForMails') - ->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) { + ->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, Authorization $authorization) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -1995,7 +2002,7 @@ App::post('/v1/account/tokens/magic-url') ]); $user->removeAttribute('$sequence'); - $user = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); } $tokenSecret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_MAGIC_URL); @@ -2012,7 +2019,7 @@ App::post('/v1/account/tokens/magic-url') 'ip' => $request->getIP(), ]); - $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2185,7 +2192,8 @@ App::post('/v1/account/tokens/email') ->inject('locale') ->inject('queueForEvents') ->inject('queueForMails') - ->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails) { + ->inject('authorization') + ->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, Authorization $authorization) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -2243,9 +2251,9 @@ App::post('/v1/account/tokens/email') ]); $user->removeAttribute('$sequence'); - $user = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = $dbForProject->getAuthorization()->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())), @@ -2283,7 +2291,7 @@ App::post('/v1/account/tokens/email') 'ip' => $request->getIP(), ]); - $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -2464,6 +2472,7 @@ App::put('/v1/account/sessions/magic-url') ->inject('geodb') ->inject('queueForEvents') ->inject('queueForMails') + ->inject('authorization') ->action($createSession); App::put('/v1/account/sessions/phone') @@ -2505,6 +2514,7 @@ App::put('/v1/account/sessions/phone') ->inject('geodb') ->inject('queueForEvents') ->inject('queueForMails') + ->inject('authorization') ->action($createSession); App::post('/v1/account/tokens/phone') @@ -2545,7 +2555,8 @@ App::post('/v1/account/tokens/phone') ->inject('timelimit') ->inject('queueForStatsUsage') ->inject('plan') - ->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan) { + ->inject('authorization') + ->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Authorization $authorization) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -2590,9 +2601,9 @@ App::post('/v1/account/tokens/phone') ]); $user->removeAttribute('$sequence'); - $user = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('users', $user)); + $user = $authorization->skip(fn () => $dbForProject->createDocument('users', $user)); try { - $target = $dbForProject->getAuthorization()->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())), @@ -2638,7 +2649,7 @@ App::post('/v1/account/tokens/phone') 'ip' => $request->getIP(), ]); - $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $token = $dbForProject->createDocument('tokens', $token ->setAttribute('$permissions', [ @@ -3023,7 +3034,8 @@ App::patch('/v1/account/email') ->inject('queueForEvents') ->inject('project') ->inject('hooks') - ->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks) { + ->inject('authorization') + ->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, Authorization $authorization) { // passwordUpdate will be empty if the user has never set a password $passwordUpdate = $user->getAttribute('passwordUpdate'); @@ -3062,7 +3074,7 @@ App::patch('/v1/account/email') ->setAttribute('passwordUpdate', DateTime::now()); } - $target = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->findOne('targets', [ + $target = $authorization->skip(fn () => $dbForProject->findOne('targets', [ Query::equal('identifier', [$email]), ])); @@ -3078,7 +3090,7 @@ App::patch('/v1/account/email') $oldTarget = $user->find('identifier', $oldEmail, 'targets'); if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) { - $dbForProject->getAuthorization()->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) { @@ -3120,7 +3132,8 @@ App::patch('/v1/account/phone') ->inject('queueForEvents') ->inject('project') ->inject('hooks') - ->action(function (string $phone, string $password, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks) { + ->inject('authorization') + ->action(function (string $phone, string $password, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, Authorization $authorization) { // passwordUpdate will be empty if the user has never set a password $passwordUpdate = $user->getAttribute('passwordUpdate'); @@ -3133,7 +3146,7 @@ App::patch('/v1/account/phone') $hooks->trigger('passwordValidator', [$dbForProject, $project, $password, &$user, false]); - $target = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->findOne('targets', [ + $target = $authorization->skip(fn () => $dbForProject->findOne('targets', [ Query::equal('identifier', [$phone]), ])); @@ -3164,7 +3177,7 @@ App::patch('/v1/account/phone') $oldTarget = $user->find('identifier', $oldPhone, 'targets'); if ($oldTarget instanceof Document && !$oldTarget->isEmpty()) { - $dbForProject->getAuthorization()->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) { @@ -3298,7 +3311,8 @@ App::post('/v1/account/recovery') ->inject('locale') ->inject('queueForMails') ->inject('queueForEvents') - ->action(function (string $email, string $url, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Mail $queueForMails, Event $queueForEvents) { + ->inject('authorization') + ->action(function (string $email, string $url, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Mail $queueForMails, Event $queueForEvents, Authorization $authorization) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); @@ -3334,7 +3348,7 @@ App::post('/v1/account/recovery') 'ip' => $request->getIP(), ]); - $dbForProject->getAuthorization()->addRole(Role::user($profile->getId())->toString()); + $authorization->addRole(Role::user($profile->getId())->toString()); $recovery = $dbForProject->createDocument('tokens', $recovery ->setAttribute('$permissions', [ @@ -3476,7 +3490,8 @@ App::put('/v1/account/recovery') ->inject('project') ->inject('queueForEvents') ->inject('hooks') - ->action(function (string $userId, string $secret, string $password, Response $response, Document $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks) { + ->inject('authorization') + ->action(function (string $userId, string $secret, string $password, Response $response, Document $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks, Authorization $authorization) { $profile = $dbForProject->getDocument('users', $userId); if ($profile->isEmpty()) { @@ -3490,7 +3505,7 @@ App::put('/v1/account/recovery') throw new Exception(Exception::USER_INVALID_TOKEN); } - $dbForProject->getAuthorization()->addRole(Role::user($profile->getId())->toString()); + $authorization->addRole(Role::user($profile->getId())->toString()); $newPassword = Auth::passwordHash($password, Auth::DEFAULT_ALGO, Auth::DEFAULT_ALGO_OPTIONS); @@ -3588,7 +3603,8 @@ App::post('/v1/account/verifications/email') ->inject('locale') ->inject('queueForEvents') ->inject('queueForMails') - ->action(function (string $url, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails) { + ->inject('authorization') + ->action(function (string $url, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, Authorization $authorization) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); @@ -3617,7 +3633,7 @@ App::post('/v1/account/verifications/email') 'ip' => $request->getIP(), ]); - $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $verification = $dbForProject->createDocument('tokens', $verification ->setAttribute('$permissions', [ @@ -3800,9 +3816,10 @@ App::put('/v1/account/verifications/email') ->inject('user') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { + ->inject('authorization') + ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Authorization $authorization) { - $profile = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('users', $userId)); + $profile = $authorization->skip(fn () => $dbForProject->getDocument('users', $userId)); if ($profile->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); @@ -3815,7 +3832,7 @@ App::put('/v1/account/verifications/email') throw new Exception(Exception::USER_INVALID_TOKEN); } - $dbForProject->getAuthorization()->addRole(Role::user($profile->getId())->toString()); + $authorization->addRole(Role::user($profile->getId())->toString()); $profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('emailVerification', true)); @@ -3874,7 +3891,8 @@ App::post('/v1/account/verifications/phone') ->inject('timelimit') ->inject('queueForStatsUsage') ->inject('plan') - ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan) { + ->inject('authorization') + ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Authorization $authorization) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -3913,7 +3931,7 @@ App::post('/v1/account/verifications/phone') 'ip' => $request->getIP(), ]); - $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $verification = $dbForProject->createDocument('tokens', $verification ->setAttribute('$permissions', [ @@ -4018,9 +4036,10 @@ App::put('/v1/account/verifications/phone') ->inject('user') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { + ->inject('authorization') + ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Authorization $authorization) { - $profile = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('users', $userId)); + $profile = $authorization->skip(fn () => $dbForProject->getDocument('users', $userId)); if ($profile->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); @@ -4032,7 +4051,7 @@ App::put('/v1/account/verifications/phone') throw new Exception(Exception::USER_INVALID_TOKEN); } - $dbForProject->getAuthorization()->addRole(Role::user($profile->getId())->toString()); + $authorization->addRole(Role::user($profile->getId())->toString()); $profile = $dbForProject->updateDocument('users', $profile->getId(), $profile->setAttribute('phoneVerification', true)); @@ -5020,12 +5039,13 @@ App::post('/v1/account/targets/push') ->inject('request') ->inject('response') ->inject('dbForProject') - ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject) { + ->inject('authorization') + ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $authorization) { $targetId = $targetId == 'unique()' ? ID::unique() : $targetId; - $provider = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('providers', $providerId)); + $provider = $authorization->skip(fn () => $dbForProject->getDocument('providers', $providerId)); - $target = $dbForProject->getAuthorization()->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); @@ -5100,9 +5120,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 = $dbForProject->getAuthorization()->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); @@ -5165,8 +5186,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 = $dbForProject->getAuthorization()->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 4952a763fc..0751f0a2a6 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -16,6 +16,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Domains\Domain; use Utopia\Fetch\Client; @@ -66,9 +67,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 = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); @@ -119,7 +120,7 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro ->setAttribute('providerRefreshToken', $refreshToken) ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry(''))); - $dbForProject->getAuthorization()->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) { @@ -127,7 +128,7 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro do { $previousAccessToken = $gitHubSession->getAttribute('providerAccessToken'); - $user = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); $gitHubSession = new Document(); @@ -656,8 +657,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 = $dbForPlatform->getAuthorization()->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); @@ -668,7 +670,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, $logger, $authorization); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; @@ -863,8 +865,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 = $dbForPlatform->getAuthorization()->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); @@ -874,7 +877,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, $logger, $authorization); $githubId = $gitHub['id'] ?? ''; $isHero = \array_key_exists($email, $heroes); @@ -941,8 +944,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 = $dbForPlatform->getAuthorization()->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); @@ -957,7 +961,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, $logger, $authorization); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 551be5c19c..5caae49864 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -35,6 +35,7 @@ use Utopia\Database\Exception\Order as OrderException; 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; @@ -1068,8 +1069,9 @@ App::get('/v1/messaging/providers') ->param('queries', [], new Providers(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Providers::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, Database $dbForProject, Response $response) { + ->action(function (array $queries, string $search, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -1095,7 +1097,7 @@ App::get('/v1/messaging/providers') } $providerId = $cursor->getValue(); - $cursorDocument = $dbForProject->getAuthorization()->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."); @@ -2473,8 +2475,9 @@ App::get('/v1/messaging/topics') ->param('queries', [], new Topics(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Topics::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, Database $dbForProject, Response $response) { + ->action(function (array $queries, string $search, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -2500,7 +2503,7 @@ App::get('/v1/messaging/topics') } $topicId = $cursor->getValue(); - $cursorDocument = $dbForProject->getAuthorization()->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."); @@ -2775,26 +2778,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 = $dbForProject->getAuthorization()->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 (!$dbForProject->getAuthorization()->isValid(new Input('subscribe', $topic->getAttribute('subscribe')))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + if (!$authorization->isValid(new Input('subscribe', $topic->getAttribute('subscribe')))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } - $target = $dbForProject->getAuthorization()->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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); + $user = $authorization->skip(fn () => $dbForProject->getDocument('users', $target->getAttribute('userId'))); $subscriber = new Document([ '$id' => $subscriberId, @@ -2827,7 +2831,7 @@ App::post('/v1/messaging/topics/:topicId/subscribers') default => throw new Exception(Exception::TARGET_PROVIDER_INVALID_TYPE), }; - $dbForProject->getAuthorization()->skip(fn () => $dbForProject->increaseDocumentAttribute( + $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute( 'topics', $topicId, $totalAttribute, @@ -2871,8 +2875,9 @@ App::get('/v1/messaging/topics/:topicId/subscribers') ->param('queries', [], new Subscribers(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Providers::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (string $topicId, array $queries, string $search, Database $dbForProject, Response $response) { + ->action(function (string $topicId, array $queries, string $search, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -2883,7 +2888,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') $queries[] = Query::search('search', $search); } - $topic = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('topics', $topicId)); + $topic = $authorization->skip(fn () => $dbForProject->getDocument('topics', $topicId)); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); @@ -2906,7 +2911,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') } $subscriberId = $cursor->getValue(); - $cursorDocument = $dbForProject->getAuthorization()->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."); @@ -2920,10 +2925,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); - $user = $dbForProject->getAuthorization()->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) @@ -3057,9 +3062,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 = $dbForProject->getAuthorization()->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); @@ -3071,8 +3077,8 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId') throw new Exception(Exception::SUBSCRIBER_NOT_FOUND); } - $target = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('targets', $subscriber->getAttribute('targetId'))); - $user = $dbForProject->getAuthorization()->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) @@ -3108,9 +3114,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 = $dbForProject->getAuthorization()->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); @@ -3133,7 +3140,7 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId') default => throw new Exception(Exception::TARGET_PROVIDER_INVALID_TYPE), }; - $dbForProject->getAuthorization()->skip(fn () => $dbForProject->decreaseDocumentAttribute( + $authorization->skip(fn () => $dbForProject->decreaseDocumentAttribute( 'topics', $topicId, $totalAttribute, @@ -3689,8 +3696,9 @@ App::get('/v1/messaging/messages') ->param('queries', [], new Messages(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Messages::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('dbForProject') + ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, Database $dbForProject, Response $response) { + ->action(function (array $queries, string $search, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -3716,7 +3724,7 @@ App::get('/v1/messaging/messages') } $messageId = $cursor->getValue(); - $cursorDocument = $dbForProject->getAuthorization()->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 db1b867a4b..7d526580ad 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -19,6 +19,7 @@ use Utopia\Database\Exception\Order as OrderException; 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\Queries\Documents; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; @@ -334,18 +335,19 @@ App::post('/v1/migrations/csv/imports') ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') + ->inject('authorization') ->inject('project') ->inject('deviceForFiles') ->inject('deviceForMigrations') ->inject('queueForEvents') ->inject('queueForMigrations') - ->action(function (string $bucketId, string $fileId, string $resourceId, bool $internalFile, Response $response, Database $dbForProject, Database $dbForPlatform, Document $project, Device $deviceForFiles, Device $deviceForMigrations, Event $queueForEvents, Migration $queueForMigrations) { - $isAPIKey = Auth::isAppUser($dbForPlatform->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForPlatform->getAuthorization()->getRoles()); + ->action(function (string $bucketId, string $fileId, string $resourceId, bool $internalFile, Response $response, Database $dbForProject, Database $dbForPlatform, Authorization $authorization, Document $project, Device $deviceForFiles, Device $deviceForMigrations, Event $queueForEvents, Migration $queueForMigrations) { + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($internalFile && !$isPrivilegedUser) { throw new Exception(Exception::USER_UNAUTHORIZED); } - $bucket = $dbForPlatform->getAuthorization()->skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) { + $bucket = $authorization->skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) { if ($internalFile) { return $dbForPlatform->getDocument('buckets', 'default'); } @@ -356,7 +358,7 @@ App::post('/v1/migrations/csv/imports') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $dbForPlatform->getAuthorization()->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); } @@ -472,6 +474,7 @@ App::post('/v1/migrations/csv/exports') ->inject('user') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->inject('project') ->inject('queueForEvents') ->inject('queueForMigrations') @@ -489,6 +492,7 @@ App::post('/v1/migrations/csv/exports') Document $user, Response $response, Database $dbForProject, + Authorization $authorization, Document $project, Event $queueForEvents, Migration $queueForMigrations @@ -499,7 +503,7 @@ App::post('/v1/migrations/csv/exports') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); if ($bucket->isEmpty()) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -512,12 +516,12 @@ App::post('/v1/migrations/csv/exports') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getAuthorization()->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 061711c96a..86f8f786c6 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -14,6 +14,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\Datetime as DateTimeValidator; use Utopia\Database\Validator\UID; use Utopia\Validator\Boolean; @@ -43,9 +44,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); @@ -100,7 +102,7 @@ App::get('/v1/project/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - $dbForProject->getAuthorization()->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; @@ -284,7 +286,7 @@ App::get('/v1/project/usage') }, $dbForProject->find('functions')); // This total is includes free and paid SMS usage - $authPhoneTotal = $dbForProject->getAuthorization()->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), @@ -292,7 +294,7 @@ App::get('/v1/project/usage') ])); // This estimate is only for paid SMS usage - $authPhoneMetrics = $dbForProject->getAuthorization()->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/storage.php b/app/controllers/api/storage.php index 1224bdd46e..f764b64ef6 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -31,6 +31,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\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\Query\Cursor; @@ -426,19 +427,20 @@ App::post('/v1/storage/buckets/:bucketId/files') ->inject('mode') ->inject('deviceForFiles') ->inject('deviceForLocal') - ->action(function (string $bucketId, string $fileId, mixed $file, ?array $permissions, Request $request, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, string $mode, Device $deviceForFiles, Device $deviceForLocal) { + ->inject('authorization') + ->action(function (string $bucketId, string $fileId, mixed $file, ?array $permissions, Request $request, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, string $mode, Device $deviceForFiles, Device $deviceForLocal, Authorization $authorization) { - $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - if (!$dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } $allowedPermissions = [ @@ -461,7 +463,7 @@ App::post('/v1/storage/buckets/:bucketId/files') } // Users can only manage their own roles, API keys and Admin users can manage any - $roles = $dbForProject->getAuthorization()->getRoles(); + $roles = $authorization->getRoles(); if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -474,7 +476,7 @@ App::post('/v1/storage/buckets/:bucketId/files') $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$dbForProject->getAuthorization()->hasRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -694,10 +696,10 @@ App::post('/v1/storage/buckets/:bucketId/files') * 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 (!$dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } - $file = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } } else { if ($file->isEmpty()) { @@ -736,12 +738,12 @@ App::post('/v1/storage/buckets/:bucketId/files') * 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 (!$dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + if (!$authorization->isValid(new Input(Database::PERMISSION_CREATE, $bucket->getCreate()))) { + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } try { - $file = $dbForProject->getAuthorization()->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); } @@ -784,21 +786,22 @@ App::get('/v1/storage/buckets/:bucketId/files') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->inject('mode') - ->action(function (string $bucketId, array $queries, string $search, Response $response, Database $dbForProject, string $mode) { - $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + ->action(function (string $bucketId, array $queries, string $search, Response $response, Database $dbForProject, Authorization $authorization, string $mode) { + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } $queries = Query::parseQueries($queries); @@ -827,7 +830,7 @@ App::get('/v1/storage/buckets/:bucketId/files') if ($fileSecurity && !$valid) { $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $cursorDocument = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $cursorDocument = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($cursorDocument->isEmpty()) { @@ -844,8 +847,8 @@ App::get('/v1/storage/buckets/:bucketId/files') $files = $dbForProject->find('bucket_' . $bucket->getSequence(), $queries); $total = $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT); } else { - $files = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); - $total = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)); + $files = $authorization->skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); + $total = $authorization->skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -884,27 +887,28 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId') ->param('fileId', '', new UID(), 'File ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->inject('mode') - ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, string $mode) { - $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, Authorization $authorization, string $mode) { + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($fileSecurity && !$valid) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = $authorization->skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { @@ -960,17 +964,18 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') ->inject('deviceForFiles') ->inject('deviceForLocal') ->inject('project') - ->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, ?string $token, Request $request, Response $response, Database $dbForProject, Document $resourceToken, Device $deviceForFiles, Device $deviceForLocal, Document $project) { + ->inject('authorization') + ->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, ?string $token, Request $request, Response $response, Database $dbForProject, Document $resourceToken, Device $deviceForFiles, Device $deviceForLocal, Document $project, Authorization $authorization) { if (!\extension_loaded('imagick')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing'); } /* @type Document $bucket */ - $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -978,20 +983,20 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = $dbForProject->getAuthorization()->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()) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($file->isEmpty()) { @@ -1109,11 +1114,11 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; //Do not update transformedAt if it's a console user - if (!Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles())) { + if (!Auth::isPrivilegedUser($authorization->getRoles())) { $transformedAt = $file->getAttribute('transformedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) { $file->setAttribute('transformedAt', DateTime::now()); - $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); + $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); } } @@ -1153,15 +1158,16 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') ->inject('request') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->inject('mode') ->inject('resourceToken') ->inject('deviceForFiles') - ->action(function (string $bucketId, string $fileId, ?string $token, Request $request, Response $response, Database $dbForProject, string $mode, Document $resourceToken, Device $deviceForFiles) { + ->action(function (string $bucketId, string $fileId, ?string $token, Request $request, Response $response, Database $dbForProject, Authorization $authorization, string $mode, Document $resourceToken, Device $deviceForFiles) { /* @type Document $bucket */ - $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -1169,20 +1175,20 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = $dbForProject->getAuthorization()->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()) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($file->isEmpty()) { @@ -1316,12 +1322,13 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') ->inject('mode') ->inject('resourceToken') ->inject('deviceForFiles') - ->action(function (string $bucketId, string $fileId, ?string $token, Response $response, Request $request, Database $dbForProject, string $mode, Document $resourceToken, Device $deviceForFiles) { + ->inject('authorization') + ->action(function (string $bucketId, string $fileId, ?string $token, Response $response, Request $request, Database $dbForProject, string $mode, Document $resourceToken, Device $deviceForFiles, Authorization $authorization) { /* @type Document $bucket */ - $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -1329,20 +1336,20 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { /* @type Document $file */ - $file = $dbForProject->getAuthorization()->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()) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($file->isEmpty()) { @@ -1470,15 +1477,16 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') ->inject('project') ->inject('mode') ->inject('deviceForFiles') - ->action(function (string $bucketId, string $fileId, string $jwt, Response $response, Request $request, Database $dbForProject, Document $project, string $mode, Device $deviceForFiles) { - $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + ->inject('authorization') + ->action(function (string $bucketId, string $fileId, string $jwt, Response $response, Request $request, Database $dbForProject, Document $project, string $mode, Device $deviceForFiles, Authorization $authorization) { + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); $decoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); try { $decoded = $decoder->decode($jwt); } catch (JWTException) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ( @@ -1486,17 +1494,17 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') $decoded['bucketId'] !== $bucketId || $decoded['fileId'] !== $fileId ) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $dbForProject->getAuthorization()->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); @@ -1642,25 +1650,26 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') ->inject('user') ->inject('mode') ->inject('queueForEvents') - ->action(function (string $bucketId, string $fileId, ?string $name, ?array $permissions, Response $response, Database $dbForProject, Document $user, string $mode, Event $queueForEvents) { + ->inject('authorization') + ->action(function (string $bucketId, string $fileId, ?string $name, ?array $permissions, Response $response, Database $dbForProject, Document $user, string $mode, Event $queueForEvents, Authorization $authorization) { - $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); + $valid = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } // Read permission should not be required for update - $file = $dbForProject->getAuthorization()->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); @@ -1674,7 +1683,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') ]); // Users can only manage their own roles, API keys and Admin users can manage any - $roles = $dbForProject->getAuthorization()->getRoles(); + $roles = $authorization->getRoles(); if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles) && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -1687,7 +1696,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$dbForProject->getAuthorization()->hasRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -1708,7 +1717,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') if ($fileSecurity && !$valid) { $file = $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file); } else { - $file = $dbForProject->getAuthorization()->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); @@ -1756,33 +1765,34 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') ->inject('mode') ->inject('deviceForFiles') ->inject('queueForDeletes') - ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, Event $queueForEvents, string $mode, Device $deviceForFiles, Delete $queueForDeletes) { - $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + ->inject('authorization') + ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, Event $queueForEvents, string $mode, Device $deviceForFiles, Delete $queueForDeletes, Authorization $authorization) { + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_DELETE, $bucket->getDelete())); + $valid = $authorization->isValid(new Input(Database::PERMISSION_DELETE, $bucket->getDelete())); if (!$fileSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } // Read permission should not be required for delete - $file = $dbForProject->getAuthorization()->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 - $validFile = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_DELETE, $file->getDelete())); + $validFile = $authorization->isValid(new Input(Database::PERMISSION_DELETE, $file->getDelete())); if ($fileSecurity && !$valid && !$validFile) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } $deviceDeleted = false; @@ -1806,7 +1816,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') if ($fileSecurity && !$valid) { $deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $deleted = $dbForProject->getAuthorization()->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); @@ -1851,7 +1861,8 @@ App::get('/v1/storage/usage') ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') - ->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 = []; @@ -1863,7 +1874,7 @@ App::get('/v1/storage/usage') ]; $total = []; - $dbForProject->getAuthorization()->skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) { + $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), @@ -1941,7 +1952,8 @@ App::get('/v1/storage/:bucketId/usage') ->inject('project') ->inject('dbForProject') ->inject('getLogsDB') - ->action(function (string $bucketId, string $range, Response $response, Document $project, Database $dbForProject, callable $getLogsDB) { + ->inject('authorization') + ->action(function (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); @@ -1959,7 +1971,7 @@ App::get('/v1/storage/:bucketId/usage') str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED), ]; - $dbForProject->getAuthorization()->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/app/controllers/api/teams.php b/app/controllers/api/teams.php index 5843cebeca..c208da5c1c 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -41,6 +41,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\Key; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Cursor; @@ -81,16 +82,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 = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); - $isAppUser = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAppUser = Auth::isAppUser($authorization->getRoles()); $teamId = $teamId == 'unique()' ? ID::unique() : $teamId; try { - $team = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('teams', new Document([ + $team = $authorization->skip(fn () => $dbForProject->createDocument('teams', new Document([ '$id' => $teamId, '$permissions' => [ Permission::read(Role::team($teamId)), @@ -485,6 +487,7 @@ App::post('/v1/teams/:teamId/memberships') ->inject('project') ->inject('user') ->inject('dbForProject') + ->inject('authorization') ->inject('locale') ->inject('queueForMails') ->inject('queueForMessaging') @@ -492,9 +495,9 @@ App::post('/v1/teams/:teamId/memberships') ->inject('timelimit') ->inject('queueForStatsUsage') ->inject('plan') - ->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) { - $isAppUser = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->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) { + $isAppUser = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); $url = htmlentities($url); if (empty($url)) { @@ -565,7 +568,7 @@ App::post('/v1/teams/:teamId/memberships') try { $userId = ID::unique(); - $invitee = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('users', new Document([ + $invitee = $authorization->skip(fn () => $dbForProject->createDocument('users', new Document([ '$id' => $userId, '$permissions' => [ Permission::read(Role::any()), @@ -601,7 +604,7 @@ App::post('/v1/teams/:teamId/memberships') } } - $isOwner = $dbForProject->getAuthorization()->hasRole('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'); @@ -637,11 +640,11 @@ App::post('/v1/teams/:teamId/memberships') ]); $membership = ($isPrivilegedUser || $isAppUser) ? - $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('memberships', $membership)) : + $authorization->skip(fn () => $dbForProject->createDocument('memberships', $membership)) : $dbForProject->createDocument('memberships', $membership); if ($isPrivilegedUser || $isAppUser) { - $dbForProject->getAuthorization()->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); } } elseif ($membership->getAttribute('confirm') === false) { @@ -654,7 +657,7 @@ App::post('/v1/teams/:teamId/memberships') } $membership = ($isPrivilegedUser || $isAppUser) ? - $dbForProject->getAuthorization()->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); @@ -840,7 +843,8 @@ App::get('/v1/teams/:teamId/memberships') ->inject('response') ->inject('project') ->inject('dbForProject') - ->action(function (string $teamId, array $queries, string $search, Response $response, Document $project, Database $dbForProject) { + ->inject('authorization') + ->action(function (string $teamId, array $queries, string $search, Response $response, Document $project, Database $dbForProject, Authorization $authorization) { $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -910,7 +914,7 @@ App::get('/v1/teams/:teamId/memberships') 'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true, ]; - $roles = $dbForProject->getAuthorization()->getRoles(); + $roles = $authorization->getRoles(); $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); @@ -981,7 +985,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); @@ -1001,7 +1006,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') 'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true, ]; - $roles = $dbForProject->getAuthorization()->getRoles(); + $roles = $authorization->getRoles(); $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); @@ -1080,8 +1085,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()) { @@ -1098,9 +1104,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') throw new Exception(Exception::USER_NOT_FOUND); } - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); - $isAppUser = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isOwner = $dbForProject->getAuthorization()->hasRole('team:' . $team->getId() . '/owner'); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAppUser = Auth::isAppUser($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 @@ -1181,10 +1187,11 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->inject('response') ->inject('user') ->inject('dbForProject') + ->inject('authorization') ->inject('project') ->inject('geodb') ->inject('queueForEvents') - ->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Reader $geodb, Event $queueForEvents) { + ->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Authorization $authorization, Document $project, Reader $geodb, Event $queueForEvents) { $protocol = $request->getProtocol(); $membership = $dbForProject->getDocument('memberships', $membershipId); @@ -1193,7 +1200,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') throw new Exception(Exception::MEMBERSHIP_NOT_FOUND); } - $team = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('teams', $teamId)); + $team = $authorization->skip(fn () => $dbForProject->getDocument('teams', $teamId)); if ($team->isEmpty()) { throw new Exception(Exception::TEAM_NOT_FOUND); @@ -1229,11 +1236,11 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->setAttribute('confirm', true) ; - $dbForProject->getAuthorization()->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) { - $dbForProject->getAuthorization()->addRole(Role::user($user->getId())->toString()); + $authorization->addRole(Role::user($user->getId())->toString()); $detector = new Detector($request->getUserAgent('UNKNOWN')); $record = $geodb->get($request->getIP()); @@ -1261,7 +1268,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $session = $dbForProject->createDocument('sessions', $session); - $dbForProject->getAuthorization()->addRole(Role::user($userId)->toString()); + $authorization->addRole(Role::user($userId)->toString()); if (!Config::getParam('domainVerification')) { $response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); @@ -1294,7 +1301,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $dbForProject->purgeCachedDocument('users', $user->getId()); - $dbForProject->getAuthorization()->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + $authorization->skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); $queueForEvents ->setParam('userId', $user->getId()) @@ -1338,8 +1345,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); @@ -1397,7 +1405,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') $dbForProject->purgeCachedDocument('users', $profile->getId()); if ($membership->getAttribute('confirm')) { // Count only confirmed members - $dbForProject->getAuthorization()->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 d7b4b56806..f7a814c51f 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -43,6 +43,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\Queries; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\Query\Limit; @@ -2617,8 +2618,9 @@ App::get('/v1/users/usage') ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->inject('register') - ->action(function (string $range, Response $response, Database $dbForProject) { + ->action(function (string $range, Response $response, Database $dbForProject, Authorization $authorization) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -2628,7 +2630,7 @@ App::get('/v1/users/usage') METRIC_SESSIONS, ]; - $dbForProject->getAuthorization()->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 88998dd798..7e46e35299 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.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\Database\Validator\Query\Cursor; use Utopia\Detector\Detection\Framework\Analog; use Utopia\Detector\Detection\Framework\Angular; @@ -70,7 +71,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, Request $request) { +$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) { $errors = []; foreach ($repositories as $repository) { try { @@ -81,12 +82,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } $projectId = $repository->getAttribute('projectId'); - $project = $dbForPlatform->getAuthorization()->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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId)); + $resource = $authorization->skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId)); $resourceInternalId = $resource->getSequence(); $deploymentId = ID::unique(); @@ -135,7 +136,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = ''; if (!empty($providerPullRequestId) && $resource->getAttribute('providerSilentMode', false) === false) { - $latestComment = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->findOne('vcsComments', [ + $latestComment = $authorization->skip(fn () => $dbForPlatform->findOne('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerPullRequestId', [$providerPullRequestId]), Query::orderDesc('$createdAt'), @@ -174,7 +175,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 { @@ -185,7 +186,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId if (!empty($latestCommentId)) { $teamId = $project->getAttribute('teamId', ''); - $latestComment = $dbForPlatform->getAuthorization()->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))), @@ -206,7 +207,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } } } elseif (!empty($providerBranch)) { - $latestComments = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->find('vcsComments', [ + $latestComments = $authorization->skip(fn () => $dbForPlatform->find('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerBranch', [$providerBranch]), Query::orderDesc('$createdAt'), @@ -245,7 +246,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)); } } } @@ -288,7 +289,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $commands[] = $resource->getAttribute('commands', ''); } - $deployment = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('deployments', new Document([ + $deployment = $authorization->skip(fn () => $dbForProject->createDocument('deployments', new Document([ '$id' => $deploymentId, '$permissions' => [ Permission::read(Role::any()), @@ -328,7 +329,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); - $dbForProject->getAuthorization()->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(); @@ -338,7 +339,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = ID::unique() . "." . $sitesDomain; $ruleId = md5($domain); $previewRuleId = $ruleId; - $dbForProject->getAuthorization()->skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -371,7 +372,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { - $dbForProject->getAuthorization()->skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -402,7 +403,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $domain = "commit-" . substr($providerCommitHash, 0, 16) . ".{$sitesDomain}"; $ruleId = md5($domain); try { - $dbForProject->getAuthorization()->skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -454,7 +455,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId if ($lockAcquired) { // Wrap in try/finally to ensure lock file gets deleted try { - $rule = $dbForPlatform->getAuthorization()->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', '')) : ''; @@ -466,7 +467,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)); } } } @@ -1382,10 +1383,11 @@ App::post('/v1/vcs/github/events') ->inject('request') ->inject('response') ->inject('dbForPlatform') + ->inject('authorization') ->inject('getProjectDB') ->inject('queueForBuilds') ->action( - function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds) use ($createGitDeployments) { + function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, Authorization $authorization, callable $getProjectDB, Build $queueForBuilds) use ($createGitDeployments) { $payload = $request->getRawPayload(); $signatureRemote = $request->getHeader('x-hub-signature-256', ''); $signatureLocal = System::getEnv('_APP_VCS_GITHUB_WEBHOOK_SECRET', ''); @@ -1421,14 +1423,14 @@ App::post('/v1/vcs/github/events') $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); //find resourceId from relevant resources table - $repositories = $dbForPlatform->getAuthorization()->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, $request); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthorName, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request); } } elseif ($event == $github::EVENT_INSTALLATION) { if ($parsedPayload["action"] == "deleted") { @@ -1441,16 +1443,16 @@ App::post('/v1/vcs/github/events') ]); foreach ($installations as $installation) { - $repositories = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('installationInternalId', [$installation->getSequence()]), Query::limit(1000) ])); foreach ($repositories as $repository) { - $dbForProject->getAuthorization()->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) { @@ -1479,12 +1481,12 @@ App::post('/v1/vcs/github/events') $providerCommitAuthor = $commitDetails["commitAuthor"] ?? ''; $providerCommitMessage = $commitDetails["commitMessage"] ?? ''; - $repositories = $dbForPlatform->getAuthorization()->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, $request); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request); } elseif ($parsedPayload["action"] == "closed") { // Allowed external contributions cleanup @@ -1493,7 +1495,7 @@ App::post('/v1/vcs/github/events') $external = $parsedPayload["external"] ?? true; if ($external) { - $repositories = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->find('repositories', [ + $repositories = $authorization->skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); @@ -1504,7 +1506,7 @@ App::post('/v1/vcs/github/events') if (\in_array($providerPullRequestId, $providerPullRequestIds)) { $providerPullRequestIds = \array_diff($providerPullRequestIds, [$providerPullRequestId]); $repository = $repository->setAttribute('providerPullRequestIds', $providerPullRequestIds); - $repository = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); + $repository = $authorization->skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); } } } @@ -1691,16 +1693,17 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor ->inject('response') ->inject('project') ->inject('dbForPlatform') + ->inject('authorization') ->inject('getProjectDB') ->inject('queueForBuilds') - ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Request $request, Response $response, Document $project, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds) 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) use ($createGitDeployments) { $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); } - $repository = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('repositories', $repositoryId, [ + $repository = $authorization->skip(fn () => $dbForPlatform->getDocument('repositories', $repositoryId, [ Query::equal('projectInternalId', [$project->getSequence()]) ])); @@ -1717,7 +1720,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor // TODO: Delete from array when PR is closed - $repository = $dbForPlatform->getAuthorization()->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'); @@ -1741,7 +1744,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor $providerBranch = \explode(':', $pullRequestResponse['head']['label'])[1] ?? ''; $providerCommitHash = $pullRequestResponse['head']['sha'] ?? ''; - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerCommitHash, $providerPullRequestId, true, $dbForPlatform, $queueForBuilds, $getProjectDB, $request); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, '', '', '', '', $providerCommitHash, '', '', '', '', $providerPullRequestId, true, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request); $response->noContent(); }); diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php index 2abe4e0957..55a60a5cbf 100644 --- a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -10,6 +10,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Domains\Domain as Domain; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -58,6 +59,7 @@ class Get extends Action ->param('type', '', new WhiteList(['rules']), 'Resource type.') ->inject('response') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -65,7 +67,8 @@ class Get extends Action string $value, string $type, Response $response, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { if ($type === 'rules') { $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); @@ -123,7 +126,7 @@ class Get extends Action throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.'); } - $document = $dbForPlatform->getAuthorization()->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/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Delete.php index ec8005993c..07ab604a5a 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 @@ -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\IndexDependency as IndexDependencyValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; @@ -66,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $db = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } 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 158184e336..d31b17667e 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 @@ -9,6 +9,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; @@ -67,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } 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 a502c2012b..411fd3bf5b 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 @@ -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; @@ -81,15 +82,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): 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; $twoWayKey ??= $collectionId; - $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } 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 e632f6397e..c56a3c5c00 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 @@ -14,6 +14,7 @@ use Utopia\Database\Document; 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\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -61,12 +62,13 @@ class XList extends Action ->param('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Attributes::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } 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 8a9088382d..71ea9a99a7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -19,6 +19,7 @@ use Utopia\Database\Exception\Limit as LimitException; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -76,12 +77,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, 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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); 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 a9eebbc9d6..67f53fa33a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Delete.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\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -63,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } 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 bbf62b2e83..d42dca57fa 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 @@ -7,6 +7,7 @@ use Appwrite\Extend\Exception; use Appwrite\Platform\Action as AppwriteAction; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; abstract class Action extends AppwriteAction { @@ -257,6 +258,7 @@ abstract class Action extends AppwriteAction Document $collection, Document $document, Database $dbForProject, + Authorization $authorization, /* options */ array &$collectionsCache, @@ -296,7 +298,7 @@ abstract class Action extends AppwriteAction $relatedCollectionId = $relationship->getAttribute('relatedCollection'); if (!isset($collectionsCache[$relatedCollectionId])) { - $relatedCollectionDoc = $dbForProject->getAuthorization()->skip( + $relatedCollectionDoc = $authorization->skip( fn () => $dbForProject->getDocument( 'database_' . $database->getSequence(), $relatedCollectionId 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 9f92a707f8..904f3be95e 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 @@ -21,6 +21,7 @@ use Utopia\Database\Exception\Limit as LimitException; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Exception\Type as TypeException; use Utopia\Database\Helpers\ID; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -83,20 +84,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 = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); - $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getAuthorization()->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()); } @@ -104,7 +106,7 @@ class Decrement extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $dbForProject->getAuthorization()->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 b97a937e58..ec23672f98 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 @@ -21,6 +21,7 @@ use Utopia\Database\Exception\Limit as LimitException; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Exception\Type as TypeException; use Utopia\Database\Helpers\ID; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -83,20 +84,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 = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); - $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getAuthorization()->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()); } @@ -104,7 +106,7 @@ class Increment extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $dbForProject->getAuthorization()->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 011a9f5a52..d7ec69777d 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 @@ -23,6 +23,7 @@ use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; @@ -131,9 +132,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) @@ -177,19 +179,19 @@ class Create extends Action $documents = [$data]; } - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization()->getRoles()); if ($isBulk && !$isAPIKey && !$isPrivilegedUser) { throw new Exception(Exception::GENERAL_UNAUTHORIZED_SCOPE); } - $database = $dbForProject->getAuthorization()->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); } - $collection = $dbForProject->getAuthorization()->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()); } @@ -246,8 +248,8 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$dbForProject->getAuthorization()->hasRole($role)) { - throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $dbForProject->getAuthorization()->getRoles()) . ')'); + if (!$authorization()->hasRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $authorization()->getRoles()) . ')'); } } } @@ -263,20 +265,20 @@ class Create extends Action $documentSecurity = $collection->getAttribute('documentSecurity', false); - $validCollection = $dbForProject->getAuthorization()->isValid( + $validCollection = $authorization()->isValid( new Input($permission, $collection->getPermissionsByType($permission)) ); if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$validCollection) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization()->getDescription()); } if ($permission === Database::PERMISSION_UPDATE) { - $validDocument = $dbForProject->getAuthorization()->isValid( + $validDocument = $authorization()->isValid( new Input($permission, $document->getUpdate()) ); $valid = $validCollection || $validDocument; if ($documentSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization()->getDescription()); } } @@ -301,7 +303,7 @@ class Create extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = $dbForProject->getAuthorization()->skip( + $relatedCollection = $authorization()->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -317,7 +319,7 @@ class Create extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $current = $dbForProject->getAuthorization()->skip( + $current = $authorization()->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId()) ); @@ -372,7 +374,7 @@ class Create extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $dbForProject->getAuthorization()->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); 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 325072f97e..fe754b6a68 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 @@ -18,6 +18,7 @@ use Utopia\Database\Document; use Utopia\Database\Exception\Conflict as ConflictException; use Utopia\Database\Exception\Restricted as RestrictedException; use Utopia\Database\Helpers\ID; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -81,6 +82,7 @@ class Delete extends Action ->inject('queueForStatsUsage') ->inject('transactionState') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -95,18 +97,19 @@ class Delete extends Action Event $queueForEvents, StatsUsage $queueForStatsUsage, TransactionState $transactionState, - array $plan + array $plan, + Authorization $authorization ): void { - $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getAuthorization()->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()); @@ -119,7 +122,7 @@ class Delete extends Action // Use transaction-aware document retrieval to see changes from same transaction $document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $document = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $document = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($document->isEmpty()) { @@ -129,7 +132,7 @@ class Delete extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $dbForProject->getAuthorization()->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); 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 93f66ed989..5dcef98b90 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 @@ -15,6 +15,7 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; @@ -68,20 +69,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 = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); - $database = $dbForProject->getAuthorization()->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); } - $collection = $dbForProject->getAuthorization()->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()); 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 6c38a03ea2..68fd41221d 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 @@ -18,6 +18,7 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Limit; use Utopia\Database\Validator\Query\Offset; @@ -72,12 +73,13 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): void + public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization): void { - $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } 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 a969585b6c..128f57708f 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 @@ -22,6 +22,7 @@ use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -85,10 +86,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 @@ -96,16 +98,16 @@ class Update extends Action throw new Exception($this->getMissingPayloadException()); } - $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getAuthorization()->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()); @@ -119,7 +121,7 @@ class Update extends Action // Use transaction-aware document retrieval to see changes from same transaction $document = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $document = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $document = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($document->isEmpty()) { @@ -134,7 +136,7 @@ class Update extends Action ]); // Users can only manage their own roles, API keys and Admin users can manage any - $roles = $dbForProject->getAuthorization()->getRoles(); + $roles = $authorization->getRoles(); if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -147,7 +149,7 @@ class Update extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$dbForProject->getAuthorization()->hasRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -189,7 +191,7 @@ class Update extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = $dbForProject->getAuthorization()->skip( + $relatedCollection = $authorization->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -206,7 +208,7 @@ class Update extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $oldDocument = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument( + $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); @@ -244,7 +246,7 @@ class Update extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $dbForProject->getAuthorization()->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); 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 6cf2f646eb..139ff7c466 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 @@ -23,6 +23,7 @@ use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -89,10 +90,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 @@ -104,15 +106,15 @@ class Upsert extends Action throw new Exception($this->getMissingPayloadException()); } - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); - $database = $dbForProject->getAuthorization()->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); } - $collection = $dbForProject->getAuthorization()->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()); } @@ -133,7 +135,7 @@ class Upsert extends Action // Use transaction-aware document retrieval to see changes from same transaction $oldDocument = $transactionState->getDocument($collectionTableId, $documentId, $transactionId); } else { - $oldDocument = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); + $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument($collectionTableId, $documentId)); } if ($oldDocument->isEmpty()) { if (!empty($user->getId())) { @@ -149,7 +151,7 @@ class Upsert extends Action } // Users can only manage their own roles, API keys and Admin users can manage any - $roles = $dbForProject->getAuthorization()->getRoles(); + $roles = $authorization->getRoles(); if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -162,7 +164,7 @@ class Upsert extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$dbForProject->getAuthorization()->hasRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -199,7 +201,7 @@ class Upsert extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = $dbForProject->getAuthorization()->skip( + $relatedCollection = $authorization->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -216,7 +218,7 @@ class Upsert extends Action if ($relation instanceof Document) { $relation = $this->removeReadonlyAttributes($relation, $isAPIKey || $isPrivilegedUser); - $oldDocument = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument( + $oldDocument = $authorization->skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); @@ -253,7 +255,7 @@ class Upsert extends Action // Handle transaction staging if ($transactionId !== null) { $transaction = ($isAPIKey || $isPrivilegedUser) - ? $dbForProject->getAuthorization()->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); 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 dbb30fcc1b..483c34708a 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 @@ -17,6 +17,7 @@ use Utopia\Database\Document; 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\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -70,20 +71,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, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void + public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState, Authorization $authorization): void { - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); - $database = $dbForProject->getAuthorization()->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); } - $collection = $dbForProject->getAuthorization()->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()); } @@ -111,7 +113,7 @@ class XList extends Action $documentId = $cursor->getValue(); - $cursorDocument = $dbForProject->getAuthorization()->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()); 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 9d4183d75f..725b53ff9e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Get.php @@ -10,6 +10,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\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -56,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); 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 7c0d61b588..6afc29a265 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 @@ -16,6 +16,7 @@ use Utopia\Database\Document; use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Index as IndexValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; @@ -78,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $db = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); 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 cc6ed66466..89d79ef353 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 @@ -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,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $db = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); 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 01b186b2c9..27e0767f88 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 @@ -10,6 +10,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; @@ -58,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); 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 7828b91221..cacfd39f44 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 @@ -15,6 +15,7 @@ use Utopia\Database\Document; 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\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -63,13 +64,14 @@ class XList extends Action ->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { /** @var Document $database */ - $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); @@ -109,7 +111,7 @@ class XList extends Action } $indexId = $cursor->getValue(); - $cursorDocument = $dbForProject->getAuthorization()->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 a7f24e7c2b..928ba55ee0 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 @@ -18,6 +18,7 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Limit; use Utopia\Database\Validator\Query\Offset; @@ -71,12 +72,13 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): void + public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization): void { - $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); 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 116b8cdccf..d1760089f6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Update.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Helpers\Permission; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -69,12 +70,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } 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 9ade789cb9..beca779bf6 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 @@ -14,6 +14,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\WhiteList; @@ -62,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); @@ -82,7 +84,7 @@ class Get extends Action str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collectionDocument->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), ]; - $dbForProject->getAuthorization()->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 43b4d59255..9e3829abe4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -15,6 +15,7 @@ use Utopia\Database\Document; 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\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -64,12 +65,13 @@ class XList extends Action ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, array $queries, string $search, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, array $queries, string $search, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): void { - $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); 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 cd01a03ca4..41d3f3022a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Create.php @@ -12,6 +12,7 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; +use Utopia\Database\Validator\Authorization; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Range; @@ -54,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())) { @@ -72,7 +74,7 @@ class Create extends Action } } - $transaction = $dbForProject->getAuthorization()->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 1e90d7f2b5..98a0708f66 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 @@ -17,6 +17,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\Authorization\Input; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; @@ -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 = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); // API keys and admins can read any transaction, regular users need permissions $transaction = ($isAPIKey || $isPrivilegedUser) - ? $dbForProject->getAuthorization()->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); @@ -113,13 +115,13 @@ class Create extends Action throw new Exception(Exception::USER_UNAUTHORIZED); } - $database = $databases[$operation['databaseId']] ??= $dbForProject->getAuthorization()->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); } $collection = $collections[$operation[$this->getGroupId()]] ??= - $dbForProject->getAuthorization()->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); @@ -166,17 +168,17 @@ class Create extends Action if (!$isAPIKey && !$isPrivilegedUser) { $documentSecurity = $collection->getAttribute('documentSecurity', false); - $collectionValid = $dbForProject->getAuthorization()->isValid( + $collectionValid = $authorization->isValid( new Input($permissionType, $collection->getPermissionsByType($permissionType)) ); $documentValid = false; if ($document !== null && !$document->isEmpty() && $documentSecurity) { if ($permissionType === Database::PERMISSION_UPDATE) { - $documentValid = $dbForProject->getAuthorization()->isValid( + $documentValid = $authorization->isValid( new Input(Database::PERMISSION_UPDATE, $document->getUpdate()) ); } elseif ($permissionType === Database::PERMISSION_DELETE) { - $documentValid = $dbForProject->getAuthorization()->isValid( + $documentValid = $authorization->isValid( new Input(Database::PERMISSION_DELETE, $document->getDelete()) ); } @@ -195,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 = $dbForProject->getAuthorization()->getRoles(); + $roles = $authorization->getRoles(); foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); @@ -207,7 +209,7 @@ class Create extends Action $permission->getIdentifier(), $permission->getDimension() ))->toString(); - if (!$dbForProject->getAuthorization()->hasRole($role)) { + if (!$authorization->hasRole($role)) { throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); } } @@ -236,7 +238,7 @@ class Create extends Action } } - $transaction = $dbForProject->getAuthorization()->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 ec43cfa87f..24e149800d 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 = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); $transaction = ($isAPIKey || $isPrivilegedUser) - ? $dbForProject->getAuthorization()->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); @@ -138,11 +139,11 @@ class Update extends Action try { $dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, $queueForEvents, $queueForStatsUsage, $queueForRealtime, $queueForFunctions, $queueForWebhooks) { - $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'committing', ]))); - $operations = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->find('transactionLogs', [ + $operations = $authorization->skip(fn () => $dbForProject->find('transactionLogs', [ Query::equal('transactionInternalId', [$transaction->getSequence()]), Query::orderAsc(), Query::limit(PHP_INT_MAX), @@ -218,7 +219,7 @@ class Update extends Action } } - $transaction = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument( + $transaction = $authorization->skip(fn () => $dbForProject->updateDocument( 'transactions', $transactionId, new Document(['status' => 'committed']) @@ -230,32 +231,32 @@ class Update extends Action }); } catch (NotFoundException $e) { - $dbForProject->getAuthorization()->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); } catch (DuplicateException|ConflictException $e) { - $dbForProject->getAuthorization()->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) { - $dbForProject->getAuthorization()->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) { - $dbForProject->getAuthorization()->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) { - $dbForProject->getAuthorization()->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) { - $dbForProject->getAuthorization()->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()); @@ -283,11 +284,11 @@ class Update extends Action $data = $data->getArrayCopy(); } - $database = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->findOne('databases', [ + $database = $authorization->skip(fn () => $dbForProject->findOne('databases', [ Query::equal('$sequence', [$databaseInternalId]) ])); - $collection = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->findOne('database_' . $databaseInternalId, [ + $collection = $authorization->skip(fn () => $dbForProject->findOne('database_' . $databaseInternalId, [ Query::equal('$sequence', [$collectionInternalId]) ])); @@ -379,7 +380,7 @@ class Update extends Action } if ($rollback) { - $transaction = $dbForProject->getAuthorization()->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 f75506e5cf..7668ad0a79 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/Get.php @@ -13,6 +13,7 @@ use Utopia\Config\Config; 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\Action; use Utopia\Swoole\Response as SwooleResponse; @@ -58,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); @@ -80,7 +82,7 @@ class Get extends Action str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES) ]; - $dbForProject->getAuthorization()->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 5927f98a02..757f845c68 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Usage/XList.php @@ -12,6 +12,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\WhiteList; @@ -55,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', []); @@ -73,7 +75,7 @@ class XList extends Action METRIC_DATABASES_OPERATIONS_WRITES, ]; - $dbForProject->getAuthorization()->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/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index 572736f975..a3b9b31380 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -26,6 +26,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\Authorization\Input; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\UID; @@ -93,6 +94,7 @@ class Create extends Base ->inject('queueForFunctions') ->inject('geodb') ->inject('executor') + ->inject('authorization') ->callback($this->action(...)); } @@ -114,7 +116,8 @@ class Create extends Base StatsUsage $queueForStatsUsage, Func $queueForFunctions, Reader $geodb, - Executor $executor + Executor $executor, + Authorization $authorization ) { $async = \strval($async) === 'true' || \strval($async) === '1'; @@ -152,10 +155,10 @@ class Create extends Base throw new Exception($validator->getDescription(), 400); } - $function = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); @@ -171,7 +174,7 @@ class Create extends Base throw new Exception(Exception::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); } - $deployment = $dbForProject->getAuthorization()->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'); @@ -185,8 +188,8 @@ class Create extends Base throw new Exception(Exception::BUILD_NOT_READY); } - if (!$dbForProject->getAuthorization()->isValid(new Input('execute', $function->getAttribute('execute')))) { // Check if user has write access to execute function - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->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 @@ -284,7 +287,7 @@ class Create extends Base if ($async) { if (is_null($scheduledAt)) { - $execution = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); $queueForFunctions ->setType('http') ->setExecution($execution) @@ -325,7 +328,7 @@ class Create extends Base ->setAttribute('scheduleInternalId', $schedule->getSequence()) ->setAttribute('scheduledAt', $scheduledAt); - $execution = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('executions', $execution)); + $execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution)); } return $response @@ -478,7 +481,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 = $dbForProject->getAuthorization()->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 c9dffc82b8..ccf345dbb5 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php @@ -13,6 +13,7 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -60,6 +61,7 @@ class Delete extends Base ->inject('dbForProject') ->inject('dbForPlatform') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -69,7 +71,8 @@ class Delete extends Base Response $response, Database $dbForProject, Database $dbForPlatform, - Event $queueForEvents + Event $queueForEvents, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -107,7 +110,7 @@ class Delete extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('active', false); - $dbForPlatform->getAuthorization()->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 1f11976b8a..69c4080f8a 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php @@ -10,6 +10,7 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -51,6 +52,7 @@ class Get extends Base ->param('executionId', '', new UID(), 'Execution ID.') ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } @@ -58,12 +60,13 @@ class Get extends Base string $functionId, string $executionId, Response $response, - Database $dbForProject + Database $dbForProject, + Authorization $authorization ) { - $function = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($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 3cd07b6cea..0237689b88 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -15,6 +15,7 @@ use Utopia\Database\Document; 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\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -57,6 +58,7 @@ class XList extends Base ->param('queries', [], new Executions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Executions::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') + ->inject('authorization') ->callback($this->action(...)); } @@ -64,12 +66,13 @@ class XList extends Base string $functionId, array $queries, Response $response, - Database $dbForProject + Database $dbForProject, + Authorization $authorization ) { - $function = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($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 6105aa49c7..182f39e274 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php @@ -27,6 +27,7 @@ use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Roles; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -114,6 +115,7 @@ class Create extends Base ->inject('dbForPlatform') ->inject('request') ->inject('gitHub') + ->inject('authorization') ->callback($this->action(...)); } @@ -151,7 +153,8 @@ class Create extends Base Func $queueForFunctions, Database $dbForPlatform, Request $request, - GitHub $github + GitHub $github, + Authorization $authorization ) { // Temporary abuse check @@ -236,7 +239,7 @@ class Create extends Base throw new Exception(Exception::FUNCTION_ALREADY_EXISTS); } - $schedule = $dbForProject->getAuthorization()->skip( + $schedule = $authorization->skip( fn () => $dbForPlatform->createDocument('schedules', new Document([ 'region' => $project->getAttribute('region'), 'resourceType' => SCHEDULE_RESOURCE_TYPE_FUNCTION, @@ -364,7 +367,7 @@ class Create extends Base // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); - $rule = $dbForPlatform->getAuthorization()->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 5b87031fa0..6c9c9c3c6f 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php @@ -13,6 +13,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\DateTime; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -60,6 +61,7 @@ class Delete extends Base ->inject('queueForDeletes') ->inject('queueForEvents') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -69,7 +71,8 @@ class Delete extends Base Database $dbForProject, DeleteEvent $queueForDeletes, Event $queueForEvents, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -86,7 +89,7 @@ class Delete extends Base $schedule ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('active', false); - $dbForPlatform->getAuthorization()->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 c1851e3eb3..b913848a13 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -13,6 +13,7 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -61,6 +62,7 @@ class Update extends Base ->inject('dbForProject') ->inject('queueForEvents') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -71,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); @@ -100,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'))); - $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queries = [ Query::equal('trigger', ['manual']), @@ -111,12 +114,12 @@ class Update extends Base Query::equal('projectInternalId', [$project->getSequence()]) ]; - $dbForPlatform->getAuthorization()->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()); - $dbForPlatform->getAuthorization()->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 d571d81d84..d182bb67ea 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php @@ -22,6 +22,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\Roles; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -103,6 +104,7 @@ class Update extends Base ->inject('dbForPlatform') ->inject('gitHub') ->inject('executor') + ->inject('authorization') ->callback($this->action(...)); } @@ -133,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); @@ -281,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'))); - $dbForPlatform->getAuthorization()->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 501b6bb468..1fa65d0cc9 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php @@ -12,6 +12,7 @@ use Utopia\Config\Config; 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\Action; use Utopia\Platform\Scope\HTTP; @@ -54,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); @@ -82,7 +84,7 @@ class Get extends Base str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), ]; - $dbForProject->getAuthorization()->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 2b8308a75a..38a95d4469 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php @@ -11,6 +11,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\WhiteList; @@ -51,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 = []; @@ -74,7 +76,7 @@ class XList extends Base str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_FAILED), ]; - $dbForProject->getAuthorization()->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 4aedbdabc5..c61a610617 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php @@ -20,6 +20,7 @@ use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Boolean; use Utopia\Validator\Text; +use Utopia\Database\Validator\Authorization; class Create extends Base { @@ -64,6 +65,7 @@ class Create extends Base ->inject('dbForProject') ->inject('dbForPlatform') ->inject('project') + ->inject('authorization') ->callback($this->action(...)); } @@ -75,7 +77,8 @@ class Create extends Base Response $response, Database $dbForProject, Database $dbForPlatform, - Document $project + Document $project, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -118,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'))); - $dbForPlatform->getAuthorization()->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 ecbdf3e13b..0ab315b212 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php @@ -14,6 +14,7 @@ use Utopia\Database\DateTime; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; +use Utopia\Database\Validator\Authorization; class Delete extends Base { @@ -56,6 +57,7 @@ class Delete extends Base ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -64,7 +66,8 @@ class Delete extends Base string $variableId, Response $response, Database $dbForProject, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -91,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'))); - $dbForPlatform->getAuthorization()->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 d83af69a0b..e581c3e887 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php @@ -16,6 +16,7 @@ use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Boolean; use Utopia\Validator\Text; +use Utopia\Database\Validator\Authorization; class Update extends Base { @@ -60,6 +61,7 @@ class Update extends Base ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -71,7 +73,8 @@ class Update extends Base ?bool $secret, Response $response, Database $dbForProject, - Database $dbForPlatform + Database $dbForPlatform, + Authorization $authorization ) { $function = $dbForProject->getDocument('functions', $functionId); @@ -108,7 +111,7 @@ class Update extends Base ->setAttribute('resourceUpdatedAt', DateTime::now()) ->setAttribute('schedule', $function->getAttribute('schedule')) ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); - $dbForPlatform->getAuthorization()->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/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index 9e3812bb1c..b590f7c1d3 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php @@ -29,6 +29,7 @@ use Utopia\Swoole\Request; use Utopia\System\System; use Utopia\Validator\Boolean; use Utopia\Validator\Text; +use Utopia\Database\Validator\Authorization; class Create extends Action { @@ -85,6 +86,7 @@ class Create extends Action ->inject('deviceForLocal') ->inject('queueForBuilds') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -104,7 +106,8 @@ class Create extends Action Device $deviceForSites, Device $deviceForLocal, Build $queueForBuilds, - array $plan + array $plan, + Authorization $authorization ) { $activate = \strval($activate) === 'true' || \strval($activate) === '1'; @@ -273,7 +276,7 @@ class Create extends Action // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); - $dbForPlatform->getAuthorization()->skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -338,7 +341,7 @@ class Create extends Action $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); $domain = ID::unique() . "." . $sitesDomain; $ruleId = md5($domain); - $dbForPlatform->getAuthorization()->skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), 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 4a3b7c804f..21f86aea35 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php @@ -12,6 +12,7 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -64,6 +65,7 @@ class Create extends Action ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('deviceForSites') + ->inject('authorization') ->callback($this->action(...)); } @@ -77,7 +79,8 @@ class Create extends Action Database $dbForPlatform, Event $queueForEvents, Build $queueForBuilds, - Device $deviceForSites + Device $deviceForSites, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -145,7 +148,7 @@ class Create extends Action // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); - $dbForPlatform->getAuthorization()->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 5888040476..7909b5ca3e 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php @@ -23,6 +23,7 @@ use Utopia\System\System; use Utopia\Validator\Boolean; use Utopia\Validator\Text; use Utopia\VCS\Adapter\Git\GitHub; +use Utopia\Database\Validator\Authorization; class Create extends Base { @@ -76,6 +77,7 @@ class Create extends Base ->inject('queueForEvents') ->inject('queueForBuilds') ->inject('gitHub') + ->inject('authorization') ->callback($this->action(...)); } @@ -93,7 +95,8 @@ class Create extends Base Document $project, Event $queueForEvents, Build $queueForBuilds, - GitHub $github + GitHub $github, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -175,7 +178,7 @@ class Create extends Base // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); - $dbForPlatform->getAuthorization()->skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), 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 d89014f7d8..382039f85d 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -12,6 +12,7 @@ use Appwrite\Utopia\Response; 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\Action; use Utopia\Platform\Scope\HTTP; @@ -59,6 +60,7 @@ class Update extends Base ->inject('dbForProject') ->inject('queueForEvents') ->inject('dbForPlatform') + ->inject('authorization') ->callback($this->action(...)); } @@ -69,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); @@ -103,12 +106,12 @@ class Update extends Base Query::equal('projectInternalId', [$project->getSequence()]) ]; - $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { + $authorization->skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getSequence()); - $dbForPlatform->getAuthorization()->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 ca1ef5d9f3..5c274d6a20 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php @@ -12,6 +12,7 @@ use Utopia\Config\Config; 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\Action; use Utopia\Platform\Scope\HTTP; @@ -54,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(...)); } @@ -61,7 +63,8 @@ class Get extends Base string $siteId, string $range, Response $response, - Database $dbForProject + Database $dbForProject, + Authorization $authorization ) { $site = $dbForProject->getDocument('sites', $siteId); @@ -90,7 +93,7 @@ class Get extends Base ]; - $dbForProject->getAuthorization()->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 f29ca2bec3..a90cb0cab9 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php @@ -11,6 +11,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\WhiteList; @@ -51,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 = []; @@ -77,7 +79,7 @@ class XList extends Base METRIC_SITES_OUTBOUND, ]; - $dbForProject->getAuthorization()->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/Create.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php index e0f51308d4..0a5a3da15b 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 @@ -13,6 +13,7 @@ use Appwrite\Utopia\Response; 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; @@ -65,10 +66,11 @@ 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 { /** @@ -78,10 +80,10 @@ class Create extends Action ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $bucketId, $fileId); $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $bucketPermission = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); + $bucketPermission = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); if ($fileSecurity) { - $filePermission = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_UPDATE, $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/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index 4bab864653..1fd7525937 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -9,6 +9,7 @@ use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Exception; +use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Registry\Registry; use Utopia\Validator\Text; @@ -30,6 +31,7 @@ class Migrate extends Action ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('register') + ->inject('authorization') ->callback($this->action(...)); } @@ -46,8 +48,9 @@ class Migrate extends Action Database $dbForPlatform, callable $getProjectDB, Registry $register, + Authorization $authorization ): void { - $dbForPlatform->getAuthorization()->disable(); + $authorization->disable(); if (!\array_key_exists($version, Migration::$versions)) { Console::error("No migration found for version $version."); diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php index 345c855920..b7da5d227d 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; /** @@ -44,10 +45,11 @@ class StatsResources extends Action ->inject('dbForPlatform') ->inject('logError') ->inject('queueForStatsResources') + ->inject('authorization') ->callback($this->action(...)); } - public function action(Database $dbForPlatform, callable $logError, EventStatsResources $queue): void + public function action(Database $dbForPlatform, callable $logError, EventStatsResources $queue, Authorization $authorization): void { $this->logError = $logError; $this->dbForPlatform = $dbForPlatform; @@ -60,9 +62,9 @@ class StatsResources extends Action $interval = (int) System::getEnv('_APP_STATS_RESOURCES_INTERVAL', '3600'); - Console::loop(function () use ($queue, $dbForPlatform) { - $dbForPlatform->getAuthorization()->disable(); - $dbForPlatform->getAuthorization()->setDefaultStatus(false); + Console::loop(function () use ($queue, $dbForPlatform, $authorization) { + $authorization->disable(); + $authorization->setDefaultStatus(false); $last24Hours = (new \DateTime())->sub(\DateInterval::createFromDateString('24 hours')); /** From 68b0fe8c70ecaee27ffc6a076db31021b93ea1a6 Mon Sep 17 00:00:00 2001 From: shimon Date: Wed, 29 Oct 2025 20:33:36 +0200 Subject: [PATCH 28/77] linter --- app/cli.php | 2 +- app/worker.php | 18 +++++++++++------- .../Functions/Http/Variables/Create.php | 2 +- .../Functions/Http/Variables/Delete.php | 4 ++-- .../Functions/Http/Variables/Update.php | 2 +- .../Modules/Sites/Http/Deployments/Create.php | 2 +- .../Sites/Http/Deployments/Template/Create.php | 2 +- 7 files changed, 18 insertions(+), 14 deletions(-) diff --git a/app/cli.php b/app/cli.php index 4186aff6b7..0900926346 100644 --- a/app/cli.php +++ b/app/cli.php @@ -185,9 +185,9 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorizatio $adapter = new DatabasePool($pools->get('logs')); $database = new Database($adapter, $cache); - $database->setAuthorization($authorization); $database + ->setAuthorization($authorization) ->setSharedTables(true) ->setNamespace('logsV1') ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_TASK) diff --git a/app/worker.php b/app/worker.php index c54d9183b4..319be088d5 100644 --- a/app/worker.php +++ b/app/worker.php @@ -59,8 +59,10 @@ 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); - $dbForPlatform->setNamespace('_console'); + + $dbForPlatform + ->setAuthorization($authorization) + ->setNamespace('_console'); return $dbForPlatform; @@ -93,7 +95,7 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, $adapter = new DatabasePool($pools->get($dsn->getHost())); $database = new Database($adapter, $cache); - $database->setAuthorization($authorization); + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); if (\in_array($dsn->getHost(), $sharedTables)) { @@ -108,7 +110,9 @@ 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', 'authorization']); @@ -149,9 +153,7 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf } $adapter = new DatabasePool($pools->get($dsn->getHost())); - $adapter->setAuthorization($authorization); $database = new Database($adapter, $cache); - $database->setAuthorization($authorization); $databases[$dsn->getHost()] = $database; @@ -169,7 +171,9 @@ 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; }; diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php index c61a610617..ae74bfa98a 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php @@ -15,12 +15,12 @@ use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Boolean; use Utopia\Validator\Text; -use Utopia\Database\Validator\Authorization; class Create extends Base { diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php index 0ab315b212..dcb80e4c8c 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php @@ -11,10 +11,10 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\DateTime; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; -use Utopia\Database\Validator\Authorization; class Delete extends Base { @@ -94,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 e581c3e887..7a97a53650 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php @@ -11,12 +11,12 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Exception\Duplicate as DuplicateException; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Boolean; use Utopia\Validator\Text; -use Utopia\Database\Validator\Authorization; class Update extends Base { diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index b590f7c1d3..ff20d27334 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/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; @@ -29,7 +30,6 @@ use Utopia\Swoole\Request; use Utopia\System\System; use Utopia\Validator\Boolean; use Utopia\Validator\Text; -use Utopia\Database\Validator\Authorization; class Create extends Action { 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 7909b5ca3e..377b3321ae 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/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; @@ -23,7 +24,6 @@ use Utopia\System\System; use Utopia\Validator\Boolean; use Utopia\Validator\Text; use Utopia\VCS\Adapter\Git\GitHub; -use Utopia\Database\Validator\Authorization; class Create extends Base { From 0904881de851a5ef3de68b825ea862f2128ed4bf Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 2 Nov 2025 18:11:56 +0200 Subject: [PATCH 29/77] Refactor authorization handling to ensure consistent usage of the Authorization class across various modules, enhancing code maintainability and clarity. Update method signatures to include authorization as a parameter where necessary. --- app/config/storage/resource_limits.php | 4 +- app/controllers/api/messaging.php | 8 +-- app/controllers/api/storage.php | 2 +- app/controllers/api/teams.php | 2 +- app/init/resources.php | 58 +++++++++---------- app/worker.php | 4 +- composer.lock | 24 ++++---- src/Appwrite/Migration/Migration.php | 6 +- .../Platform/Modules/Compute/Base.php | 9 +-- .../Modules/Console/Http/Resources/Get.php | 2 +- .../Collections/Attributes/Action.php | 11 ++-- .../Collections/Attributes/Boolean/Create.php | 6 +- .../Attributes/Datetime/Create.php | 7 ++- .../Collections/Attributes/Email/Create.php | 4 +- .../Collections/Attributes/Enum/Create.php | 7 ++- .../Collections/Attributes/Float/Create.php | 6 +- .../Collections/Attributes/IP/Create.php | 7 ++- .../Collections/Attributes/Integer/Create.php | 6 +- .../Collections/Attributes/Line/Create.php | 6 +- .../Collections/Attributes/Point/Create.php | 6 +- .../Collections/Attributes/Polygon/Create.php | 6 +- .../Attributes/Relationship/Create.php | 4 +- .../Collections/Attributes/String/Create.php | 8 ++- .../Collections/Attributes/URL/Create.php | 7 ++- .../Collections/Attributes/XList.php | 2 +- .../Collections/Documents/Action.php | 6 +- .../Collections/Documents/Create.php | 31 +++++----- .../Collections/Documents/Delete.php | 1 + .../Databases/Collections/Documents/Get.php | 1 + .../Collections/Documents/Update.php | 3 +- .../Collections/Documents/Upsert.php | 3 +- .../Databases/Collections/Documents/XList.php | 5 +- .../Databases/Collections/Indexes/XList.php | 2 +- .../Http/Databases/Collections/Logs/XList.php | 34 +++++------ .../Http/Databases/Collections/XList.php | 2 +- .../Http/Databases/Transactions/Update.php | 2 +- .../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 | 1 + .../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 + .../Modules/Functions/Workers/Builds.php | 16 +++-- .../Http/Deployments/Template/Create.php | 1 + .../Sites/Http/Deployments/Vcs/Create.php | 6 +- .../Sites/Http/Sites/Deployment/Update.php | 2 +- .../Http/Tokens/Buckets/Files/Action.php | 15 ++--- .../Http/Tokens/Buckets/Files/Create.php | 2 +- .../Http/Tokens/Buckets/Files/XList.php | 6 +- src/Appwrite/Platform/Tasks/Migrate.php | 9 ++- src/Appwrite/Platform/Tasks/ScheduleBase.php | 2 +- .../Platform/Tasks/StatsResources.php | 7 +-- src/Appwrite/Platform/Workers/Deletes.php | 6 +- src/Appwrite/Platform/Workers/Functions.php | 2 - src/Appwrite/Platform/Workers/Migrations.php | 4 -- src/Appwrite/Utopia/Request/Filter.php | 2 +- src/Appwrite/Utopia/Request/Filters/V20.php | 4 +- 108 files changed, 268 insertions(+), 175 deletions(-) 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/messaging.php b/app/controllers/api/messaging.php index ddd00a1b91..460b341f3c 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -1072,7 +1072,7 @@ App::get('/v1/messaging/providers') ->inject('dbForProject') ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, Database $dbForProject, Authorization $authorization, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -2480,7 +2480,7 @@ App::get('/v1/messaging/topics') ->inject('dbForProject') ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, Database $dbForProject, Authorization $authorization, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -2882,7 +2882,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') ->inject('dbForProject') ->inject('authorization') ->inject('response') - ->action(function (string $topicId, array $queries, string $search, Database $dbForProject, Authorization $authorization, 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) { @@ -3705,7 +3705,7 @@ App::get('/v1/messaging/messages') ->inject('dbForProject') ->inject('authorization') ->inject('response') - ->action(function (array $queries, string $search, Database $dbForProject, Authorization $authorization, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Authorization $authorization, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 67c78a68d5..9a211ba290 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -790,7 +790,7 @@ App::get('/v1/storage/buckets/:bucketId/files') ->inject('dbForProject') ->inject('authorization') ->inject('mode') - ->action(function (string $bucketId, array $queries, string $search, Response $response, Database $dbForProject, Authorization $authorization, string $mode) { + ->action(function (string $bucketId, array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject, Authorization $authorization, string $mode) { $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); $isAPIKey = Auth::isAppUser($authorization->getRoles()); diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 4fd56b3e59..563c6009aa 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -847,7 +847,7 @@ App::get('/v1/teams/:teamId/memberships') ->inject('project') ->inject('dbForProject') ->inject('authorization') - ->action(function (string $teamId, array $queries, string $search, Response $response, Document $project, Database $dbForProject, Authorization $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()) { diff --git a/app/init/resources.php b/app/init/resources.php index d00cd5a6fa..7d33377f7e 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -152,7 +152,7 @@ App::setResource('queueForMigrations', function (Publisher $publisher) { App::setResource('queueForStatsResources', function (Publisher $publisher) { return new StatsResources($publisher); }, ['publisher']); -App::setResource('platforms', function (Request $request, Document $console, Document $project, Database $dbForPlatform) { +App::setResource('platforms', function (Request $request, Document $console, Document $project, Database $dbForPlatform, Authorization $authorization) { $console->setAttribute('platforms', [ // Always allow current host '$collection' => ID::custom('platforms'), 'name' => 'Current Host', @@ -200,9 +200,9 @@ App::setResource('platforms', function (Request $request, Document $console, Doc // Safe if rule with same project ID exists if (!empty($origin)) { if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { - $rule = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('rules', md5($origin ?? ''))); + $rule = $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($origin ?? ''))); } else { - $rule = $dbForPlatform->getAuthorization()->skip( + $rule = $authorization->skip( fn () => $dbForPlatform->find('rules', [ Query::equal('domain', [$origin]), Query::limit(1) @@ -224,9 +224,9 @@ App::setResource('platforms', function (Request $request, Document $console, Doc ...$console->getAttribute('platforms', []), ...$project->getAttribute('platforms', []), ]; -}, ['request', 'console', 'project', 'dbForPlatform']); +}, ['request', 'console', 'project', 'dbForPlatform', 'authorization']); -App::setResource('user', function ($mode, $project, $console, $request, $response, $dbForProject, $dbForPlatform) { +App::setResource('user', function ($mode, $project, $console, $request, $response, $dbForProject, $dbForPlatform, $authorization) { /** @var Appwrite\Utopia\Request $request */ /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Document $project */ @@ -235,7 +235,7 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons /** @var Utopia\Database\Authorization $authorization */ /** @var string $mode */ - $dbForPlatform->getAuthorization()->setDefaultStatus(true); + $authorization->setDefaultStatus(true); Auth::setCookieName('a_session_' . $project->getId()); @@ -299,7 +299,7 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons // 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([]); // } @@ -337,9 +337,9 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons $dbForPlatform->setMetadata('user', $user->getId()); return $user; -}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform']); +}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', '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 */ @@ -350,10 +350,10 @@ App::setResource('project', function ($dbForPlatform, $request, $console) { return $console; } - $project = $dbForPlatform->getAuthorization()->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 (Document $user) { if ($user->isEmpty()) { @@ -713,7 +713,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'] ?? []); @@ -723,8 +723,8 @@ App::setResource('schema', function ($utopia, $dbForProject) { return $complexity * $limit; }; - $attributes = function (int $limit, int $offset) use ($dbForProject) { - $attrs = $dbForProject->getAuthorization()->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), ])); @@ -798,7 +798,7 @@ App::setResource('schema', function ($utopia, $dbForProject) { $urls, $params, ); -}, ['utopia', 'dbForProject']); +}, ['utopia', 'dbForProject', 'authorization']); App::setResource('contributors', function () { $path = 'app/config/contributors.json'; @@ -844,7 +844,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 @@ -863,7 +863,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()); - $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('devKeys', $key->getId(), $key)); $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } @@ -880,14 +880,14 @@ App::setResource('devKey', function (Request $request, Document $project, array /** Update access time as well */ $key->setAttribute('accessedAt', DatabaseDateTime::now()); - $key = $dbForPlatform->getAuthorization()->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', ''); @@ -897,7 +897,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 = $dbForPlatform->getAuthorization()->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', ''); @@ -906,7 +906,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A return new Document([]); } - $team = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('teams', $teamId)); + $team = $authorization->skip(fn () => $dbForPlatform->getDocument('teams', $teamId)); return $team; } } @@ -915,14 +915,14 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A return new Document([]); } - $team = $dbForPlatform->getAuthorization()->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', @@ -960,7 +960,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 @@ -977,7 +977,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { return new Document([]); } - $token = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId)); + $token = $authorization->skip(fn () => $dbForProject->getDocument('resourceTokens', $tokenId)); if ($token->isEmpty()) { return new Document([]); @@ -995,7 +995,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')); @@ -1006,7 +1006,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()); - $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token)); + $authorization->skip(fn () => $dbForProject->updateDocument('resourceTokens', $token->getId(), $token)); } return new Document([ @@ -1021,7 +1021,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { }; } return new Document([]); -}, ['project', 'dbForProject', 'request']); +}, ['project', 'dbForProject', 'request', 'authorization']); App::setResource('httpReferrer', function (Request $request): string { $referrer = $request->getReferer(); diff --git a/app/worker.php b/app/worker.php index 319be088d5..ef04ffec05 100644 --- a/app/worker.php +++ b/app/worker.php @@ -61,8 +61,8 @@ Server::setResource('dbForPlatform', function (Cache $cache, Registry $register, $dbForPlatform = new Database($adapter, $cache); $dbForPlatform - ->setAuthorization($authorization) - ->setNamespace('_console'); + ->setAuthorization($authorization) + ->setNamespace('_console'); return $dbForPlatform; diff --git a/composer.lock b/composer.lock index 93a4d68546..b67055890f 100644 --- a/composer.lock +++ b/composer.lock @@ -5253,16 +5253,16 @@ }, { "name": "webmozart/assert", - "version": "1.12.0", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "541057574806f942c94662b817a50f63f7345360" + "reference": "9be6926d8b485f55b9229203f962b51ed377ba68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/541057574806f942c94662b817a50f63f7345360", - "reference": "541057574806f942c94662b817a50f63f7345360", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/9be6926d8b485f55b9229203f962b51ed377ba68", + "reference": "9be6926d8b485f55b9229203f962b51ed377ba68", "shasum": "" }, "require": { @@ -5305,9 +5305,9 @@ ], "support": { "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.12.0" + "source": "https://github.com/webmozarts/assert/tree/1.12.1" }, - "time": "2025-10-20T12:43:39+00:00" + "time": "2025-10-29T15:56:20+00:00" }, { "name": "webonyx/graphql-php", @@ -5378,16 +5378,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.4.15", + "version": "1.4.16", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "b4a2fd9e92903c2e156f17fc5dafe102e6cfdfda" + "reference": "08f839443f678208eb56a6c5a7456dd632adfc9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/b4a2fd9e92903c2e156f17fc5dafe102e6cfdfda", - "reference": "b4a2fd9e92903c2e156f17fc5dafe102e6cfdfda", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/08f839443f678208eb56a6c5a7456dd632adfc9a", + "reference": "08f839443f678208eb56a6c5a7456dd632adfc9a", "shasum": "" }, "require": { @@ -5423,9 +5423,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/1.4.15" + "source": "https://github.com/appwrite/sdk-generator/tree/1.4.16" }, - "time": "2025-10-28T04:52:59+00:00" + "time": "2025-10-29T08:39:55+00:00" }, { "name": "doctrine/annotations", diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 27387b8867..4d2db6a3dc 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -13,6 +13,7 @@ use Utopia\Database\Exception\Limit; use Utopia\Database\Exception\Structure; use Utopia\Database\Helpers\ID; use Utopia\Database\PDO; +use Utopia\Database\Validator\Authorization; abstract class Migration { @@ -125,6 +126,7 @@ abstract class Migration Document $project, Database $dbForProject, Database $dbForPlatform, + Authorization $authorization, ?callable $getProjectDB = null ): self { $this->project = $project; @@ -132,8 +134,8 @@ abstract class Migration $this->dbForPlatform = $dbForPlatform; $this->getProjectDB = $getProjectDB; - $this->dbForPlatform->getAuthorization()->disable(); - $this->dbForPlatform->getAuthorization()->setDefaultStatus(false); + $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 eb6dd6d75d..70014b2728 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\Validator\Authorization; use Utopia\Swoole\Request; use Utopia\System\System; use Utopia\VCS\Adapter\Git\GitHub; @@ -141,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, 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', ''); @@ -237,7 +238,7 @@ class Base extends Action // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); - $dbForProject->getAuthorization()->skip( + $authorization->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -263,7 +264,7 @@ class Base extends Action $domain = "commit-" . substr($commitDetails['commitHash'], 0, 16) . ".{$sitesDomain}"; $ruleId = md5($domain); try { - $dbForProject->getAuthorization()->skip( + $authorization()->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -300,7 +301,7 @@ class Base extends Action $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { - $dbForProject->getAuthorization()->skip( + $authorization()->skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php index 55a60a5cbf..a0f8e9421e 100644 --- a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -126,7 +126,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 5b41c42200..6c5305f299 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 @@ -17,6 +17,7 @@ use Utopia\Database\Exception\Relationship as RelationshipException; use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Exception\Truncate as TruncateException; use Utopia\Database\Helpers\ID; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Structure; use Utopia\Platform\Action as UtopiaAction; use Utopia\Swoole\Response as SwooleResponse; @@ -291,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', ''); @@ -309,7 +310,7 @@ abstract class Action extends UtopiaAction throw new Exception($this->getSpatialTypeNotSupportedException()); } - $db = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $db = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); @@ -370,7 +371,7 @@ abstract class Action extends UtopiaAction \in_array($attribute->getAttribute('type'), Database::SPATIAL_TYPES) && $attribute->getAttribute('required') ) { - $hasData = !$dbForProject->getAuthorization()->skip(fn () => $dbForProject + $hasData = !$authorization->skip(fn () => $dbForProject ->findOne('database_' . $db->getSequence() . '_collection_' . $collection->getSequence())) ->isEmpty(); @@ -471,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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $db = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($db->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); 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 6c8e5dcf3d..b22b6318c1 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; @@ -68,10 +69,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, @@ -80,7 +82,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/Datetime/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Create.php index 1f2098e7af..5e5dc25c57 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; @@ -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, ?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, @@ -89,7 +91,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/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Create.php index cbfd66e4d9..e848dec37c 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; @@ -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, ?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, 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 98ed83861d..fb7216b241 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; @@ -72,10 +73,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'); @@ -97,7 +99,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $response 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 83deb92edc..b5085b804e 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; @@ -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, ?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; @@ -99,7 +101,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/IP/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Create.php index 6e6264466c..99f683521c 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; @@ -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, ?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, @@ -89,7 +91,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $response 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 090d63c403..8fe7ccfde7 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; @@ -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, ?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; @@ -101,7 +103,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/Line/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Create.php index f691fc29cf..7a92b3e13d 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/Point/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Create.php index aae715ba1e..9aff7cba34 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/Polygon/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Create.php index 6fbbd46d2c..bc3dd75ace 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/Relationship/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Create.php index 411fd3bf5b..8a11019168 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 @@ -91,7 +91,7 @@ class Create extends Action $key ??= $relatedCollectionId; $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); } @@ -150,7 +150,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/String/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Create.php index 1527c4d1d9..564a72269a 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; @@ -76,6 +77,7 @@ class Create extends Action ->inject('queueForDatabase') ->inject('queueForEvents') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -92,7 +94,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() . '.'); @@ -131,7 +134,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/URL/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Create.php index ce0175966b..15295a0850 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; @@ -69,6 +70,7 @@ class Create extends Action ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } @@ -82,7 +84,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, @@ -92,7 +95,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/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index 798e6a3771..be61b260b3 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 @@ -68,7 +68,7 @@ class XList extends Action ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): 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)); if ($database->isEmpty()) { 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 d42dca57fa..7c5428931d 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,10 +258,9 @@ abstract class Action extends AppwriteAction Document $collection, Document $document, Database $dbForProject, - Authorization $authorization, - /* options */ array &$collectionsCache, + Authorization $authorization, ?int &$operations = null, ): bool { @@ -324,7 +323,8 @@ abstract class Action extends AppwriteAction document: $relation, dbForProject: $dbForProject, collectionsCache: $collectionsCache, - operations: $operations + operations: $operations, + authorization: $authorization ); } } 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 d7ec69777d..d6d56b66fc 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 @@ -179,19 +179,19 @@ class Create extends Action $documents = [$data]; } - $isAPIKey = Auth::isAppUser($authorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($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); } - $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()); } @@ -205,7 +205,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) { + $setPermissions = function (Document $document, ?array $permissions) use ($user, $isAPIKey, $isPrivilegedUser, $isBulk, $dbForProject, $authorization) { $allowedPermissions = [ Database::PERMISSION_READ, Database::PERMISSION_UPDATE, @@ -248,8 +248,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->hasRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $authorization->getRoles()) . ')'); } } } @@ -260,25 +260,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); - $validCollection = $authorization()->isValid( + $validCollection = $authorization->isValid( new Input($permission, $collection->getPermissionsByType($permission)) ); if (($permission === Database::PERMISSION_UPDATE && !$documentSecurity) || !$validCollection) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } if ($permission === Database::PERMISSION_UPDATE) { - $validDocument = $authorization()->isValid( + $validDocument = $authorization->isValid( new Input($permission, $document->getUpdate()) ); $valid = $validCollection || $validDocument; if ($documentSecurity && !$valid) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization()->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); } } @@ -303,7 +303,7 @@ class Create extends Action } $relatedCollectionId = $relationship->getAttribute('relatedCollection'); - $relatedCollection = $authorization()->skip( + $relatedCollection = $authorization->skip( fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); @@ -319,7 +319,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()) ); @@ -374,7 +374,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); @@ -471,6 +471,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 fe754b6a68..cc98255dff 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 @@ -204,6 +204,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 5dcef98b90..7fd00b4ad1 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 @@ -125,6 +125,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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index 128f57708f..3dbc86682e 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 @@ -167,7 +167,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( @@ -334,6 +334,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 139ff7c466..9fac2af060 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 @@ -177,7 +177,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( @@ -355,6 +355,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 e10e6abfd9..5c01b1e215 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 @@ -77,7 +77,7 @@ class XList extends Action ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState, Authorization $authorization): 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 = Auth::isAppUser($authorization->getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); @@ -161,7 +161,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/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index 268ae4fc09..d6e59dc4fa 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 @@ -70,7 +70,7 @@ class XList extends Action ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): 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)); 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 928ba55ee0..f193c15299 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 @@ -116,9 +116,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'], @@ -126,20 +126,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/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index a45c4c539a..11b60e35a7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -71,7 +71,7 @@ class XList extends Action ->callback($this->action(...)); } - public function action(string $databaseId, array $queries, string $search, UtopiaResponse $response, Database $dbForProject, Authorization $authorization): 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)); 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 24e149800d..4f488445f0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php @@ -138,7 +138,7 @@ class Update extends Action $databaseOperations = []; try { - $dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, $queueForEvents, $queueForStatsUsage, $queueForRealtime, $queueForFunctions, $queueForWebhooks) { + $dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, $queueForEvents, $queueForStatsUsage, $queueForRealtime, $queueForFunctions, $queueForWebhooks, $authorization) { $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'committing', ]))); 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 039964b2c6..687898b83a 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 @@ -59,6 +59,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 7df901a1cc..bc6ceabb72 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 db5a3059f1..7f5a5ae4f5 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 @@ -61,6 +61,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 151422af75..fbcec4cd0b 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 26f4ffa898..62152453fe 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 3a8d492e4e..65ab2cb573 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 @@ -60,6 +60,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 4d32489357..2a6d0f56b8 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 68dc2f8e08..a66834b438 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 @@ -63,6 +63,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 3b611a5fde..07c78070f6 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 9fe6987cab..e62dec9477 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 @@ -62,6 +62,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 023e2e834e..360b680f0f 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 c20ef58a39..0e7e079a02 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 81ca8da81f..180777c550 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 @@ -60,6 +60,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 0db95b0206..645b54bdd9 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 dfca51a6c5..a5fd5b0b06 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 @@ -62,6 +62,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 a1568d069b..24192b3efb 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 4aa173707b..469fb6851f 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 d3823445a2..a485453ba5 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 b8ae563def..715348e1f4 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 3c855e137c..3df8e0aee7 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 e0a2cf32cd..38c9eaf284 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 866bbaf8b0..905f165de6 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 0a6c76d8c5..b76b03d86b 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 @@ -72,6 +72,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 b645454be1..8eea93d286 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 @@ -64,6 +64,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 6fe9fd679c..5ecb781f83 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 @@ -65,6 +65,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 5ec9b78dda..60b9ba85ce 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 99ec36b721..1b0f30418e 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 @@ -60,6 +60,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 51168b0383..8528e8fb05 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 1e0b641b32..950d38f8a7 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 4f62200d7c..d71295170f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php @@ -62,6 +62,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 de068d5b29..79b9e7beef 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 be6ec5d9e7..e264ec0411 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 3802ee32b8..2d14785bb8 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,7 @@ 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 57ab466ee8..cb552a086c 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 271d842631..3c01f1b64d 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 0ea52eaf1b..a6206f06dd 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 0680649544..f9111287c3 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') ->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 86e9a48f63..902034441e 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 @@ -65,6 +65,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 5005ab4f41..3ab636139e 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 @@ -67,6 +67,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 d0a1f08003..6dc575fe04 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 @@ -67,6 +67,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 d42cf5e9eb..605db6d024 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 @@ -66,6 +66,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 c58e16c8e3..d86cb373a6 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 @@ -66,6 +66,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 bfc832f2b5..927ea517cf 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 @@ -110,6 +110,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 687b1c8c11..ef5303776d 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 @@ -69,6 +69,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 f8b70516b6..16cb5c5557 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 @@ -57,6 +57,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 5f1efa2953..5117e77ea9 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') ->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 cb1d5888cf..87c0831356 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 @@ -68,6 +68,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 0bc373cc93..bf8403d930 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 @@ -71,6 +71,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 b96e84b722..d8eb08ae17 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 @@ -58,6 +58,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 8424b37a6d..c80bf914f3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Update.php @@ -61,6 +61,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 5e8fcfc3c8..eafb291037 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 bc79b86ca3..1c6f0f95ca 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 5a98f22f37..2e3b73e395 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 4d55af93a4..250c9e0bc4 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/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index c2b5f0262f..93bac56fa4 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; @@ -919,11 +918,11 @@ class Builds extends Action ->trigger(); try { - $rule = $dbForPlatform->getAuthorization()->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"); @@ -933,7 +932,7 @@ class Builds extends Action $client->setTimeout(\intval($resource->getAttribute('timeout', '15'))); $client->addHeader('content-type', FetchClient::CONTENT_TYPE_APPLICATION_JSON); - $bucket = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); + $bucket = $dbForPlatform->getDocument('buckets', 'screenshots'); $configs = [ 'screenshotLight' => [ @@ -1055,7 +1054,7 @@ class Builds extends Action 'metadata' => ['content_type' => $mimeType], ]); - $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->createDocument('bucket_' . $bucket->getSequence(), $file)); + $dbForPlatform->createDocument('bucket_' . $bucket->getSequence(), $file); $deployment->setAttribute($key, $fileId); } @@ -1278,7 +1277,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->getAuthorization()->skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule); } Console::info('Deployment action finished'); @@ -1485,7 +1484,6 @@ class Builds extends Action * @return void * @throws Structure * @throws \Utopia\Database\Exception - * @throws Authorization * @throws Conflict * @throws Restricted */ @@ -1573,11 +1571,11 @@ class Builds extends Action default => throw new \Exception('Invalid resource type') }; - $rule = $dbForPlatform->getAuthorization()->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/Template/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php index 377b3321ae..e849ee92aa 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php @@ -125,6 +125,7 @@ class Create extends Base template: $template, github: $github, activate: $activate, + authorization: $authorization, ); $queueForEvents 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 ddad5d793a..09dc4a1618 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 382039f85d..e3cab865a9 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -106,7 +106,7 @@ 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()); 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 709a12a957..2c57c57611 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 @@ -7,29 +7,30 @@ use Appwrite\Extend\Exception; use Utopia\Database\Database; use Utopia\Database\Validator\Authorization\Input; use Utopia\Platform\Action as UtopiaAction; +use Utopia\Database\Validator\Authorization; 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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($dbForProject->getAuthorization()->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - if (!$dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead()))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $dbForProject->getAuthorization()->getDescription()); + 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 = $dbForProject->getAuthorization()->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 0a5a3da15b..b632bbad77 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 @@ -77,7 +77,7 @@ class Create extends Action * @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); $bucketPermission = $authorization->isValid(new Input(Database::PERMISSION_UPDATE, $bucket->getUpdate())); 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..78cef8251f 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 @@ -16,6 +16,7 @@ use Utopia\Database\Query; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Boolean; +use Utopia\Database\Validator\Authorization; class XList extends Action { @@ -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 1fd7525937..cc6981fa1b 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -31,7 +31,7 @@ class Migrate extends Action ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('register') - ->inject('authorization') + ->inject('authorisation') ->callback($this->action(...)); } @@ -50,7 +50,6 @@ class Migrate extends Action Registry $register, Authorization $authorization ): void { - $authorization->disable(); if (!\array_key_exists($version, Migration::$versions)) { Console::error("No migration found for version $version."); @@ -68,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) { @@ -90,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 4e8a5beb76..33a01346a8 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -61,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->getAuthorization()->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 b7da5d227d..87d4858351 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; /** @@ -49,7 +48,7 @@ class StatsResources extends Action ->callback($this->action(...)); } - public function action(Database $dbForPlatform, callable $logError, EventStatsResources $queue, Authorization $authorization): void + public function action(Database $dbForPlatform, callable $logError, EventStatsResources $queue): void { $this->logError = $logError; $this->dbForPlatform = $dbForPlatform; @@ -62,9 +61,7 @@ class StatsResources extends Action $interval = (int) System::getEnv('_APP_STATS_RESOURCES_INTERVAL', '3600'); - Console::loop(function () use ($queue, $dbForPlatform, $authorization) { - $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 ee0587fad4..60e615efc1 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -19,7 +19,6 @@ 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; @@ -197,7 +196,6 @@ class Deletes extends Action * @param string $datetime * @param Document|null $document * @return void - * @throws Authorization * @throws Conflict * @throws Restricted * @throws Structure @@ -953,14 +951,14 @@ class Deletes extends Action } Console::info("Deleting screenshots for deployment " . $deployment->getId()); - $bucket = $dbForPlatform->getAuthorization()->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 = $dbForPlatform->getAuthorization()->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 df1833ad33..8ed95ac2fc 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; @@ -326,7 +325,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 fe06f9c366..1d6e57fe94 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -11,7 +11,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\Restricted; use Utopia\Database\Exception\Structure; @@ -223,7 +222,6 @@ class Migrations extends Action } /** - * @throws Authorization * @throws Structure * @throws Conflict * @throws \Utopia\Database\Exception @@ -282,7 +280,6 @@ class Migrations extends Action } /** - * @throws Authorization * @throws Conflict * @throws Restricted * @throws Structure @@ -421,7 +418,6 @@ class Migrations extends Action * @param Document $migration * @param Mail $queueForMails * @return void - * @throws Authorization * @throws Structure * @throws \Utopia\Database\Exception * @throws Exception 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 df369a0b9a..e130178083 100644 --- a/src/Appwrite/Utopia/Request/Filters/V20.php +++ b/src/Appwrite/Utopia/Request/Filters/V20.php @@ -149,10 +149,10 @@ class V20 extends Filter } try { - $collection = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument( + $collection = $dbForProject->getDocument( 'database_' . $database->getSequence(), $collectionId - )); + ); if ($collection->isEmpty()) { return []; } From 9b82dd04117963311fff5393cf72b32427c074c1 Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 2 Nov 2025 18:14:31 +0200 Subject: [PATCH 30/77] Update composer.lock to reflect version upgrades for utopia-php/detector (0.2.1 to 0.2.2) and appwrite/sdk-generator (1.4.16 to 1.5.0), including updated references and source URLs. --- composer.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/composer.lock b/composer.lock index b67055890f..8e139e31b2 100644 --- a/composer.lock +++ b/composer.lock @@ -3898,16 +3898,16 @@ }, { "name": "utopia-php/detector", - "version": "0.2.1", + "version": "0.2.2", "source": { "type": "git", "url": "https://github.com/utopia-php/detector.git", - "reference": "89f96e864220de13800cf398a1f1686a85401eaa" + "reference": "9a41be5f21efe2d865de79b08dff94fff85ce5e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/detector/zipball/89f96e864220de13800cf398a1f1686a85401eaa", - "reference": "89f96e864220de13800cf398a1f1686a85401eaa", + "url": "https://api.github.com/repos/utopia-php/detector/zipball/9a41be5f21efe2d865de79b08dff94fff85ce5e9", + "reference": "9a41be5f21efe2d865de79b08dff94fff85ce5e9", "shasum": "" }, "require": { @@ -3937,9 +3937,9 @@ ], "support": { "issues": "https://github.com/utopia-php/detector/issues", - "source": "https://github.com/utopia-php/detector/tree/0.2.1" + "source": "https://github.com/utopia-php/detector/tree/0.2.2" }, - "time": "2025-10-27T13:38:33+00:00" + "time": "2025-10-31T12:43:31+00:00" }, { "name": "utopia-php/dns", @@ -5378,16 +5378,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.4.16", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "08f839443f678208eb56a6c5a7456dd632adfc9a" + "reference": "42df22195d6457e52e4c819678168470b114a816" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/08f839443f678208eb56a6c5a7456dd632adfc9a", - "reference": "08f839443f678208eb56a6c5a7456dd632adfc9a", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/42df22195d6457e52e4c819678168470b114a816", + "reference": "42df22195d6457e52e4c819678168470b114a816", "shasum": "" }, "require": { @@ -5423,9 +5423,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/1.4.16" + "source": "https://github.com/appwrite/sdk-generator/tree/1.5.0" }, - "time": "2025-10-29T08:39:55+00:00" + "time": "2025-10-31T10:10:25+00:00" }, { "name": "doctrine/annotations", From d96c7eb3e9f61fcbf4041d1ea5076d29f0168eaf Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 2 Nov 2025 18:58:41 +0200 Subject: [PATCH 31/77] Enhance TransactionState to utilize Authorization class for improved transaction management. Updated method signatures and resource initialization to include authorization, ensuring consistent handling across the application. --- app/init/resources.php | 6 +++--- src/Appwrite/Databases/TransactionState.php | 11 +++++++---- .../Http/Databases/Collections/Attributes/Action.php | 4 ++-- .../Collections/Attributes/Boolean/Update.php | 5 ++++- .../Collections/Attributes/Datetime/Update.php | 5 ++++- .../Databases/Collections/Attributes/Email/Update.php | 5 ++++- .../Databases/Collections/Attributes/Enum/Update.php | 5 ++++- .../Databases/Collections/Attributes/Float/Update.php | 5 ++++- .../Databases/Collections/Attributes/IP/Update.php | 5 ++++- .../Collections/Attributes/Integer/Update.php | 5 ++++- .../Databases/Collections/Attributes/Line/Update.php | 5 ++++- .../Databases/Collections/Attributes/Point/Update.php | 5 ++++- .../Collections/Attributes/Polygon/Update.php | 5 ++++- .../Collections/Attributes/Relationship/Update.php | 6 +++++- .../Collections/Attributes/String/Update.php | 6 +++++- .../Databases/Collections/Attributes/URL/Update.php | 6 +++++- 16 files changed, 67 insertions(+), 22 deletions(-) diff --git a/app/init/resources.php b/app/init/resources.php index 7d33377f7e..db2cc093f0 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -1054,6 +1054,6 @@ App::setResource('httpReferrerSafe', function (Request $request, string $httpRef return $referrer; }, ['request', 'httpReferrer', 'platforms', 'dbForPlatform', 'project', 'utopia']); -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/src/Appwrite/Databases/TransactionState.php b/src/Appwrite/Databases/TransactionState.php index 44ba62c4a4..8e098774e6 100644 --- a/src/Appwrite/Databases/TransactionState.php +++ b/src/Appwrite/Databases/TransactionState.php @@ -7,6 +7,7 @@ use Utopia\Database\Document; use Utopia\Database\Exception; use Utopia\Database\Exception\Timeout; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; /** * Service for managing transaction state and providing transaction-aware document operations @@ -19,10 +20,12 @@ use Utopia\Database\Query; 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; } @@ -341,12 +344,12 @@ class TransactionState */ private function getTransactionState(string $transactionId): array { - $transaction = $this->dbForProject->getAuthorization()->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 = $this->dbForProject->getAuthorization()->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/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Action.php index 6c5305f299..9bf487bca2 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 @@ -614,7 +614,7 @@ abstract class Action extends UtopiaAction } } else { try { - $dbForProject->updateAttribute( + $authorization->skip(fn () => $dbForProject->updateAttribute( collection: $collectionId, id: $key, size: $size, @@ -622,7 +622,7 @@ abstract class Action extends UtopiaAction default: $default, formatOptions: $options, newKey: $newKey ?? null - ); + )); } catch (DuplicateException) { throw new Exception($this->getDuplicateException()); } catch (IndexException $e) { 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 d4724ea551..97d7010a03 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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Datetime/Update.php index cb4d0d924b..7760bf009c 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/Email/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Email/Update.php index 2446722f7a..108d3b4fce 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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Enum/Update.php index 23dc807360..72037db0db 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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Float/Update.php index 7f295a1a94..96970e7708 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/IP/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/IP/Update.php index 6cedf10760..077a20754d 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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Integer/Update.php index b6ae79bd8a..8afb055686 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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Line/Update.php index 52f04ba5bc..cecf59ff7d 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 @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Validator\Key; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Spatial; 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, ?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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Point/Update.php index 73964ab461..6490b778e1 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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Polygon/Update.php index 23eb06f45d..a4d05c15bf 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 @@ -5,6 +5,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attribu use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Action; use Appwrite\SDK\AuthType; +use Utopia\Database\Validator\Authorization; use Appwrite\SDK\ContentType; use Appwrite\SDK\Deprecated; use Appwrite\SDK\Method; @@ -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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/Relationship/Update.php index 897cbd434f..cc7d1f83eb 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; @@ -70,6 +71,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: $databaseId, @@ -89,6 +92,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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/String/Update.php index 8614dfb202..6a71b7e6e5 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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/URL/Update.php index 7ba12ad98a..e33f2a6509 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, From dbccb16784bb79fcb19f27b87d811bc9afd6caee Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 2 Nov 2025 19:01:59 +0200 Subject: [PATCH 32/77] linter --- .../Http/Databases/Collections/Attributes/Line/Update.php | 2 +- .../Http/Databases/Collections/Attributes/Polygon/Update.php | 2 +- .../Modules/Tokens/Http/Tokens/Buckets/Files/Action.php | 2 +- .../Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) 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 cecf59ff7d..1c2845c795 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,8 +11,8 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; -use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Spatial; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; 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 a4d05c15bf..ed4ab4ac48 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 @@ -5,13 +5,13 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attribu use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Action; use Appwrite\SDK\AuthType; -use Utopia\Database\Validator\Authorization; use Appwrite\SDK\ContentType; use Appwrite\SDK\Deprecated; 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; 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 2c57c57611..e05418b90d 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 @@ -5,9 +5,9 @@ namespace Appwrite\Platform\Modules\Tokens\Http\Tokens\Buckets\Files; use Appwrite\Auth\Auth; use Appwrite\Extend\Exception; use Utopia\Database\Database; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Authorization\Input; use Utopia\Platform\Action as UtopiaAction; -use Utopia\Database\Validator\Authorization; class Action extends UtopiaAction { 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 78cef8251f..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,10 +13,10 @@ 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; -use Utopia\Database\Validator\Authorization; class XList extends Action { From c13aed651ae811b71ff265032176e2df005d1050 Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 2 Nov 2025 21:24:11 +0200 Subject: [PATCH 33/77] Refactor storage file retrieval to use queries directly for counting, improving consistency in authorization handling. Update Action class to remove unnecessary authorization skip, and include authorization in Email/Create class constructor for better dependency management. --- app/controllers/api/storage.php | 6 ++---- .../Http/Databases/Collections/Attributes/Action.php | 4 ++-- .../Http/Databases/Collections/Attributes/Email/Create.php | 3 ++- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 9a211ba290..beb212b0ef 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -842,15 +842,13 @@ App::get('/v1/storage/buckets/:bucketId/files') $cursor->setValue($cursorDocument); } - $filterQueries = Query::groupByType($queries)['filters']; - try { if ($fileSecurity && !$valid) { $files = $dbForProject->find('bucket_' . $bucket->getSequence(), $queries); - $total = $includeTotal ? $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT) : 0; + $total = $includeTotal ? $dbForProject->count('bucket_' . $bucket->getSequence(), $queries, APP_LIMIT_COUNT) : 0; } else { $files = $authorization->skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); - $total = $authorization->skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)); + $total = $includeTotal ? $authorization->skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $queries, APP_LIMIT_COUNT)) : 0; } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); 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 9bf487bca2..6c5305f299 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 @@ -614,7 +614,7 @@ abstract class Action extends UtopiaAction } } else { try { - $authorization->skip(fn () => $dbForProject->updateAttribute( + $dbForProject->updateAttribute( collection: $collectionId, id: $key, size: $size, @@ -622,7 +622,7 @@ abstract class Action extends UtopiaAction default: $default, formatOptions: $options, newKey: $newKey ?? null - )); + ); } catch (DuplicateException) { throw new Exception($this->getDuplicateException()); } catch (IndexException $e) { 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 e848dec37c..c6dd85be75 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 @@ -91,7 +91,8 @@ class Create extends Action $response, $dbForProject, $queueForDatabase, - $queueForEvents + $queueForEvents, + $authorization ); $response From cd1b2b6c053510cfd04395b4bfc2449827ae62b1 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 3 Nov 2025 09:07:44 +0200 Subject: [PATCH 34/77] Refactor authorization handling by replacing method calls with direct class references, ensuring consistent usage of the Authorization class across various modules. Update method signatures to include Authorization as a parameter where necessary, and remove unnecessary injections. Additionally, correct the documentation in CHANGES.md for clarity. --- .github/workflows/auto-label-issue.yml | 22 ------------------- CHANGES.md | 2 +- app/controllers/api/users.php | 1 - .../Platform/Modules/Compute/Base.php | 4 ++-- .../Collections/Documents/Bulk/Delete.php | 3 ++- .../Collections/Documents/Bulk/Upsert.php | 3 ++- .../TablesDB/Tables/Columns/IP/Update.php | 1 - .../Tables/Columns/Integer/Update.php | 1 - .../TablesDB/Tables/Columns/Point/Update.php | 1 - .../Tables/Columns/Polygon/Update.php | 1 - .../Tables/Columns/Relationship/Update.php | 1 - .../TablesDB/Tables/Columns/String/Update.php | 1 - .../TablesDB/Tables/Columns/URL/Update.php | 1 - .../Http/TablesDB/Tables/Indexes/Create.php | 11 ++++++++++ src/Appwrite/Utopia/Response.php | 2 +- 15 files changed, 19 insertions(+), 36 deletions(-) delete mode 100644 .github/workflows/auto-label-issue.yml diff --git a/.github/workflows/auto-label-issue.yml b/.github/workflows/auto-label-issue.yml deleted file mode 100644 index e0eb0de98d..0000000000 --- a/.github/workflows/auto-label-issue.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Auto Label Issue - -on: - issues: - types: [opened] - -permissions: - issues: write - contents: read - -jobs: - labeler: - runs-on: ubuntu-latest - steps: - - name: Issue Labeler - uses: github/issue-labeler@v3.4 - with: - configuration-path: .github/labeler.yml - enable-versioned-regex: false - include-title: 1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGES.md b/CHANGES.md index 7460fc64b5..74b46b7edc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1543,7 +1543,7 @@ * Bump console to version 3.2.7 [#7148](https://github.com/appwrite/appwrite/pull/7148) * Chore update database to 0.45.2 [#7138](https://github.com/appwrite/appwrite/pull/7138) * Implement queue thresholds for the health API [#7123](https://github.com/appwrite/appwrite/pull/7123) -* Add Authorization->skip to the usage worker [#7124](https://github.com/appwrite/appwrite/pull/7124) +* Add Authorization::skip to the usage worker [#7124](https://github.com/appwrite/appwrite/pull/7124) ## Bug fixes * fix: use queueForDeletes in git installation delete endpoint [#7140](https://github.com/appwrite/appwrite/pull/7140) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 5534a70acc..08591794dd 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -2624,7 +2624,6 @@ App::get('/v1/users/usage') ->inject('response') ->inject('dbForProject') ->inject('authorization') - ->inject('register') ->action(function (string $range, Response $response, Database $dbForProject, Authorization $authorization) { $periods = Config::getParam('usage', []); diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 70014b2728..8ff5d88dd4 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -264,7 +264,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(), @@ -301,7 +301,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(), diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php index 4b1251e016..afca273830 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php @@ -19,6 +19,7 @@ use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Exception\Restricted as RestrictedException; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; @@ -83,7 +84,7 @@ class Delete extends Action ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void + public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, Authorization $authorization, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void { $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php index a2156484a8..63bd3d1205 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php @@ -19,6 +19,7 @@ use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Exception\Relationship as RelationshipException; use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Helpers\ID; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; @@ -85,7 +86,7 @@ class Upsert extends Action ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void + public function action(string $databaseId, string $collectionId, array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, Authorization $authorization): void { $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { 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 645b54bdd9..0db95b0206 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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php index 24192b3efb..a1568d069b 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/Point/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php index 3df8e0aee7..3c855e137c 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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php index 905f165de6..866bbaf8b0 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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Relationship/Update.php index 8eea93d286..b645454be1 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 @@ -64,7 +64,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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php index 60b9ba85ce..5ec9b78dda 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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php index 8528e8fb05..51168b0383 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/Indexes/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/Create.php index 2d14785bb8..165f014320 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 @@ -2,6 +2,8 @@ namespace Appwrite\Platform\Modules\Databases\Http\TablesDB\Tables\Indexes; +use Appwrite\Event\Database as EventDatabase; +use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Create as IndexCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -9,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,4 +72,12 @@ class Create extends IndexCreate ->inject('authorization') ->callback($this->action(...)); } + + public function action(string $databaseId, string $tableId, string $key, string $type, array $columns, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void + { + // Map TablesDB parameters to Collections API parameters + // tableId -> collectionId + // columns -> attributes + parent::action($databaseId, $tableId, $key, $type, $columns, $orders, $lengths, $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); + } } diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index da614a5a6a..c92d49ade8 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -809,7 +809,7 @@ class Response extends SwooleResponse } if ($rule['sensitive']) { - $roles = $this->authorization?->getRoles() ?? []; + $roles = $this->authorization->getRoles() ?? []; $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); From a3742bc65e8492e828048c088c9bf35dff4c15d6 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 3 Nov 2025 09:13:04 +0200 Subject: [PATCH 35/77] compose.lock --- composer.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.lock b/composer.lock index be5e4b2fa3..8e139e31b2 100644 --- a/composer.lock +++ b/composer.lock @@ -8932,5 +8932,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } From f613a06d19963044e71d0f7750d7fac79c8cb662 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 3 Nov 2025 10:04:01 +0200 Subject: [PATCH 36/77] composer.lock --- composer.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.lock b/composer.lock index 5b70c4a229..8b06671dc1 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": "6a0ff41b0f382016b899d52307df5983", + "content-hash": "881b001010468bad06d1eef0693e8ed0", "packages": [ { "name": "adhocore/jwt", @@ -3922,8 +3922,8 @@ "utopia" ], "support": { - "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/feat-authorization-instance" + "source": "https://github.com/utopia-php/database/tree/feat-authorization-instance", + "issues": "https://github.com/utopia-php/database/issues" }, "time": "2025-10-27T08:34:29+00:00" }, From 89d5a28c28fecad389c52075e22b9b8e73f2554d Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 3 Nov 2025 10:37:05 +0200 Subject: [PATCH 37/77] Refactor authorization handling to consistently utilize the Authorization class across multiple controllers and functions. Update method signatures to include Authorization as a parameter, ensuring cleaner and more maintainable code. This change enhances the overall structure and readability of the authorization logic. --- app/controllers/general.php | 55 ++++++++++++++++++---------------- app/controllers/shared/api.php | 52 +++++++++++++++++--------------- app/http.php | 18 ++++++----- 3 files changed, 69 insertions(+), 56 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 332f0c1d15..4da331fcc4 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -56,7 +56,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, 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, string $previewHostname, Authorization $authorization, ?Key $apiKey) { $host = $request->getHostname() ?? ''; if (!empty($previewHostname)) { @@ -65,9 +65,9 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw // TODO: @christyjacob remove once we migrate the rules in 1.7.x if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { - $rule = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('rules', md5($host))); + $rule = $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($host))); } else { - $rule = $dbForPlatform->getAuthorization()->skip( + $rule = $authorization->skip( fn () => $dbForPlatform->find('rules', [ Query::equal('domain', [$host]), Query::limit(1) @@ -108,7 +108,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $projectId = $rule->getAttribute('projectId'); - $project = $dbForPlatform->getAuthorization()->skip( + $project = $authorization->skip( fn () => $dbForPlatform->getDocument('projects', $projectId) ); @@ -116,7 +116,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()); - $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } /** @@ -155,7 +155,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw /** @var Document $deployment */ if (!empty($rule->getAttribute('deploymentId', ''))) { - $deployment = $dbForProject->getAuthorization()->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 @@ -169,15 +169,15 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw // Document of site or function $resource = $resourceType === 'function' ? - $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('functions', $resourceId)) : - $dbForProject->getAuthorization()->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 = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('deployments', $activeDeploymentId)); + $deployment = $authorization->skip(fn () => $dbForProject->getDocument('deployments', $activeDeploymentId)); } if ($deployment->getAttribute('resourceType', '') === 'functions') { @@ -196,8 +196,8 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $resource = $type === 'function' ? - $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) : - $dbForProject->getAuthorization()->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'); @@ -239,7 +239,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $userExists = false; $userId = $payload['userId'] ?? ''; if (!empty($userId)) { - $user = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('users', $userId)); + $user = $authorization->skip(fn () => $dbForPlatform->getDocument('users', $userId)); if (!$user->isEmpty() && $user->getAttribute('status', false)) { $userExists = true; } @@ -252,7 +252,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $membershipExists = false; - $project = $dbForPlatform->getAuthorization()->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'); @@ -863,7 +863,8 @@ App::init() ->inject('apiKey') ->inject('httpReferrer') ->inject('httpReferrerSafe') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $platforms, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, Executor $executor, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, string $httpReferrer, string $httpReferrerSafe) { + ->inject('authorization') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $platforms, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, Executor $executor, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, string $httpReferrer, string $httpReferrerSafe, Authorization $authorization) { /* * Appwrite Router */ @@ -871,7 +872,7 @@ App::init() $mainDomain = System::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain || !empty($previewHostname)) { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $authorization, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -919,7 +920,7 @@ App::init() } elseif (str_starts_with($request->getURI(), '/.well-known/acme-challenge')) { Console::warning('Skipping SSL certificates generation on ACME challenge.'); } else { - $dbForPlatform->getAuthorization()->disable(); + $authorization->disable(); $envDomain = System::getEnv('_APP_DOMAIN', ''); $mainDomain = null; @@ -989,7 +990,7 @@ App::init() } $domains[$domain->get()] = true; - $dbForPlatform->getAuthorization()->reset(); // ensure authorization is re-enabled + $authorization->reset(); // ensure authorization is re-enabled } Config::setParam('domains', $domains); } @@ -1125,7 +1126,8 @@ App::options() ->inject('project') ->inject('devKey') ->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, string $previewHostname, Document $project, Document $devKey, ?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, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, Authorization $authorization) { /* * Appwrite Router */ @@ -1133,7 +1135,7 @@ App::options() $mainDomain = System::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain || !empty($previewHostname)) { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $authorization, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1442,7 +1444,8 @@ App::get('/robots.txt') ->inject('isResourceBlocked') ->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, 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, string $previewHostname, ?Key $apiKey, Authorization $authorization) { $host = $request->getHostname() ?? ''; $consoleDomain = System::getEnv('_APP_CONSOLE_DOMAIN', ''); $mainDomain = System::getEnv('_APP_DOMAIN', ''); @@ -1451,7 +1454,7 @@ App::get('/robots.txt') $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, $previewHostname, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $authorization, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1476,7 +1479,8 @@ App::get('/humans.txt') ->inject('isResourceBlocked') ->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, 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, string $previewHostname, ?Key $apiKey, Authorization $authorization) { $host = $request->getHostname() ?? ''; $consoleDomain = System::getEnv('_APP_CONSOLE_DOMAIN', ''); $mainDomain = System::getEnv('_APP_DOMAIN', ''); @@ -1485,7 +1489,7 @@ App::get('/humans.txt') $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, $previewHostname, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $authorization, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1569,7 +1573,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); } @@ -1581,7 +1586,7 @@ App::get('/v1/ping') ->setAttribute('pingCount', $pingCount) ->setAttribute('pingedAt', $pingedAt); - $dbForPlatform->getAuthorization()->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 8ea1198c27..a1b9e7fef4 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -28,6 +28,7 @@ use Utopia\Database\Database; 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; @@ -232,7 +233,8 @@ App::init() ->inject('mode') ->inject('team') ->inject('apiKey') - ->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) { + ->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(); if ($project->isEmpty()) { @@ -262,7 +264,7 @@ App::init() if ($apiKey->getRole() === Auth::USER_ROLE_APPS) { // Disable authorization checks for API keys - $dbForPlatform->getAuthorization()->setDefaultStatus(false); + $authorization->setDefaultStatus(false); $user = new Document([ '$id' => '', @@ -335,14 +337,14 @@ App::init() $scopes = \array_merge($scopes, $roles[$role]['scopes']); } - $dbForPlatform->getAuthorization()->setDefaultStatus(false); // Cancel security segmentation for admin users. + $authorization->setDefaultStatus(false); // Cancel security segmentation for admin users. } $scopes = \array_unique($scopes); - $dbForPlatform->getAuthorization()->addRole($role); - foreach (Auth::getRoles($user, $dbForPlatform->getAuthorization()) as $authRole) { - $dbForPlatform->getAuthorization()->addRole($authRole); + $authorization->addRole($role); + foreach (Auth::getRoles($user, $authorization) as $authRole) { + $authorization->addRole($authRole); } // Update project last activity @@ -350,7 +352,7 @@ App::init() $accessedAt = $project->getAttribute('accessedAt', 0); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { $project->setAttribute('accessedAt', DateTime::now()); - $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + $authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); } } @@ -385,7 +387,7 @@ App::init() if ( array_key_exists($namespace, $project->getAttribute('services', [])) && !$project->getAttribute('services', [])[$namespace] - && !(Auth::isPrivilegedUser($dbForPlatform->getAuthorization()->getRoles()) || Auth::isAppUser($dbForPlatform->getAuthorization()->getRoles())) + && !(Auth::isPrivilegedUser($authorization->getRoles()) || Auth::isAppUser($authorization->getRoles())) ) { throw new Exception(Exception::GENERAL_SERVICE_DISABLED); } @@ -445,14 +447,15 @@ App::init() ->inject('plan') ->inject('devKey') ->inject('telemetry') - ->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, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry) 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, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, Authorization $authorization) use ($usageDatabaseListener, $eventDatabaseListener) { $route = $utopia->getRoute(); if ( array_key_exists('rest', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['rest'] - && !(Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()) || Auth::isAppUser($dbForProject->getAuthorization() ->getRoles())) + && !(Auth::isPrivilegedUser($authorization->getRoles()) || Auth::isAppUser($authorization->getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -482,7 +485,7 @@ App::init() $closestLimit = null; - $roles = $dbForProject->getAuthorization()->getRoles(); + $roles = $authorization->getRoles(); $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); @@ -582,10 +585,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 && !Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !Auth::isPrivilegedUser($authorization->getRoles()); $key = $request->cacheIdentifier(); - $cacheLog = $dbForProject->getAuthorization()->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()) ); @@ -602,17 +605,17 @@ App::init() if ($type === 'bucket' && (!$isImageTransformation || !$isDisabled)) { $bucketId = $parts[1] ?? null; - $bucket = $dbForProject->getAuthorization()->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); - $isPrivilegedUser = Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAppUser && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } $fileSecurity = $bucket->getAttribute('fileSecurity', false); - $valid = $dbForProject->getAuthorization()->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); + $valid = $authorization->isValid(new Input(Database::PERMISSION_READ, $bucket->getRead())); if (!$fileSecurity && !$valid && !$isToken) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -623,7 +626,7 @@ App::init() if ($fileSecurity && !$valid && !$isToken) { $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = $dbForProject->getAuthorization()->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()) { @@ -634,11 +637,11 @@ App::init() throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } //Do not update transformedAt if it's a console user - if (!Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles())) { + if (!Auth::isPrivilegedUser($authorization->getRoles())) { $transformedAt = $file->getAttribute('transformedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) { $file->setAttribute('transformedAt', DateTime::now()); - $dbForProject->getAuthorization()->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); + $authorization->skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); } } } @@ -734,7 +737,8 @@ App::shutdown() ->inject('queueForWebhooks') ->inject('queueForRealtime') ->inject('dbForProject') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $queueForEvents, Audit $queueForAudits, StatsUsage $queueForStatsUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject) use ($parseLabel) { + ->inject('authorization') + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $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) use ($parseLabel) { $responsePayload = $response->getPayload(); @@ -860,11 +864,11 @@ App::shutdown() $key = $request->cacheIdentifier(); $signature = md5($data['payload']); - $cacheLog = $dbForProject->getAuthorization()->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()) { - $dbForProject->getAuthorization()->skip(fn () => $dbForProject->createDocument('cache', new Document([ + $authorization->skip(fn () => $dbForProject->createDocument('cache', new Document([ '$id' => $key, 'resource' => $resource, 'resourceType' => $resourceType, @@ -874,7 +878,7 @@ App::shutdown() ]))); } elseif (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_CACHE_UPDATE)) > $accessedAt) { $cacheLog->setAttribute('accessedAt', $now); - $dbForProject->getAuthorization()->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']); } @@ -886,7 +890,7 @@ App::shutdown() } if ($project->getId() !== 'console') { - if (!Auth::isPrivilegedUser($dbForProject->getAuthorization()->getRoles())) { + if (!Auth::isPrivilegedUser($authorization->getRoles())) { $fileSize = 0; $file = $request->getFiles('file'); if (!empty($file)) { diff --git a/app/http.php b/app/http.php index 5ca72c45ed..b1e757012f 100644 --- a/app/http.php +++ b/app/http.php @@ -25,6 +25,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; @@ -258,7 +259,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(Audit::COLLECTION)->isEmpty()) { $audit = new Audit($dbForPlatform); $audit->setup(); @@ -317,9 +320,9 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes); } - if ($dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) { + if ($authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) { Console::info(" └── Creating screenshots bucket..."); - $dbForPlatform->getAuthorization()->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', @@ -334,7 +337,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'search' => 'buckets Screenshots', ]))); - $bucket = $dbForPlatform->getAuthorization()->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'] ?? []; @@ -362,7 +365,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'orders' => $index['orders'], ]), $files['indexes']); - $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes)); + $authorization->skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes)); } }); @@ -559,7 +562,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; @@ -576,7 +579,8 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) { } $results = []; try { - $results = $dbForPlatform->getAuthorization()->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()); } From 5709265f6c79eedd2c5593af03314f12e6d8cad2 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 3 Nov 2025 11:02:30 +0200 Subject: [PATCH 38/77] linter --- app/http.php | 3 +-- .../Http/Databases/Collections/Documents/Bulk/Delete.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/http.php b/app/http.php index b1e757012f..568571fad2 100644 --- a/app/http.php +++ b/app/http.php @@ -25,7 +25,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,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg // 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'); - + if ($dbForPlatform->getCollection(Audit::COLLECTION)->isEmpty()) { $audit = new Audit($dbForPlatform); $audit->setup(); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php index afca273830..d3e18420a7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php @@ -84,7 +84,7 @@ class Delete extends Action ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, Authorization $authorization, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void + public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void { $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { From 3391563829846184d4e5e418b5c493044ca5cc61 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 3 Nov 2025 11:07:17 +0200 Subject: [PATCH 39/77] Remove unused Authorization import from Bulk Delete.php to clean up code and improve maintainability. --- .../Http/Databases/Collections/Documents/Bulk/Delete.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php index d3e18420a7..4b1251e016 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Delete.php @@ -19,7 +19,6 @@ use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Exception\Restricted as RestrictedException; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; From 02dd275be4fc08623fce930bc598d874d4eee588 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 3 Nov 2025 11:54:50 +0200 Subject: [PATCH 40/77] Update composer.lock with new reference for utopia-php/database and modify Upsert action method to remove unused Authorization parameter and enhance document validation. This improves code clarity and maintainability. --- composer.lock | 8 ++++---- .../Http/Databases/Collections/Documents/Bulk/Upsert.php | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index 8b06671dc1..6d7f1c307a 100644 --- a/composer.lock +++ b/composer.lock @@ -3844,12 +3844,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "22123ad30782be131ecad4e9298b843d8daf387b" + "reference": "61d06624a5b96b6e4665ef1de740e31428b868ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/22123ad30782be131ecad4e9298b843d8daf387b", - "reference": "22123ad30782be131ecad4e9298b843d8daf387b", + "url": "https://api.github.com/repos/utopia-php/database/zipball/61d06624a5b96b6e4665ef1de740e31428b868ec", + "reference": "61d06624a5b96b6e4665ef1de740e31428b868ec", "shasum": "" }, "require": { @@ -3925,7 +3925,7 @@ "source": "https://github.com/utopia-php/database/tree/feat-authorization-instance", "issues": "https://github.com/utopia-php/database/issues" }, - "time": "2025-10-27T08:34:29+00:00" + "time": "2025-11-03T09:42:43+00:00" }, { "name": "utopia-php/detector", diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php index 80e53170da..6c869723a7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Bulk/Upsert.php @@ -19,7 +19,6 @@ use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Exception\Relationship as RelationshipException; use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Helpers\ID; -use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; @@ -86,7 +85,7 @@ class Upsert extends Action ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, Event $queueForEvents, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan): void { $database = $dbForProject->getDocument('databases', $databaseId); if ($database->isEmpty()) { From d721425cfecbdaebdf063feb6afac9bb8abfc098 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 3 Nov 2025 12:33:07 +0200 Subject: [PATCH 41/77] composer.lock --- composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.lock b/composer.lock index 6d7f1c307a..1f10c437cf 100644 --- a/composer.lock +++ b/composer.lock @@ -3844,12 +3844,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "61d06624a5b96b6e4665ef1de740e31428b868ec" + "reference": "5464da0f13d159096b1ee62acfddf0440be36596" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/61d06624a5b96b6e4665ef1de740e31428b868ec", - "reference": "61d06624a5b96b6e4665ef1de740e31428b868ec", + "url": "https://api.github.com/repos/utopia-php/database/zipball/5464da0f13d159096b1ee62acfddf0440be36596", + "reference": "5464da0f13d159096b1ee62acfddf0440be36596", "shasum": "" }, "require": { @@ -3925,7 +3925,7 @@ "source": "https://github.com/utopia-php/database/tree/feat-authorization-instance", "issues": "https://github.com/utopia-php/database/issues" }, - "time": "2025-11-03T09:42:43+00:00" + "time": "2025-11-03T10:08:55+00:00" }, { "name": "utopia-php/detector", From e1fbaf14eb6cfb1fb7850cef992a0c8767f9adde Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 3 Nov 2025 12:51:21 +0200 Subject: [PATCH 42/77] Inject authorization dependency into the Update class for improved authorization handling in relationship updates. --- .../Http/TablesDB/Tables/Columns/Relationship/Update.php | 1 + 1 file changed, 1 insertion(+) 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 b645454be1..8eea93d286 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 @@ -64,6 +64,7 @@ class Update extends RelationshipUpdate ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') + ->inject('authorization') ->callback($this->action(...)); } } From dc43b5977ffad4310564e0f2297c54a9b6bf9aac Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 3 Nov 2025 12:58:22 +0200 Subject: [PATCH 43/77] Inject authorization dependency into the Update class to enhance authorization handling for string column updates. --- .../Modules/Databases/Http/TablesDB/Tables/Columns/IP/Update.php | 1 + .../Databases/Http/TablesDB/Tables/Columns/Integer/Update.php | 1 + .../Databases/Http/TablesDB/Tables/Columns/Point/Update.php | 1 + .../Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php | 1 + .../Databases/Http/TablesDB/Tables/Columns/String/Update.php | 1 + .../Databases/Http/TablesDB/Tables/Columns/URL/Update.php | 1 + 6 files changed, 6 insertions(+) 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 0db95b0206..645b54bdd9 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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Integer/Update.php index a1568d069b..24192b3efb 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/Point/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Point/Update.php index 3c855e137c..3df8e0aee7 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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/Polygon/Update.php index 866bbaf8b0..905f165de6 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/String/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/String/Update.php index 5ec9b78dda..60b9ba85ce 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/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/URL/Update.php index 51168b0383..8528e8fb05 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(...)); } } From f0e4c9184d35729ab9137dc781054c3917063dc7 Mon Sep 17 00:00:00 2001 From: shimon Date: Tue, 4 Nov 2025 16:44:09 +0200 Subject: [PATCH 44/77] Update composer.json and composer.lock to reflect new version constraints for utopia-php/audit and utopia-php/database, ensuring compatibility with the latest releases. Adjusted versioning for utopia-php/migration and appwrite/sdk-generator to their respective latest versions. --- composer.json | 4 +-- composer.lock | 74 ++++++++++++++++++++------------------------------- 2 files changed, 31 insertions(+), 47 deletions(-) diff --git a/composer.json b/composer.json index 42194d664d..b4850aaaca 100644 --- a/composer.json +++ b/composer.json @@ -47,11 +47,11 @@ "appwrite/php-clamav": "2.0.*", "utopia-php/abuse": "1.*", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "dev-feat-auth-single-instance as 1.1.0", + "utopia-php/audit": "1.*", "utopia-php/cache": "0.13.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "dev-feat-authorization-instance as 3.0.2", + "utopia-php/database": "4.*", "utopia-php/detector": "0.2.*", "utopia-php/domains": "0.9.*", "utopia-php/emails": "0.6.*", diff --git a/composer.lock b/composer.lock index 1f10c437cf..dc3dc2407e 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": "881b001010468bad06d1eef0693e8ed0", + "content-hash": "550f8ddb2f6c846a6476916ca35fb1c6", "packages": [ { "name": "adhocore/jwt", @@ -3547,21 +3547,21 @@ }, { "name": "utopia-php/audit", - "version": "dev-feat-auth-single-instance", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "b74a6f8213b444e0af6ce0714ec85ea2859b3508" + "reference": "15656acfddb9d6f03c395b73673fc66c793c10a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/b74a6f8213b444e0af6ce0714ec85ea2859b3508", - "reference": "b74a6f8213b444e0af6ce0714ec85ea2859b3508", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/15656acfddb9d6f03c395b73673fc66c793c10a5", + "reference": "15656acfddb9d6f03c395b73673fc66c793c10a5", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "dev-feat-authorization-instance as 3.0.2" + "utopia-php/database": "4.*" }, "require-dev": { "laravel/pint": "1.*", @@ -3588,9 +3588,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/feat-auth-single-instance" + "source": "https://github.com/utopia-php/audit/tree/1.0.3" }, - "time": "2025-10-27T13:39:14+00:00" + "time": "2025-11-04T11:27:42+00:00" }, { "name": "utopia-php/cache", @@ -3840,16 +3840,16 @@ }, { "name": "utopia-php/database", - "version": "dev-feat-authorization-instance", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "5464da0f13d159096b1ee62acfddf0440be36596" + "reference": "da9d021b2722abdf4df08a739126f1be2707cf6d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/5464da0f13d159096b1ee62acfddf0440be36596", - "reference": "5464da0f13d159096b1ee62acfddf0440be36596", + "url": "https://api.github.com/repos/utopia-php/database/zipball/da9d021b2722abdf4df08a739126f1be2707cf6d", + "reference": "da9d021b2722abdf4df08a739126f1be2707cf6d", "shasum": "" }, "require": { @@ -3922,10 +3922,10 @@ "utopia" ], "support": { - "source": "https://github.com/utopia-php/database/tree/feat-authorization-instance", + "source": "https://github.com/utopia-php/database/tree/4.0.0", "issues": "https://github.com/utopia-php/database/issues" }, - "time": "2025-11-03T10:08:55+00:00" + "time": "2025-11-04T10:55:46+00:00" }, { "name": "utopia-php/detector", @@ -4514,16 +4514,16 @@ }, { "name": "utopia-php/migration", - "version": "1.3.3", + "version": "1.3.4", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "731b3a963c58c30e0b2368695d57a7e8fcb7455c" + "reference": "81e1be6ff3257d4768aa7483cf64628836244a09" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/731b3a963c58c30e0b2368695d57a7e8fcb7455c", - "reference": "731b3a963c58c30e0b2368695d57a7e8fcb7455c", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/81e1be6ff3257d4768aa7483cf64628836244a09", + "reference": "81e1be6ff3257d4768aa7483cf64628836244a09", "shasum": "" }, "require": { @@ -4532,7 +4532,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.*" }, @@ -4580,10 +4580,10 @@ "utopia" ], "support": { - "source": "https://github.com/utopia-php/migration/tree/1.3.3", + "source": "https://github.com/utopia-php/migration/tree/1.3.4", "issues": "https://github.com/utopia-php/migration/issues" }, - "time": "2025-10-28T04:02:08+00:00" + "time": "2025-11-04T11:28:50+00:00" }, { "name": "utopia-php/mongo", @@ -5468,16 +5468,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.5.0", + "version": "1.5.1", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "42df22195d6457e52e4c819678168470b114a816" + "reference": "cd712674e34136f706e9170641ed6f4ce160e772" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/42df22195d6457e52e4c819678168470b114a816", - "reference": "42df22195d6457e52e4c819678168470b114a816", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/cd712674e34136f706e9170641ed6f4ce160e772", + "reference": "cd712674e34136f706e9170641ed6f4ce160e772", "shasum": "" }, "require": { @@ -5513,9 +5513,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.5.0" + "source": "https://github.com/appwrite/sdk-generator/tree/1.5.1" }, - "time": "2025-10-31T10:10:25+00:00" + "time": "2025-11-04T09:55:47+00:00" }, { "name": "doctrine/annotations", @@ -8980,25 +8980,9 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [ - { - "package": "utopia-php/audit", - "version": "dev-feat-auth-single-instance", - "alias": "1.1.0", - "alias_normalized": "1.1.0.0" - }, - { - "package": "utopia-php/database", - "version": "dev-feat-authorization-instance", - "alias": "3.0.2", - "alias_normalized": "3.0.2.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/audit": 20, - "utopia-php/database": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From f3fd2fd1910d879b715dd4bddd466271e7537c89 Mon Sep 17 00:00:00 2001 From: shimon Date: Tue, 4 Nov 2025 17:11:45 +0200 Subject: [PATCH 45/77] composer.lock --- composer.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.lock b/composer.lock index 16301dffa6..560f311036 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": "550f8ddb2f6c846a6476916ca35fb1c6", + "content-hash": "352d5b81626632665fbc8e3e76a1b950", "packages": [ { "name": "adhocore/jwt", @@ -3457,7 +3457,7 @@ "reference": "611fa66a97e87c0dbbc133a717d970da7a5ca828" }, "dist": { - "type": "zip",\ + "type": "zip", "url": "https://api.github.com/repos/utopia-php/abuse/zipball/611fa66a97e87c0dbbc133a717d970da7a5ca828", "reference": "611fa66a97e87c0dbbc133a717d970da7a5ca828", "shasum": "" @@ -8981,7 +8981,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From 501cba216b010b74f2197334fc1558cccb935d0c Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 5 Nov 2025 16:09:20 +1300 Subject: [PATCH 46/77] Update app/init/resources.php --- app/init/resources.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/init/resources.php b/app/init/resources.php index db2cc093f0..8b111e950c 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -485,7 +485,6 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform $adapter = new DatabasePool($pools->get($dsn->getHost())); $database = new Database($adapter, $cache); - $database->setAuthorization($authorization); $databases[$dsn->getHost()] = $database; $configure($database); From 16d6c9e5e310723ead25fda72557c9ee451be049 Mon Sep 17 00:00:00 2001 From: shimon Date: Thu, 6 Nov 2025 16:11:57 +0200 Subject: [PATCH 47/77] debug dbHelth --- tests/e2e/Services/Health/HealthCustomServerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/Health/HealthCustomServerTest.php b/tests/e2e/Services/Health/HealthCustomServerTest.php index 4b7062dc22..7f7621f1c7 100644 --- a/tests/e2e/Services/Health/HealthCustomServerTest.php +++ b/tests/e2e/Services/Health/HealthCustomServerTest.php @@ -40,7 +40,7 @@ class HealthCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); - + var_dump($response); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals('pass', $response['body']['statuses'][0]['status']); $this->assertIsInt($response['body']['statuses'][0]['ping']); From d0f2293755e14b26ae9be48692c9ad67188c46e1 Mon Sep 17 00:00:00 2001 From: shimon Date: Thu, 6 Nov 2025 16:42:58 +0200 Subject: [PATCH 48/77] debug health db --- app/controllers/api/health.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 765688e1ee..a411002532 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -132,8 +132,9 @@ App::get('/v1/health/db') } if (!empty($failures)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'DB failure on: ' . implode(", ", $failures)); - } + $output= $failures; + //throw new Exception(Exception::GENERAL_SERVER_ERROR, 'DB failure on: ' . implode(", ", $failures)); + } $response->dynamic(new Document([ 'statuses' => $output, From 3d471bae5618bfc8cd62ff6c3ef36f442de46d3c Mon Sep 17 00:00:00 2001 From: shimon Date: Thu, 6 Nov 2025 17:37:31 +0200 Subject: [PATCH 49/77] health db debug --- app/controllers/api/health.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index a411002532..765688e1ee 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -132,9 +132,8 @@ App::get('/v1/health/db') } if (!empty($failures)) { - $output= $failures; - //throw new Exception(Exception::GENERAL_SERVER_ERROR, 'DB failure on: ' . implode(", ", $failures)); - } + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'DB failure on: ' . implode(", ", $failures)); + } $response->dynamic(new Document([ 'statuses' => $output, From ae2ffd259ca524d9a65b771e5dcb71269207f907 Mon Sep 17 00:00:00 2001 From: shimon Date: Thu, 6 Nov 2025 17:54:44 +0200 Subject: [PATCH 50/77] Remove debug output from HealthCustomServerTest --- tests/e2e/Services/Health/HealthCustomServerTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/e2e/Services/Health/HealthCustomServerTest.php b/tests/e2e/Services/Health/HealthCustomServerTest.php index 7f7621f1c7..63516f624d 100644 --- a/tests/e2e/Services/Health/HealthCustomServerTest.php +++ b/tests/e2e/Services/Health/HealthCustomServerTest.php @@ -40,7 +40,6 @@ class HealthCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); - var_dump($response); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals('pass', $response['body']['statuses'][0]['status']); $this->assertIsInt($response['body']['statuses'][0]['ping']); From 3ef6154ebe7065154ad168015855ea0b3b910d3d Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 9 Nov 2025 10:10:22 +0200 Subject: [PATCH 51/77] Update composer.lock to reflect package version upgrades and dependency changes, including Symfony components and Utopia PHP libraries. --- composer.lock | 132 ++++++++++++++++++++++++++------------------------ 1 file changed, 69 insertions(+), 63 deletions(-) diff --git a/composer.lock b/composer.lock index f00d089566..957969c639 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": "352d5b81626632665fbc8e3e76a1b950", + "content-hash": "3b502f78f5e31f2ea7b4c69e3301283a", "packages": [ { "name": "adhocore/jwt", @@ -2673,16 +2673,16 @@ }, { "name": "symfony/http-client", - "version": "v7.3.4", + "version": "v7.3.6", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "4b62871a01c49457cf2a8e560af7ee8a94b87a62" + "reference": "3c0a55a2c8e21e30a37022801c11c7ab5a6cb2de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/4b62871a01c49457cf2a8e560af7ee8a94b87a62", - "reference": "4b62871a01c49457cf2a8e560af7ee8a94b87a62", + "url": "https://api.github.com/repos/symfony/http-client/zipball/3c0a55a2c8e21e30a37022801c11c7ab5a6cb2de", + "reference": "3c0a55a2c8e21e30a37022801c11c7ab5a6cb2de", "shasum": "" }, "require": { @@ -2749,7 +2749,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.3.4" + "source": "https://github.com/symfony/http-client/tree/v7.3.6" }, "funding": [ { @@ -2769,7 +2769,7 @@ "type": "tidelift" } ], - "time": "2025-09-11T10:12:26+00:00" + "time": "2025-11-05T17:41:46+00:00" }, { "name": "symfony/http-client-contracts", @@ -3176,16 +3176,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.6.0", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", "shasum": "" }, "require": { @@ -3239,7 +3239,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" }, "funding": [ { @@ -3250,12 +3250,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-25T09:37:31+00:00" + "time": "2025-07-15T11:30:57+00:00" }, { "name": "tbachert/spi", @@ -3840,16 +3844,16 @@ }, { "name": "utopia-php/database", - "version": "4.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "da9d021b2722abdf4df08a739126f1be2707cf6d" + "reference": "c34cb23844944ebda952d0f2390bc9d0285f8c12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/da9d021b2722abdf4df08a739126f1be2707cf6d", - "reference": "da9d021b2722abdf4df08a739126f1be2707cf6d", + "url": "https://api.github.com/repos/utopia-php/database/zipball/c34cb23844944ebda952d0f2390bc9d0285f8c12", + "reference": "c34cb23844944ebda952d0f2390bc9d0285f8c12", "shasum": "" }, "require": { @@ -3891,10 +3895,10 @@ "utopia" ], "support": { - "source": "https://github.com/utopia-php/database/tree/4.0.0", - "issues": "https://github.com/utopia-php/database/issues" + "issues": "https://github.com/utopia-php/database/issues", + "source": "https://github.com/utopia-php/database/tree/4.0.1" }, - "time": "2025-11-04T10:55:46+00:00" + "time": "2025-11-05T03:39:09+00:00" }, { "name": "utopia-php/detector", @@ -3943,22 +3947,24 @@ }, { "name": "utopia-php/dns", - "version": "1.1.0", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/utopia-php/dns.git", - "reference": "d6eca184883262bdcb4261e57491c91b16079b9a" + "reference": "1e6b4bac735329c9e5ec69a6a5d899ec2d050707" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/dns/zipball/d6eca184883262bdcb4261e57491c91b16079b9a", - "reference": "d6eca184883262bdcb4261e57491c91b16079b9a", + "url": "https://api.github.com/repos/utopia-php/dns/zipball/1e6b4bac735329c9e5ec69a6a5d899ec2d050707", + "reference": "1e6b4bac735329c9e5ec69a6a5d899ec2d050707", "shasum": "" }, "require": { "php": ">=8.3", "utopia-php/console": "0.0.*", - "utopia-php/telemetry": "0.1.*" + "utopia-php/domains": "0.9.*", + "utopia-php/telemetry": "0.1.*", + "utopia-php/validators": "^0.0.2" }, "require-dev": { "laravel/pint": "1.25.*", @@ -3992,9 +3998,9 @@ ], "support": { "issues": "https://github.com/utopia-php/dns/issues", - "source": "https://github.com/utopia-php/dns/tree/1.1.0" + "source": "https://github.com/utopia-php/dns/tree/1.1.3" }, - "time": "2025-11-03T22:49:02+00:00" + "time": "2025-11-06T19:08:29+00:00" }, { "name": "utopia-php/domains", @@ -4502,8 +4508,8 @@ "utopia" ], "support": { - "source": "https://github.com/utopia-php/migration/tree/1.3.4", - "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.3.4" }, "time": "2025-11-04T11:28:50+00:00" }, @@ -6077,24 +6083,24 @@ }, { "name": "phpbench/container", - "version": "2.2.2", + "version": "2.2.3", "source": { "type": "git", "url": "https://github.com/phpbench/container.git", - "reference": "a59b929e00b87b532ca6d0edd8eca0967655af33" + "reference": "0c7b2d36c1ea53fe27302fb8873ded7172047196" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpbench/container/zipball/a59b929e00b87b532ca6d0edd8eca0967655af33", - "reference": "a59b929e00b87b532ca6d0edd8eca0967655af33", + "url": "https://api.github.com/repos/phpbench/container/zipball/0c7b2d36c1ea53fe27302fb8873ded7172047196", + "reference": "0c7b2d36c1ea53fe27302fb8873ded7172047196", "shasum": "" }, "require": { "psr/container": "^1.0|^2.0", - "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0 || ^7.0" + "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0 || ^7.0 || ^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.16", + "php-cs-fixer/shim": "^3.89", "phpstan/phpstan": "^0.12.52", "phpunit/phpunit": "^8" }, @@ -6122,22 +6128,22 @@ "description": "Simple, configurable, service container.", "support": { "issues": "https://github.com/phpbench/container/issues", - "source": "https://github.com/phpbench/container/tree/2.2.2" + "source": "https://github.com/phpbench/container/tree/2.2.3" }, - "time": "2023-10-30T13:38:26+00:00" + "time": "2025-11-06T09:05:13+00:00" }, { "name": "phpbench/phpbench", - "version": "1.4.2", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/phpbench/phpbench.git", - "reference": "bb61ae6c54b3d58642be154eb09f4e73c3511018" + "reference": "b641dde59d969ea42eed70a39f9b51950bc96878" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpbench/phpbench/zipball/bb61ae6c54b3d58642be154eb09f4e73c3511018", - "reference": "bb61ae6c54b3d58642be154eb09f4e73c3511018", + "url": "https://api.github.com/repos/phpbench/phpbench/zipball/b641dde59d969ea42eed70a39f9b51950bc96878", + "reference": "b641dde59d969ea42eed70a39f9b51950bc96878", "shasum": "" }, "require": { @@ -6152,26 +6158,26 @@ "phpbench/container": "^2.2", "psr/log": "^1.1 || ^2.0 || ^3.0", "seld/jsonlint": "^1.1", - "symfony/console": "^6.1 || ^7.0", - "symfony/filesystem": "^6.1 || ^7.0", - "symfony/finder": "^6.1 || ^7.0", - "symfony/options-resolver": "^6.1 || ^7.0", - "symfony/process": "^6.1 || ^7.0", + "symfony/console": "^6.1 || ^7.0 || ^8.0", + "symfony/filesystem": "^6.1 || ^7.0 || ^8.0", + "symfony/finder": "^6.1 || ^7.0 || ^8.0", + "symfony/options-resolver": "^6.1 || ^7.0 || ^8.0", + "symfony/process": "^6.1 || ^7.0 || ^8.0", "webmozart/glob": "^4.6" }, "require-dev": { "dantleech/invoke": "^2.0", "ergebnis/composer-normalize": "^2.39", - "friendsofphp/php-cs-fixer": "^3.0", "jangregor/phpstan-prophecy": "^1.0", + "php-cs-fixer/shim": "^3.9", "phpspec/prophecy": "^1.22", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.0", "phpstan/phpstan-phpunit": "^1.0", "phpunit/phpunit": "^10.4 || ^11.0", "rector/rector": "^1.2", - "symfony/error-handler": "^6.1 || ^7.0", - "symfony/var-dumper": "^6.1 || ^7.0" + "symfony/error-handler": "^6.1 || ^7.0 || ^8.0", + "symfony/var-dumper": "^6.1 || ^7.0 || ^8.0" }, "suggest": { "ext-xdebug": "For Xdebug profiling extension." @@ -6214,7 +6220,7 @@ ], "support": { "issues": "https://github.com/phpbench/phpbench/issues", - "source": "https://github.com/phpbench/phpbench/tree/1.4.2" + "source": "https://github.com/phpbench/phpbench/tree/1.4.3" }, "funding": [ { @@ -6222,7 +6228,7 @@ "type": "github" } ], - "time": "2025-10-26T14:21:59+00:00" + "time": "2025-11-06T19:07:31+00:00" }, { "name": "phpstan/phpstan", @@ -7871,16 +7877,16 @@ }, { "name": "symfony/console", - "version": "v7.3.5", + "version": "v7.3.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7" + "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/cdb80fa5869653c83cfe1a9084a673b6daf57ea7", - "reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7", + "url": "https://api.github.com/repos/symfony/console/zipball/c28ad91448f86c5f6d9d2c70f0cf68bf135f252a", + "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a", "shasum": "" }, "require": { @@ -7945,7 +7951,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.5" + "source": "https://github.com/symfony/console/tree/v7.3.6" }, "funding": [ { @@ -7965,20 +7971,20 @@ "type": "tidelift" } ], - "time": "2025-10-14T15:46:26+00:00" + "time": "2025-11-04T01:21:42+00:00" }, { "name": "symfony/filesystem", - "version": "v7.3.2", + "version": "v7.3.6", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd" + "reference": "e9bcfd7837928ab656276fe00464092cc9e1826a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/edcbb768a186b5c3f25d0643159a787d3e63b7fd", - "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/e9bcfd7837928ab656276fe00464092cc9e1826a", + "reference": "e9bcfd7837928ab656276fe00464092cc9e1826a", "shasum": "" }, "require": { @@ -8015,7 +8021,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.3.2" + "source": "https://github.com/symfony/filesystem/tree/v7.3.6" }, "funding": [ { @@ -8035,7 +8041,7 @@ "type": "tidelift" } ], - "time": "2025-07-07T08:17:47+00:00" + "time": "2025-11-05T09:52:27+00:00" }, { "name": "symfony/finder", From c784cf950bb9dd749e1337e629fdabcd006b2474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 10 Nov 2025 16:20:48 +0100 Subject: [PATCH 52/77] Add variables suggestion --- app/controllers/api/vcs.php | 63 ++++++++ composer.lock | 140 +++++++++--------- .../Response/Model/DetectionFramework.php | 7 + .../Response/Model/DetectionRuntime.php | 7 + .../Response/Model/ProviderRepository.php | 7 + 5 files changed, 157 insertions(+), 67 deletions(-) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index a6e72bf476..fd4d04cbd0 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -14,6 +14,7 @@ use Appwrite\Utopia\Database\Validator\Queries\Installations; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Appwrite\Vcs\Comment; +use Swoole\Coroutine\WaitGroup; use Utopia\App; use Utopia\CLI\Console; use Utopia\Config\Config; @@ -963,6 +964,37 @@ App::post('/v1/vcs/github/installations/:installationId/detections') throw new Exception(Exception::FUNCTION_RUNTIME_NOT_DETECTED); } } + + $wg = new WaitGroup(); + $envNames = []; + foreach ($files as $file) { + if (!(\str_starts_with($file, '.env'))) { + continue; + } + + $wg->add(); + go(function () use ($github, $owner, $repositoryName, $providerRootDirectory, $file, $wg, &$envNames) { + try { + $contentResponse = $github->getRepositoryContent($owner, $repositoryName, \rtrim($providerRootDirectory, '/') . '/' . $file); + $envFile = $contentResponse['content'] ?? ''; + + $envLines = \explode("\n", $envFile); + foreach ($envLines as $line) { + $parts = \explode('=', $line, 2); + $envName = \trim($parts[0] ?? ''); + if (!empty($envName)) { + $envNames[] = $envName; + } + } + } finally { + $wg->done(); + } + }); + } + $wg->wait(); + + $output->setAttribute('variables', \array_unique($envNames)); + $response->dynamic($output, $type === 'framework' ? Response::MODEL_DETECTION_FRAMEWORK : Response::MODEL_DETECTION_RUNTIME); }); @@ -1137,6 +1169,37 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') $repo['runtime'] = $runtimeWithVersion ?? ''; } } + + $wg = new WaitGroup(); + $envNames = []; + foreach ($files as $file) { + if (!(\str_starts_with($file, '.env'))) { + continue; + } + + $wg->add(); + go(function () use ($github, $repo, $file, $wg, &$envNames) { + try { + $contentResponse = $github->getRepositoryContent($repo['organization'], $repo['name'], $file); + $envFile = $contentResponse['content'] ?? ''; + + $envLines = \explode("\n", $envFile); + foreach ($envLines as $line) { + $parts = \explode('=', $line, 2); + $envName = \trim($parts[0] ?? ''); + if (!empty($envName)) { + $envNames[] = $envName; + } + } + } finally { + $wg->done(); + } + }); + } + $wg->wait(); + + $repo['variables'] = \array_unique($envNames); + return $repo; }; }, $repos)); diff --git a/composer.lock b/composer.lock index 87eaf28a3e..d0ea4e720a 100644 --- a/composer.lock +++ b/composer.lock @@ -2673,16 +2673,16 @@ }, { "name": "symfony/http-client", - "version": "v7.3.4", + "version": "v7.3.6", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "4b62871a01c49457cf2a8e560af7ee8a94b87a62" + "reference": "3c0a55a2c8e21e30a37022801c11c7ab5a6cb2de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/4b62871a01c49457cf2a8e560af7ee8a94b87a62", - "reference": "4b62871a01c49457cf2a8e560af7ee8a94b87a62", + "url": "https://api.github.com/repos/symfony/http-client/zipball/3c0a55a2c8e21e30a37022801c11c7ab5a6cb2de", + "reference": "3c0a55a2c8e21e30a37022801c11c7ab5a6cb2de", "shasum": "" }, "require": { @@ -2749,7 +2749,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.3.4" + "source": "https://github.com/symfony/http-client/tree/v7.3.6" }, "funding": [ { @@ -2769,7 +2769,7 @@ "type": "tidelift" } ], - "time": "2025-09-11T10:12:26+00:00" + "time": "2025-11-05T17:41:46+00:00" }, { "name": "symfony/http-client-contracts", @@ -3176,16 +3176,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.6.0", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", "shasum": "" }, "require": { @@ -3239,7 +3239,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" }, "funding": [ { @@ -3250,12 +3250,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-25T09:37:31+00:00" + "time": "2025-07-15T11:30:57+00:00" }, { "name": "tbachert/spi", @@ -3840,16 +3844,16 @@ }, { "name": "utopia-php/database", - "version": "3.1.5", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "76568b81f25d89fc1e0c53f0370f139130eeb939" + "reference": "f2d01b6b38057891184f62107bf70a55bc2ea068" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/76568b81f25d89fc1e0c53f0370f139130eeb939", - "reference": "76568b81f25d89fc1e0c53f0370f139130eeb939", + "url": "https://api.github.com/repos/utopia-php/database/zipball/f2d01b6b38057891184f62107bf70a55bc2ea068", + "reference": "f2d01b6b38057891184f62107bf70a55bc2ea068", "shasum": "" }, "require": { @@ -3892,9 +3896,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/3.1.5" + "source": "https://github.com/utopia-php/database/tree/3.2.0" }, - "time": "2025-11-05T10:17:55+00:00" + "time": "2025-11-06T05:41:54+00:00" }, { "name": "utopia-php/detector", @@ -3943,22 +3947,24 @@ }, { "name": "utopia-php/dns", - "version": "1.1.0", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/utopia-php/dns.git", - "reference": "d6eca184883262bdcb4261e57491c91b16079b9a" + "reference": "1e6b4bac735329c9e5ec69a6a5d899ec2d050707" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/dns/zipball/d6eca184883262bdcb4261e57491c91b16079b9a", - "reference": "d6eca184883262bdcb4261e57491c91b16079b9a", + "url": "https://api.github.com/repos/utopia-php/dns/zipball/1e6b4bac735329c9e5ec69a6a5d899ec2d050707", + "reference": "1e6b4bac735329c9e5ec69a6a5d899ec2d050707", "shasum": "" }, "require": { "php": ">=8.3", "utopia-php/console": "0.0.*", - "utopia-php/telemetry": "0.1.*" + "utopia-php/domains": "0.9.*", + "utopia-php/telemetry": "0.1.*", + "utopia-php/validators": "^0.0.2" }, "require-dev": { "laravel/pint": "1.25.*", @@ -3992,9 +3998,9 @@ ], "support": { "issues": "https://github.com/utopia-php/dns/issues", - "source": "https://github.com/utopia-php/dns/tree/1.1.0" + "source": "https://github.com/utopia-php/dns/tree/1.1.3" }, - "time": "2025-11-03T22:49:02+00:00" + "time": "2025-11-06T19:08:29+00:00" }, { "name": "utopia-php/domains", @@ -5377,16 +5383,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.5.1", + "version": "1.5.3", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "cd712674e34136f706e9170641ed6f4ce160e772" + "reference": "1a7a3b89147aa8c1bde5247f8eeb7e4832c6016d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/cd712674e34136f706e9170641ed6f4ce160e772", - "reference": "cd712674e34136f706e9170641ed6f4ce160e772", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/1a7a3b89147aa8c1bde5247f8eeb7e4832c6016d", + "reference": "1a7a3b89147aa8c1bde5247f8eeb7e4832c6016d", "shasum": "" }, "require": { @@ -5422,9 +5428,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.5.1" + "source": "https://github.com/appwrite/sdk-generator/tree/1.5.3" }, - "time": "2025-11-04T09:55:47+00:00" + "time": "2025-11-10T09:50:41+00:00" }, { "name": "doctrine/annotations", @@ -6077,24 +6083,24 @@ }, { "name": "phpbench/container", - "version": "2.2.2", + "version": "2.2.3", "source": { "type": "git", "url": "https://github.com/phpbench/container.git", - "reference": "a59b929e00b87b532ca6d0edd8eca0967655af33" + "reference": "0c7b2d36c1ea53fe27302fb8873ded7172047196" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpbench/container/zipball/a59b929e00b87b532ca6d0edd8eca0967655af33", - "reference": "a59b929e00b87b532ca6d0edd8eca0967655af33", + "url": "https://api.github.com/repos/phpbench/container/zipball/0c7b2d36c1ea53fe27302fb8873ded7172047196", + "reference": "0c7b2d36c1ea53fe27302fb8873ded7172047196", "shasum": "" }, "require": { "psr/container": "^1.0|^2.0", - "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0 || ^7.0" + "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0 || ^7.0 || ^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.16", + "php-cs-fixer/shim": "^3.89", "phpstan/phpstan": "^0.12.52", "phpunit/phpunit": "^8" }, @@ -6122,22 +6128,22 @@ "description": "Simple, configurable, service container.", "support": { "issues": "https://github.com/phpbench/container/issues", - "source": "https://github.com/phpbench/container/tree/2.2.2" + "source": "https://github.com/phpbench/container/tree/2.2.3" }, - "time": "2023-10-30T13:38:26+00:00" + "time": "2025-11-06T09:05:13+00:00" }, { "name": "phpbench/phpbench", - "version": "1.4.2", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/phpbench/phpbench.git", - "reference": "bb61ae6c54b3d58642be154eb09f4e73c3511018" + "reference": "b641dde59d969ea42eed70a39f9b51950bc96878" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpbench/phpbench/zipball/bb61ae6c54b3d58642be154eb09f4e73c3511018", - "reference": "bb61ae6c54b3d58642be154eb09f4e73c3511018", + "url": "https://api.github.com/repos/phpbench/phpbench/zipball/b641dde59d969ea42eed70a39f9b51950bc96878", + "reference": "b641dde59d969ea42eed70a39f9b51950bc96878", "shasum": "" }, "require": { @@ -6152,26 +6158,26 @@ "phpbench/container": "^2.2", "psr/log": "^1.1 || ^2.0 || ^3.0", "seld/jsonlint": "^1.1", - "symfony/console": "^6.1 || ^7.0", - "symfony/filesystem": "^6.1 || ^7.0", - "symfony/finder": "^6.1 || ^7.0", - "symfony/options-resolver": "^6.1 || ^7.0", - "symfony/process": "^6.1 || ^7.0", + "symfony/console": "^6.1 || ^7.0 || ^8.0", + "symfony/filesystem": "^6.1 || ^7.0 || ^8.0", + "symfony/finder": "^6.1 || ^7.0 || ^8.0", + "symfony/options-resolver": "^6.1 || ^7.0 || ^8.0", + "symfony/process": "^6.1 || ^7.0 || ^8.0", "webmozart/glob": "^4.6" }, "require-dev": { "dantleech/invoke": "^2.0", "ergebnis/composer-normalize": "^2.39", - "friendsofphp/php-cs-fixer": "^3.0", "jangregor/phpstan-prophecy": "^1.0", + "php-cs-fixer/shim": "^3.9", "phpspec/prophecy": "^1.22", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.0", "phpstan/phpstan-phpunit": "^1.0", "phpunit/phpunit": "^10.4 || ^11.0", "rector/rector": "^1.2", - "symfony/error-handler": "^6.1 || ^7.0", - "symfony/var-dumper": "^6.1 || ^7.0" + "symfony/error-handler": "^6.1 || ^7.0 || ^8.0", + "symfony/var-dumper": "^6.1 || ^7.0 || ^8.0" }, "suggest": { "ext-xdebug": "For Xdebug profiling extension." @@ -6214,7 +6220,7 @@ ], "support": { "issues": "https://github.com/phpbench/phpbench/issues", - "source": "https://github.com/phpbench/phpbench/tree/1.4.2" + "source": "https://github.com/phpbench/phpbench/tree/1.4.3" }, "funding": [ { @@ -6222,7 +6228,7 @@ "type": "github" } ], - "time": "2025-10-26T14:21:59+00:00" + "time": "2025-11-06T19:07:31+00:00" }, { "name": "phpstan/phpstan", @@ -7871,16 +7877,16 @@ }, { "name": "symfony/console", - "version": "v7.3.5", + "version": "v7.3.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7" + "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/cdb80fa5869653c83cfe1a9084a673b6daf57ea7", - "reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7", + "url": "https://api.github.com/repos/symfony/console/zipball/c28ad91448f86c5f6d9d2c70f0cf68bf135f252a", + "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a", "shasum": "" }, "require": { @@ -7945,7 +7951,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.5" + "source": "https://github.com/symfony/console/tree/v7.3.6" }, "funding": [ { @@ -7965,20 +7971,20 @@ "type": "tidelift" } ], - "time": "2025-10-14T15:46:26+00:00" + "time": "2025-11-04T01:21:42+00:00" }, { "name": "symfony/filesystem", - "version": "v7.3.2", + "version": "v7.3.6", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd" + "reference": "e9bcfd7837928ab656276fe00464092cc9e1826a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/edcbb768a186b5c3f25d0643159a787d3e63b7fd", - "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/e9bcfd7837928ab656276fe00464092cc9e1826a", + "reference": "e9bcfd7837928ab656276fe00464092cc9e1826a", "shasum": "" }, "require": { @@ -8015,7 +8021,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.3.2" + "source": "https://github.com/symfony/filesystem/tree/v7.3.6" }, "funding": [ { @@ -8035,7 +8041,7 @@ "type": "tidelift" } ], - "time": "2025-07-07T08:17:47+00:00" + "time": "2025-11-05T09:52:27+00:00" }, { "name": "symfony/finder", @@ -8891,7 +8897,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8915,5 +8921,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.3.0" } diff --git a/src/Appwrite/Utopia/Response/Model/DetectionFramework.php b/src/Appwrite/Utopia/Response/Model/DetectionFramework.php index 9aeb885f76..899ad8766e 100644 --- a/src/Appwrite/Utopia/Response/Model/DetectionFramework.php +++ b/src/Appwrite/Utopia/Response/Model/DetectionFramework.php @@ -33,6 +33,13 @@ class DetectionFramework extends Model 'description' => 'Site Output Directory', 'default' => '', 'example' => 'dist', + ]) + ->addRule('variables', [ + 'type' => self::TYPE_STRING, + 'description' => 'Environment variables found in .env files', + 'default' => [], + 'array' => true, + 'example' => ['PORT', 'NODE_ENV'], ]); } diff --git a/src/Appwrite/Utopia/Response/Model/DetectionRuntime.php b/src/Appwrite/Utopia/Response/Model/DetectionRuntime.php index 1c7c0be16b..20fde90491 100644 --- a/src/Appwrite/Utopia/Response/Model/DetectionRuntime.php +++ b/src/Appwrite/Utopia/Response/Model/DetectionRuntime.php @@ -27,6 +27,13 @@ class DetectionRuntime extends Model 'description' => 'Function install and build commands', 'default' => '', 'example' => 'npm install && npm run build', + ]) + ->addRule('variables', [ + 'type' => self::TYPE_STRING, + 'description' => 'Environment variables found in .env files', + 'default' => [], + 'array' => true, + 'example' => ['PORT', 'NODE_ENV'], ]); } diff --git a/src/Appwrite/Utopia/Response/Model/ProviderRepository.php b/src/Appwrite/Utopia/Response/Model/ProviderRepository.php index eee058a05b..ddad0b059c 100644 --- a/src/Appwrite/Utopia/Response/Model/ProviderRepository.php +++ b/src/Appwrite/Utopia/Response/Model/ProviderRepository.php @@ -53,6 +53,13 @@ class ProviderRepository extends Model 'default' => APP_DATABASE_ATTRIBUTE_DATETIME, 'example' => APP_DATABASE_ATTRIBUTE_DATETIME, 'array' => false, + ]) + ->addRule('variables', [ + 'type' => self::TYPE_STRING, + 'description' => 'Environment variables found in .env files', + 'default' => [], + 'array' => true, + 'example' => ['PORT', 'NODE_ENV'], ]); } From 831a261c04e76f5a75089ec506dc89c70a1a16ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 10 Nov 2025 16:29:34 +0100 Subject: [PATCH 53/77] Sync unit tests with DNS lib validator --- tests/unit/Network/Validators/DNSTest.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/unit/Network/Validators/DNSTest.php b/tests/unit/Network/Validators/DNSTest.php index 9f8928b87f..4611e00f4d 100644 --- a/tests/unit/Network/Validators/DNSTest.php +++ b/tests/unit/Network/Validators/DNSTest.php @@ -51,8 +51,10 @@ class DNSTest extends TestCase #[Retry(count: 5)] public function testCAA(): void { - $certainly = new DNS('certainly.com', Record::TYPE_CAA, 'ns1.digitalocean.com'); - $letsencrypt = new DNS('letsencrypt.org', Record::TYPE_CAA, 'ns1.digitalocean.com'); + $digitalOceanIp = '172.64.52.210'; // ping ns1.digitalocean.com + + $certainly = new DNS('certainly.com', Record::TYPE_CAA, $digitalOceanIp); + $letsencrypt = new DNS('letsencrypt.org', Record::TYPE_CAA, $digitalOceanIp); // No CAA record succeeds on main domain & subdomains for any issuer $this->assertEquals($certainly->isValid('caa.appwrite.org'), true); From 37910a4c5c4d14c4d45e0c57b4eb332f498599ab Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 12 Nov 2025 16:59:50 +1300 Subject: [PATCH 54/77] Fix space --- app/controllers/api/account.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 0dee54ef29..b6e1ebcc61 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1112,7 +1112,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'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; From 1da4736d5d2b3a299b43c97ea84ad18378dd05f1 Mon Sep 17 00:00:00 2001 From: shimon Date: Thu, 13 Nov 2025 11:23:26 +0200 Subject: [PATCH 55/77] composer.lock --- composer.lock | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/composer.lock b/composer.lock index 64c5df8f51..8692e3e3de 100644 --- a/composer.lock +++ b/composer.lock @@ -756,16 +756,16 @@ }, { "name": "google/protobuf", - "version": "v4.33.0", + "version": "v4.33.1", "source": { "type": "git", "url": "https://github.com/protocolbuffers/protobuf-php.git", - "reference": "b50269e23204e5ae859a326ec3d90f09efe3047d" + "reference": "0cd73ccf0cd26c3e72299cce1ea6144091a57e12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/b50269e23204e5ae859a326ec3d90f09efe3047d", - "reference": "b50269e23204e5ae859a326ec3d90f09efe3047d", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/0cd73ccf0cd26c3e72299cce1ea6144091a57e12", + "reference": "0cd73ccf0cd26c3e72299cce1ea6144091a57e12", "shasum": "" }, "require": { @@ -794,9 +794,9 @@ "proto" ], "support": { - "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.33.0" + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.33.1" }, - "time": "2025-10-15T20:10:28+00:00" + "time": "2025-11-12T21:58:05+00:00" }, { "name": "league/csv", @@ -3844,16 +3844,16 @@ }, { "name": "utopia-php/database", - "version": "4.1.0", + "version": "4.2.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "ce3986e82edc4968fe7eca152c0f5e0006059df9" + "reference": "3038eb6336dfef6da3f4d68178baa70d00cfc906" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/ce3986e82edc4968fe7eca152c0f5e0006059df9", - "reference": "ce3986e82edc4968fe7eca152c0f5e0006059df9", + "url": "https://api.github.com/repos/utopia-php/database/zipball/3038eb6336dfef6da3f4d68178baa70d00cfc906", + "reference": "3038eb6336dfef6da3f4d68178baa70d00cfc906", "shasum": "" }, "require": { @@ -3896,9 +3896,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/4.1.0" + "source": "https://github.com/utopia-php/database/tree/4.2.0" }, - "time": "2025-11-12T03:43:25+00:00" + "time": "2025-11-12T09:03:35+00:00" }, { "name": "utopia-php/detector", @@ -5383,16 +5383,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.5.3", + "version": "1.5.4", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "1a7a3b89147aa8c1bde5247f8eeb7e4832c6016d" + "reference": "958947b6483a79e11c3812f23bb3056199fa4105" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/1a7a3b89147aa8c1bde5247f8eeb7e4832c6016d", - "reference": "1a7a3b89147aa8c1bde5247f8eeb7e4832c6016d", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/958947b6483a79e11c3812f23bb3056199fa4105", + "reference": "958947b6483a79e11c3812f23bb3056199fa4105", "shasum": "" }, "require": { @@ -5428,9 +5428,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.5.3" + "source": "https://github.com/appwrite/sdk-generator/tree/1.5.4" }, - "time": "2025-11-10T09:50:41+00:00" + "time": "2025-11-12T12:43:42+00:00" }, { "name": "doctrine/annotations", @@ -8897,7 +8897,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8921,5 +8921,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.2.0" } From afb0fcbc6f9f5903a5850ed4f7ab76d74edda543 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 14 Nov 2025 16:45:21 +1300 Subject: [PATCH 56/77] Update DB --- composer.lock | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/composer.lock b/composer.lock index 8692e3e3de..8a91ad171e 100644 --- a/composer.lock +++ b/composer.lock @@ -3844,16 +3844,16 @@ }, { "name": "utopia-php/database", - "version": "4.2.0", + "version": "4.3.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "3038eb6336dfef6da3f4d68178baa70d00cfc906" + "reference": "fe7a1326ad623609e65587fe8c01a630a7075fee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/3038eb6336dfef6da3f4d68178baa70d00cfc906", - "reference": "3038eb6336dfef6da3f4d68178baa70d00cfc906", + "url": "https://api.github.com/repos/utopia-php/database/zipball/fe7a1326ad623609e65587fe8c01a630a7075fee", + "reference": "fe7a1326ad623609e65587fe8c01a630a7075fee", "shasum": "" }, "require": { @@ -3896,9 +3896,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/4.2.0" + "source": "https://github.com/utopia-php/database/tree/4.3.0" }, - "time": "2025-11-12T09:03:35+00:00" + "time": "2025-11-14T03:43:10+00:00" }, { "name": "utopia-php/detector", @@ -8718,16 +8718,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.2.3", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/d74205c497bfbca49f34d4bc4c19c17e22db4ebb", + "reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb", "shasum": "" }, "require": { @@ -8756,7 +8756,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "source": "https://github.com/theseer/tokenizer/tree/1.3.0" }, "funding": [ { @@ -8764,7 +8764,7 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-11-13T13:44:09+00:00" }, { "name": "twig/twig", @@ -8897,7 +8897,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8921,5 +8921,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.6.0" } From 2349401a865cfb1124476610b82913dc1c46f962 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 14 Nov 2025 18:49:26 +1300 Subject: [PATCH 57/77] Fix merge --- .../Databases/Http/Databases/Transactions/Update.php | 2 +- src/Appwrite/Platform/Workers/Migrations.php | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) 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 bf84b05e04..ec5f0e4c04 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php @@ -166,7 +166,7 @@ class Update extends Action } if (!isset($collections[$collectionId])) { - $collections[$collectionId] = Authorization::skip( + $collections[$collectionId] = $authorization->skip( fn () => $dbForProject->getCollection($collectionId) ); } diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 0bd5c50e04..0dff335f4d 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -84,6 +84,7 @@ class Migrations extends Action ->inject('deviceForFiles') ->inject('queueForMails') ->inject('plan') + ->inject('authorization') ->callback($this->action(...)); } @@ -101,6 +102,7 @@ class Migrations extends Action Device $deviceForFiles, Mail $queueForMails, array $plan, + Authorization $authorization, ): void { $payload = $message->getPayload() ?? []; $this->deviceForMigrations = $deviceForMigrations; @@ -127,7 +129,7 @@ class Migrations extends Action return; } - $this->processMigration($migration, $queueForRealtime, $queueForMails); + $this->processMigration($migration, $queueForRealtime, $queueForMails, $authorization); } /** @@ -296,6 +298,7 @@ class Migrations extends Action Document $migration, Realtime $queueForRealtime, Mail $queueForMails, + Authorization $authorization, ): void { $project = $this->dbForPlatform->getDocument('projects', $this->project->getId()); $tempAPIKey = $this->generateAPIKey($project); @@ -432,7 +435,8 @@ class Migrations extends Action protected function handleCSVExportComplete( Document $project, Document $migration, - Mail $queueForMails + Mail $queueForMails, + Authorization $authorization, ): void { $options = $migration->getAttribute('options', []); $bucketId = 'default'; // Always use platform default bucket @@ -446,7 +450,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'); } From c961316f464a59d3040dc9f993d8a802d298d46a Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 14 Nov 2025 19:08:33 +1300 Subject: [PATCH 58/77] Fix params --- src/Appwrite/Platform/Workers/Migrations.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 0dff335f4d..08782fd825 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -414,7 +414,7 @@ class Migrations extends Action $source?->success(); if ($migration->getAttribute('destination') === DestinationCSV::getName()) { - $this->handleCSVExportComplete($project, $migration, $queueForMails); + $this->handleCSVExportComplete($project, $migration, $queueForMails, $authorization); } } } From db1b87ecbb79a9e17d545fd3a017773cf681de36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Fri, 14 Nov 2025 15:49:19 +0100 Subject: [PATCH 59/77] Add env var value detection --- app/controllers/api/vcs.php | 32 +++++++++---- src/Appwrite/Utopia/Response.php | 3 ++ .../Utopia/Response/Model/Detection.php | 22 +++++++++ .../Response/Model/DetectionFramework.php | 12 ++--- .../Response/Model/DetectionRuntime.php | 12 ++--- .../Response/Model/DetectionVariable.php | 46 +++++++++++++++++++ 6 files changed, 101 insertions(+), 26 deletions(-) create mode 100644 src/Appwrite/Utopia/Response/Model/Detection.php create mode 100644 src/Appwrite/Utopia/Response/Model/DetectionVariable.php diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index fd4d04cbd0..2ac6cd0b26 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -966,14 +966,14 @@ App::post('/v1/vcs/github/installations/:installationId/detections') } $wg = new WaitGroup(); - $envNames = []; + $envs = []; foreach ($files as $file) { if (!(\str_starts_with($file, '.env'))) { continue; } $wg->add(); - go(function () use ($github, $owner, $repositoryName, $providerRootDirectory, $file, $wg, &$envNames) { + go(function () use ($github, $owner, $repositoryName, $providerRootDirectory, $file, $wg, &$envs) { try { $contentResponse = $github->getRepositoryContent($owner, $repositoryName, \rtrim($providerRootDirectory, '/') . '/' . $file); $envFile = $contentResponse['content'] ?? ''; @@ -982,8 +982,9 @@ App::post('/v1/vcs/github/installations/:installationId/detections') foreach ($envLines as $line) { $parts = \explode('=', $line, 2); $envName = \trim($parts[0] ?? ''); + $envValue = \trim($parts[1] ?? ''); if (!empty($envName)) { - $envNames[] = $envName; + $envs[$envName] = $envValue; } } } finally { @@ -993,7 +994,15 @@ App::post('/v1/vcs/github/installations/:installationId/detections') } $wg->wait(); - $output->setAttribute('variables', \array_unique($envNames)); + $variables = []; + foreach ($envs as $key => $value) { + $variables[] = [ + 'name' => $key, + 'value' => $value, + ]; + } + + $output->setAttribute('variables', $variables); $response->dynamic($output, $type === 'framework' ? Response::MODEL_DETECTION_FRAMEWORK : Response::MODEL_DETECTION_RUNTIME); }); @@ -1171,14 +1180,14 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') } $wg = new WaitGroup(); - $envNames = []; + $envs = []; foreach ($files as $file) { if (!(\str_starts_with($file, '.env'))) { continue; } $wg->add(); - go(function () use ($github, $repo, $file, $wg, &$envNames) { + go(function () use ($github, $repo, $file, $wg, &$envs) { try { $contentResponse = $github->getRepositoryContent($repo['organization'], $repo['name'], $file); $envFile = $contentResponse['content'] ?? ''; @@ -1187,8 +1196,9 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') foreach ($envLines as $line) { $parts = \explode('=', $line, 2); $envName = \trim($parts[0] ?? ''); + $envValue = \trim($parts[1] ?? ''); if (!empty($envName)) { - $envNames[] = $envName; + $envs[$envName] = $envValue; } } } finally { @@ -1198,7 +1208,13 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') } $wg->wait(); - $repo['variables'] = \array_unique($envNames); + $repo['variables'] = []; + foreach ($envs as $key => $value) { + $repo['variables'][] = [ + 'name' => $key, + 'value' => $value, + ]; + } return $repo; }; diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index b391f0ea72..19a451e2c0 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -59,6 +59,7 @@ use Appwrite\Utopia\Response\Model\Database; use Appwrite\Utopia\Response\Model\Deployment; use Appwrite\Utopia\Response\Model\DetectionFramework; use Appwrite\Utopia\Response\Model\DetectionRuntime; +use Appwrite\Utopia\Response\Model\DetectionVariable; use Appwrite\Utopia\Response\Model\DevKey; use Appwrite\Utopia\Response\Model\Document as ModelDocument; use Appwrite\Utopia\Response\Model\Error; @@ -316,6 +317,7 @@ class Response extends SwooleResponse public const MODEL_BRANCH = 'branch'; public const MODEL_BRANCH_LIST = 'branchList'; public const MODEL_DETECTION_FRAMEWORK = 'detectionFramework'; + public const MODEL_DETECTION_VARIABLE = 'detectionVariable'; public const MODEL_DETECTION_RUNTIME = 'detectionRuntime'; public const MODEL_VCS_CONTENT = 'vcsContent'; public const MODEL_VCS_CONTENT_LIST = 'vcsContentList'; @@ -563,6 +565,7 @@ class Response extends SwooleResponse ->setModel(new ProviderRepositoryRuntime()) ->setModel(new DetectionFramework()) ->setModel(new DetectionRuntime()) + ->setModel(new DetectionVariable()) ->setModel(new VcsContent()) ->setModel(new Branch()) ->setModel(new Runtime()) diff --git a/src/Appwrite/Utopia/Response/Model/Detection.php b/src/Appwrite/Utopia/Response/Model/Detection.php new file mode 100644 index 0000000000..007182d1e9 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/Detection.php @@ -0,0 +1,22 @@ +addRule('variables', [ + 'type' => Response::MODEL_DETECTION_VARIABLE, + 'description' => 'Environment variables found in .env files', + 'required' => false, + 'default' => [], + 'example' => new \stdClass(), + 'array' => true, + ]); + } +} diff --git a/src/Appwrite/Utopia/Response/Model/DetectionFramework.php b/src/Appwrite/Utopia/Response/Model/DetectionFramework.php index 899ad8766e..4cdf37bbcf 100644 --- a/src/Appwrite/Utopia/Response/Model/DetectionFramework.php +++ b/src/Appwrite/Utopia/Response/Model/DetectionFramework.php @@ -3,12 +3,13 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; -use Appwrite\Utopia\Response\Model; -class DetectionFramework extends Model +class DetectionFramework extends Detection { public function __construct() { + parent::__construct(); + $this ->addRule('framework', [ 'type' => self::TYPE_STRING, @@ -33,13 +34,6 @@ class DetectionFramework extends Model 'description' => 'Site Output Directory', 'default' => '', 'example' => 'dist', - ]) - ->addRule('variables', [ - 'type' => self::TYPE_STRING, - 'description' => 'Environment variables found in .env files', - 'default' => [], - 'array' => true, - 'example' => ['PORT', 'NODE_ENV'], ]); } diff --git a/src/Appwrite/Utopia/Response/Model/DetectionRuntime.php b/src/Appwrite/Utopia/Response/Model/DetectionRuntime.php index 20fde90491..1e63929092 100644 --- a/src/Appwrite/Utopia/Response/Model/DetectionRuntime.php +++ b/src/Appwrite/Utopia/Response/Model/DetectionRuntime.php @@ -3,12 +3,13 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; -use Appwrite\Utopia\Response\Model; -class DetectionRuntime extends Model +class DetectionRuntime extends Detection { public function __construct() { + parent::__construct(); + $this ->addRule('runtime', [ 'type' => self::TYPE_STRING, @@ -27,13 +28,6 @@ class DetectionRuntime extends Model 'description' => 'Function install and build commands', 'default' => '', 'example' => 'npm install && npm run build', - ]) - ->addRule('variables', [ - 'type' => self::TYPE_STRING, - 'description' => 'Environment variables found in .env files', - 'default' => [], - 'array' => true, - 'example' => ['PORT', 'NODE_ENV'], ]); } diff --git a/src/Appwrite/Utopia/Response/Model/DetectionVariable.php b/src/Appwrite/Utopia/Response/Model/DetectionVariable.php new file mode 100644 index 0000000000..a5a2d2acc0 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/DetectionVariable.php @@ -0,0 +1,46 @@ +addRule('name', [ + 'type' => self::TYPE_STRING, + 'description' => 'Name of environment variable', + 'default' => '', + 'example' => 'NODE_ENV', + ]) + ->addRule('value', [ + 'type' => self::TYPE_STRING, + 'description' => 'Value of environment variable', + 'default' => '', + 'example' => 'production', + ]); + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'DetectionVariable'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_DETECTION_VARIABLE; + } +} From 793057c82394aaff6ce27d0222ddf62d440e257c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Fri, 14 Nov 2025 18:06:20 +0100 Subject: [PATCH 60/77] Update composer.lock --- composer.lock | 86 +++++++++++++++++++++++++-------------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/composer.lock b/composer.lock index d0ea4e720a..bc61d61460 100644 --- a/composer.lock +++ b/composer.lock @@ -161,16 +161,16 @@ }, { "name": "appwrite/php-runtimes", - "version": "0.19.1", + "version": "0.19.2", "source": { "type": "git", "url": "https://github.com/appwrite/runtimes.git", - "reference": "7bd0cc3cb97de625d7b07230bd91b121f88e72ae" + "reference": "e5c142519df5aced37de9c302971c29c079ce3d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/runtimes/zipball/7bd0cc3cb97de625d7b07230bd91b121f88e72ae", - "reference": "7bd0cc3cb97de625d7b07230bd91b121f88e72ae", + "url": "https://api.github.com/repos/appwrite/runtimes/zipball/e5c142519df5aced37de9c302971c29c079ce3d9", + "reference": "e5c142519df5aced37de9c302971c29c079ce3d9", "shasum": "" }, "require": { @@ -210,9 +210,9 @@ ], "support": { "issues": "https://github.com/appwrite/runtimes/issues", - "source": "https://github.com/appwrite/runtimes/tree/0.19.1" + "source": "https://github.com/appwrite/runtimes/tree/0.19.2" }, - "time": "2025-05-27T07:12:56+00:00" + "time": "2025-11-11T13:44:44+00:00" }, { "name": "beberlei/assert", @@ -756,16 +756,16 @@ }, { "name": "google/protobuf", - "version": "v4.33.0", + "version": "v4.33.1", "source": { "type": "git", "url": "https://github.com/protocolbuffers/protobuf-php.git", - "reference": "b50269e23204e5ae859a326ec3d90f09efe3047d" + "reference": "0cd73ccf0cd26c3e72299cce1ea6144091a57e12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/b50269e23204e5ae859a326ec3d90f09efe3047d", - "reference": "b50269e23204e5ae859a326ec3d90f09efe3047d", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/0cd73ccf0cd26c3e72299cce1ea6144091a57e12", + "reference": "0cd73ccf0cd26c3e72299cce1ea6144091a57e12", "shasum": "" }, "require": { @@ -794,9 +794,9 @@ "proto" ], "support": { - "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.33.0" + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.33.1" }, - "time": "2025-10-15T20:10:28+00:00" + "time": "2025-11-12T21:58:05+00:00" }, { "name": "league/csv", @@ -961,16 +961,16 @@ }, { "name": "mongodb/mongodb", - "version": "2.1.1", + "version": "2.1.2", "source": { "type": "git", "url": "https://github.com/mongodb/mongo-php-library.git", - "reference": "f399d24905dd42f97dfe0af9706129743ef247ac" + "reference": "0a2472ba9cbb932f7e43a8770aedb2fc30612a67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mongodb/mongo-php-library/zipball/f399d24905dd42f97dfe0af9706129743ef247ac", - "reference": "f399d24905dd42f97dfe0af9706129743ef247ac", + "url": "https://api.github.com/repos/mongodb/mongo-php-library/zipball/0a2472ba9cbb932f7e43a8770aedb2fc30612a67", + "reference": "0a2472ba9cbb932f7e43a8770aedb2fc30612a67", "shasum": "" }, "require": { @@ -986,7 +986,7 @@ "require-dev": { "doctrine/coding-standard": "^12.0", "phpunit/phpunit": "^10.5.35", - "rector/rector": "^1.2", + "rector/rector": "^2.1.4", "squizlabs/php_codesniffer": "^3.7", "vimeo/psalm": "6.5.*" }, @@ -1032,9 +1032,9 @@ ], "support": { "issues": "https://github.com/mongodb/mongo-php-library/issues", - "source": "https://github.com/mongodb/mongo-php-library/tree/2.1.1" + "source": "https://github.com/mongodb/mongo-php-library/tree/2.1.2" }, - "time": "2025-08-13T20:50:05+00:00" + "time": "2025-10-06T12:12:40+00:00" }, { "name": "mustangostang/spyc", @@ -3844,16 +3844,16 @@ }, { "name": "utopia-php/database", - "version": "3.2.0", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "f2d01b6b38057891184f62107bf70a55bc2ea068" + "reference": "e10b4faa4f3a3ef30a5f6d76acdb605469924aec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/f2d01b6b38057891184f62107bf70a55bc2ea068", - "reference": "f2d01b6b38057891184f62107bf70a55bc2ea068", + "url": "https://api.github.com/repos/utopia-php/database/zipball/e10b4faa4f3a3ef30a5f6d76acdb605469924aec", + "reference": "e10b4faa4f3a3ef30a5f6d76acdb605469924aec", "shasum": "" }, "require": { @@ -3896,9 +3896,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/3.2.0" + "source": "https://github.com/utopia-php/database/tree/3.4.0" }, - "time": "2025-11-06T05:41:54+00:00" + "time": "2025-11-13T06:34:20+00:00" }, { "name": "utopia-php/detector", @@ -4212,16 +4212,16 @@ }, { "name": "utopia-php/framework", - "version": "0.33.28", + "version": "0.33.29", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "5aaa94d406577b0059ad28c78022606890dc6de0" + "reference": "6e63939fdb33b847f92839499cd6e8df626c278d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/5aaa94d406577b0059ad28c78022606890dc6de0", - "reference": "5aaa94d406577b0059ad28c78022606890dc6de0", + "url": "https://api.github.com/repos/utopia-php/http/zipball/6e63939fdb33b847f92839499cd6e8df626c278d", + "reference": "6e63939fdb33b847f92839499cd6e8df626c278d", "shasum": "" }, "require": { @@ -4253,9 +4253,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.28" + "source": "https://github.com/utopia-php/http/tree/0.33.29" }, - "time": "2025-09-25T10:44:24+00:00" + "time": "2025-11-14T06:33:29+00:00" }, { "name": "utopia-php/image", @@ -5383,16 +5383,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.5.3", + "version": "1.5.5", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "1a7a3b89147aa8c1bde5247f8eeb7e4832c6016d" + "reference": "1f3686e41a2d10829220b74f54c80a770e9f968a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/1a7a3b89147aa8c1bde5247f8eeb7e4832c6016d", - "reference": "1a7a3b89147aa8c1bde5247f8eeb7e4832c6016d", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/1f3686e41a2d10829220b74f54c80a770e9f968a", + "reference": "1f3686e41a2d10829220b74f54c80a770e9f968a", "shasum": "" }, "require": { @@ -5428,9 +5428,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.5.3" + "source": "https://github.com/appwrite/sdk-generator/tree/1.5.5" }, - "time": "2025-11-10T09:50:41+00:00" + "time": "2025-11-14T05:56:33+00:00" }, { "name": "doctrine/annotations", @@ -8718,16 +8718,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.2.3", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/d74205c497bfbca49f34d4bc4c19c17e22db4ebb", + "reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb", "shasum": "" }, "require": { @@ -8756,7 +8756,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "source": "https://github.com/theseer/tokenizer/tree/1.3.0" }, "funding": [ { @@ -8764,7 +8764,7 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-11-13T13:44:09+00:00" }, { "name": "twig/twig", From 3568af54b3176612bcd9e1e50959401cb23c20a3 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 18 Nov 2025 09:51:20 +0530 Subject: [PATCH 61/77] consistent naming --- app/controllers/api/storage.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index df177bc8e5..c2adc1e195 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -980,14 +980,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') /* @type Document $bucket */ $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAppUser = Auth::isAppUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser($authorization->getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); - if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAppUser && !$isPrivilegedUser)) { + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - if (!$bucket->getAttribute('transformations', true) && !$isAppUser && !$isPrivilegedUser) { + if (!$bucket->getAttribute('transformations', true) && !$isAPIKey && !$isPrivilegedUser) { throw new Exception(Exception::STORAGE_BUCKET_TRANSFORMATIONS_DISABLED); } From f9274dad3ffea75a546f4f282c2fa94c16faf650 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 18 Nov 2025 09:53:13 +0530 Subject: [PATCH 62/77] regenerate specs --- app/config/specs/open-api3-1.8.x-console.json | 169 +++++++++++++++-- app/config/specs/open-api3-1.8.x-server.json | 73 ++++++-- .../specs/open-api3-latest-console.json | 127 ++++++++++++- app/config/specs/open-api3-latest-server.json | 31 +++- app/config/specs/swagger2-1.8.x-console.json | 175 ++++++++++++++++-- app/config/specs/swagger2-1.8.x-server.json | 77 ++++++-- app/config/specs/swagger2-latest-console.json | 131 ++++++++++++- app/config/specs/swagger2-latest-server.json | 33 +++- 8 files changed, 728 insertions(+), 88 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 6b6ab7409f..fded6c46b0 100644 --- a/app/config/specs/open-api3-1.8.x-console.json +++ b/app/config/specs/open-api3-1.8.x-console.json @@ -7753,7 +7753,8 @@ "default": { "type": "string", "description": "Default value for the attribute in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when attribute is required.", - "x-example": null + "x-example": null, + "x-nullable": true }, "array": { "type": "boolean", @@ -14414,10 +14415,22 @@ "description": "Path to function code in the template repo.", "x-example": "" }, - "version": { + "type": { "type": "string", - "description": "Version (tag) for the repo linked to the function template.", - "x-example": "" + "description": "Type for the reference provided. Can be commit, branch, or tag", + "x-example": "commit", + "enum": [ + "commit", + "branch", + "tag" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "reference": { + "type": "string", + "description": "Reference value, can be a commit hash, branch name, or release tag", + "x-example": "" }, "activate": { "type": "boolean", @@ -14429,7 +14442,8 @@ "repository", "owner", "rootDirectory", - "version" + "type", + "reference" ] } } @@ -32314,10 +32328,22 @@ "description": "Path to site code in the template repo.", "x-example": "" }, - "version": { + "type": { "type": "string", - "description": "Version (tag) for the repo linked to the site template.", - "x-example": "" + "description": "Type for the reference provided. Can be commit, branch, or tag", + "x-example": "branch", + "enum": [ + "branch", + "commit", + "tag" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "reference": { + "type": "string", + "description": "Reference value, can be a commit hash, branch name, or release tag", + "x-example": "" }, "activate": { "type": "boolean", @@ -32329,7 +32355,8 @@ "repository", "owner", "rootDirectory", - "version" + "type", + "reference" ] } } @@ -33455,7 +33482,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: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus", + "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: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus, transformations", "required": false, "schema": { "type": "array", @@ -33605,6 +33632,11 @@ "type": "boolean", "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Are image transformations enabled?", + "x-example": false } }, "required": [ @@ -33799,6 +33831,11 @@ "type": "boolean", "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Are image transformations enabled?", + "x-example": false } }, "required": [ @@ -36096,7 +36133,7 @@ }, "rowSecurity": { "type": "boolean", - "description": "Enables configuring permissions for individual rows. A user needs one of row or table level permissions to access a document. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "description": "Enables configuring permissions for individual rows. A user needs one of row or table-level permissions to access a row. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", "x-example": false }, "enabled": { @@ -36593,7 +36630,8 @@ "default": { "type": "string", "description": "Default value for the column in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when column is required.", - "x-example": null + "x-example": null, + "x-nullable": true }, "array": { "type": "boolean", @@ -53579,6 +53617,11 @@ "type": "boolean", "description": "Virus scanning is enabled.", "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Image transformations are enabled.", + "x-example": false } }, "required": [ @@ -53593,7 +53636,8 @@ "allowedFileExtensions", "compression", "encryption", - "antivirus" + "antivirus", + "transformations" ], "example": { "$id": "5e5ea5c16897e", @@ -53612,7 +53656,8 @@ ], "compression": "gzip", "encryption": false, - "antivirus": false + "antivirus": false, + "transformations": false } }, "resourceToken": { @@ -54798,6 +54843,17 @@ "type": "string", "description": "Last commit date in ISO 8601 format.", "x-example": "datetime" + }, + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "type": "string" + }, + "x-example": [ + "PORT", + "NODE_ENV" + ] } }, "required": [ @@ -54807,7 +54863,8 @@ "provider", "private", "defaultBranch", - "pushedAt" + "pushedAt", + "variables" ], "example": { "id": "5e5ea5c16897e", @@ -54816,7 +54873,11 @@ "provider": "github", "private": true, "defaultBranch": "main", - "pushedAt": "datetime" + "pushedAt": "datetime", + "variables": [ + "PORT", + "NODE_ENV" + ] } }, "providerRepositoryFramework": { @@ -54858,6 +54919,17 @@ "description": "Last commit date in ISO 8601 format.", "x-example": "datetime" }, + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "type": "string" + }, + "x-example": [ + "PORT", + "NODE_ENV" + ] + }, "framework": { "type": "string", "description": "Auto-detected framework. Empty if type is not \"framework\".", @@ -54872,6 +54944,7 @@ "private", "defaultBranch", "pushedAt", + "variables", "framework" ], "example": { @@ -54882,6 +54955,10 @@ "private": true, "defaultBranch": "main", "pushedAt": "datetime", + "variables": [ + "PORT", + "NODE_ENV" + ], "framework": "nextjs" } }, @@ -54924,6 +55001,17 @@ "description": "Last commit date in ISO 8601 format.", "x-example": "datetime" }, + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "type": "string" + }, + "x-example": [ + "PORT", + "NODE_ENV" + ] + }, "runtime": { "type": "string", "description": "Auto-detected runtime. Empty if type is not \"runtime\".", @@ -54938,6 +55026,7 @@ "private", "defaultBranch", "pushedAt", + "variables", "runtime" ], "example": { @@ -54948,6 +55037,10 @@ "private": true, "defaultBranch": "main", "pushedAt": "datetime", + "variables": [ + "PORT", + "NODE_ENV" + ], "runtime": "node-22" } }, @@ -54955,6 +55048,15 @@ "description": "DetectionFramework", "type": "object", "properties": { + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "$ref": "#\/components\/schemas\/detectionVariable" + }, + "x-example": {}, + "nullable": true + }, "framework": { "type": "string", "description": "Framework", @@ -54983,6 +55085,7 @@ "outputDirectory" ], "example": { + "variables": {}, "framework": "nuxt", "installCommand": "npm install", "buildCommand": "npm run build", @@ -54993,6 +55096,15 @@ "description": "DetectionRuntime", "type": "object", "properties": { + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "$ref": "#\/components\/schemas\/detectionVariable" + }, + "x-example": {}, + "nullable": true + }, "runtime": { "type": "string", "description": "Runtime", @@ -55015,11 +55127,36 @@ "commands" ], "example": { + "variables": {}, "runtime": "node", "entrypoint": "index.js", "commands": "npm install && npm run build" } }, + "detectionVariable": { + "description": "DetectionVariable", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of environment variable", + "x-example": "NODE_ENV" + }, + "value": { + "type": "string", + "description": "Value of environment variable", + "x-example": "production" + } + }, + "required": [ + "name", + "value" + ], + "example": { + "name": "NODE_ENV", + "value": "production" + } + }, "vcsContent": { "description": "VcsContents", "type": "object", 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 8fc49b1db5..2cb6a74853 100644 --- a/app/config/specs/open-api3-1.8.x-server.json +++ b/app/config/specs/open-api3-1.8.x-server.json @@ -7222,7 +7222,8 @@ "default": { "type": "string", "description": "Default value for the attribute in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when attribute is required.", - "x-example": null + "x-example": null, + "x-nullable": true }, "array": { "type": "boolean", @@ -13203,10 +13204,22 @@ "description": "Path to function code in the template repo.", "x-example": "" }, - "version": { + "type": { "type": "string", - "description": "Version (tag) for the repo linked to the function template.", - "x-example": "" + "description": "Type for the reference provided. Can be commit, branch, or tag", + "x-example": "commit", + "enum": [ + "commit", + "branch", + "tag" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "reference": { + "type": "string", + "description": "Reference value, can be a commit hash, branch name, or release tag", + "x-example": "" }, "activate": { "type": "boolean", @@ -13218,7 +13231,8 @@ "repository", "owner", "rootDirectory", - "version" + "type", + "reference" ] } } @@ -22838,10 +22852,22 @@ "description": "Path to site code in the template repo.", "x-example": "" }, - "version": { + "type": { "type": "string", - "description": "Version (tag) for the repo linked to the site template.", - "x-example": "" + "description": "Type for the reference provided. Can be commit, branch, or tag", + "x-example": "branch", + "enum": [ + "branch", + "commit", + "tag" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "reference": { + "type": "string", + "description": "Reference value, can be a commit hash, branch name, or release tag", + "x-example": "" }, "activate": { "type": "boolean", @@ -22853,7 +22879,8 @@ "repository", "owner", "rootDirectory", - "version" + "type", + "reference" ] } } @@ -23911,7 +23938,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: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus", + "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: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus, transformations", "required": false, "schema": { "type": "array", @@ -24062,6 +24089,11 @@ "type": "boolean", "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Are image transformations enabled?", + "x-example": false } }, "required": [ @@ -24258,6 +24290,11 @@ "type": "boolean", "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Are image transformations enabled?", + "x-example": false } }, "required": [ @@ -26342,7 +26379,7 @@ }, "rowSecurity": { "type": "boolean", - "description": "Enables configuring permissions for individual rows. A user needs one of row or table level permissions to access a document. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "description": "Enables configuring permissions for individual rows. A user needs one of row or table-level permissions to access a row. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", "x-example": false }, "enabled": { @@ -26844,7 +26881,8 @@ "default": { "type": "string", "description": "Default value for the column in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when column is required.", - "x-example": null + "x-example": null, + "x-nullable": true }, "array": { "type": "boolean", @@ -42256,6 +42294,11 @@ "type": "boolean", "description": "Virus scanning is enabled.", "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Image transformations are enabled.", + "x-example": false } }, "required": [ @@ -42270,7 +42313,8 @@ "allowedFileExtensions", "compression", "encryption", - "antivirus" + "antivirus", + "transformations" ], "example": { "$id": "5e5ea5c16897e", @@ -42289,7 +42333,8 @@ ], "compression": "gzip", "encryption": false, - "antivirus": false + "antivirus": false, + "transformations": false } }, "resourceToken": { diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 12d2d30ab9..fded6c46b0 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -7753,7 +7753,8 @@ "default": { "type": "string", "description": "Default value for the attribute in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when attribute is required.", - "x-example": null + "x-example": null, + "x-nullable": true }, "array": { "type": "boolean", @@ -33481,7 +33482,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: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus", + "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: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus, transformations", "required": false, "schema": { "type": "array", @@ -33631,6 +33632,11 @@ "type": "boolean", "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Are image transformations enabled?", + "x-example": false } }, "required": [ @@ -33825,6 +33831,11 @@ "type": "boolean", "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Are image transformations enabled?", + "x-example": false } }, "required": [ @@ -36122,7 +36133,7 @@ }, "rowSecurity": { "type": "boolean", - "description": "Enables configuring permissions for individual rows. A user needs one of row or table level permissions to access a document. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "description": "Enables configuring permissions for individual rows. A user needs one of row or table-level permissions to access a row. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", "x-example": false }, "enabled": { @@ -36619,7 +36630,8 @@ "default": { "type": "string", "description": "Default value for the column in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when column is required.", - "x-example": null + "x-example": null, + "x-nullable": true }, "array": { "type": "boolean", @@ -53605,6 +53617,11 @@ "type": "boolean", "description": "Virus scanning is enabled.", "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Image transformations are enabled.", + "x-example": false } }, "required": [ @@ -53619,7 +53636,8 @@ "allowedFileExtensions", "compression", "encryption", - "antivirus" + "antivirus", + "transformations" ], "example": { "$id": "5e5ea5c16897e", @@ -53638,7 +53656,8 @@ ], "compression": "gzip", "encryption": false, - "antivirus": false + "antivirus": false, + "transformations": false } }, "resourceToken": { @@ -54824,6 +54843,17 @@ "type": "string", "description": "Last commit date in ISO 8601 format.", "x-example": "datetime" + }, + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "type": "string" + }, + "x-example": [ + "PORT", + "NODE_ENV" + ] } }, "required": [ @@ -54833,7 +54863,8 @@ "provider", "private", "defaultBranch", - "pushedAt" + "pushedAt", + "variables" ], "example": { "id": "5e5ea5c16897e", @@ -54842,7 +54873,11 @@ "provider": "github", "private": true, "defaultBranch": "main", - "pushedAt": "datetime" + "pushedAt": "datetime", + "variables": [ + "PORT", + "NODE_ENV" + ] } }, "providerRepositoryFramework": { @@ -54884,6 +54919,17 @@ "description": "Last commit date in ISO 8601 format.", "x-example": "datetime" }, + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "type": "string" + }, + "x-example": [ + "PORT", + "NODE_ENV" + ] + }, "framework": { "type": "string", "description": "Auto-detected framework. Empty if type is not \"framework\".", @@ -54898,6 +54944,7 @@ "private", "defaultBranch", "pushedAt", + "variables", "framework" ], "example": { @@ -54908,6 +54955,10 @@ "private": true, "defaultBranch": "main", "pushedAt": "datetime", + "variables": [ + "PORT", + "NODE_ENV" + ], "framework": "nextjs" } }, @@ -54950,6 +55001,17 @@ "description": "Last commit date in ISO 8601 format.", "x-example": "datetime" }, + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "type": "string" + }, + "x-example": [ + "PORT", + "NODE_ENV" + ] + }, "runtime": { "type": "string", "description": "Auto-detected runtime. Empty if type is not \"runtime\".", @@ -54964,6 +55026,7 @@ "private", "defaultBranch", "pushedAt", + "variables", "runtime" ], "example": { @@ -54974,6 +55037,10 @@ "private": true, "defaultBranch": "main", "pushedAt": "datetime", + "variables": [ + "PORT", + "NODE_ENV" + ], "runtime": "node-22" } }, @@ -54981,6 +55048,15 @@ "description": "DetectionFramework", "type": "object", "properties": { + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "$ref": "#\/components\/schemas\/detectionVariable" + }, + "x-example": {}, + "nullable": true + }, "framework": { "type": "string", "description": "Framework", @@ -55009,6 +55085,7 @@ "outputDirectory" ], "example": { + "variables": {}, "framework": "nuxt", "installCommand": "npm install", "buildCommand": "npm run build", @@ -55019,6 +55096,15 @@ "description": "DetectionRuntime", "type": "object", "properties": { + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "$ref": "#\/components\/schemas\/detectionVariable" + }, + "x-example": {}, + "nullable": true + }, "runtime": { "type": "string", "description": "Runtime", @@ -55041,11 +55127,36 @@ "commands" ], "example": { + "variables": {}, "runtime": "node", "entrypoint": "index.js", "commands": "npm install && npm run build" } }, + "detectionVariable": { + "description": "DetectionVariable", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of environment variable", + "x-example": "NODE_ENV" + }, + "value": { + "type": "string", + "description": "Value of environment variable", + "x-example": "production" + } + }, + "required": [ + "name", + "value" + ], + "example": { + "name": "NODE_ENV", + "value": "production" + } + }, "vcsContent": { "description": "VcsContents", "type": "object", diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index b11c69442b..2cb6a74853 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -7222,7 +7222,8 @@ "default": { "type": "string", "description": "Default value for the attribute in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when attribute is required.", - "x-example": null + "x-example": null, + "x-nullable": true }, "array": { "type": "boolean", @@ -23937,7 +23938,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: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus", + "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: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus, transformations", "required": false, "schema": { "type": "array", @@ -24088,6 +24089,11 @@ "type": "boolean", "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Are image transformations enabled?", + "x-example": false } }, "required": [ @@ -24284,6 +24290,11 @@ "type": "boolean", "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Are image transformations enabled?", + "x-example": false } }, "required": [ @@ -26368,7 +26379,7 @@ }, "rowSecurity": { "type": "boolean", - "description": "Enables configuring permissions for individual rows. A user needs one of row or table level permissions to access a document. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "description": "Enables configuring permissions for individual rows. A user needs one of row or table-level permissions to access a row. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", "x-example": false }, "enabled": { @@ -26870,7 +26881,8 @@ "default": { "type": "string", "description": "Default value for the column in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when column is required.", - "x-example": null + "x-example": null, + "x-nullable": true }, "array": { "type": "boolean", @@ -42282,6 +42294,11 @@ "type": "boolean", "description": "Virus scanning is enabled.", "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Image transformations are enabled.", + "x-example": false } }, "required": [ @@ -42296,7 +42313,8 @@ "allowedFileExtensions", "compression", "encryption", - "antivirus" + "antivirus", + "transformations" ], "example": { "$id": "5e5ea5c16897e", @@ -42315,7 +42333,8 @@ ], "compression": "gzip", "encryption": false, - "antivirus": false + "antivirus": false, + "transformations": false } }, "resourceToken": { diff --git a/app/config/specs/swagger2-1.8.x-console.json b/app/config/specs/swagger2-1.8.x-console.json index 384011f2fd..28a4f76c61 100644 --- a/app/config/specs/swagger2-1.8.x-console.json +++ b/app/config/specs/swagger2-1.8.x-console.json @@ -7851,7 +7851,8 @@ "type": "string", "description": "Default value for the attribute in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when attribute is required.", "default": null, - "x-example": null + "x-example": null, + "x-nullable": true }, "array": { "type": "boolean", @@ -14355,11 +14356,24 @@ "default": null, "x-example": "" }, - "version": { + "type": { "type": "string", - "description": "Version (tag) for the repo linked to the function template.", + "description": "Type for the reference provided. Can be commit, branch, or tag", "default": null, - "x-example": "" + "x-example": "commit", + "enum": [ + "commit", + "branch", + "tag" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "reference": { + "type": "string", + "description": "Reference value, can be a commit hash, branch name, or release tag", + "default": null, + "x-example": "" }, "activate": { "type": "boolean", @@ -14372,7 +14386,8 @@ "repository", "owner", "rootDirectory", - "version" + "type", + "reference" ] } } @@ -32416,11 +32431,24 @@ "default": null, "x-example": "" }, - "version": { + "type": { "type": "string", - "description": "Version (tag) for the repo linked to the site template.", + "description": "Type for the reference provided. Can be commit, branch, or tag", "default": null, - "x-example": "" + "x-example": "branch", + "enum": [ + "branch", + "commit", + "tag" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "reference": { + "type": "string", + "description": "Reference value, can be a commit hash, branch name, or release tag", + "default": null, + "x-example": "" }, "activate": { "type": "boolean", @@ -32433,7 +32461,8 @@ "repository", "owner", "rootDirectory", - "version" + "type", + "reference" ] } } @@ -33536,7 +33565,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: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus", + "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: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus, transformations", "required": false, "type": "array", "collectionFormat": "multi", @@ -33694,6 +33723,12 @@ "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", "default": true, "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Are image transformations enabled?", + "default": true, + "x-example": false } }, "required": [ @@ -33893,6 +33928,12 @@ "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", "default": true, "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Are image transformations enabled?", + "default": true, + "x-example": false } }, "required": [ @@ -36122,7 +36163,7 @@ }, "rowSecurity": { "type": "boolean", - "description": "Enables configuring permissions for individual rows. A user needs one of row or table level permissions to access a document. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "description": "Enables configuring permissions for individual rows. A user needs one of row or table-level permissions to access a row. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", "default": false, "x-example": false }, @@ -36610,7 +36651,8 @@ "type": "string", "description": "Default value for the column in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when column is required.", "default": null, - "x-example": null + "x-example": null, + "x-nullable": true }, "array": { "type": "boolean", @@ -53397,6 +53439,11 @@ "type": "boolean", "description": "Virus scanning is enabled.", "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Image transformations are enabled.", + "x-example": false } }, "required": [ @@ -53411,7 +53458,8 @@ "allowedFileExtensions", "compression", "encryption", - "antivirus" + "antivirus", + "transformations" ], "example": { "$id": "5e5ea5c16897e", @@ -53430,7 +53478,8 @@ ], "compression": "gzip", "encryption": false, - "antivirus": false + "antivirus": false, + "transformations": false } }, "resourceToken": { @@ -54623,6 +54672,17 @@ "type": "string", "description": "Last commit date in ISO 8601 format.", "x-example": "datetime" + }, + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "type": "string" + }, + "x-example": [ + "PORT", + "NODE_ENV" + ] } }, "required": [ @@ -54632,7 +54692,8 @@ "provider", "private", "defaultBranch", - "pushedAt" + "pushedAt", + "variables" ], "example": { "id": "5e5ea5c16897e", @@ -54641,7 +54702,11 @@ "provider": "github", "private": true, "defaultBranch": "main", - "pushedAt": "datetime" + "pushedAt": "datetime", + "variables": [ + "PORT", + "NODE_ENV" + ] } }, "providerRepositoryFramework": { @@ -54683,6 +54748,17 @@ "description": "Last commit date in ISO 8601 format.", "x-example": "datetime" }, + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "type": "string" + }, + "x-example": [ + "PORT", + "NODE_ENV" + ] + }, "framework": { "type": "string", "description": "Auto-detected framework. Empty if type is not \"framework\".", @@ -54697,6 +54773,7 @@ "private", "defaultBranch", "pushedAt", + "variables", "framework" ], "example": { @@ -54707,6 +54784,10 @@ "private": true, "defaultBranch": "main", "pushedAt": "datetime", + "variables": [ + "PORT", + "NODE_ENV" + ], "framework": "nextjs" } }, @@ -54749,6 +54830,17 @@ "description": "Last commit date in ISO 8601 format.", "x-example": "datetime" }, + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "type": "string" + }, + "x-example": [ + "PORT", + "NODE_ENV" + ] + }, "runtime": { "type": "string", "description": "Auto-detected runtime. Empty if type is not \"runtime\".", @@ -54763,6 +54855,7 @@ "private", "defaultBranch", "pushedAt", + "variables", "runtime" ], "example": { @@ -54773,6 +54866,10 @@ "private": true, "defaultBranch": "main", "pushedAt": "datetime", + "variables": [ + "PORT", + "NODE_ENV" + ], "runtime": "node-22" } }, @@ -54780,6 +54877,16 @@ "description": "DetectionFramework", "type": "object", "properties": { + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "type": "object", + "$ref": "#\/definitions\/detectionVariable" + }, + "x-example": {}, + "x-nullable": true + }, "framework": { "type": "string", "description": "Framework", @@ -54808,6 +54915,7 @@ "outputDirectory" ], "example": { + "variables": {}, "framework": "nuxt", "installCommand": "npm install", "buildCommand": "npm run build", @@ -54818,6 +54926,16 @@ "description": "DetectionRuntime", "type": "object", "properties": { + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "type": "object", + "$ref": "#\/definitions\/detectionVariable" + }, + "x-example": {}, + "x-nullable": true + }, "runtime": { "type": "string", "description": "Runtime", @@ -54840,11 +54958,36 @@ "commands" ], "example": { + "variables": {}, "runtime": "node", "entrypoint": "index.js", "commands": "npm install && npm run build" } }, + "detectionVariable": { + "description": "DetectionVariable", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of environment variable", + "x-example": "NODE_ENV" + }, + "value": { + "type": "string", + "description": "Value of environment variable", + "x-example": "production" + } + }, + "required": [ + "name", + "value" + ], + "example": { + "name": "NODE_ENV", + "value": "production" + } + }, "vcsContent": { "description": "VcsContents", "type": "object", diff --git a/app/config/specs/swagger2-1.8.x-server.json b/app/config/specs/swagger2-1.8.x-server.json index af417d5788..e760c1bb7d 100644 --- a/app/config/specs/swagger2-1.8.x-server.json +++ b/app/config/specs/swagger2-1.8.x-server.json @@ -7310,7 +7310,8 @@ "type": "string", "description": "Default value for the attribute in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when attribute is required.", "default": null, - "x-example": null + "x-example": null, + "x-nullable": true }, "array": { "type": "boolean", @@ -13171,11 +13172,24 @@ "default": null, "x-example": "" }, - "version": { + "type": { "type": "string", - "description": "Version (tag) for the repo linked to the function template.", + "description": "Type for the reference provided. Can be commit, branch, or tag", "default": null, - "x-example": "" + "x-example": "commit", + "enum": [ + "commit", + "branch", + "tag" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "reference": { + "type": "string", + "description": "Reference value, can be a commit hash, branch name, or release tag", + "default": null, + "x-example": "" }, "activate": { "type": "boolean", @@ -13188,7 +13202,8 @@ "repository", "owner", "rootDirectory", - "version" + "type", + "reference" ] } } @@ -22989,11 +23004,24 @@ "default": null, "x-example": "" }, - "version": { + "type": { "type": "string", - "description": "Version (tag) for the repo linked to the site template.", + "description": "Type for the reference provided. Can be commit, branch, or tag", "default": null, - "x-example": "" + "x-example": "branch", + "enum": [ + "branch", + "commit", + "tag" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "reference": { + "type": "string", + "description": "Reference value, can be a commit hash, branch name, or release tag", + "default": null, + "x-example": "" }, "activate": { "type": "boolean", @@ -23006,7 +23034,8 @@ "repository", "owner", "rootDirectory", - "version" + "type", + "reference" ] } } @@ -24045,7 +24074,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: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus", + "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: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus, transformations", "required": false, "type": "array", "collectionFormat": "multi", @@ -24204,6 +24233,12 @@ "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", "default": true, "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Are image transformations enabled?", + "default": true, + "x-example": false } }, "required": [ @@ -24405,6 +24440,12 @@ "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", "default": true, "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Are image transformations enabled?", + "default": true, + "x-example": false } }, "required": [ @@ -26429,7 +26470,7 @@ }, "rowSecurity": { "type": "boolean", - "description": "Enables configuring permissions for individual rows. A user needs one of row or table level permissions to access a document. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "description": "Enables configuring permissions for individual rows. A user needs one of row or table-level permissions to access a row. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", "default": false, "x-example": false }, @@ -26922,7 +26963,8 @@ "type": "string", "description": "Default value for the column in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when column is required.", "default": null, - "x-example": null + "x-example": null, + "x-nullable": true }, "array": { "type": "boolean", @@ -42175,6 +42217,11 @@ "type": "boolean", "description": "Virus scanning is enabled.", "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Image transformations are enabled.", + "x-example": false } }, "required": [ @@ -42189,7 +42236,8 @@ "allowedFileExtensions", "compression", "encryption", - "antivirus" + "antivirus", + "transformations" ], "example": { "$id": "5e5ea5c16897e", @@ -42208,7 +42256,8 @@ ], "compression": "gzip", "encryption": false, - "antivirus": false + "antivirus": false, + "transformations": false } }, "resourceToken": { diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index efa5d9bdee..28a4f76c61 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -7851,7 +7851,8 @@ "type": "string", "description": "Default value for the attribute in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when attribute is required.", "default": null, - "x-example": null + "x-example": null, + "x-nullable": true }, "array": { "type": "boolean", @@ -33564,7 +33565,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: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus", + "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: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus, transformations", "required": false, "type": "array", "collectionFormat": "multi", @@ -33722,6 +33723,12 @@ "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", "default": true, "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Are image transformations enabled?", + "default": true, + "x-example": false } }, "required": [ @@ -33921,6 +33928,12 @@ "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", "default": true, "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Are image transformations enabled?", + "default": true, + "x-example": false } }, "required": [ @@ -36150,7 +36163,7 @@ }, "rowSecurity": { "type": "boolean", - "description": "Enables configuring permissions for individual rows. A user needs one of row or table level permissions to access a document. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "description": "Enables configuring permissions for individual rows. A user needs one of row or table-level permissions to access a row. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", "default": false, "x-example": false }, @@ -36638,7 +36651,8 @@ "type": "string", "description": "Default value for the column in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when column is required.", "default": null, - "x-example": null + "x-example": null, + "x-nullable": true }, "array": { "type": "boolean", @@ -53425,6 +53439,11 @@ "type": "boolean", "description": "Virus scanning is enabled.", "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Image transformations are enabled.", + "x-example": false } }, "required": [ @@ -53439,7 +53458,8 @@ "allowedFileExtensions", "compression", "encryption", - "antivirus" + "antivirus", + "transformations" ], "example": { "$id": "5e5ea5c16897e", @@ -53458,7 +53478,8 @@ ], "compression": "gzip", "encryption": false, - "antivirus": false + "antivirus": false, + "transformations": false } }, "resourceToken": { @@ -54651,6 +54672,17 @@ "type": "string", "description": "Last commit date in ISO 8601 format.", "x-example": "datetime" + }, + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "type": "string" + }, + "x-example": [ + "PORT", + "NODE_ENV" + ] } }, "required": [ @@ -54660,7 +54692,8 @@ "provider", "private", "defaultBranch", - "pushedAt" + "pushedAt", + "variables" ], "example": { "id": "5e5ea5c16897e", @@ -54669,7 +54702,11 @@ "provider": "github", "private": true, "defaultBranch": "main", - "pushedAt": "datetime" + "pushedAt": "datetime", + "variables": [ + "PORT", + "NODE_ENV" + ] } }, "providerRepositoryFramework": { @@ -54711,6 +54748,17 @@ "description": "Last commit date in ISO 8601 format.", "x-example": "datetime" }, + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "type": "string" + }, + "x-example": [ + "PORT", + "NODE_ENV" + ] + }, "framework": { "type": "string", "description": "Auto-detected framework. Empty if type is not \"framework\".", @@ -54725,6 +54773,7 @@ "private", "defaultBranch", "pushedAt", + "variables", "framework" ], "example": { @@ -54735,6 +54784,10 @@ "private": true, "defaultBranch": "main", "pushedAt": "datetime", + "variables": [ + "PORT", + "NODE_ENV" + ], "framework": "nextjs" } }, @@ -54777,6 +54830,17 @@ "description": "Last commit date in ISO 8601 format.", "x-example": "datetime" }, + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "type": "string" + }, + "x-example": [ + "PORT", + "NODE_ENV" + ] + }, "runtime": { "type": "string", "description": "Auto-detected runtime. Empty if type is not \"runtime\".", @@ -54791,6 +54855,7 @@ "private", "defaultBranch", "pushedAt", + "variables", "runtime" ], "example": { @@ -54801,6 +54866,10 @@ "private": true, "defaultBranch": "main", "pushedAt": "datetime", + "variables": [ + "PORT", + "NODE_ENV" + ], "runtime": "node-22" } }, @@ -54808,6 +54877,16 @@ "description": "DetectionFramework", "type": "object", "properties": { + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "type": "object", + "$ref": "#\/definitions\/detectionVariable" + }, + "x-example": {}, + "x-nullable": true + }, "framework": { "type": "string", "description": "Framework", @@ -54836,6 +54915,7 @@ "outputDirectory" ], "example": { + "variables": {}, "framework": "nuxt", "installCommand": "npm install", "buildCommand": "npm run build", @@ -54846,6 +54926,16 @@ "description": "DetectionRuntime", "type": "object", "properties": { + "variables": { + "type": "array", + "description": "Environment variables found in .env files", + "items": { + "type": "object", + "$ref": "#\/definitions\/detectionVariable" + }, + "x-example": {}, + "x-nullable": true + }, "runtime": { "type": "string", "description": "Runtime", @@ -54868,11 +54958,36 @@ "commands" ], "example": { + "variables": {}, "runtime": "node", "entrypoint": "index.js", "commands": "npm install && npm run build" } }, + "detectionVariable": { + "description": "DetectionVariable", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of environment variable", + "x-example": "NODE_ENV" + }, + "value": { + "type": "string", + "description": "Value of environment variable", + "x-example": "production" + } + }, + "required": [ + "name", + "value" + ], + "example": { + "name": "NODE_ENV", + "value": "production" + } + }, "vcsContent": { "description": "VcsContents", "type": "object", diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index e48f00475a..e760c1bb7d 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -7310,7 +7310,8 @@ "type": "string", "description": "Default value for the attribute in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when attribute is required.", "default": null, - "x-example": null + "x-example": null, + "x-nullable": true }, "array": { "type": "boolean", @@ -24073,7 +24074,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: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus", + "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: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus, transformations", "required": false, "type": "array", "collectionFormat": "multi", @@ -24232,6 +24233,12 @@ "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", "default": true, "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Are image transformations enabled?", + "default": true, + "x-example": false } }, "required": [ @@ -24433,6 +24440,12 @@ "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", "default": true, "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Are image transformations enabled?", + "default": true, + "x-example": false } }, "required": [ @@ -26457,7 +26470,7 @@ }, "rowSecurity": { "type": "boolean", - "description": "Enables configuring permissions for individual rows. A user needs one of row or table level permissions to access a document. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "description": "Enables configuring permissions for individual rows. A user needs one of row or table-level permissions to access a row. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", "default": false, "x-example": false }, @@ -26950,7 +26963,8 @@ "type": "string", "description": "Default value for the column in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when column is required.", "default": null, - "x-example": null + "x-example": null, + "x-nullable": true }, "array": { "type": "boolean", @@ -42203,6 +42217,11 @@ "type": "boolean", "description": "Virus scanning is enabled.", "x-example": false + }, + "transformations": { + "type": "boolean", + "description": "Image transformations are enabled.", + "x-example": false } }, "required": [ @@ -42217,7 +42236,8 @@ "allowedFileExtensions", "compression", "encryption", - "antivirus" + "antivirus", + "transformations" ], "example": { "$id": "5e5ea5c16897e", @@ -42236,7 +42256,8 @@ ], "compression": "gzip", "encryption": false, - "antivirus": false + "antivirus": false, + "transformations": false } }, "resourceToken": { From 39c5b6c4d0a6adff6fe0f2cecdcd3aeeb0e37666 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 18 Nov 2025 09:53:55 +0530 Subject: [PATCH 63/77] regenerate sdk examples --- .../1.8.x/client-flutter/examples/avatars/get-browser.md | 2 +- .../1.8.x/client-flutter/examples/avatars/get-credit-card.md | 2 +- .../1.8.x/client-flutter/examples/avatars/get-favicon.md | 2 +- .../1.8.x/client-flutter/examples/avatars/get-flag.md | 2 +- .../1.8.x/client-flutter/examples/avatars/get-image.md | 2 +- .../1.8.x/client-flutter/examples/avatars/get-initials.md | 2 +- .../examples/1.8.x/client-flutter/examples/avatars/get-qr.md | 2 +- .../1.8.x/client-flutter/examples/avatars/get-screenshot.md | 2 +- .../client-flutter/examples/storage/get-file-download.md | 2 +- .../client-flutter/examples/storage/get-file-preview.md | 2 +- .../1.8.x/client-flutter/examples/storage/get-file-view.md | 2 +- .../examples/functions/create-template-deployment.md | 3 ++- .../console-cli/examples/sites/create-template-deployment.md | 3 ++- .../examples/functions/create-template-deployment.md | 5 +++-- .../console-web/examples/sites/create-template-deployment.md | 5 +++-- .../1.8.x/console-web/examples/storage/create-bucket.md | 3 ++- .../1.8.x/console-web/examples/storage/update-bucket.md | 3 ++- .../1.8.x/server-dart/examples/avatars/get-browser.md | 2 +- .../1.8.x/server-dart/examples/avatars/get-credit-card.md | 2 +- .../1.8.x/server-dart/examples/avatars/get-favicon.md | 2 +- docs/examples/1.8.x/server-dart/examples/avatars/get-flag.md | 2 +- .../examples/1.8.x/server-dart/examples/avatars/get-image.md | 2 +- .../1.8.x/server-dart/examples/avatars/get-initials.md | 2 +- docs/examples/1.8.x/server-dart/examples/avatars/get-qr.md | 2 +- .../1.8.x/server-dart/examples/avatars/get-screenshot.md | 2 +- .../examples/functions/create-template-deployment.md | 3 ++- .../examples/functions/get-deployment-download.md | 2 +- .../server-dart/examples/sites/create-template-deployment.md | 3 ++- .../server-dart/examples/sites/get-deployment-download.md | 2 +- .../1.8.x/server-dart/examples/storage/create-bucket.md | 1 + .../1.8.x/server-dart/examples/storage/get-file-download.md | 2 +- .../1.8.x/server-dart/examples/storage/get-file-preview.md | 2 +- .../1.8.x/server-dart/examples/storage/get-file-view.md | 2 +- .../1.8.x/server-dart/examples/storage/update-bucket.md | 1 + .../examples/functions/create-template-deployment.md | 4 +++- .../examples/sites/create-template-deployment.md | 4 +++- .../1.8.x/server-dotnet/examples/storage/create-bucket.md | 3 ++- .../1.8.x/server-dotnet/examples/storage/update-bucket.md | 3 ++- .../examples/functions/create-template-deployment.md | 3 ++- .../server-go/examples/sites/create-template-deployment.md | 3 ++- .../1.8.x/server-go/examples/storage/create-bucket.md | 1 + .../1.8.x/server-go/examples/storage/update-bucket.md | 1 + .../examples/functions/create-template-deployment.md | 3 ++- .../examples/sites/create-template-deployment.md | 3 ++- .../1.8.x/server-graphql/examples/storage/create-bucket.md | 4 +++- .../1.8.x/server-graphql/examples/storage/update-bucket.md | 4 +++- .../java/functions/create-template-deployment.md | 4 +++- .../server-kotlin/java/sites/create-template-deployment.md | 4 +++- .../1.8.x/server-kotlin/java/storage/create-bucket.md | 1 + .../1.8.x/server-kotlin/java/storage/update-bucket.md | 1 + .../kotlin/functions/create-template-deployment.md | 4 +++- .../server-kotlin/kotlin/sites/create-template-deployment.md | 4 +++- .../1.8.x/server-kotlin/kotlin/storage/create-bucket.md | 3 ++- .../1.8.x/server-kotlin/kotlin/storage/update-bucket.md | 3 ++- .../examples/functions/create-template-deployment.md | 3 ++- .../examples/sites/create-template-deployment.md | 3 ++- .../1.8.x/server-nodejs/examples/storage/create-bucket.md | 3 ++- .../1.8.x/server-nodejs/examples/storage/update-bucket.md | 3 ++- .../examples/functions/create-template-deployment.md | 4 +++- .../server-php/examples/sites/create-template-deployment.md | 4 +++- .../1.8.x/server-php/examples/storage/create-bucket.md | 3 ++- .../1.8.x/server-php/examples/storage/update-bucket.md | 3 ++- .../examples/functions/create-template-deployment.md | 4 +++- .../examples/sites/create-template-deployment.md | 4 +++- .../1.8.x/server-python/examples/storage/create-bucket.md | 3 ++- .../1.8.x/server-python/examples/storage/update-bucket.md | 3 ++- .../examples/functions/create-template-deployment.md | 3 ++- .../server-rest/examples/sites/create-template-deployment.md | 3 ++- .../1.8.x/server-rest/examples/storage/create-bucket.md | 3 ++- .../1.8.x/server-rest/examples/storage/update-bucket.md | 3 ++- .../examples/functions/create-template-deployment.md | 4 +++- .../server-ruby/examples/sites/create-template-deployment.md | 4 +++- .../1.8.x/server-ruby/examples/storage/create-bucket.md | 3 ++- .../1.8.x/server-ruby/examples/storage/update-bucket.md | 3 ++- .../examples/functions/create-template-deployment.md | 4 +++- .../examples/sites/create-template-deployment.md | 4 +++- .../1.8.x/server-swift/examples/storage/create-bucket.md | 3 ++- .../1.8.x/server-swift/examples/storage/update-bucket.md | 3 ++- 78 files changed, 144 insertions(+), 74 deletions(-) diff --git a/docs/examples/1.8.x/client-flutter/examples/avatars/get-browser.md b/docs/examples/1.8.x/client-flutter/examples/avatars/get-browser.md index e97d24ab4f..50c28ff378 100644 --- a/docs/examples/1.8.x/client-flutter/examples/avatars/get-browser.md +++ b/docs/examples/1.8.x/client-flutter/examples/avatars/get-browser.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); // Downloading file -UInt8List bytes = await avatars.getBrowser( +Uint8List bytes = await avatars.getBrowser( code: Browser.avantBrowser, width: 0, // optional height: 0, // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/avatars/get-credit-card.md b/docs/examples/1.8.x/client-flutter/examples/avatars/get-credit-card.md index 9ec42588b4..c3471fc2e8 100644 --- a/docs/examples/1.8.x/client-flutter/examples/avatars/get-credit-card.md +++ b/docs/examples/1.8.x/client-flutter/examples/avatars/get-credit-card.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); // Downloading file -UInt8List bytes = await avatars.getCreditCard( +Uint8List bytes = await avatars.getCreditCard( code: CreditCard.americanExpress, width: 0, // optional height: 0, // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/avatars/get-favicon.md b/docs/examples/1.8.x/client-flutter/examples/avatars/get-favicon.md index 0df5ed0d2a..abd61a0974 100644 --- a/docs/examples/1.8.x/client-flutter/examples/avatars/get-favicon.md +++ b/docs/examples/1.8.x/client-flutter/examples/avatars/get-favicon.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); // Downloading file -UInt8List bytes = await avatars.getFavicon( +Uint8List bytes = await avatars.getFavicon( url: 'https://example.com', ) diff --git a/docs/examples/1.8.x/client-flutter/examples/avatars/get-flag.md b/docs/examples/1.8.x/client-flutter/examples/avatars/get-flag.md index 99d43409a0..e5a4c60ba9 100644 --- a/docs/examples/1.8.x/client-flutter/examples/avatars/get-flag.md +++ b/docs/examples/1.8.x/client-flutter/examples/avatars/get-flag.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); // Downloading file -UInt8List bytes = await avatars.getFlag( +Uint8List bytes = await avatars.getFlag( code: Flag.afghanistan, width: 0, // optional height: 0, // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/avatars/get-image.md b/docs/examples/1.8.x/client-flutter/examples/avatars/get-image.md index 5b9d1b58c1..bbfcc03885 100644 --- a/docs/examples/1.8.x/client-flutter/examples/avatars/get-image.md +++ b/docs/examples/1.8.x/client-flutter/examples/avatars/get-image.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); // Downloading file -UInt8List bytes = await avatars.getImage( +Uint8List bytes = await avatars.getImage( url: 'https://example.com', width: 0, // optional height: 0, // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/avatars/get-initials.md b/docs/examples/1.8.x/client-flutter/examples/avatars/get-initials.md index 0c5b62a309..29940c17bf 100644 --- a/docs/examples/1.8.x/client-flutter/examples/avatars/get-initials.md +++ b/docs/examples/1.8.x/client-flutter/examples/avatars/get-initials.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); // Downloading file -UInt8List bytes = await avatars.getInitials( +Uint8List bytes = await avatars.getInitials( name: '', // optional width: 0, // optional height: 0, // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/avatars/get-qr.md b/docs/examples/1.8.x/client-flutter/examples/avatars/get-qr.md index d9a533c886..0a75a6682f 100644 --- a/docs/examples/1.8.x/client-flutter/examples/avatars/get-qr.md +++ b/docs/examples/1.8.x/client-flutter/examples/avatars/get-qr.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); // Downloading file -UInt8List bytes = await avatars.getQR( +Uint8List bytes = await avatars.getQR( text: '', size: 1, // optional margin: 0, // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/avatars/get-screenshot.md b/docs/examples/1.8.x/client-flutter/examples/avatars/get-screenshot.md index 768cb8f271..f8cb6cfbcc 100644 --- a/docs/examples/1.8.x/client-flutter/examples/avatars/get-screenshot.md +++ b/docs/examples/1.8.x/client-flutter/examples/avatars/get-screenshot.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); // Downloading file -UInt8List bytes = await avatars.getScreenshot( +Uint8List bytes = await avatars.getScreenshot( url: 'https://example.com', headers: {}, // optional viewportWidth: 1, // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/storage/get-file-download.md b/docs/examples/1.8.x/client-flutter/examples/storage/get-file-download.md index 5bef06ee7d..2cdba9b1fa 100644 --- a/docs/examples/1.8.x/client-flutter/examples/storage/get-file-download.md +++ b/docs/examples/1.8.x/client-flutter/examples/storage/get-file-download.md @@ -7,7 +7,7 @@ Client client = Client() Storage storage = Storage(client); // Downloading file -UInt8List bytes = await storage.getFileDownload( +Uint8List bytes = await storage.getFileDownload( bucketId: '', fileId: '', token: '', // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/storage/get-file-preview.md b/docs/examples/1.8.x/client-flutter/examples/storage/get-file-preview.md index 96338bd25a..6fd148e935 100644 --- a/docs/examples/1.8.x/client-flutter/examples/storage/get-file-preview.md +++ b/docs/examples/1.8.x/client-flutter/examples/storage/get-file-preview.md @@ -7,7 +7,7 @@ Client client = Client() Storage storage = Storage(client); // Downloading file -UInt8List bytes = await storage.getFilePreview( +Uint8List bytes = await storage.getFilePreview( bucketId: '', fileId: '', width: 0, // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/storage/get-file-view.md b/docs/examples/1.8.x/client-flutter/examples/storage/get-file-view.md index 6587f086bd..bcf5902c4e 100644 --- a/docs/examples/1.8.x/client-flutter/examples/storage/get-file-view.md +++ b/docs/examples/1.8.x/client-flutter/examples/storage/get-file-view.md @@ -7,7 +7,7 @@ Client client = Client() Storage storage = Storage(client); // Downloading file -UInt8List bytes = await storage.getFileView( +Uint8List bytes = await storage.getFileView( bucketId: '', fileId: '', token: '', // optional diff --git a/docs/examples/1.8.x/console-cli/examples/functions/create-template-deployment.md b/docs/examples/1.8.x/console-cli/examples/functions/create-template-deployment.md index f3c8487cf7..72fa62b3c4 100644 --- a/docs/examples/1.8.x/console-cli/examples/functions/create-template-deployment.md +++ b/docs/examples/1.8.x/console-cli/examples/functions/create-template-deployment.md @@ -3,4 +3,5 @@ appwrite functions create-template-deployment \ --repository \ --owner \ --root-directory \ - --version + --type commit \ + --reference diff --git a/docs/examples/1.8.x/console-cli/examples/sites/create-template-deployment.md b/docs/examples/1.8.x/console-cli/examples/sites/create-template-deployment.md index 2eece41976..5242534073 100644 --- a/docs/examples/1.8.x/console-cli/examples/sites/create-template-deployment.md +++ b/docs/examples/1.8.x/console-cli/examples/sites/create-template-deployment.md @@ -3,4 +3,5 @@ appwrite sites create-template-deployment \ --repository \ --owner \ --root-directory \ - --version + --type branch \ + --reference diff --git a/docs/examples/1.8.x/console-web/examples/functions/create-template-deployment.md b/docs/examples/1.8.x/console-web/examples/functions/create-template-deployment.md index 8820ba3565..5bf812c1bc 100644 --- a/docs/examples/1.8.x/console-web/examples/functions/create-template-deployment.md +++ b/docs/examples/1.8.x/console-web/examples/functions/create-template-deployment.md @@ -1,4 +1,4 @@ -import { Client, Functions } from "@appwrite.io/console"; +import { Client, Functions, } from "@appwrite.io/console"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -11,7 +11,8 @@ const result = await functions.createTemplateDeployment({ repository: '', owner: '', rootDirectory: '', - version: '', + type: .Commit, + reference: '', activate: false // optional }); diff --git a/docs/examples/1.8.x/console-web/examples/sites/create-template-deployment.md b/docs/examples/1.8.x/console-web/examples/sites/create-template-deployment.md index 969a0b855c..4f1d0184f7 100644 --- a/docs/examples/1.8.x/console-web/examples/sites/create-template-deployment.md +++ b/docs/examples/1.8.x/console-web/examples/sites/create-template-deployment.md @@ -1,4 +1,4 @@ -import { Client, Sites } from "@appwrite.io/console"; +import { Client, Sites, } from "@appwrite.io/console"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -11,7 +11,8 @@ const result = await sites.createTemplateDeployment({ repository: '', owner: '', rootDirectory: '', - version: '', + type: .Branch, + reference: '', activate: false // optional }); diff --git a/docs/examples/1.8.x/console-web/examples/storage/create-bucket.md b/docs/examples/1.8.x/console-web/examples/storage/create-bucket.md index 343568a408..4fd742bd32 100644 --- a/docs/examples/1.8.x/console-web/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/console-web/examples/storage/create-bucket.md @@ -16,7 +16,8 @@ const result = await storage.createBucket({ allowedFileExtensions: [], // optional compression: .None, // optional encryption: false, // optional - antivirus: false // optional + antivirus: false, // optional + transformations: false // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/storage/update-bucket.md b/docs/examples/1.8.x/console-web/examples/storage/update-bucket.md index b2c2eaa885..6914c374c9 100644 --- a/docs/examples/1.8.x/console-web/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/console-web/examples/storage/update-bucket.md @@ -16,7 +16,8 @@ const result = await storage.updateBucket({ allowedFileExtensions: [], // optional compression: .None, // optional encryption: false, // optional - antivirus: false // optional + antivirus: false, // optional + transformations: false // optional }); console.log(result); diff --git a/docs/examples/1.8.x/server-dart/examples/avatars/get-browser.md b/docs/examples/1.8.x/server-dart/examples/avatars/get-browser.md index 8d5287511d..1f326e8066 100644 --- a/docs/examples/1.8.x/server-dart/examples/avatars/get-browser.md +++ b/docs/examples/1.8.x/server-dart/examples/avatars/get-browser.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); -UInt8List result = await avatars.getBrowser( +Uint8List result = await avatars.getBrowser( code: Browser.avantBrowser, width: 0, // (optional) height: 0, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/avatars/get-credit-card.md b/docs/examples/1.8.x/server-dart/examples/avatars/get-credit-card.md index 88fe35ebd9..8232d7b2b9 100644 --- a/docs/examples/1.8.x/server-dart/examples/avatars/get-credit-card.md +++ b/docs/examples/1.8.x/server-dart/examples/avatars/get-credit-card.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); -UInt8List result = await avatars.getCreditCard( +Uint8List result = await avatars.getCreditCard( code: CreditCard.americanExpress, width: 0, // (optional) height: 0, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/avatars/get-favicon.md b/docs/examples/1.8.x/server-dart/examples/avatars/get-favicon.md index d4cd8eae83..e2df21f6fd 100644 --- a/docs/examples/1.8.x/server-dart/examples/avatars/get-favicon.md +++ b/docs/examples/1.8.x/server-dart/examples/avatars/get-favicon.md @@ -7,6 +7,6 @@ Client client = Client() Avatars avatars = Avatars(client); -UInt8List result = await avatars.getFavicon( +Uint8List result = await avatars.getFavicon( url: 'https://example.com', ); diff --git a/docs/examples/1.8.x/server-dart/examples/avatars/get-flag.md b/docs/examples/1.8.x/server-dart/examples/avatars/get-flag.md index 56046681bc..0aea028e5b 100644 --- a/docs/examples/1.8.x/server-dart/examples/avatars/get-flag.md +++ b/docs/examples/1.8.x/server-dart/examples/avatars/get-flag.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); -UInt8List result = await avatars.getFlag( +Uint8List result = await avatars.getFlag( code: Flag.afghanistan, width: 0, // (optional) height: 0, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/avatars/get-image.md b/docs/examples/1.8.x/server-dart/examples/avatars/get-image.md index b6db1858c5..fc727f481e 100644 --- a/docs/examples/1.8.x/server-dart/examples/avatars/get-image.md +++ b/docs/examples/1.8.x/server-dart/examples/avatars/get-image.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); -UInt8List result = await avatars.getImage( +Uint8List result = await avatars.getImage( url: 'https://example.com', width: 0, // (optional) height: 0, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/avatars/get-initials.md b/docs/examples/1.8.x/server-dart/examples/avatars/get-initials.md index 7dc0989b4d..be77c67147 100644 --- a/docs/examples/1.8.x/server-dart/examples/avatars/get-initials.md +++ b/docs/examples/1.8.x/server-dart/examples/avatars/get-initials.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); -UInt8List result = await avatars.getInitials( +Uint8List result = await avatars.getInitials( name: '', // (optional) width: 0, // (optional) height: 0, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/avatars/get-qr.md b/docs/examples/1.8.x/server-dart/examples/avatars/get-qr.md index f64fe8a4ff..f44ce59076 100644 --- a/docs/examples/1.8.x/server-dart/examples/avatars/get-qr.md +++ b/docs/examples/1.8.x/server-dart/examples/avatars/get-qr.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); -UInt8List result = await avatars.getQR( +Uint8List result = await avatars.getQR( text: '', size: 1, // (optional) margin: 0, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/avatars/get-screenshot.md b/docs/examples/1.8.x/server-dart/examples/avatars/get-screenshot.md index 7630648f98..0af7edafbf 100644 --- a/docs/examples/1.8.x/server-dart/examples/avatars/get-screenshot.md +++ b/docs/examples/1.8.x/server-dart/examples/avatars/get-screenshot.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); -UInt8List result = await avatars.getScreenshot( +Uint8List result = await avatars.getScreenshot( url: 'https://example.com', headers: {}, // (optional) viewportWidth: 1, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/functions/create-template-deployment.md b/docs/examples/1.8.x/server-dart/examples/functions/create-template-deployment.md index cc293b0c3b..bfd94b1963 100644 --- a/docs/examples/1.8.x/server-dart/examples/functions/create-template-deployment.md +++ b/docs/examples/1.8.x/server-dart/examples/functions/create-template-deployment.md @@ -12,6 +12,7 @@ Deployment result = await functions.createTemplateDeployment( repository: '', owner: '', rootDirectory: '', - version: '', + type: .commit, + reference: '', activate: false, // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/functions/get-deployment-download.md b/docs/examples/1.8.x/server-dart/examples/functions/get-deployment-download.md index e7bbacf344..1b93e3bad9 100644 --- a/docs/examples/1.8.x/server-dart/examples/functions/get-deployment-download.md +++ b/docs/examples/1.8.x/server-dart/examples/functions/get-deployment-download.md @@ -7,7 +7,7 @@ Client client = Client() Functions functions = Functions(client); -UInt8List result = await functions.getDeploymentDownload( +Uint8List result = await functions.getDeploymentDownload( functionId: '', deploymentId: '', type: DeploymentDownloadType.source, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/sites/create-template-deployment.md b/docs/examples/1.8.x/server-dart/examples/sites/create-template-deployment.md index 348b4652b6..93c9b1d283 100644 --- a/docs/examples/1.8.x/server-dart/examples/sites/create-template-deployment.md +++ b/docs/examples/1.8.x/server-dart/examples/sites/create-template-deployment.md @@ -12,6 +12,7 @@ Deployment result = await sites.createTemplateDeployment( repository: '', owner: '', rootDirectory: '', - version: '', + type: .branch, + reference: '', activate: false, // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/sites/get-deployment-download.md b/docs/examples/1.8.x/server-dart/examples/sites/get-deployment-download.md index ad21070b8a..f6bbb3c35d 100644 --- a/docs/examples/1.8.x/server-dart/examples/sites/get-deployment-download.md +++ b/docs/examples/1.8.x/server-dart/examples/sites/get-deployment-download.md @@ -7,7 +7,7 @@ Client client = Client() Sites sites = Sites(client); -UInt8List result = await sites.getDeploymentDownload( +Uint8List result = await sites.getDeploymentDownload( siteId: '', deploymentId: '', type: DeploymentDownloadType.source, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/storage/create-bucket.md b/docs/examples/1.8.x/server-dart/examples/storage/create-bucket.md index 79357d0e4a..7907b93297 100644 --- a/docs/examples/1.8.x/server-dart/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-dart/examples/storage/create-bucket.md @@ -20,4 +20,5 @@ Bucket result = await storage.createBucket( compression: .none, // (optional) encryption: false, // (optional) antivirus: false, // (optional) + transformations: false, // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/storage/get-file-download.md b/docs/examples/1.8.x/server-dart/examples/storage/get-file-download.md index 8c119c386c..34f40685fe 100644 --- a/docs/examples/1.8.x/server-dart/examples/storage/get-file-download.md +++ b/docs/examples/1.8.x/server-dart/examples/storage/get-file-download.md @@ -7,7 +7,7 @@ Client client = Client() Storage storage = Storage(client); -UInt8List result = await storage.getFileDownload( +Uint8List result = await storage.getFileDownload( bucketId: '', fileId: '', token: '', // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/storage/get-file-preview.md b/docs/examples/1.8.x/server-dart/examples/storage/get-file-preview.md index a1f3c09b33..a14e12c630 100644 --- a/docs/examples/1.8.x/server-dart/examples/storage/get-file-preview.md +++ b/docs/examples/1.8.x/server-dart/examples/storage/get-file-preview.md @@ -7,7 +7,7 @@ Client client = Client() Storage storage = Storage(client); -UInt8List result = await storage.getFilePreview( +Uint8List result = await storage.getFilePreview( bucketId: '', fileId: '', width: 0, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/storage/get-file-view.md b/docs/examples/1.8.x/server-dart/examples/storage/get-file-view.md index d48b51c19c..a1d9271f13 100644 --- a/docs/examples/1.8.x/server-dart/examples/storage/get-file-view.md +++ b/docs/examples/1.8.x/server-dart/examples/storage/get-file-view.md @@ -7,7 +7,7 @@ Client client = Client() Storage storage = Storage(client); -UInt8List result = await storage.getFileView( +Uint8List result = await storage.getFileView( bucketId: '', fileId: '', token: '', // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/storage/update-bucket.md b/docs/examples/1.8.x/server-dart/examples/storage/update-bucket.md index f3eea941a3..83d0a16380 100644 --- a/docs/examples/1.8.x/server-dart/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-dart/examples/storage/update-bucket.md @@ -20,4 +20,5 @@ Bucket result = await storage.updateBucket( compression: .none, // (optional) encryption: false, // (optional) antivirus: false, // (optional) + transformations: false, // (optional) ); diff --git a/docs/examples/1.8.x/server-dotnet/examples/functions/create-template-deployment.md b/docs/examples/1.8.x/server-dotnet/examples/functions/create-template-deployment.md index 019a9bf256..125eeda5cc 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/functions/create-template-deployment.md +++ b/docs/examples/1.8.x/server-dotnet/examples/functions/create-template-deployment.md @@ -1,4 +1,5 @@ using Appwrite; +using Appwrite.Enums; using Appwrite.Models; using Appwrite.Services; @@ -14,6 +15,7 @@ Deployment result = await functions.CreateTemplateDeployment( repository: "", owner: "", rootDirectory: "", - version: "", + type: .Commit, + reference: "", activate: false // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/sites/create-template-deployment.md b/docs/examples/1.8.x/server-dotnet/examples/sites/create-template-deployment.md index 57f9a83d9c..9775cb659f 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/sites/create-template-deployment.md +++ b/docs/examples/1.8.x/server-dotnet/examples/sites/create-template-deployment.md @@ -1,4 +1,5 @@ using Appwrite; +using Appwrite.Enums; using Appwrite.Models; using Appwrite.Services; @@ -14,6 +15,7 @@ Deployment result = await sites.CreateTemplateDeployment( repository: "", owner: "", rootDirectory: "", - version: "", + type: .Branch, + reference: "", activate: false // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/storage/create-bucket.md b/docs/examples/1.8.x/server-dotnet/examples/storage/create-bucket.md index f009f694ad..8a13ad7093 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-dotnet/examples/storage/create-bucket.md @@ -20,5 +20,6 @@ Bucket result = await storage.CreateBucket( allowedFileExtensions: new List(), // optional compression: .None, // optional encryption: false, // optional - antivirus: false // optional + antivirus: false, // optional + transformations: false // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/storage/update-bucket.md b/docs/examples/1.8.x/server-dotnet/examples/storage/update-bucket.md index d41a45961c..dd02eb771d 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-dotnet/examples/storage/update-bucket.md @@ -20,5 +20,6 @@ Bucket result = await storage.UpdateBucket( allowedFileExtensions: new List(), // optional compression: .None, // optional encryption: false, // optional - antivirus: false // optional + antivirus: false, // optional + transformations: false // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-go/examples/functions/create-template-deployment.md b/docs/examples/1.8.x/server-go/examples/functions/create-template-deployment.md index 14f694ba4a..df9591f461 100644 --- a/docs/examples/1.8.x/server-go/examples/functions/create-template-deployment.md +++ b/docs/examples/1.8.x/server-go/examples/functions/create-template-deployment.md @@ -19,6 +19,7 @@ response, error := service.CreateTemplateDeployment( "", "", "", - "", + "commit", + "", functions.WithCreateTemplateDeploymentActivate(false), ) diff --git a/docs/examples/1.8.x/server-go/examples/sites/create-template-deployment.md b/docs/examples/1.8.x/server-go/examples/sites/create-template-deployment.md index 483d3e79ff..85bf2a3cf6 100644 --- a/docs/examples/1.8.x/server-go/examples/sites/create-template-deployment.md +++ b/docs/examples/1.8.x/server-go/examples/sites/create-template-deployment.md @@ -19,6 +19,7 @@ response, error := service.CreateTemplateDeployment( "", "", "", - "", + "branch", + "", sites.WithCreateTemplateDeploymentActivate(false), ) diff --git a/docs/examples/1.8.x/server-go/examples/storage/create-bucket.md b/docs/examples/1.8.x/server-go/examples/storage/create-bucket.md index 64e3c40191..7bec2acb68 100644 --- a/docs/examples/1.8.x/server-go/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-go/examples/storage/create-bucket.md @@ -25,4 +25,5 @@ response, error := service.CreateBucket( storage.WithCreateBucketCompression("none"), storage.WithCreateBucketEncryption(false), storage.WithCreateBucketAntivirus(false), + storage.WithCreateBucketTransformations(false), ) diff --git a/docs/examples/1.8.x/server-go/examples/storage/update-bucket.md b/docs/examples/1.8.x/server-go/examples/storage/update-bucket.md index bb5f7aa76d..7092c688b1 100644 --- a/docs/examples/1.8.x/server-go/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-go/examples/storage/update-bucket.md @@ -25,4 +25,5 @@ response, error := service.UpdateBucket( storage.WithUpdateBucketCompression("none"), storage.WithUpdateBucketEncryption(false), storage.WithUpdateBucketAntivirus(false), + storage.WithUpdateBucketTransformations(false), ) diff --git a/docs/examples/1.8.x/server-graphql/examples/functions/create-template-deployment.md b/docs/examples/1.8.x/server-graphql/examples/functions/create-template-deployment.md index 0ce968e5f4..9b0da7ec47 100644 --- a/docs/examples/1.8.x/server-graphql/examples/functions/create-template-deployment.md +++ b/docs/examples/1.8.x/server-graphql/examples/functions/create-template-deployment.md @@ -4,7 +4,8 @@ mutation { repository: "", owner: "", rootDirectory: "", - version: "", + type: "commit", + reference: "", activate: false ) { _id diff --git a/docs/examples/1.8.x/server-graphql/examples/sites/create-template-deployment.md b/docs/examples/1.8.x/server-graphql/examples/sites/create-template-deployment.md index f63d8c5e5a..f528811cc3 100644 --- a/docs/examples/1.8.x/server-graphql/examples/sites/create-template-deployment.md +++ b/docs/examples/1.8.x/server-graphql/examples/sites/create-template-deployment.md @@ -4,7 +4,8 @@ mutation { repository: "", owner: "", rootDirectory: "", - version: "", + type: "branch", + reference: "", activate: false ) { _id diff --git a/docs/examples/1.8.x/server-graphql/examples/storage/create-bucket.md b/docs/examples/1.8.x/server-graphql/examples/storage/create-bucket.md index 45d03802d2..fe54321f90 100644 --- a/docs/examples/1.8.x/server-graphql/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-graphql/examples/storage/create-bucket.md @@ -9,7 +9,8 @@ mutation { allowedFileExtensions: [], compression: "none", encryption: false, - antivirus: false + antivirus: false, + transformations: false ) { _id _createdAt @@ -23,5 +24,6 @@ mutation { compression encryption antivirus + transformations } } diff --git a/docs/examples/1.8.x/server-graphql/examples/storage/update-bucket.md b/docs/examples/1.8.x/server-graphql/examples/storage/update-bucket.md index 8265a15a58..ab4dc776fa 100644 --- a/docs/examples/1.8.x/server-graphql/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-graphql/examples/storage/update-bucket.md @@ -9,7 +9,8 @@ mutation { allowedFileExtensions: [], compression: "none", encryption: false, - antivirus: false + antivirus: false, + transformations: false ) { _id _createdAt @@ -23,5 +24,6 @@ mutation { compression encryption antivirus + transformations } } diff --git a/docs/examples/1.8.x/server-kotlin/java/functions/create-template-deployment.md b/docs/examples/1.8.x/server-kotlin/java/functions/create-template-deployment.md index 53b5a9ae6a..9a0642b04e 100644 --- a/docs/examples/1.8.x/server-kotlin/java/functions/create-template-deployment.md +++ b/docs/examples/1.8.x/server-kotlin/java/functions/create-template-deployment.md @@ -1,6 +1,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Functions; +import io.appwrite.enums.Type; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint @@ -14,7 +15,8 @@ functions.createTemplateDeployment( "", // repository "", // owner "", // rootDirectory - "", // version + .COMMIT, // type + "", // reference false, // activate (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { diff --git a/docs/examples/1.8.x/server-kotlin/java/sites/create-template-deployment.md b/docs/examples/1.8.x/server-kotlin/java/sites/create-template-deployment.md index 63aba4a067..a501461a2c 100644 --- a/docs/examples/1.8.x/server-kotlin/java/sites/create-template-deployment.md +++ b/docs/examples/1.8.x/server-kotlin/java/sites/create-template-deployment.md @@ -1,6 +1,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Sites; +import io.appwrite.enums.Type; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint @@ -14,7 +15,8 @@ sites.createTemplateDeployment( "", // repository "", // owner "", // rootDirectory - "", // version + .BRANCH, // type + "", // reference false, // activate (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { diff --git a/docs/examples/1.8.x/server-kotlin/java/storage/create-bucket.md b/docs/examples/1.8.x/server-kotlin/java/storage/create-bucket.md index d48db24094..248fd8d739 100644 --- a/docs/examples/1.8.x/server-kotlin/java/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-kotlin/java/storage/create-bucket.md @@ -22,6 +22,7 @@ storage.createBucket( .NONE, // compression (optional) false, // encryption (optional) false, // antivirus (optional) + false, // transformations (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/storage/update-bucket.md b/docs/examples/1.8.x/server-kotlin/java/storage/update-bucket.md index 586b113578..866c7548a8 100644 --- a/docs/examples/1.8.x/server-kotlin/java/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-kotlin/java/storage/update-bucket.md @@ -22,6 +22,7 @@ storage.updateBucket( .NONE, // compression (optional) false, // encryption (optional) false, // antivirus (optional) + false, // transformations (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/functions/create-template-deployment.md b/docs/examples/1.8.x/server-kotlin/kotlin/functions/create-template-deployment.md index 90c311ec7a..b8eb44b4fa 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/functions/create-template-deployment.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/functions/create-template-deployment.md @@ -1,6 +1,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Functions +import io.appwrite.enums.Type val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint @@ -14,6 +15,7 @@ val response = functions.createTemplateDeployment( repository = "", owner = "", rootDirectory = "", - version = "", + type = .COMMIT, + reference = "", activate = false // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/sites/create-template-deployment.md b/docs/examples/1.8.x/server-kotlin/kotlin/sites/create-template-deployment.md index bf246be089..1f3d7d386a 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/sites/create-template-deployment.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/sites/create-template-deployment.md @@ -1,6 +1,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Sites +import io.appwrite.enums.Type val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint @@ -14,6 +15,7 @@ val response = sites.createTemplateDeployment( repository = "", owner = "", rootDirectory = "", - version = "", + type = .BRANCH, + reference = "", activate = false // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/storage/create-bucket.md b/docs/examples/1.8.x/server-kotlin/kotlin/storage/create-bucket.md index 872932eeff..d89dca3b1f 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/storage/create-bucket.md @@ -21,5 +21,6 @@ val response = storage.createBucket( allowedFileExtensions = listOf(), // optional compression = "none", // optional encryption = false, // optional - antivirus = false // optional + antivirus = false, // optional + transformations = false // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/storage/update-bucket.md b/docs/examples/1.8.x/server-kotlin/kotlin/storage/update-bucket.md index cb8187343e..f51fee9007 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/storage/update-bucket.md @@ -21,5 +21,6 @@ val response = storage.updateBucket( allowedFileExtensions = listOf(), // optional compression = "none", // optional encryption = false, // optional - antivirus = false // optional + antivirus = false, // optional + transformations = false // optional ) diff --git a/docs/examples/1.8.x/server-nodejs/examples/functions/create-template-deployment.md b/docs/examples/1.8.x/server-nodejs/examples/functions/create-template-deployment.md index 8f6395f8fb..999c029f8f 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/functions/create-template-deployment.md +++ b/docs/examples/1.8.x/server-nodejs/examples/functions/create-template-deployment.md @@ -12,6 +12,7 @@ const result = await functions.createTemplateDeployment({ repository: '', owner: '', rootDirectory: '', - version: '', + type: sdk..Commit, + reference: '', activate: false // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/sites/create-template-deployment.md b/docs/examples/1.8.x/server-nodejs/examples/sites/create-template-deployment.md index 7dfb4370e6..dc9736fa80 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/sites/create-template-deployment.md +++ b/docs/examples/1.8.x/server-nodejs/examples/sites/create-template-deployment.md @@ -12,6 +12,7 @@ const result = await sites.createTemplateDeployment({ repository: '', owner: '', rootDirectory: '', - version: '', + type: sdk..Branch, + reference: '', activate: false // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/storage/create-bucket.md b/docs/examples/1.8.x/server-nodejs/examples/storage/create-bucket.md index b47d2c8353..a279ab50ed 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-nodejs/examples/storage/create-bucket.md @@ -17,5 +17,6 @@ const result = await storage.createBucket({ allowedFileExtensions: [], // optional compression: sdk..None, // optional encryption: false, // optional - antivirus: false // optional + antivirus: false, // optional + transformations: false // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/storage/update-bucket.md b/docs/examples/1.8.x/server-nodejs/examples/storage/update-bucket.md index 9535914eeb..cf313c0a2b 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-nodejs/examples/storage/update-bucket.md @@ -17,5 +17,6 @@ const result = await storage.updateBucket({ allowedFileExtensions: [], // optional compression: sdk..None, // optional encryption: false, // optional - antivirus: false // optional + antivirus: false, // optional + transformations: false // optional }); diff --git a/docs/examples/1.8.x/server-php/examples/functions/create-template-deployment.md b/docs/examples/1.8.x/server-php/examples/functions/create-template-deployment.md index 9d22bdc1b4..5888396312 100644 --- a/docs/examples/1.8.x/server-php/examples/functions/create-template-deployment.md +++ b/docs/examples/1.8.x/server-php/examples/functions/create-template-deployment.md @@ -2,6 +2,7 @@ use Appwrite\Client; use Appwrite\Services\Functions; +use Appwrite\Enums\Type; $client = (new Client()) ->setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -15,6 +16,7 @@ $result = $functions->createTemplateDeployment( repository: '', owner: '', rootDirectory: '', - version: '', + type: Type::COMMIT(), + reference: '', activate: false // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/sites/create-template-deployment.md b/docs/examples/1.8.x/server-php/examples/sites/create-template-deployment.md index f2d1f3cd8b..314ffdd1b9 100644 --- a/docs/examples/1.8.x/server-php/examples/sites/create-template-deployment.md +++ b/docs/examples/1.8.x/server-php/examples/sites/create-template-deployment.md @@ -2,6 +2,7 @@ use Appwrite\Client; use Appwrite\Services\Sites; +use Appwrite\Enums\Type; $client = (new Client()) ->setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -15,6 +16,7 @@ $result = $sites->createTemplateDeployment( repository: '', owner: '', rootDirectory: '', - version: '', + type: Type::BRANCH(), + reference: '', activate: false // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/storage/create-bucket.md b/docs/examples/1.8.x/server-php/examples/storage/create-bucket.md index 3d4f717e4d..31840957a2 100644 --- a/docs/examples/1.8.x/server-php/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-php/examples/storage/create-bucket.md @@ -23,5 +23,6 @@ $result = $storage->createBucket( allowedFileExtensions: [], // optional compression: Compression::NONE(), // optional encryption: false, // optional - antivirus: false // optional + antivirus: false, // optional + transformations: false // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-php/examples/storage/update-bucket.md b/docs/examples/1.8.x/server-php/examples/storage/update-bucket.md index 77f4262c2d..1556257849 100644 --- a/docs/examples/1.8.x/server-php/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-php/examples/storage/update-bucket.md @@ -23,5 +23,6 @@ $result = $storage->updateBucket( allowedFileExtensions: [], // optional compression: Compression::NONE(), // optional encryption: false, // optional - antivirus: false // optional + antivirus: false, // optional + transformations: false // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-python/examples/functions/create-template-deployment.md b/docs/examples/1.8.x/server-python/examples/functions/create-template-deployment.md index 6083cc1cb3..d9f8f70a82 100644 --- a/docs/examples/1.8.x/server-python/examples/functions/create-template-deployment.md +++ b/docs/examples/1.8.x/server-python/examples/functions/create-template-deployment.md @@ -1,5 +1,6 @@ from appwrite.client import Client from appwrite.services.functions import Functions +from appwrite.enums import client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -13,6 +14,7 @@ result = functions.create_template_deployment( repository = '', owner = '', root_directory = '', - version = '', + type = .COMMIT, + reference = '', activate = False # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/sites/create-template-deployment.md b/docs/examples/1.8.x/server-python/examples/sites/create-template-deployment.md index ac05f9e663..fb47cb1453 100644 --- a/docs/examples/1.8.x/server-python/examples/sites/create-template-deployment.md +++ b/docs/examples/1.8.x/server-python/examples/sites/create-template-deployment.md @@ -1,5 +1,6 @@ from appwrite.client import Client from appwrite.services.sites import Sites +from appwrite.enums import client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -13,6 +14,7 @@ result = sites.create_template_deployment( repository = '', owner = '', root_directory = '', - version = '', + type = .BRANCH, + reference = '', activate = False # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/storage/create-bucket.md b/docs/examples/1.8.x/server-python/examples/storage/create-bucket.md index e08b2d0d6b..61430416bc 100644 --- a/docs/examples/1.8.x/server-python/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-python/examples/storage/create-bucket.md @@ -20,5 +20,6 @@ result = storage.create_bucket( allowed_file_extensions = [], # optional compression = .NONE, # optional encryption = False, # optional - antivirus = False # optional + antivirus = False, # optional + transformations = False # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/storage/update-bucket.md b/docs/examples/1.8.x/server-python/examples/storage/update-bucket.md index bfa7cc3fdb..977ef58448 100644 --- a/docs/examples/1.8.x/server-python/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-python/examples/storage/update-bucket.md @@ -20,5 +20,6 @@ result = storage.update_bucket( allowed_file_extensions = [], # optional compression = .NONE, # optional encryption = False, # optional - antivirus = False # optional + antivirus = False, # optional + transformations = False # optional ) diff --git a/docs/examples/1.8.x/server-rest/examples/functions/create-template-deployment.md b/docs/examples/1.8.x/server-rest/examples/functions/create-template-deployment.md index 18ebf65efe..474763831f 100644 --- a/docs/examples/1.8.x/server-rest/examples/functions/create-template-deployment.md +++ b/docs/examples/1.8.x/server-rest/examples/functions/create-template-deployment.md @@ -9,6 +9,7 @@ X-Appwrite-Key: "repository": "", "owner": "", "rootDirectory": "", - "version": "", + "type": "commit", + "reference": "", "activate": false } diff --git a/docs/examples/1.8.x/server-rest/examples/sites/create-template-deployment.md b/docs/examples/1.8.x/server-rest/examples/sites/create-template-deployment.md index 3b21f4f754..9f58d3e97e 100644 --- a/docs/examples/1.8.x/server-rest/examples/sites/create-template-deployment.md +++ b/docs/examples/1.8.x/server-rest/examples/sites/create-template-deployment.md @@ -9,6 +9,7 @@ X-Appwrite-Key: "repository": "", "owner": "", "rootDirectory": "", - "version": "", + "type": "branch", + "reference": "", "activate": false } diff --git a/docs/examples/1.8.x/server-rest/examples/storage/create-bucket.md b/docs/examples/1.8.x/server-rest/examples/storage/create-bucket.md index 59f1c4f403..81104d36f5 100644 --- a/docs/examples/1.8.x/server-rest/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-rest/examples/storage/create-bucket.md @@ -15,5 +15,6 @@ X-Appwrite-Key: "allowedFileExtensions": [], "compression": "none", "encryption": false, - "antivirus": false + "antivirus": false, + "transformations": false } diff --git a/docs/examples/1.8.x/server-rest/examples/storage/update-bucket.md b/docs/examples/1.8.x/server-rest/examples/storage/update-bucket.md index 0f966da0b5..d46ce52a58 100644 --- a/docs/examples/1.8.x/server-rest/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-rest/examples/storage/update-bucket.md @@ -14,5 +14,6 @@ X-Appwrite-Key: "allowedFileExtensions": [], "compression": "none", "encryption": false, - "antivirus": false + "antivirus": false, + "transformations": false } diff --git a/docs/examples/1.8.x/server-ruby/examples/functions/create-template-deployment.md b/docs/examples/1.8.x/server-ruby/examples/functions/create-template-deployment.md index a447b6e9aa..cfe0adc263 100644 --- a/docs/examples/1.8.x/server-ruby/examples/functions/create-template-deployment.md +++ b/docs/examples/1.8.x/server-ruby/examples/functions/create-template-deployment.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums client = Client.new .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -14,6 +15,7 @@ result = functions.create_template_deployment( repository: '', owner: '', root_directory: '', - version: '', + type: ::COMMIT, + reference: '', activate: false # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/sites/create-template-deployment.md b/docs/examples/1.8.x/server-ruby/examples/sites/create-template-deployment.md index 7df9665590..9e1cc93986 100644 --- a/docs/examples/1.8.x/server-ruby/examples/sites/create-template-deployment.md +++ b/docs/examples/1.8.x/server-ruby/examples/sites/create-template-deployment.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums client = Client.new .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -14,6 +15,7 @@ result = sites.create_template_deployment( repository: '', owner: '', root_directory: '', - version: '', + type: ::BRANCH, + reference: '', activate: false # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/storage/create-bucket.md b/docs/examples/1.8.x/server-ruby/examples/storage/create-bucket.md index 4a12518fb7..d10e7b8127 100644 --- a/docs/examples/1.8.x/server-ruby/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-ruby/examples/storage/create-bucket.md @@ -21,5 +21,6 @@ result = storage.create_bucket( allowed_file_extensions: [], # optional compression: ::NONE, # optional encryption: false, # optional - antivirus: false # optional + antivirus: false, # optional + transformations: false # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/storage/update-bucket.md b/docs/examples/1.8.x/server-ruby/examples/storage/update-bucket.md index 2e44aad536..dbb491df5a 100644 --- a/docs/examples/1.8.x/server-ruby/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-ruby/examples/storage/update-bucket.md @@ -21,5 +21,6 @@ result = storage.update_bucket( allowed_file_extensions: [], # optional compression: ::NONE, # optional encryption: false, # optional - antivirus: false # optional + antivirus: false, # optional + transformations: false # optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/functions/create-template-deployment.md b/docs/examples/1.8.x/server-swift/examples/functions/create-template-deployment.md index 27c5311c7a..6a9045637c 100644 --- a/docs/examples/1.8.x/server-swift/examples/functions/create-template-deployment.md +++ b/docs/examples/1.8.x/server-swift/examples/functions/create-template-deployment.md @@ -1,4 +1,5 @@ import Appwrite +import AppwriteEnums let client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint @@ -12,7 +13,8 @@ let deployment = try await functions.createTemplateDeployment( repository: "", owner: "", rootDirectory: "", - version: "", + type: .commit, + reference: "", activate: false // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/sites/create-template-deployment.md b/docs/examples/1.8.x/server-swift/examples/sites/create-template-deployment.md index 1cb3e42030..250eb124a5 100644 --- a/docs/examples/1.8.x/server-swift/examples/sites/create-template-deployment.md +++ b/docs/examples/1.8.x/server-swift/examples/sites/create-template-deployment.md @@ -1,4 +1,5 @@ import Appwrite +import AppwriteEnums let client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint @@ -12,7 +13,8 @@ let deployment = try await sites.createTemplateDeployment( repository: "", owner: "", rootDirectory: "", - version: "", + type: .branch, + reference: "", activate: false // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/storage/create-bucket.md b/docs/examples/1.8.x/server-swift/examples/storage/create-bucket.md index a97f450bfe..9931b81943 100644 --- a/docs/examples/1.8.x/server-swift/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-swift/examples/storage/create-bucket.md @@ -18,6 +18,7 @@ let bucket = try await storage.createBucket( allowedFileExtensions: [], // optional compression: .none, // optional encryption: false, // optional - antivirus: false // optional + antivirus: false, // optional + transformations: false // optional ) diff --git a/docs/examples/1.8.x/server-swift/examples/storage/update-bucket.md b/docs/examples/1.8.x/server-swift/examples/storage/update-bucket.md index 2d89d7c464..be283b7d6a 100644 --- a/docs/examples/1.8.x/server-swift/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-swift/examples/storage/update-bucket.md @@ -18,6 +18,7 @@ let bucket = try await storage.updateBucket( allowedFileExtensions: [], // optional compression: .none, // optional encryption: false, // optional - antivirus: false // optional + antivirus: false, // optional + transformations: false // optional ) From b6fbddad81aa644f5dff511698d0759395d78870 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 18 Nov 2025 11:07:50 +0530 Subject: [PATCH 64/77] fix: a lot of enum examples generated --- composer.json | 2 +- composer.lock | 32 ++++++++++--------- .../java/avatars/get-screenshot.md | 9 ++++-- .../java/functions/create-execution.md | 1 + .../java/storage/get-file-preview.md | 2 ++ .../kotlin/avatars/get-screenshot.md | 3 ++ .../kotlin/functions/create-execution.md | 1 + .../kotlin/storage/get-file-preview.md | 2 ++ .../examples/avatars/get-browser.md | 2 +- .../examples/avatars/get-credit-card.md | 2 +- .../examples/avatars/get-favicon.md | 2 +- .../examples/avatars/get-flag.md | 2 +- .../examples/avatars/get-image.md | 2 +- .../examples/avatars/get-initials.md | 2 +- .../client-flutter/examples/avatars/get-qr.md | 2 +- .../examples/avatars/get-screenshot.md | 14 ++++---- .../examples/storage/get-file-download.md | 2 +- .../examples/storage/get-file-preview.md | 2 +- .../examples/storage/get-file-view.md | 2 +- .../examples/avatars/get-screenshot.md | 8 ++--- .../examples/avatars/get-screenshot.md | 8 ++--- .../examples/avatars/get-screenshot.md | 8 ++--- .../console-web/examples/functions/create.md | 4 +-- .../console-web/examples/functions/update.md | 4 +-- .../examples/health/get-failed-jobs.md | 4 +-- .../console-web/examples/projects/create.md | 4 +-- .../examples/projects/update-api-status.md | 4 +-- .../examples/proxy/create-redirect-rule.md | 4 +-- .../console-web/examples/sites/create.md | 8 ++--- .../console-web/examples/sites/update.md | 8 ++--- .../examples/storage/create-bucket.md | 4 +-- .../examples/storage/update-bucket.md | 4 +-- .../examples/avatars/get-browser.md | 2 +- .../examples/avatars/get-credit-card.md | 2 +- .../examples/avatars/get-favicon.md | 2 +- .../server-dart/examples/avatars/get-flag.md | 2 +- .../server-dart/examples/avatars/get-image.md | 2 +- .../examples/avatars/get-initials.md | 2 +- .../server-dart/examples/avatars/get-qr.md | 2 +- .../examples/avatars/get-screenshot.md | 8 ++--- .../server-dart/examples/functions/create.md | 2 +- .../functions/get-deployment-download.md | 2 +- .../server-dart/examples/functions/update.md | 2 +- .../examples/health/get-failed-jobs.md | 2 +- .../server-dart/examples/sites/create.md | 6 ++-- .../examples/sites/get-deployment-download.md | 2 +- .../server-dart/examples/sites/update.md | 6 ++-- .../examples/storage/create-bucket.md | 2 +- .../examples/storage/get-file-download.md | 2 +- .../examples/storage/get-file-preview.md | 2 +- .../examples/storage/get-file-view.md | 2 +- .../examples/storage/update-bucket.md | 2 +- .../examples/avatars/get-screenshot.md | 6 ++-- .../examples/functions/create.md | 2 +- .../examples/functions/update.md | 2 +- .../examples/health/get-failed-jobs.md | 2 +- .../server-dotnet/examples/sites/create.md | 6 ++-- .../server-dotnet/examples/sites/update.md | 6 ++-- .../examples/storage/create-bucket.md | 2 +- .../examples/storage/update-bucket.md | 2 +- .../java/avatars/get-screenshot.md | 9 ++++-- .../create-relationship-attribute.md | 1 + .../update-relationship-attribute.md | 1 + .../java/functions/create-execution.md | 1 + .../server-kotlin/java/functions/create.md | 2 +- .../java/functions/get-deployment-download.md | 1 + .../server-kotlin/java/functions/update.md | 3 +- .../java/health/get-failed-jobs.md | 2 +- .../java/messaging/create-push.md | 1 + .../java/messaging/create-smtp-provider.md | 1 + .../java/messaging/update-push.md | 1 + .../java/messaging/update-smtp-provider.md | 1 + .../1.8.x/server-kotlin/java/sites/create.md | 7 ++-- .../java/sites/get-deployment-download.md | 1 + .../1.8.x/server-kotlin/java/sites/update.md | 8 +++-- .../java/storage/create-bucket.md | 3 +- .../java/storage/get-file-preview.md | 2 ++ .../java/storage/update-bucket.md | 3 +- .../tablesdb/create-relationship-column.md | 1 + .../tablesdb/update-relationship-column.md | 1 + .../java/users/create-sha-user.md | 1 + .../kotlin/avatars/get-screenshot.md | 3 ++ .../create-relationship-attribute.md | 1 + .../update-relationship-attribute.md | 1 + .../kotlin/functions/create-execution.md | 1 + .../server-kotlin/kotlin/functions/create.md | 2 +- .../functions/get-deployment-download.md | 1 + .../server-kotlin/kotlin/functions/update.md | 1 + .../kotlin/health/get-failed-jobs.md | 2 +- .../kotlin/messaging/create-push.md | 1 + .../kotlin/messaging/create-smtp-provider.md | 1 + .../kotlin/messaging/update-push.md | 1 + .../kotlin/messaging/update-smtp-provider.md | 1 + .../server-kotlin/kotlin/sites/create.md | 5 +-- .../kotlin/sites/get-deployment-download.md | 1 + .../server-kotlin/kotlin/sites/update.md | 4 ++- .../kotlin/storage/create-bucket.md | 1 + .../kotlin/storage/get-file-preview.md | 2 ++ .../kotlin/storage/update-bucket.md | 1 + .../tablesdb/create-relationship-column.md | 1 + .../tablesdb/update-relationship-column.md | 1 + .../kotlin/users/create-sha-user.md | 1 + .../examples/avatars/get-screenshot.md | 6 ++-- .../examples/functions/create.md | 2 +- .../examples/functions/update.md | 2 +- .../examples/health/get-failed-jobs.md | 2 +- .../server-nodejs/examples/sites/create.md | 6 ++-- .../server-nodejs/examples/sites/update.md | 6 ++-- .../examples/storage/create-bucket.md | 2 +- .../examples/storage/update-bucket.md | 2 +- .../examples/avatars/get-screenshot.md | 9 ++++-- .../create-relationship-attribute.md | 1 + .../update-relationship-attribute.md | 1 + .../examples/functions/create-execution.md | 1 + .../examples/functions/create.md | 4 +-- .../functions/get-deployment-download.md | 1 + .../examples/functions/update.md | 3 +- .../examples/health/get-failed-jobs.md | 4 +-- .../examples/messaging/create-push.md | 1 + .../messaging/create-smtp-provider.md | 1 + .../examples/messaging/update-push.md | 1 + .../messaging/update-smtp-provider.md | 1 + .../server-python/examples/sites/create.md | 11 ++++--- .../examples/sites/get-deployment-download.md | 1 + .../server-python/examples/sites/update.md | 10 +++--- .../examples/storage/create-bucket.md | 3 +- .../examples/storage/get-file-preview.md | 2 ++ .../examples/storage/update-bucket.md | 3 +- .../tablesdb/create-relationship-column.md | 1 + .../tablesdb/update-relationship-column.md | 1 + .../examples/users/create-sha-user.md | 1 + .../examples/avatars/get-screenshot.md | 7 ++-- .../update-relationship-attribute.md | 1 + .../examples/functions/create-execution.md | 1 + .../server-ruby/examples/functions/create.md | 2 +- .../functions/get-deployment-download.md | 1 + .../server-ruby/examples/functions/update.md | 3 +- .../examples/health/get-failed-jobs.md | 2 +- .../examples/messaging/create-push.md | 1 + .../messaging/create-smtp-provider.md | 1 + .../examples/messaging/update-push.md | 1 + .../messaging/update-smtp-provider.md | 1 + .../server-ruby/examples/sites/create.md | 6 ++-- .../examples/sites/get-deployment-download.md | 1 + .../server-ruby/examples/sites/update.md | 6 ++-- .../examples/storage/create-bucket.md | 3 +- .../examples/storage/get-file-preview.md | 1 + .../examples/storage/update-bucket.md | 3 +- .../tablesdb/update-relationship-column.md | 1 + .../examples/users/create-sha-user.md | 1 + 150 files changed, 277 insertions(+), 179 deletions(-) diff --git a/composer.json b/composer.json index 1cff497d08..0a4e347d7f 100644 --- a/composer.json +++ b/composer.json @@ -88,7 +88,7 @@ }, "require-dev": { "ext-fileinfo": "*", - "appwrite/sdk-generator": "*", + "appwrite/sdk-generator": "dev-fix-enum-rendering", "phpunit/phpunit": "9.*", "swoole/ide-helper": "5.1.2", "phpstan/phpstan": "1.8.*", diff --git a/composer.lock b/composer.lock index afbbaa516d..f173903669 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": "3b502f78f5e31f2ea7b4c69e3301283a", + "content-hash": "bc877cc8bf639e146710e0d7656adbec", "packages": [ { "name": "adhocore/jwt", @@ -5383,16 +5383,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.5.5", + "version": "dev-fix-enum-rendering", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "1f3686e41a2d10829220b74f54c80a770e9f968a" + "reference": "3f39061b0db19057219bab6352afa2201306eedf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/1f3686e41a2d10829220b74f54c80a770e9f968a", - "reference": "1f3686e41a2d10829220b74f54c80a770e9f968a", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/3f39061b0db19057219bab6352afa2201306eedf", + "reference": "3f39061b0db19057219bab6352afa2201306eedf", "shasum": "" }, "require": { @@ -5428,9 +5428,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.5.5" + "source": "https://github.com/appwrite/sdk-generator/tree/fix-enum-rendering" }, - "time": "2025-11-14T05:56:33+00:00" + "time": "2025-11-18T05:35:14+00:00" }, { "name": "doctrine/annotations", @@ -8718,16 +8718,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.3.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb" + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/d74205c497bfbca49f34d4bc4c19c17e22db4ebb", - "reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { @@ -8756,7 +8756,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.3.0" + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { @@ -8764,7 +8764,7 @@ "type": "github" } ], - "time": "2025-11-13T13:44:09+00:00" + "time": "2025-11-17T20:03:58+00:00" }, { "name": "twig/twig", @@ -8897,7 +8897,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "appwrite/sdk-generator": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8921,5 +8923,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/docs/examples/1.8.x/client-android/java/avatars/get-screenshot.md b/docs/examples/1.8.x/client-android/java/avatars/get-screenshot.md index 077716f523..48babdca20 100644 --- a/docs/examples/1.8.x/client-android/java/avatars/get-screenshot.md +++ b/docs/examples/1.8.x/client-android/java/avatars/get-screenshot.md @@ -1,6 +1,9 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Avatars; +import io.appwrite.enums.Theme; +import io.appwrite.enums.Timezone; +import io.appwrite.enums.Output; Client client = new Client(context) .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint @@ -14,11 +17,11 @@ avatars.getScreenshot( 1, // viewportWidth (optional) 1, // viewportHeight (optional) 0.1, // scale (optional) - theme.LIGHT, // theme (optional) + Theme.LIGHT, // theme (optional) "", // userAgent (optional) false, // fullpage (optional) "", // locale (optional) - timezone.AFRICA_ABIDJAN, // timezone (optional) + Timezone.AFRICA_ABIDJAN, // timezone (optional) -90, // latitude (optional) -180, // longitude (optional) 0, // accuracy (optional) @@ -28,7 +31,7 @@ avatars.getScreenshot( 0, // width (optional) 0, // height (optional) -1, // quality (optional) - output.JPG, // output (optional) + Output.JPG, // output (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/client-android/java/functions/create-execution.md b/docs/examples/1.8.x/client-android/java/functions/create-execution.md index 06c50278a5..758881d13c 100644 --- a/docs/examples/1.8.x/client-android/java/functions/create-execution.md +++ b/docs/examples/1.8.x/client-android/java/functions/create-execution.md @@ -1,6 +1,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Functions; +import io.appwrite.enums.ExecutionMethod; Client client = new Client(context) .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/client-android/java/storage/get-file-preview.md b/docs/examples/1.8.x/client-android/java/storage/get-file-preview.md index 67b92ebf85..392ef11649 100644 --- a/docs/examples/1.8.x/client-android/java/storage/get-file-preview.md +++ b/docs/examples/1.8.x/client-android/java/storage/get-file-preview.md @@ -1,6 +1,8 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Storage; +import io.appwrite.enums.ImageGravity; +import io.appwrite.enums.ImageFormat; Client client = new Client(context) .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/client-android/kotlin/avatars/get-screenshot.md b/docs/examples/1.8.x/client-android/kotlin/avatars/get-screenshot.md index 014ca90fd8..2638e9e6a5 100644 --- a/docs/examples/1.8.x/client-android/kotlin/avatars/get-screenshot.md +++ b/docs/examples/1.8.x/client-android/kotlin/avatars/get-screenshot.md @@ -1,6 +1,9 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Avatars +import io.appwrite.enums.Theme +import io.appwrite.enums.Timezone +import io.appwrite.enums.Output val client = Client(context) .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/client-android/kotlin/functions/create-execution.md b/docs/examples/1.8.x/client-android/kotlin/functions/create-execution.md index 5e1950b8d9..8f7b49b849 100644 --- a/docs/examples/1.8.x/client-android/kotlin/functions/create-execution.md +++ b/docs/examples/1.8.x/client-android/kotlin/functions/create-execution.md @@ -1,6 +1,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Functions +import io.appwrite.enums.ExecutionMethod val client = Client(context) .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/client-android/kotlin/storage/get-file-preview.md b/docs/examples/1.8.x/client-android/kotlin/storage/get-file-preview.md index d766dc7174..a4841d53c4 100644 --- a/docs/examples/1.8.x/client-android/kotlin/storage/get-file-preview.md +++ b/docs/examples/1.8.x/client-android/kotlin/storage/get-file-preview.md @@ -1,6 +1,8 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Storage +import io.appwrite.enums.ImageGravity +import io.appwrite.enums.ImageFormat val client = Client(context) .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/client-flutter/examples/avatars/get-browser.md b/docs/examples/1.8.x/client-flutter/examples/avatars/get-browser.md index e97d24ab4f..50c28ff378 100644 --- a/docs/examples/1.8.x/client-flutter/examples/avatars/get-browser.md +++ b/docs/examples/1.8.x/client-flutter/examples/avatars/get-browser.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); // Downloading file -UInt8List bytes = await avatars.getBrowser( +Uint8List bytes = await avatars.getBrowser( code: Browser.avantBrowser, width: 0, // optional height: 0, // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/avatars/get-credit-card.md b/docs/examples/1.8.x/client-flutter/examples/avatars/get-credit-card.md index 9ec42588b4..c3471fc2e8 100644 --- a/docs/examples/1.8.x/client-flutter/examples/avatars/get-credit-card.md +++ b/docs/examples/1.8.x/client-flutter/examples/avatars/get-credit-card.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); // Downloading file -UInt8List bytes = await avatars.getCreditCard( +Uint8List bytes = await avatars.getCreditCard( code: CreditCard.americanExpress, width: 0, // optional height: 0, // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/avatars/get-favicon.md b/docs/examples/1.8.x/client-flutter/examples/avatars/get-favicon.md index 0df5ed0d2a..abd61a0974 100644 --- a/docs/examples/1.8.x/client-flutter/examples/avatars/get-favicon.md +++ b/docs/examples/1.8.x/client-flutter/examples/avatars/get-favicon.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); // Downloading file -UInt8List bytes = await avatars.getFavicon( +Uint8List bytes = await avatars.getFavicon( url: 'https://example.com', ) diff --git a/docs/examples/1.8.x/client-flutter/examples/avatars/get-flag.md b/docs/examples/1.8.x/client-flutter/examples/avatars/get-flag.md index 99d43409a0..e5a4c60ba9 100644 --- a/docs/examples/1.8.x/client-flutter/examples/avatars/get-flag.md +++ b/docs/examples/1.8.x/client-flutter/examples/avatars/get-flag.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); // Downloading file -UInt8List bytes = await avatars.getFlag( +Uint8List bytes = await avatars.getFlag( code: Flag.afghanistan, width: 0, // optional height: 0, // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/avatars/get-image.md b/docs/examples/1.8.x/client-flutter/examples/avatars/get-image.md index 5b9d1b58c1..bbfcc03885 100644 --- a/docs/examples/1.8.x/client-flutter/examples/avatars/get-image.md +++ b/docs/examples/1.8.x/client-flutter/examples/avatars/get-image.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); // Downloading file -UInt8List bytes = await avatars.getImage( +Uint8List bytes = await avatars.getImage( url: 'https://example.com', width: 0, // optional height: 0, // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/avatars/get-initials.md b/docs/examples/1.8.x/client-flutter/examples/avatars/get-initials.md index 0c5b62a309..29940c17bf 100644 --- a/docs/examples/1.8.x/client-flutter/examples/avatars/get-initials.md +++ b/docs/examples/1.8.x/client-flutter/examples/avatars/get-initials.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); // Downloading file -UInt8List bytes = await avatars.getInitials( +Uint8List bytes = await avatars.getInitials( name: '', // optional width: 0, // optional height: 0, // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/avatars/get-qr.md b/docs/examples/1.8.x/client-flutter/examples/avatars/get-qr.md index d9a533c886..0a75a6682f 100644 --- a/docs/examples/1.8.x/client-flutter/examples/avatars/get-qr.md +++ b/docs/examples/1.8.x/client-flutter/examples/avatars/get-qr.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); // Downloading file -UInt8List bytes = await avatars.getQR( +Uint8List bytes = await avatars.getQR( text: '', size: 1, // optional margin: 0, // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/avatars/get-screenshot.md b/docs/examples/1.8.x/client-flutter/examples/avatars/get-screenshot.md index 768cb8f271..42a5ca7230 100644 --- a/docs/examples/1.8.x/client-flutter/examples/avatars/get-screenshot.md +++ b/docs/examples/1.8.x/client-flutter/examples/avatars/get-screenshot.md @@ -7,17 +7,17 @@ Client client = Client() Avatars avatars = Avatars(client); // Downloading file -UInt8List bytes = await avatars.getScreenshot( +Uint8List bytes = await avatars.getScreenshot( url: 'https://example.com', headers: {}, // optional viewportWidth: 1, // optional viewportHeight: 1, // optional scale: 0.1, // optional - theme: .light, // optional + theme: Theme.light, // optional userAgent: '', // optional fullpage: false, // optional locale: '', // optional - timezone: .africaAbidjan, // optional + timezone: Timezone.africaAbidjan, // optional latitude: -90, // optional longitude: -180, // optional accuracy: 0, // optional @@ -27,7 +27,7 @@ UInt8List bytes = await avatars.getScreenshot( width: 0, // optional height: 0, // optional quality: -1, // optional - output: .jpg, // optional + output: Output.jpg, // optional ) final file = File('path_to_file/filename.ext'); @@ -41,11 +41,11 @@ FutureBuilder( viewportWidth:1 , // optional viewportHeight:1 , // optional scale:0.1 , // optional - theme: .light, // optional + theme: Theme.light, // optional userAgent:'' , // optional fullpage:false , // optional locale:'' , // optional - timezone: .africaAbidjan, // optional + timezone: Timezone.africaAbidjan, // optional latitude:-90 , // optional longitude:-180 , // optional accuracy:0 , // optional @@ -55,7 +55,7 @@ FutureBuilder( width:0 , // optional height:0 , // optional quality:-1 , // optional - output: .jpg, // optional + output: Output.jpg, // optional ), // Works for both public file and private file, for private files you need to be logged in builder: (context, snapshot) { return snapshot.hasData && snapshot.data != null diff --git a/docs/examples/1.8.x/client-flutter/examples/storage/get-file-download.md b/docs/examples/1.8.x/client-flutter/examples/storage/get-file-download.md index 5bef06ee7d..2cdba9b1fa 100644 --- a/docs/examples/1.8.x/client-flutter/examples/storage/get-file-download.md +++ b/docs/examples/1.8.x/client-flutter/examples/storage/get-file-download.md @@ -7,7 +7,7 @@ Client client = Client() Storage storage = Storage(client); // Downloading file -UInt8List bytes = await storage.getFileDownload( +Uint8List bytes = await storage.getFileDownload( bucketId: '', fileId: '', token: '', // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/storage/get-file-preview.md b/docs/examples/1.8.x/client-flutter/examples/storage/get-file-preview.md index 96338bd25a..6fd148e935 100644 --- a/docs/examples/1.8.x/client-flutter/examples/storage/get-file-preview.md +++ b/docs/examples/1.8.x/client-flutter/examples/storage/get-file-preview.md @@ -7,7 +7,7 @@ Client client = Client() Storage storage = Storage(client); // Downloading file -UInt8List bytes = await storage.getFilePreview( +Uint8List bytes = await storage.getFilePreview( bucketId: '', fileId: '', width: 0, // optional diff --git a/docs/examples/1.8.x/client-flutter/examples/storage/get-file-view.md b/docs/examples/1.8.x/client-flutter/examples/storage/get-file-view.md index 6587f086bd..bcf5902c4e 100644 --- a/docs/examples/1.8.x/client-flutter/examples/storage/get-file-view.md +++ b/docs/examples/1.8.x/client-flutter/examples/storage/get-file-view.md @@ -7,7 +7,7 @@ Client client = Client() Storage storage = Storage(client); // Downloading file -UInt8List bytes = await storage.getFileView( +Uint8List bytes = await storage.getFileView( bucketId: '', fileId: '', token: '', // optional diff --git a/docs/examples/1.8.x/client-react-native/examples/avatars/get-screenshot.md b/docs/examples/1.8.x/client-react-native/examples/avatars/get-screenshot.md index 7482b4cf0e..918ab667d6 100644 --- a/docs/examples/1.8.x/client-react-native/examples/avatars/get-screenshot.md +++ b/docs/examples/1.8.x/client-react-native/examples/avatars/get-screenshot.md @@ -1,4 +1,4 @@ -import { Client, Avatars, , , } from "react-native-appwrite"; +import { Client, Avatars, Theme, Timezone, Output } from "react-native-appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -12,11 +12,11 @@ const result = avatars.getScreenshot({ viewportWidth: 1, // optional viewportHeight: 1, // optional scale: 0.1, // optional - theme: .Light, // optional + theme: Theme.Light, // optional userAgent: '', // optional fullpage: false, // optional locale: '', // optional - timezone: .AfricaAbidjan, // optional + timezone: Timezone.AfricaAbidjan, // optional latitude: -90, // optional longitude: -180, // optional accuracy: 0, // optional @@ -26,7 +26,7 @@ const result = avatars.getScreenshot({ width: 0, // optional height: 0, // optional quality: -1, // optional - output: .Jpg // optional + output: Output.Jpg // optional }); console.log(result); diff --git a/docs/examples/1.8.x/client-web/examples/avatars/get-screenshot.md b/docs/examples/1.8.x/client-web/examples/avatars/get-screenshot.md index c4722be633..75d6bcf80c 100644 --- a/docs/examples/1.8.x/client-web/examples/avatars/get-screenshot.md +++ b/docs/examples/1.8.x/client-web/examples/avatars/get-screenshot.md @@ -1,4 +1,4 @@ -import { Client, Avatars, , , } from "appwrite"; +import { Client, Avatars, Theme, Timezone, Output } from "appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -12,11 +12,11 @@ const result = avatars.getScreenshot({ viewportWidth: 1, // optional viewportHeight: 1, // optional scale: 0.1, // optional - theme: .Light, // optional + theme: Theme.Light, // optional userAgent: '', // optional fullpage: false, // optional locale: '', // optional - timezone: .AfricaAbidjan, // optional + timezone: Timezone.AfricaAbidjan, // optional latitude: -90, // optional longitude: -180, // optional accuracy: 0, // optional @@ -26,7 +26,7 @@ const result = avatars.getScreenshot({ width: 0, // optional height: 0, // optional quality: -1, // optional - output: .Jpg // optional + output: Output.Jpg // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/avatars/get-screenshot.md b/docs/examples/1.8.x/console-web/examples/avatars/get-screenshot.md index 3a9437515d..25ccc040f0 100644 --- a/docs/examples/1.8.x/console-web/examples/avatars/get-screenshot.md +++ b/docs/examples/1.8.x/console-web/examples/avatars/get-screenshot.md @@ -1,4 +1,4 @@ -import { Client, Avatars, , , } from "@appwrite.io/console"; +import { Client, Avatars, Theme, Timezone, Output } from "@appwrite.io/console"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -12,11 +12,11 @@ const result = avatars.getScreenshot({ viewportWidth: 1, // optional viewportHeight: 1, // optional scale: 0.1, // optional - theme: .Light, // optional + theme: Theme.Light, // optional userAgent: '', // optional fullpage: false, // optional locale: '', // optional - timezone: .AfricaAbidjan, // optional + timezone: Timezone.AfricaAbidjan, // optional latitude: -90, // optional longitude: -180, // optional accuracy: 0, // optional @@ -26,7 +26,7 @@ const result = avatars.getScreenshot({ width: 0, // optional height: 0, // optional quality: -1, // optional - output: .Jpg // optional + output: Output.Jpg // optional }); console.log(result); diff --git a/docs/examples/1.8.x/console-web/examples/functions/create.md b/docs/examples/1.8.x/console-web/examples/functions/create.md index b3ebbaf5a4..695d929daf 100644 --- a/docs/examples/1.8.x/console-web/examples/functions/create.md +++ b/docs/examples/1.8.x/console-web/examples/functions/create.md @@ -1,4 +1,4 @@ -import { Client, Functions, } from "@appwrite.io/console"; +import { Client, Functions, Runtime } from "@appwrite.io/console"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -9,7 +9,7 @@ const functions = new Functions(client); const result = await functions.create({ functionId: '', name: '', - runtime: .Node145, + runtime: Runtime.Node145, execute: ["any"], // optional events: [], // optional schedule: '', // optional diff --git a/docs/examples/1.8.x/console-web/examples/functions/update.md b/docs/examples/1.8.x/console-web/examples/functions/update.md index 377712bfb7..53fe85bf80 100644 --- a/docs/examples/1.8.x/console-web/examples/functions/update.md +++ b/docs/examples/1.8.x/console-web/examples/functions/update.md @@ -1,4 +1,4 @@ -import { Client, Functions, } from "@appwrite.io/console"; +import { Client, Functions, Runtime } from "@appwrite.io/console"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -9,7 +9,7 @@ const functions = new Functions(client); const result = await functions.update({ functionId: '', name: '', - runtime: .Node145, // optional + runtime: Runtime.Node145, // optional execute: ["any"], // optional events: [], // optional schedule: '', // optional diff --git a/docs/examples/1.8.x/console-web/examples/health/get-failed-jobs.md b/docs/examples/1.8.x/console-web/examples/health/get-failed-jobs.md index d0bac0cd6f..f47927214f 100644 --- a/docs/examples/1.8.x/console-web/examples/health/get-failed-jobs.md +++ b/docs/examples/1.8.x/console-web/examples/health/get-failed-jobs.md @@ -1,4 +1,4 @@ -import { Client, Health, } from "@appwrite.io/console"; +import { Client, Health, Name } from "@appwrite.io/console"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -7,7 +7,7 @@ const client = new Client() const health = new Health(client); const result = await health.getFailedJobs({ - name: .V1Database, + name: Name.V1Database, threshold: null // optional }); diff --git a/docs/examples/1.8.x/console-web/examples/projects/create.md b/docs/examples/1.8.x/console-web/examples/projects/create.md index 44abc021ef..2bfcaa79bb 100644 --- a/docs/examples/1.8.x/console-web/examples/projects/create.md +++ b/docs/examples/1.8.x/console-web/examples/projects/create.md @@ -1,4 +1,4 @@ -import { Client, Projects, } from "@appwrite.io/console"; +import { Client, Projects, Region } from "@appwrite.io/console"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -10,7 +10,7 @@ const result = await projects.create({ projectId: '', name: '', teamId: '', - region: .Default, // optional + region: Region.Default, // optional description: '', // optional logo: '', // optional url: 'https://example.com', // optional diff --git a/docs/examples/1.8.x/console-web/examples/projects/update-api-status.md b/docs/examples/1.8.x/console-web/examples/projects/update-api-status.md index 7ec06fee58..7f0f7ca970 100644 --- a/docs/examples/1.8.x/console-web/examples/projects/update-api-status.md +++ b/docs/examples/1.8.x/console-web/examples/projects/update-api-status.md @@ -1,4 +1,4 @@ -import { Client, Projects, } from "@appwrite.io/console"; +import { Client, Projects, Api } from "@appwrite.io/console"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -8,7 +8,7 @@ const projects = new Projects(client); const result = await projects.updateAPIStatus({ projectId: '', - api: .Rest, + api: Api.Rest, status: false }); diff --git a/docs/examples/1.8.x/console-web/examples/proxy/create-redirect-rule.md b/docs/examples/1.8.x/console-web/examples/proxy/create-redirect-rule.md index 396d6dee58..83a98438ec 100644 --- a/docs/examples/1.8.x/console-web/examples/proxy/create-redirect-rule.md +++ b/docs/examples/1.8.x/console-web/examples/proxy/create-redirect-rule.md @@ -1,4 +1,4 @@ -import { Client, Proxy, , ProxyResourceType } from "@appwrite.io/console"; +import { Client, Proxy, StatusCode, ProxyResourceType } from "@appwrite.io/console"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -9,7 +9,7 @@ const proxy = new Proxy(client); const result = await proxy.createRedirectRule({ domain: '', url: 'https://example.com', - statusCode: .MovedPermanently301, + statusCode: StatusCode.MovedPermanently301, resourceId: '', resourceType: ProxyResourceType.Site }); diff --git a/docs/examples/1.8.x/console-web/examples/sites/create.md b/docs/examples/1.8.x/console-web/examples/sites/create.md index bd4e2d1f08..e59139a1e2 100644 --- a/docs/examples/1.8.x/console-web/examples/sites/create.md +++ b/docs/examples/1.8.x/console-web/examples/sites/create.md @@ -1,4 +1,4 @@ -import { Client, Sites, , , } from "@appwrite.io/console"; +import { Client, Sites, Framework, BuildRuntime, Adapter } from "@appwrite.io/console"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -9,15 +9,15 @@ const sites = new Sites(client); const result = await sites.create({ siteId: '', name: '', - framework: .Analog, - buildRuntime: .Node145, + framework: Framework.Analog, + buildRuntime: BuildRuntime.Node145, enabled: false, // optional logging: false, // optional timeout: 1, // optional installCommand: '', // optional buildCommand: '', // optional outputDirectory: '', // optional - adapter: .Static, // optional + adapter: Adapter.Static, // optional installationId: '', // optional fallbackFile: '', // optional providerRepositoryId: '', // optional diff --git a/docs/examples/1.8.x/console-web/examples/sites/update.md b/docs/examples/1.8.x/console-web/examples/sites/update.md index 68bd073c50..c68fe2924b 100644 --- a/docs/examples/1.8.x/console-web/examples/sites/update.md +++ b/docs/examples/1.8.x/console-web/examples/sites/update.md @@ -1,4 +1,4 @@ -import { Client, Sites, , , } from "@appwrite.io/console"; +import { Client, Sites, Framework, BuildRuntime, Adapter } from "@appwrite.io/console"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -9,15 +9,15 @@ const sites = new Sites(client); const result = await sites.update({ siteId: '', name: '', - framework: .Analog, + framework: Framework.Analog, enabled: false, // optional logging: false, // optional timeout: 1, // optional installCommand: '', // optional buildCommand: '', // optional outputDirectory: '', // optional - buildRuntime: .Node145, // optional - adapter: .Static, // optional + buildRuntime: BuildRuntime.Node145, // optional + adapter: Adapter.Static, // optional fallbackFile: '', // optional installationId: '', // optional providerRepositoryId: '', // optional diff --git a/docs/examples/1.8.x/console-web/examples/storage/create-bucket.md b/docs/examples/1.8.x/console-web/examples/storage/create-bucket.md index 343568a408..19ddf890a9 100644 --- a/docs/examples/1.8.x/console-web/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/console-web/examples/storage/create-bucket.md @@ -1,4 +1,4 @@ -import { Client, Storage, , Permission, Role } from "@appwrite.io/console"; +import { Client, Storage, Compression, Permission, Role } from "@appwrite.io/console"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -14,7 +14,7 @@ const result = await storage.createBucket({ enabled: false, // optional maximumFileSize: 1, // optional allowedFileExtensions: [], // optional - compression: .None, // optional + compression: Compression.None, // optional encryption: false, // optional antivirus: false // optional }); diff --git a/docs/examples/1.8.x/console-web/examples/storage/update-bucket.md b/docs/examples/1.8.x/console-web/examples/storage/update-bucket.md index b2c2eaa885..70ef0ef759 100644 --- a/docs/examples/1.8.x/console-web/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/console-web/examples/storage/update-bucket.md @@ -1,4 +1,4 @@ -import { Client, Storage, , Permission, Role } from "@appwrite.io/console"; +import { Client, Storage, Compression, Permission, Role } from "@appwrite.io/console"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint @@ -14,7 +14,7 @@ const result = await storage.updateBucket({ enabled: false, // optional maximumFileSize: 1, // optional allowedFileExtensions: [], // optional - compression: .None, // optional + compression: Compression.None, // optional encryption: false, // optional antivirus: false // optional }); diff --git a/docs/examples/1.8.x/server-dart/examples/avatars/get-browser.md b/docs/examples/1.8.x/server-dart/examples/avatars/get-browser.md index 8d5287511d..1f326e8066 100644 --- a/docs/examples/1.8.x/server-dart/examples/avatars/get-browser.md +++ b/docs/examples/1.8.x/server-dart/examples/avatars/get-browser.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); -UInt8List result = await avatars.getBrowser( +Uint8List result = await avatars.getBrowser( code: Browser.avantBrowser, width: 0, // (optional) height: 0, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/avatars/get-credit-card.md b/docs/examples/1.8.x/server-dart/examples/avatars/get-credit-card.md index 88fe35ebd9..8232d7b2b9 100644 --- a/docs/examples/1.8.x/server-dart/examples/avatars/get-credit-card.md +++ b/docs/examples/1.8.x/server-dart/examples/avatars/get-credit-card.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); -UInt8List result = await avatars.getCreditCard( +Uint8List result = await avatars.getCreditCard( code: CreditCard.americanExpress, width: 0, // (optional) height: 0, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/avatars/get-favicon.md b/docs/examples/1.8.x/server-dart/examples/avatars/get-favicon.md index d4cd8eae83..e2df21f6fd 100644 --- a/docs/examples/1.8.x/server-dart/examples/avatars/get-favicon.md +++ b/docs/examples/1.8.x/server-dart/examples/avatars/get-favicon.md @@ -7,6 +7,6 @@ Client client = Client() Avatars avatars = Avatars(client); -UInt8List result = await avatars.getFavicon( +Uint8List result = await avatars.getFavicon( url: 'https://example.com', ); diff --git a/docs/examples/1.8.x/server-dart/examples/avatars/get-flag.md b/docs/examples/1.8.x/server-dart/examples/avatars/get-flag.md index 56046681bc..0aea028e5b 100644 --- a/docs/examples/1.8.x/server-dart/examples/avatars/get-flag.md +++ b/docs/examples/1.8.x/server-dart/examples/avatars/get-flag.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); -UInt8List result = await avatars.getFlag( +Uint8List result = await avatars.getFlag( code: Flag.afghanistan, width: 0, // (optional) height: 0, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/avatars/get-image.md b/docs/examples/1.8.x/server-dart/examples/avatars/get-image.md index b6db1858c5..fc727f481e 100644 --- a/docs/examples/1.8.x/server-dart/examples/avatars/get-image.md +++ b/docs/examples/1.8.x/server-dart/examples/avatars/get-image.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); -UInt8List result = await avatars.getImage( +Uint8List result = await avatars.getImage( url: 'https://example.com', width: 0, // (optional) height: 0, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/avatars/get-initials.md b/docs/examples/1.8.x/server-dart/examples/avatars/get-initials.md index 7dc0989b4d..be77c67147 100644 --- a/docs/examples/1.8.x/server-dart/examples/avatars/get-initials.md +++ b/docs/examples/1.8.x/server-dart/examples/avatars/get-initials.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); -UInt8List result = await avatars.getInitials( +Uint8List result = await avatars.getInitials( name: '', // (optional) width: 0, // (optional) height: 0, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/avatars/get-qr.md b/docs/examples/1.8.x/server-dart/examples/avatars/get-qr.md index f64fe8a4ff..f44ce59076 100644 --- a/docs/examples/1.8.x/server-dart/examples/avatars/get-qr.md +++ b/docs/examples/1.8.x/server-dart/examples/avatars/get-qr.md @@ -7,7 +7,7 @@ Client client = Client() Avatars avatars = Avatars(client); -UInt8List result = await avatars.getQR( +Uint8List result = await avatars.getQR( text: '', size: 1, // (optional) margin: 0, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/avatars/get-screenshot.md b/docs/examples/1.8.x/server-dart/examples/avatars/get-screenshot.md index 7630648f98..c787a82298 100644 --- a/docs/examples/1.8.x/server-dart/examples/avatars/get-screenshot.md +++ b/docs/examples/1.8.x/server-dart/examples/avatars/get-screenshot.md @@ -7,17 +7,17 @@ Client client = Client() Avatars avatars = Avatars(client); -UInt8List result = await avatars.getScreenshot( +Uint8List result = await avatars.getScreenshot( url: 'https://example.com', headers: {}, // (optional) viewportWidth: 1, // (optional) viewportHeight: 1, // (optional) scale: 0.1, // (optional) - theme: .light, // (optional) + theme: Theme.light, // (optional) userAgent: '', // (optional) fullpage: false, // (optional) locale: '', // (optional) - timezone: .africaAbidjan, // (optional) + timezone: Timezone.africaAbidjan, // (optional) latitude: -90, // (optional) longitude: -180, // (optional) accuracy: 0, // (optional) @@ -27,5 +27,5 @@ UInt8List result = await avatars.getScreenshot( width: 0, // (optional) height: 0, // (optional) quality: -1, // (optional) - output: .jpg, // (optional) + output: Output.jpg, // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/functions/create.md b/docs/examples/1.8.x/server-dart/examples/functions/create.md index f3f2683000..2276872e91 100644 --- a/docs/examples/1.8.x/server-dart/examples/functions/create.md +++ b/docs/examples/1.8.x/server-dart/examples/functions/create.md @@ -10,7 +10,7 @@ Functions functions = Functions(client); Func result = await functions.create( functionId: '', name: '', - runtime: .node145, + runtime: Runtime.node145, execute: ["any"], // (optional) events: [], // (optional) schedule: '', // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/functions/get-deployment-download.md b/docs/examples/1.8.x/server-dart/examples/functions/get-deployment-download.md index e7bbacf344..1b93e3bad9 100644 --- a/docs/examples/1.8.x/server-dart/examples/functions/get-deployment-download.md +++ b/docs/examples/1.8.x/server-dart/examples/functions/get-deployment-download.md @@ -7,7 +7,7 @@ Client client = Client() Functions functions = Functions(client); -UInt8List result = await functions.getDeploymentDownload( +Uint8List result = await functions.getDeploymentDownload( functionId: '', deploymentId: '', type: DeploymentDownloadType.source, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/functions/update.md b/docs/examples/1.8.x/server-dart/examples/functions/update.md index ebe3be8cc6..bf3e39cc56 100644 --- a/docs/examples/1.8.x/server-dart/examples/functions/update.md +++ b/docs/examples/1.8.x/server-dart/examples/functions/update.md @@ -10,7 +10,7 @@ Functions functions = Functions(client); Func result = await functions.update( functionId: '', name: '', - runtime: .node145, // (optional) + runtime: Runtime.node145, // (optional) execute: ["any"], // (optional) events: [], // (optional) schedule: '', // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/health/get-failed-jobs.md b/docs/examples/1.8.x/server-dart/examples/health/get-failed-jobs.md index 6f80718f6b..b375c5793c 100644 --- a/docs/examples/1.8.x/server-dart/examples/health/get-failed-jobs.md +++ b/docs/examples/1.8.x/server-dart/examples/health/get-failed-jobs.md @@ -8,6 +8,6 @@ Client client = Client() Health health = Health(client); HealthQueue result = await health.getFailedJobs( - name: .v1Database, + name: Name.v1Database, threshold: 0, // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/sites/create.md b/docs/examples/1.8.x/server-dart/examples/sites/create.md index 448abab1df..e6ec4a6da8 100644 --- a/docs/examples/1.8.x/server-dart/examples/sites/create.md +++ b/docs/examples/1.8.x/server-dart/examples/sites/create.md @@ -10,15 +10,15 @@ Sites sites = Sites(client); Site result = await sites.create( siteId: '', name: '', - framework: .analog, - buildRuntime: .node145, + framework: Framework.analog, + buildRuntime: BuildRuntime.node145, enabled: false, // (optional) logging: false, // (optional) timeout: 1, // (optional) installCommand: '', // (optional) buildCommand: '', // (optional) outputDirectory: '', // (optional) - adapter: .static, // (optional) + adapter: Adapter.static, // (optional) installationId: '', // (optional) fallbackFile: '', // (optional) providerRepositoryId: '', // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/sites/get-deployment-download.md b/docs/examples/1.8.x/server-dart/examples/sites/get-deployment-download.md index ad21070b8a..f6bbb3c35d 100644 --- a/docs/examples/1.8.x/server-dart/examples/sites/get-deployment-download.md +++ b/docs/examples/1.8.x/server-dart/examples/sites/get-deployment-download.md @@ -7,7 +7,7 @@ Client client = Client() Sites sites = Sites(client); -UInt8List result = await sites.getDeploymentDownload( +Uint8List result = await sites.getDeploymentDownload( siteId: '', deploymentId: '', type: DeploymentDownloadType.source, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/sites/update.md b/docs/examples/1.8.x/server-dart/examples/sites/update.md index c13acfb25b..2cfd68633b 100644 --- a/docs/examples/1.8.x/server-dart/examples/sites/update.md +++ b/docs/examples/1.8.x/server-dart/examples/sites/update.md @@ -10,15 +10,15 @@ Sites sites = Sites(client); Site result = await sites.update( siteId: '', name: '', - framework: .analog, + framework: Framework.analog, enabled: false, // (optional) logging: false, // (optional) timeout: 1, // (optional) installCommand: '', // (optional) buildCommand: '', // (optional) outputDirectory: '', // (optional) - buildRuntime: .node145, // (optional) - adapter: .static, // (optional) + buildRuntime: BuildRuntime.node145, // (optional) + adapter: Adapter.static, // (optional) fallbackFile: '', // (optional) installationId: '', // (optional) providerRepositoryId: '', // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/storage/create-bucket.md b/docs/examples/1.8.x/server-dart/examples/storage/create-bucket.md index 79357d0e4a..ad0ff92f66 100644 --- a/docs/examples/1.8.x/server-dart/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-dart/examples/storage/create-bucket.md @@ -17,7 +17,7 @@ Bucket result = await storage.createBucket( enabled: false, // (optional) maximumFileSize: 1, // (optional) allowedFileExtensions: [], // (optional) - compression: .none, // (optional) + compression: Compression.none, // (optional) encryption: false, // (optional) antivirus: false, // (optional) ); diff --git a/docs/examples/1.8.x/server-dart/examples/storage/get-file-download.md b/docs/examples/1.8.x/server-dart/examples/storage/get-file-download.md index 8c119c386c..34f40685fe 100644 --- a/docs/examples/1.8.x/server-dart/examples/storage/get-file-download.md +++ b/docs/examples/1.8.x/server-dart/examples/storage/get-file-download.md @@ -7,7 +7,7 @@ Client client = Client() Storage storage = Storage(client); -UInt8List result = await storage.getFileDownload( +Uint8List result = await storage.getFileDownload( bucketId: '', fileId: '', token: '', // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/storage/get-file-preview.md b/docs/examples/1.8.x/server-dart/examples/storage/get-file-preview.md index a1f3c09b33..a14e12c630 100644 --- a/docs/examples/1.8.x/server-dart/examples/storage/get-file-preview.md +++ b/docs/examples/1.8.x/server-dart/examples/storage/get-file-preview.md @@ -7,7 +7,7 @@ Client client = Client() Storage storage = Storage(client); -UInt8List result = await storage.getFilePreview( +Uint8List result = await storage.getFilePreview( bucketId: '', fileId: '', width: 0, // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/storage/get-file-view.md b/docs/examples/1.8.x/server-dart/examples/storage/get-file-view.md index d48b51c19c..a1d9271f13 100644 --- a/docs/examples/1.8.x/server-dart/examples/storage/get-file-view.md +++ b/docs/examples/1.8.x/server-dart/examples/storage/get-file-view.md @@ -7,7 +7,7 @@ Client client = Client() Storage storage = Storage(client); -UInt8List result = await storage.getFileView( +Uint8List result = await storage.getFileView( bucketId: '', fileId: '', token: '', // (optional) diff --git a/docs/examples/1.8.x/server-dart/examples/storage/update-bucket.md b/docs/examples/1.8.x/server-dart/examples/storage/update-bucket.md index f3eea941a3..4a51d03596 100644 --- a/docs/examples/1.8.x/server-dart/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-dart/examples/storage/update-bucket.md @@ -17,7 +17,7 @@ Bucket result = await storage.updateBucket( enabled: false, // (optional) maximumFileSize: 1, // (optional) allowedFileExtensions: [], // (optional) - compression: .none, // (optional) + compression: Compression.none, // (optional) encryption: false, // (optional) antivirus: false, // (optional) ); diff --git a/docs/examples/1.8.x/server-dotnet/examples/avatars/get-screenshot.md b/docs/examples/1.8.x/server-dotnet/examples/avatars/get-screenshot.md index f5c3542a97..e2e5462484 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/avatars/get-screenshot.md +++ b/docs/examples/1.8.x/server-dotnet/examples/avatars/get-screenshot.md @@ -16,11 +16,11 @@ byte[] result = await avatars.GetScreenshot( viewportWidth: 1, // optional viewportHeight: 1, // optional scale: 0.1, // optional - theme: .Light, // optional + theme: Theme.Light, // optional userAgent: "", // optional fullpage: false, // optional locale: "", // optional - timezone: .AfricaAbidjan, // optional + timezone: Timezone.AfricaAbidjan, // optional latitude: -90, // optional longitude: -180, // optional accuracy: 0, // optional @@ -30,5 +30,5 @@ byte[] result = await avatars.GetScreenshot( width: 0, // optional height: 0, // optional quality: -1, // optional - output: .Jpg // optional + output: Output.Jpg // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/functions/create.md b/docs/examples/1.8.x/server-dotnet/examples/functions/create.md index 6e705228f1..7d26480d68 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/functions/create.md +++ b/docs/examples/1.8.x/server-dotnet/examples/functions/create.md @@ -13,7 +13,7 @@ Functions functions = new Functions(client); Function result = await functions.Create( functionId: "", name: "", - runtime: .Node145, + runtime: Runtime.Node145, execute: ["any"], // optional events: new List(), // optional schedule: "", // optional diff --git a/docs/examples/1.8.x/server-dotnet/examples/functions/update.md b/docs/examples/1.8.x/server-dotnet/examples/functions/update.md index 7160795f77..a41a0fd331 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/functions/update.md +++ b/docs/examples/1.8.x/server-dotnet/examples/functions/update.md @@ -13,7 +13,7 @@ Functions functions = new Functions(client); Function result = await functions.Update( functionId: "", name: "", - runtime: .Node145, // optional + runtime: Runtime.Node145, // optional execute: ["any"], // optional events: new List(), // optional schedule: "", // optional diff --git a/docs/examples/1.8.x/server-dotnet/examples/health/get-failed-jobs.md b/docs/examples/1.8.x/server-dotnet/examples/health/get-failed-jobs.md index 4d43479831..ee0aceaace 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/health/get-failed-jobs.md +++ b/docs/examples/1.8.x/server-dotnet/examples/health/get-failed-jobs.md @@ -11,6 +11,6 @@ Client client = new Client() Health health = new Health(client); HealthQueue result = await health.GetFailedJobs( - name: .V1Database, + name: Name.V1Database, threshold: 0 // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/sites/create.md b/docs/examples/1.8.x/server-dotnet/examples/sites/create.md index 025adca41d..ed7360d5f2 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/sites/create.md +++ b/docs/examples/1.8.x/server-dotnet/examples/sites/create.md @@ -13,15 +13,15 @@ Sites sites = new Sites(client); Site result = await sites.Create( siteId: "", name: "", - framework: .Analog, - buildRuntime: .Node145, + framework: Framework.Analog, + buildRuntime: BuildRuntime.Node145, enabled: false, // optional logging: false, // optional timeout: 1, // optional installCommand: "", // optional buildCommand: "", // optional outputDirectory: "", // optional - adapter: .Static, // optional + adapter: Adapter.Static, // optional installationId: "", // optional fallbackFile: "", // optional providerRepositoryId: "", // optional diff --git a/docs/examples/1.8.x/server-dotnet/examples/sites/update.md b/docs/examples/1.8.x/server-dotnet/examples/sites/update.md index c25e3f6df9..32da483318 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/sites/update.md +++ b/docs/examples/1.8.x/server-dotnet/examples/sites/update.md @@ -13,15 +13,15 @@ Sites sites = new Sites(client); Site result = await sites.Update( siteId: "", name: "", - framework: .Analog, + framework: Framework.Analog, enabled: false, // optional logging: false, // optional timeout: 1, // optional installCommand: "", // optional buildCommand: "", // optional outputDirectory: "", // optional - buildRuntime: .Node145, // optional - adapter: .Static, // optional + buildRuntime: BuildRuntime.Node145, // optional + adapter: Adapter.Static, // optional fallbackFile: "", // optional installationId: "", // optional providerRepositoryId: "", // optional diff --git a/docs/examples/1.8.x/server-dotnet/examples/storage/create-bucket.md b/docs/examples/1.8.x/server-dotnet/examples/storage/create-bucket.md index f009f694ad..e76358f551 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-dotnet/examples/storage/create-bucket.md @@ -18,7 +18,7 @@ Bucket result = await storage.CreateBucket( enabled: false, // optional maximumFileSize: 1, // optional allowedFileExtensions: new List(), // optional - compression: .None, // optional + compression: Compression.None, // optional encryption: false, // optional antivirus: false // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-dotnet/examples/storage/update-bucket.md b/docs/examples/1.8.x/server-dotnet/examples/storage/update-bucket.md index d41a45961c..3cfdfcc482 100644 --- a/docs/examples/1.8.x/server-dotnet/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-dotnet/examples/storage/update-bucket.md @@ -18,7 +18,7 @@ Bucket result = await storage.UpdateBucket( enabled: false, // optional maximumFileSize: 1, // optional allowedFileExtensions: new List(), // optional - compression: .None, // optional + compression: Compression.None, // optional encryption: false, // optional antivirus: false // optional ); \ No newline at end of file diff --git a/docs/examples/1.8.x/server-kotlin/java/avatars/get-screenshot.md b/docs/examples/1.8.x/server-kotlin/java/avatars/get-screenshot.md index cf734af3b2..0f1cb9c2f0 100644 --- a/docs/examples/1.8.x/server-kotlin/java/avatars/get-screenshot.md +++ b/docs/examples/1.8.x/server-kotlin/java/avatars/get-screenshot.md @@ -1,6 +1,9 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Avatars; +import io.appwrite.enums.Theme; +import io.appwrite.enums.Timezone; +import io.appwrite.enums.Output; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint @@ -15,11 +18,11 @@ avatars.getScreenshot( 1, // viewportWidth (optional) 1, // viewportHeight (optional) 0.1, // scale (optional) - .LIGHT, // theme (optional) + Theme.LIGHT, // theme (optional) "", // userAgent (optional) false, // fullpage (optional) "", // locale (optional) - .AFRICA_ABIDJAN, // timezone (optional) + Timezone.AFRICA_ABIDJAN, // timezone (optional) -90, // latitude (optional) -180, // longitude (optional) 0, // accuracy (optional) @@ -29,7 +32,7 @@ avatars.getScreenshot( 0, // width (optional) 0, // height (optional) -1, // quality (optional) - .JPG, // output (optional) + Output.JPG, // output (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/create-relationship-attribute.md b/docs/examples/1.8.x/server-kotlin/java/databases/create-relationship-attribute.md index a67f452647..580be890ba 100644 --- a/docs/examples/1.8.x/server-kotlin/java/databases/create-relationship-attribute.md +++ b/docs/examples/1.8.x/server-kotlin/java/databases/create-relationship-attribute.md @@ -2,6 +2,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Databases; import io.appwrite.enums.RelationshipType; +import io.appwrite.enums.RelationMutate; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/java/databases/update-relationship-attribute.md b/docs/examples/1.8.x/server-kotlin/java/databases/update-relationship-attribute.md index 8af20e91a9..998f0beb16 100644 --- a/docs/examples/1.8.x/server-kotlin/java/databases/update-relationship-attribute.md +++ b/docs/examples/1.8.x/server-kotlin/java/databases/update-relationship-attribute.md @@ -1,6 +1,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Databases; +import io.appwrite.enums.RelationMutate; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/java/functions/create-execution.md b/docs/examples/1.8.x/server-kotlin/java/functions/create-execution.md index 93efa0adf8..4abfe236b3 100644 --- a/docs/examples/1.8.x/server-kotlin/java/functions/create-execution.md +++ b/docs/examples/1.8.x/server-kotlin/java/functions/create-execution.md @@ -1,6 +1,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Functions; +import io.appwrite.enums.ExecutionMethod; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/java/functions/create.md b/docs/examples/1.8.x/server-kotlin/java/functions/create.md index 71871287bb..587fd54b9b 100644 --- a/docs/examples/1.8.x/server-kotlin/java/functions/create.md +++ b/docs/examples/1.8.x/server-kotlin/java/functions/create.md @@ -13,7 +13,7 @@ Functions functions = new Functions(client); functions.create( "", // functionId "", // name - .NODE_14_5, // runtime + Runtime.NODE_14_5, // runtime listOf("any"), // execute (optional) listOf(), // events (optional) "", // schedule (optional) diff --git a/docs/examples/1.8.x/server-kotlin/java/functions/get-deployment-download.md b/docs/examples/1.8.x/server-kotlin/java/functions/get-deployment-download.md index d522b12caf..2b6d38a787 100644 --- a/docs/examples/1.8.x/server-kotlin/java/functions/get-deployment-download.md +++ b/docs/examples/1.8.x/server-kotlin/java/functions/get-deployment-download.md @@ -1,6 +1,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Functions; +import io.appwrite.enums.DeploymentDownloadType; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/java/functions/update.md b/docs/examples/1.8.x/server-kotlin/java/functions/update.md index 5956c57b73..5cb560e200 100644 --- a/docs/examples/1.8.x/server-kotlin/java/functions/update.md +++ b/docs/examples/1.8.x/server-kotlin/java/functions/update.md @@ -1,6 +1,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Functions; +import io.appwrite.enums.Runtime; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint @@ -12,7 +13,7 @@ Functions functions = new Functions(client); functions.update( "", // functionId "", // name - .NODE_14_5, // runtime (optional) + Runtime.NODE_14_5, // runtime (optional) listOf("any"), // execute (optional) listOf(), // events (optional) "", // schedule (optional) diff --git a/docs/examples/1.8.x/server-kotlin/java/health/get-failed-jobs.md b/docs/examples/1.8.x/server-kotlin/java/health/get-failed-jobs.md index d2b81bd0bf..0495e265e6 100644 --- a/docs/examples/1.8.x/server-kotlin/java/health/get-failed-jobs.md +++ b/docs/examples/1.8.x/server-kotlin/java/health/get-failed-jobs.md @@ -11,7 +11,7 @@ Client client = new Client() Health health = new Health(client); health.getFailedJobs( - .V1_DATABASE, // name + Name.V1_DATABASE, // name 0, // threshold (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { diff --git a/docs/examples/1.8.x/server-kotlin/java/messaging/create-push.md b/docs/examples/1.8.x/server-kotlin/java/messaging/create-push.md index 14e8ca2679..94119e6a93 100644 --- a/docs/examples/1.8.x/server-kotlin/java/messaging/create-push.md +++ b/docs/examples/1.8.x/server-kotlin/java/messaging/create-push.md @@ -1,6 +1,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Messaging; +import io.appwrite.enums.MessagePriority; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/java/messaging/create-smtp-provider.md b/docs/examples/1.8.x/server-kotlin/java/messaging/create-smtp-provider.md index 1f1a0f998f..966436e3c1 100644 --- a/docs/examples/1.8.x/server-kotlin/java/messaging/create-smtp-provider.md +++ b/docs/examples/1.8.x/server-kotlin/java/messaging/create-smtp-provider.md @@ -1,6 +1,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Messaging; +import io.appwrite.enums.SmtpEncryption; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/java/messaging/update-push.md b/docs/examples/1.8.x/server-kotlin/java/messaging/update-push.md index ce56683674..80ad6fcd30 100644 --- a/docs/examples/1.8.x/server-kotlin/java/messaging/update-push.md +++ b/docs/examples/1.8.x/server-kotlin/java/messaging/update-push.md @@ -1,6 +1,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Messaging; +import io.appwrite.enums.MessagePriority; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/java/messaging/update-smtp-provider.md b/docs/examples/1.8.x/server-kotlin/java/messaging/update-smtp-provider.md index 36f120033a..c8ab7571ce 100644 --- a/docs/examples/1.8.x/server-kotlin/java/messaging/update-smtp-provider.md +++ b/docs/examples/1.8.x/server-kotlin/java/messaging/update-smtp-provider.md @@ -1,6 +1,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Messaging; +import io.appwrite.enums.SmtpEncryption; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/java/sites/create.md b/docs/examples/1.8.x/server-kotlin/java/sites/create.md index 19664ec57b..11e0dbba6f 100644 --- a/docs/examples/1.8.x/server-kotlin/java/sites/create.md +++ b/docs/examples/1.8.x/server-kotlin/java/sites/create.md @@ -3,6 +3,7 @@ import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Sites; import io.appwrite.enums.Framework; import io.appwrite.enums.BuildRuntime; +import io.appwrite.enums.Adapter; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint @@ -14,15 +15,15 @@ Sites sites = new Sites(client); sites.create( "", // siteId "", // name - .ANALOG, // framework - .NODE_14_5, // buildRuntime + Framework.ANALOG, // framework + BuildRuntime.NODE_14_5, // buildRuntime false, // enabled (optional) false, // logging (optional) 1, // timeout (optional) "", // installCommand (optional) "", // buildCommand (optional) "", // outputDirectory (optional) - .STATIC, // adapter (optional) + Adapter.STATIC, // adapter (optional) "", // installationId (optional) "", // fallbackFile (optional) "", // providerRepositoryId (optional) diff --git a/docs/examples/1.8.x/server-kotlin/java/sites/get-deployment-download.md b/docs/examples/1.8.x/server-kotlin/java/sites/get-deployment-download.md index 5875c7262f..ce26ba8cca 100644 --- a/docs/examples/1.8.x/server-kotlin/java/sites/get-deployment-download.md +++ b/docs/examples/1.8.x/server-kotlin/java/sites/get-deployment-download.md @@ -1,6 +1,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Sites; +import io.appwrite.enums.DeploymentDownloadType; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/java/sites/update.md b/docs/examples/1.8.x/server-kotlin/java/sites/update.md index 9a8b577ce0..0c4024b841 100644 --- a/docs/examples/1.8.x/server-kotlin/java/sites/update.md +++ b/docs/examples/1.8.x/server-kotlin/java/sites/update.md @@ -2,6 +2,8 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Sites; import io.appwrite.enums.Framework; +import io.appwrite.enums.BuildRuntime; +import io.appwrite.enums.Adapter; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint @@ -13,15 +15,15 @@ Sites sites = new Sites(client); sites.update( "", // siteId "", // name - .ANALOG, // framework + Framework.ANALOG, // framework false, // enabled (optional) false, // logging (optional) 1, // timeout (optional) "", // installCommand (optional) "", // buildCommand (optional) "", // outputDirectory (optional) - .NODE_14_5, // buildRuntime (optional) - .STATIC, // adapter (optional) + BuildRuntime.NODE_14_5, // buildRuntime (optional) + Adapter.STATIC, // adapter (optional) "", // fallbackFile (optional) "", // installationId (optional) "", // providerRepositoryId (optional) diff --git a/docs/examples/1.8.x/server-kotlin/java/storage/create-bucket.md b/docs/examples/1.8.x/server-kotlin/java/storage/create-bucket.md index d48db24094..dca688ed7d 100644 --- a/docs/examples/1.8.x/server-kotlin/java/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-kotlin/java/storage/create-bucket.md @@ -1,6 +1,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Storage; +import io.appwrite.enums.Compression; import io.appwrite.Permission; import io.appwrite.Role; @@ -19,7 +20,7 @@ storage.createBucket( false, // enabled (optional) 1, // maximumFileSize (optional) listOf(), // allowedFileExtensions (optional) - .NONE, // compression (optional) + Compression.NONE, // compression (optional) false, // encryption (optional) false, // antivirus (optional) new CoroutineCallback<>((result, error) -> { diff --git a/docs/examples/1.8.x/server-kotlin/java/storage/get-file-preview.md b/docs/examples/1.8.x/server-kotlin/java/storage/get-file-preview.md index 1a0ab596bc..61f7637256 100644 --- a/docs/examples/1.8.x/server-kotlin/java/storage/get-file-preview.md +++ b/docs/examples/1.8.x/server-kotlin/java/storage/get-file-preview.md @@ -1,6 +1,8 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Storage; +import io.appwrite.enums.ImageGravity; +import io.appwrite.enums.ImageFormat; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/java/storage/update-bucket.md b/docs/examples/1.8.x/server-kotlin/java/storage/update-bucket.md index 586b113578..61c7e9e256 100644 --- a/docs/examples/1.8.x/server-kotlin/java/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-kotlin/java/storage/update-bucket.md @@ -1,6 +1,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Storage; +import io.appwrite.enums.Compression; import io.appwrite.Permission; import io.appwrite.Role; @@ -19,7 +20,7 @@ storage.updateBucket( false, // enabled (optional) 1, // maximumFileSize (optional) listOf(), // allowedFileExtensions (optional) - .NONE, // compression (optional) + Compression.NONE, // compression (optional) false, // encryption (optional) false, // antivirus (optional) new CoroutineCallback<>((result, error) -> { diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-relationship-column.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-relationship-column.md index 956c1fa516..c7a3a5f288 100644 --- a/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-relationship-column.md +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/create-relationship-column.md @@ -2,6 +2,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.TablesDB; import io.appwrite.enums.RelationshipType; +import io.appwrite.enums.RelationMutate; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/java/tablesdb/update-relationship-column.md b/docs/examples/1.8.x/server-kotlin/java/tablesdb/update-relationship-column.md index 45aea8ae41..eaf6b1ba52 100644 --- a/docs/examples/1.8.x/server-kotlin/java/tablesdb/update-relationship-column.md +++ b/docs/examples/1.8.x/server-kotlin/java/tablesdb/update-relationship-column.md @@ -1,6 +1,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.TablesDB; +import io.appwrite.enums.RelationMutate; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/java/users/create-sha-user.md b/docs/examples/1.8.x/server-kotlin/java/users/create-sha-user.md index ad729071c2..3a37ddce95 100644 --- a/docs/examples/1.8.x/server-kotlin/java/users/create-sha-user.md +++ b/docs/examples/1.8.x/server-kotlin/java/users/create-sha-user.md @@ -1,6 +1,7 @@ import io.appwrite.Client; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Users; +import io.appwrite.enums.PasswordHash; Client client = new Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/avatars/get-screenshot.md b/docs/examples/1.8.x/server-kotlin/kotlin/avatars/get-screenshot.md index 96032bb8a4..eca5493c57 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/avatars/get-screenshot.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/avatars/get-screenshot.md @@ -1,6 +1,9 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Avatars +import io.appwrite.enums.Theme +import io.appwrite.enums.Timezone +import io.appwrite.enums.Output val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-relationship-attribute.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-relationship-attribute.md index 1bf610321a..48389f529d 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-relationship-attribute.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/create-relationship-attribute.md @@ -2,6 +2,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Databases import io.appwrite.enums.RelationshipType +import io.appwrite.enums.RelationMutate val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/databases/update-relationship-attribute.md b/docs/examples/1.8.x/server-kotlin/kotlin/databases/update-relationship-attribute.md index 001dd1a391..baf69e3602 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/databases/update-relationship-attribute.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/databases/update-relationship-attribute.md @@ -1,6 +1,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Databases +import io.appwrite.enums.RelationMutate val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/functions/create-execution.md b/docs/examples/1.8.x/server-kotlin/kotlin/functions/create-execution.md index 2734412232..9458be08e0 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/functions/create-execution.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/functions/create-execution.md @@ -1,6 +1,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Functions +import io.appwrite.enums.ExecutionMethod val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/functions/create.md b/docs/examples/1.8.x/server-kotlin/kotlin/functions/create.md index c0ea4de201..de5b191b3f 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/functions/create.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/functions/create.md @@ -13,7 +13,7 @@ val functions = Functions(client) val response = functions.create( functionId = "", name = "", - runtime = .NODE_14_5, + runtime = Runtime.NODE_14_5, execute = listOf("any"), // optional events = listOf(), // optional schedule = "", // optional diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/functions/get-deployment-download.md b/docs/examples/1.8.x/server-kotlin/kotlin/functions/get-deployment-download.md index 634cfae3b4..8a16397dc9 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/functions/get-deployment-download.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/functions/get-deployment-download.md @@ -1,6 +1,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Functions +import io.appwrite.enums.DeploymentDownloadType val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/functions/update.md b/docs/examples/1.8.x/server-kotlin/kotlin/functions/update.md index 7f0b33ebd7..1b7db783c1 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/functions/update.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/functions/update.md @@ -1,6 +1,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Functions +import io.appwrite.enums.Runtime val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/health/get-failed-jobs.md b/docs/examples/1.8.x/server-kotlin/kotlin/health/get-failed-jobs.md index 027df127cc..646d9b368d 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/health/get-failed-jobs.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/health/get-failed-jobs.md @@ -11,6 +11,6 @@ val client = Client() val health = Health(client) val response = health.getFailedJobs( - name = .V1_DATABASE, + name = Name.V1_DATABASE, threshold = 0 // optional ) diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/messaging/create-push.md b/docs/examples/1.8.x/server-kotlin/kotlin/messaging/create-push.md index d0d765a32a..e17406915c 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/messaging/create-push.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/messaging/create-push.md @@ -1,6 +1,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Messaging +import io.appwrite.enums.MessagePriority val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/messaging/create-smtp-provider.md b/docs/examples/1.8.x/server-kotlin/kotlin/messaging/create-smtp-provider.md index ce50130e80..c7dca02027 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/messaging/create-smtp-provider.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/messaging/create-smtp-provider.md @@ -1,6 +1,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Messaging +import io.appwrite.enums.SmtpEncryption val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/messaging/update-push.md b/docs/examples/1.8.x/server-kotlin/kotlin/messaging/update-push.md index 0b9c4c6535..5e2c77d569 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/messaging/update-push.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/messaging/update-push.md @@ -1,6 +1,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Messaging +import io.appwrite.enums.MessagePriority val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/messaging/update-smtp-provider.md b/docs/examples/1.8.x/server-kotlin/kotlin/messaging/update-smtp-provider.md index 7652e53166..66900e747d 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/messaging/update-smtp-provider.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/messaging/update-smtp-provider.md @@ -1,6 +1,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Messaging +import io.appwrite.enums.SmtpEncryption val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/sites/create.md b/docs/examples/1.8.x/server-kotlin/kotlin/sites/create.md index a5e9719faf..8df2d0709f 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/sites/create.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/sites/create.md @@ -3,6 +3,7 @@ import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Sites import io.appwrite.enums.Framework import io.appwrite.enums.BuildRuntime +import io.appwrite.enums.Adapter val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint @@ -14,8 +15,8 @@ val sites = Sites(client) val response = sites.create( siteId = "", name = "", - framework = .ANALOG, - buildRuntime = .NODE_14_5, + framework = Framework.ANALOG, + buildRuntime = BuildRuntime.NODE_14_5, enabled = false, // optional logging = false, // optional timeout = 1, // optional diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/sites/get-deployment-download.md b/docs/examples/1.8.x/server-kotlin/kotlin/sites/get-deployment-download.md index 84324762cc..a313a5de7e 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/sites/get-deployment-download.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/sites/get-deployment-download.md @@ -1,6 +1,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Sites +import io.appwrite.enums.DeploymentDownloadType val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/sites/update.md b/docs/examples/1.8.x/server-kotlin/kotlin/sites/update.md index 4b4a938d95..ee6f7db73f 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/sites/update.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/sites/update.md @@ -2,6 +2,8 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Sites import io.appwrite.enums.Framework +import io.appwrite.enums.BuildRuntime +import io.appwrite.enums.Adapter val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint @@ -13,7 +15,7 @@ val sites = Sites(client) val response = sites.update( siteId = "", name = "", - framework = .ANALOG, + framework = Framework.ANALOG, enabled = false, // optional logging = false, // optional timeout = 1, // optional diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/storage/create-bucket.md b/docs/examples/1.8.x/server-kotlin/kotlin/storage/create-bucket.md index 872932eeff..006466ec3e 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/storage/create-bucket.md @@ -1,6 +1,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Storage +import io.appwrite.enums.Compression import io.appwrite.Permission import io.appwrite.Role diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/storage/get-file-preview.md b/docs/examples/1.8.x/server-kotlin/kotlin/storage/get-file-preview.md index 45122de2f8..7b39d85cfa 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/storage/get-file-preview.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/storage/get-file-preview.md @@ -1,6 +1,8 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Storage +import io.appwrite.enums.ImageGravity +import io.appwrite.enums.ImageFormat val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/storage/update-bucket.md b/docs/examples/1.8.x/server-kotlin/kotlin/storage/update-bucket.md index cb8187343e..38f34ed046 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/storage/update-bucket.md @@ -1,6 +1,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Storage +import io.appwrite.enums.Compression import io.appwrite.Permission import io.appwrite.Role diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-relationship-column.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-relationship-column.md index fbdf36532f..3ece593a96 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-relationship-column.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/create-relationship-column.md @@ -2,6 +2,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.TablesDB import io.appwrite.enums.RelationshipType +import io.appwrite.enums.RelationMutate val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/update-relationship-column.md b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/update-relationship-column.md index f69defd8ec..357a57cd11 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/update-relationship-column.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/tablesdb/update-relationship-column.md @@ -1,6 +1,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.TablesDB +import io.appwrite.enums.RelationMutate val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-kotlin/kotlin/users/create-sha-user.md b/docs/examples/1.8.x/server-kotlin/kotlin/users/create-sha-user.md index 17a157b2cd..b286f8a554 100644 --- a/docs/examples/1.8.x/server-kotlin/kotlin/users/create-sha-user.md +++ b/docs/examples/1.8.x/server-kotlin/kotlin/users/create-sha-user.md @@ -1,6 +1,7 @@ import io.appwrite.Client import io.appwrite.coroutines.CoroutineCallback import io.appwrite.services.Users +import io.appwrite.enums.PasswordHash val client = Client() .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint diff --git a/docs/examples/1.8.x/server-nodejs/examples/avatars/get-screenshot.md b/docs/examples/1.8.x/server-nodejs/examples/avatars/get-screenshot.md index 5f7b40cece..60a38988cb 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/avatars/get-screenshot.md +++ b/docs/examples/1.8.x/server-nodejs/examples/avatars/get-screenshot.md @@ -13,11 +13,11 @@ const result = await avatars.getScreenshot({ viewportWidth: 1, // optional viewportHeight: 1, // optional scale: 0.1, // optional - theme: sdk..Light, // optional + theme: sdk.Theme.Light, // optional userAgent: '', // optional fullpage: false, // optional locale: '', // optional - timezone: sdk..AfricaAbidjan, // optional + timezone: sdk.Timezone.AfricaAbidjan, // optional latitude: -90, // optional longitude: -180, // optional accuracy: 0, // optional @@ -27,5 +27,5 @@ const result = await avatars.getScreenshot({ width: 0, // optional height: 0, // optional quality: -1, // optional - output: sdk..Jpg // optional + output: sdk.Output.Jpg // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/functions/create.md b/docs/examples/1.8.x/server-nodejs/examples/functions/create.md index d9f21ff796..37ac89dc5a 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/functions/create.md +++ b/docs/examples/1.8.x/server-nodejs/examples/functions/create.md @@ -10,7 +10,7 @@ const functions = new sdk.Functions(client); const result = await functions.create({ functionId: '', name: '', - runtime: sdk..Node145, + runtime: sdk.Runtime.Node145, execute: ["any"], // optional events: [], // optional schedule: '', // optional diff --git a/docs/examples/1.8.x/server-nodejs/examples/functions/update.md b/docs/examples/1.8.x/server-nodejs/examples/functions/update.md index 8ed2828f56..60653b5b77 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/functions/update.md +++ b/docs/examples/1.8.x/server-nodejs/examples/functions/update.md @@ -10,7 +10,7 @@ const functions = new sdk.Functions(client); const result = await functions.update({ functionId: '', name: '', - runtime: sdk..Node145, // optional + runtime: sdk.Runtime.Node145, // optional execute: ["any"], // optional events: [], // optional schedule: '', // optional diff --git a/docs/examples/1.8.x/server-nodejs/examples/health/get-failed-jobs.md b/docs/examples/1.8.x/server-nodejs/examples/health/get-failed-jobs.md index bf77aa26d8..32c03426b8 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/health/get-failed-jobs.md +++ b/docs/examples/1.8.x/server-nodejs/examples/health/get-failed-jobs.md @@ -8,6 +8,6 @@ const client = new sdk.Client() const health = new sdk.Health(client); const result = await health.getFailedJobs({ - name: sdk..V1Database, + name: sdk.Name.V1Database, threshold: null // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/sites/create.md b/docs/examples/1.8.x/server-nodejs/examples/sites/create.md index 25c6715748..397d2d3934 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/sites/create.md +++ b/docs/examples/1.8.x/server-nodejs/examples/sites/create.md @@ -10,15 +10,15 @@ const sites = new sdk.Sites(client); const result = await sites.create({ siteId: '', name: '', - framework: sdk..Analog, - buildRuntime: sdk..Node145, + framework: sdk.Framework.Analog, + buildRuntime: sdk.BuildRuntime.Node145, enabled: false, // optional logging: false, // optional timeout: 1, // optional installCommand: '', // optional buildCommand: '', // optional outputDirectory: '', // optional - adapter: sdk..Static, // optional + adapter: sdk.Adapter.Static, // optional installationId: '', // optional fallbackFile: '', // optional providerRepositoryId: '', // optional diff --git a/docs/examples/1.8.x/server-nodejs/examples/sites/update.md b/docs/examples/1.8.x/server-nodejs/examples/sites/update.md index 5cb52f7a3c..1a919f5d38 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/sites/update.md +++ b/docs/examples/1.8.x/server-nodejs/examples/sites/update.md @@ -10,15 +10,15 @@ const sites = new sdk.Sites(client); const result = await sites.update({ siteId: '', name: '', - framework: sdk..Analog, + framework: sdk.Framework.Analog, enabled: false, // optional logging: false, // optional timeout: 1, // optional installCommand: '', // optional buildCommand: '', // optional outputDirectory: '', // optional - buildRuntime: sdk..Node145, // optional - adapter: sdk..Static, // optional + buildRuntime: sdk.BuildRuntime.Node145, // optional + adapter: sdk.Adapter.Static, // optional fallbackFile: '', // optional installationId: '', // optional providerRepositoryId: '', // optional diff --git a/docs/examples/1.8.x/server-nodejs/examples/storage/create-bucket.md b/docs/examples/1.8.x/server-nodejs/examples/storage/create-bucket.md index b47d2c8353..b3557130e3 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-nodejs/examples/storage/create-bucket.md @@ -15,7 +15,7 @@ const result = await storage.createBucket({ enabled: false, // optional maximumFileSize: 1, // optional allowedFileExtensions: [], // optional - compression: sdk..None, // optional + compression: sdk.Compression.None, // optional encryption: false, // optional antivirus: false // optional }); diff --git a/docs/examples/1.8.x/server-nodejs/examples/storage/update-bucket.md b/docs/examples/1.8.x/server-nodejs/examples/storage/update-bucket.md index 9535914eeb..988b71ee45 100644 --- a/docs/examples/1.8.x/server-nodejs/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-nodejs/examples/storage/update-bucket.md @@ -15,7 +15,7 @@ const result = await storage.updateBucket({ enabled: false, // optional maximumFileSize: 1, // optional allowedFileExtensions: [], // optional - compression: sdk..None, // optional + compression: sdk.Compression.None, // optional encryption: false, // optional antivirus: false // optional }); diff --git a/docs/examples/1.8.x/server-python/examples/avatars/get-screenshot.md b/docs/examples/1.8.x/server-python/examples/avatars/get-screenshot.md index 34bdf8ac7a..fe7073eceb 100644 --- a/docs/examples/1.8.x/server-python/examples/avatars/get-screenshot.md +++ b/docs/examples/1.8.x/server-python/examples/avatars/get-screenshot.md @@ -1,5 +1,8 @@ from appwrite.client import Client from appwrite.services.avatars import Avatars +from appwrite.enums import Theme +from appwrite.enums import Timezone +from appwrite.enums import Output client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -14,11 +17,11 @@ result = avatars.get_screenshot( viewport_width = 1, # optional viewport_height = 1, # optional scale = 0.1, # optional - theme = .LIGHT, # optional + theme = Theme.LIGHT, # optional user_agent = '', # optional fullpage = False, # optional locale = '', # optional - timezone = .AFRICA_ABIDJAN, # optional + timezone = Timezone.AFRICA_ABIDJAN, # optional latitude = -90, # optional longitude = -180, # optional accuracy = 0, # optional @@ -28,5 +31,5 @@ result = avatars.get_screenshot( width = 0, # optional height = 0, # optional quality = -1, # optional - output = .JPG # optional + output = Output.JPG # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/databases/create-relationship-attribute.md b/docs/examples/1.8.x/server-python/examples/databases/create-relationship-attribute.md index 6c8f4dc5bb..ea859fcc33 100644 --- a/docs/examples/1.8.x/server-python/examples/databases/create-relationship-attribute.md +++ b/docs/examples/1.8.x/server-python/examples/databases/create-relationship-attribute.md @@ -1,6 +1,7 @@ from appwrite.client import Client from appwrite.services.databases import Databases from appwrite.enums import RelationshipType +from appwrite.enums import RelationMutate client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-python/examples/databases/update-relationship-attribute.md b/docs/examples/1.8.x/server-python/examples/databases/update-relationship-attribute.md index 3b6c8e93e9..8f5b0d8e69 100644 --- a/docs/examples/1.8.x/server-python/examples/databases/update-relationship-attribute.md +++ b/docs/examples/1.8.x/server-python/examples/databases/update-relationship-attribute.md @@ -1,5 +1,6 @@ from appwrite.client import Client from appwrite.services.databases import Databases +from appwrite.enums import RelationMutate client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-python/examples/functions/create-execution.md b/docs/examples/1.8.x/server-python/examples/functions/create-execution.md index f80b8646c2..8361351b35 100644 --- a/docs/examples/1.8.x/server-python/examples/functions/create-execution.md +++ b/docs/examples/1.8.x/server-python/examples/functions/create-execution.md @@ -1,5 +1,6 @@ from appwrite.client import Client from appwrite.services.functions import Functions +from appwrite.enums import ExecutionMethod client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-python/examples/functions/create.md b/docs/examples/1.8.x/server-python/examples/functions/create.md index 8758e27e50..98e16ebebe 100644 --- a/docs/examples/1.8.x/server-python/examples/functions/create.md +++ b/docs/examples/1.8.x/server-python/examples/functions/create.md @@ -1,6 +1,6 @@ from appwrite.client import Client from appwrite.services.functions import Functions -from appwrite.enums import +from appwrite.enums import Runtime client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -12,7 +12,7 @@ functions = Functions(client) result = functions.create( function_id = '', name = '', - runtime = .NODE_14_5, + runtime = Runtime.NODE_14_5, execute = ["any"], # optional events = [], # optional schedule = '', # optional diff --git a/docs/examples/1.8.x/server-python/examples/functions/get-deployment-download.md b/docs/examples/1.8.x/server-python/examples/functions/get-deployment-download.md index 1b0673c468..c633a893c6 100644 --- a/docs/examples/1.8.x/server-python/examples/functions/get-deployment-download.md +++ b/docs/examples/1.8.x/server-python/examples/functions/get-deployment-download.md @@ -1,5 +1,6 @@ from appwrite.client import Client from appwrite.services.functions import Functions +from appwrite.enums import DeploymentDownloadType client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-python/examples/functions/update.md b/docs/examples/1.8.x/server-python/examples/functions/update.md index 64ee39b29d..841c1eb839 100644 --- a/docs/examples/1.8.x/server-python/examples/functions/update.md +++ b/docs/examples/1.8.x/server-python/examples/functions/update.md @@ -1,5 +1,6 @@ from appwrite.client import Client from appwrite.services.functions import Functions +from appwrite.enums import Runtime client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -11,7 +12,7 @@ functions = Functions(client) result = functions.update( function_id = '', name = '', - runtime = .NODE_14_5, # optional + runtime = Runtime.NODE_14_5, # optional execute = ["any"], # optional events = [], # optional schedule = '', # optional diff --git a/docs/examples/1.8.x/server-python/examples/health/get-failed-jobs.md b/docs/examples/1.8.x/server-python/examples/health/get-failed-jobs.md index 5362a2d02a..6db282447e 100644 --- a/docs/examples/1.8.x/server-python/examples/health/get-failed-jobs.md +++ b/docs/examples/1.8.x/server-python/examples/health/get-failed-jobs.md @@ -1,6 +1,6 @@ from appwrite.client import Client from appwrite.services.health import Health -from appwrite.enums import +from appwrite.enums import Name client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -10,6 +10,6 @@ client.set_key('') # Your secret API key health = Health(client) result = health.get_failed_jobs( - name = .V1_DATABASE, + name = Name.V1_DATABASE, threshold = None # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/messaging/create-push.md b/docs/examples/1.8.x/server-python/examples/messaging/create-push.md index b706234227..817c157ee7 100644 --- a/docs/examples/1.8.x/server-python/examples/messaging/create-push.md +++ b/docs/examples/1.8.x/server-python/examples/messaging/create-push.md @@ -1,5 +1,6 @@ from appwrite.client import Client from appwrite.services.messaging import Messaging +from appwrite.enums import MessagePriority client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-python/examples/messaging/create-smtp-provider.md b/docs/examples/1.8.x/server-python/examples/messaging/create-smtp-provider.md index 99914f0779..6b9c345e6c 100644 --- a/docs/examples/1.8.x/server-python/examples/messaging/create-smtp-provider.md +++ b/docs/examples/1.8.x/server-python/examples/messaging/create-smtp-provider.md @@ -1,5 +1,6 @@ from appwrite.client import Client from appwrite.services.messaging import Messaging +from appwrite.enums import SmtpEncryption client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-python/examples/messaging/update-push.md b/docs/examples/1.8.x/server-python/examples/messaging/update-push.md index ce5d39466f..f9901329bb 100644 --- a/docs/examples/1.8.x/server-python/examples/messaging/update-push.md +++ b/docs/examples/1.8.x/server-python/examples/messaging/update-push.md @@ -1,5 +1,6 @@ from appwrite.client import Client from appwrite.services.messaging import Messaging +from appwrite.enums import MessagePriority client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-python/examples/messaging/update-smtp-provider.md b/docs/examples/1.8.x/server-python/examples/messaging/update-smtp-provider.md index 80019aad40..51f54a3df8 100644 --- a/docs/examples/1.8.x/server-python/examples/messaging/update-smtp-provider.md +++ b/docs/examples/1.8.x/server-python/examples/messaging/update-smtp-provider.md @@ -1,5 +1,6 @@ from appwrite.client import Client from appwrite.services.messaging import Messaging +from appwrite.enums import SmtpEncryption client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-python/examples/sites/create.md b/docs/examples/1.8.x/server-python/examples/sites/create.md index 4950cd2116..436e56ab86 100644 --- a/docs/examples/1.8.x/server-python/examples/sites/create.md +++ b/docs/examples/1.8.x/server-python/examples/sites/create.md @@ -1,7 +1,8 @@ from appwrite.client import Client from appwrite.services.sites import Sites -from appwrite.enums import -from appwrite.enums import +from appwrite.enums import Framework +from appwrite.enums import BuildRuntime +from appwrite.enums import Adapter client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -13,15 +14,15 @@ sites = Sites(client) result = sites.create( site_id = '', name = '', - framework = .ANALOG, - build_runtime = .NODE_14_5, + framework = Framework.ANALOG, + build_runtime = BuildRuntime.NODE_14_5, enabled = False, # optional logging = False, # optional timeout = 1, # optional install_command = '', # optional build_command = '', # optional output_directory = '', # optional - adapter = .STATIC, # optional + adapter = Adapter.STATIC, # optional installation_id = '', # optional fallback_file = '', # optional provider_repository_id = '', # optional diff --git a/docs/examples/1.8.x/server-python/examples/sites/get-deployment-download.md b/docs/examples/1.8.x/server-python/examples/sites/get-deployment-download.md index d6af564217..7eaa105ad3 100644 --- a/docs/examples/1.8.x/server-python/examples/sites/get-deployment-download.md +++ b/docs/examples/1.8.x/server-python/examples/sites/get-deployment-download.md @@ -1,5 +1,6 @@ from appwrite.client import Client from appwrite.services.sites import Sites +from appwrite.enums import DeploymentDownloadType client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-python/examples/sites/update.md b/docs/examples/1.8.x/server-python/examples/sites/update.md index 7d2d2865a4..56b796c276 100644 --- a/docs/examples/1.8.x/server-python/examples/sites/update.md +++ b/docs/examples/1.8.x/server-python/examples/sites/update.md @@ -1,6 +1,8 @@ from appwrite.client import Client from appwrite.services.sites import Sites -from appwrite.enums import +from appwrite.enums import Framework +from appwrite.enums import BuildRuntime +from appwrite.enums import Adapter client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -12,15 +14,15 @@ sites = Sites(client) result = sites.update( site_id = '', name = '', - framework = .ANALOG, + framework = Framework.ANALOG, enabled = False, # optional logging = False, # optional timeout = 1, # optional install_command = '', # optional build_command = '', # optional output_directory = '', # optional - build_runtime = .NODE_14_5, # optional - adapter = .STATIC, # optional + build_runtime = BuildRuntime.NODE_14_5, # optional + adapter = Adapter.STATIC, # optional fallback_file = '', # optional installation_id = '', # optional provider_repository_id = '', # optional diff --git a/docs/examples/1.8.x/server-python/examples/storage/create-bucket.md b/docs/examples/1.8.x/server-python/examples/storage/create-bucket.md index e08b2d0d6b..a2a3f9280c 100644 --- a/docs/examples/1.8.x/server-python/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-python/examples/storage/create-bucket.md @@ -1,5 +1,6 @@ from appwrite.client import Client from appwrite.services.storage import Storage +from appwrite.enums import Compression from appwrite.permission import Permission from appwrite.role import Role @@ -18,7 +19,7 @@ result = storage.create_bucket( enabled = False, # optional maximum_file_size = 1, # optional allowed_file_extensions = [], # optional - compression = .NONE, # optional + compression = Compression.NONE, # optional encryption = False, # optional antivirus = False # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/storage/get-file-preview.md b/docs/examples/1.8.x/server-python/examples/storage/get-file-preview.md index 47e3f23b55..f962edc0b6 100644 --- a/docs/examples/1.8.x/server-python/examples/storage/get-file-preview.md +++ b/docs/examples/1.8.x/server-python/examples/storage/get-file-preview.md @@ -1,5 +1,7 @@ from appwrite.client import Client from appwrite.services.storage import Storage +from appwrite.enums import ImageGravity +from appwrite.enums import ImageFormat client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-python/examples/storage/update-bucket.md b/docs/examples/1.8.x/server-python/examples/storage/update-bucket.md index bfa7cc3fdb..b095d314ac 100644 --- a/docs/examples/1.8.x/server-python/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-python/examples/storage/update-bucket.md @@ -1,5 +1,6 @@ from appwrite.client import Client from appwrite.services.storage import Storage +from appwrite.enums import Compression from appwrite.permission import Permission from appwrite.role import Role @@ -18,7 +19,7 @@ result = storage.update_bucket( enabled = False, # optional maximum_file_size = 1, # optional allowed_file_extensions = [], # optional - compression = .NONE, # optional + compression = Compression.NONE, # optional encryption = False, # optional antivirus = False # optional ) diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/create-relationship-column.md b/docs/examples/1.8.x/server-python/examples/tablesdb/create-relationship-column.md index 16acbf8fb8..d72fbfda11 100644 --- a/docs/examples/1.8.x/server-python/examples/tablesdb/create-relationship-column.md +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/create-relationship-column.md @@ -1,6 +1,7 @@ from appwrite.client import Client from appwrite.services.tables_db import TablesDB from appwrite.enums import RelationshipType +from appwrite.enums import RelationMutate client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-python/examples/tablesdb/update-relationship-column.md b/docs/examples/1.8.x/server-python/examples/tablesdb/update-relationship-column.md index 1cb93dbdf2..560590ec8c 100644 --- a/docs/examples/1.8.x/server-python/examples/tablesdb/update-relationship-column.md +++ b/docs/examples/1.8.x/server-python/examples/tablesdb/update-relationship-column.md @@ -1,5 +1,6 @@ from appwrite.client import Client from appwrite.services.tables_db import TablesDB +from appwrite.enums import RelationMutate client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-python/examples/users/create-sha-user.md b/docs/examples/1.8.x/server-python/examples/users/create-sha-user.md index 5b4c8f831a..7722c62f0c 100644 --- a/docs/examples/1.8.x/server-python/examples/users/create-sha-user.md +++ b/docs/examples/1.8.x/server-python/examples/users/create-sha-user.md @@ -1,5 +1,6 @@ from appwrite.client import Client from appwrite.services.users import Users +from appwrite.enums import PasswordHash client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-ruby/examples/avatars/get-screenshot.md b/docs/examples/1.8.x/server-ruby/examples/avatars/get-screenshot.md index f2af537fe8..f66fae3e02 100644 --- a/docs/examples/1.8.x/server-ruby/examples/avatars/get-screenshot.md +++ b/docs/examples/1.8.x/server-ruby/examples/avatars/get-screenshot.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums client = Client.new .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -15,11 +16,11 @@ result = avatars.get_screenshot( viewport_width: 1, # optional viewport_height: 1, # optional scale: 0.1, # optional - theme: ::LIGHT, # optional + theme: Theme::LIGHT, # optional user_agent: '', # optional fullpage: false, # optional locale: '', # optional - timezone: ::AFRICA_ABIDJAN, # optional + timezone: Timezone::AFRICA_ABIDJAN, # optional latitude: -90, # optional longitude: -180, # optional accuracy: 0, # optional @@ -29,5 +30,5 @@ result = avatars.get_screenshot( width: 0, # optional height: 0, # optional quality: -1, # optional - output: ::JPG # optional + output: Output::JPG # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/databases/update-relationship-attribute.md b/docs/examples/1.8.x/server-ruby/examples/databases/update-relationship-attribute.md index 679edb823e..6fddac2d58 100644 --- a/docs/examples/1.8.x/server-ruby/examples/databases/update-relationship-attribute.md +++ b/docs/examples/1.8.x/server-ruby/examples/databases/update-relationship-attribute.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums client = Client.new .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-ruby/examples/functions/create-execution.md b/docs/examples/1.8.x/server-ruby/examples/functions/create-execution.md index 666b995d77..521ee7cde0 100644 --- a/docs/examples/1.8.x/server-ruby/examples/functions/create-execution.md +++ b/docs/examples/1.8.x/server-ruby/examples/functions/create-execution.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums client = Client.new .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-ruby/examples/functions/create.md b/docs/examples/1.8.x/server-ruby/examples/functions/create.md index cad021b5f8..ce16a2b998 100644 --- a/docs/examples/1.8.x/server-ruby/examples/functions/create.md +++ b/docs/examples/1.8.x/server-ruby/examples/functions/create.md @@ -13,7 +13,7 @@ functions = Functions.new(client) result = functions.create( function_id: '', name: '', - runtime: ::NODE_14_5, + runtime: Runtime::NODE_14_5, execute: ["any"], # optional events: [], # optional schedule: '', # optional diff --git a/docs/examples/1.8.x/server-ruby/examples/functions/get-deployment-download.md b/docs/examples/1.8.x/server-ruby/examples/functions/get-deployment-download.md index a1a50a5f94..06faa7e03c 100644 --- a/docs/examples/1.8.x/server-ruby/examples/functions/get-deployment-download.md +++ b/docs/examples/1.8.x/server-ruby/examples/functions/get-deployment-download.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums client = Client.new .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-ruby/examples/functions/update.md b/docs/examples/1.8.x/server-ruby/examples/functions/update.md index 45b6e32ab3..91d8436463 100644 --- a/docs/examples/1.8.x/server-ruby/examples/functions/update.md +++ b/docs/examples/1.8.x/server-ruby/examples/functions/update.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums client = Client.new .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -12,7 +13,7 @@ functions = Functions.new(client) result = functions.update( function_id: '', name: '', - runtime: ::NODE_14_5, # optional + runtime: Runtime::NODE_14_5, # optional execute: ["any"], # optional events: [], # optional schedule: '', # optional diff --git a/docs/examples/1.8.x/server-ruby/examples/health/get-failed-jobs.md b/docs/examples/1.8.x/server-ruby/examples/health/get-failed-jobs.md index 73e1983e3a..b15f6cc41e 100644 --- a/docs/examples/1.8.x/server-ruby/examples/health/get-failed-jobs.md +++ b/docs/examples/1.8.x/server-ruby/examples/health/get-failed-jobs.md @@ -11,6 +11,6 @@ client = Client.new health = Health.new(client) result = health.get_failed_jobs( - name: ::V1_DATABASE, + name: Name::V1_DATABASE, threshold: null # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/messaging/create-push.md b/docs/examples/1.8.x/server-ruby/examples/messaging/create-push.md index f4555aa967..547c179d68 100644 --- a/docs/examples/1.8.x/server-ruby/examples/messaging/create-push.md +++ b/docs/examples/1.8.x/server-ruby/examples/messaging/create-push.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums client = Client.new .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-ruby/examples/messaging/create-smtp-provider.md b/docs/examples/1.8.x/server-ruby/examples/messaging/create-smtp-provider.md index b062e574b4..c33f772a7d 100644 --- a/docs/examples/1.8.x/server-ruby/examples/messaging/create-smtp-provider.md +++ b/docs/examples/1.8.x/server-ruby/examples/messaging/create-smtp-provider.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums client = Client.new .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-ruby/examples/messaging/update-push.md b/docs/examples/1.8.x/server-ruby/examples/messaging/update-push.md index 19b273bb24..b365069ad0 100644 --- a/docs/examples/1.8.x/server-ruby/examples/messaging/update-push.md +++ b/docs/examples/1.8.x/server-ruby/examples/messaging/update-push.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums client = Client.new .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-ruby/examples/messaging/update-smtp-provider.md b/docs/examples/1.8.x/server-ruby/examples/messaging/update-smtp-provider.md index bbaebf3c32..ab0e1b45cf 100644 --- a/docs/examples/1.8.x/server-ruby/examples/messaging/update-smtp-provider.md +++ b/docs/examples/1.8.x/server-ruby/examples/messaging/update-smtp-provider.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums client = Client.new .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-ruby/examples/sites/create.md b/docs/examples/1.8.x/server-ruby/examples/sites/create.md index 2243185485..7dc004cd71 100644 --- a/docs/examples/1.8.x/server-ruby/examples/sites/create.md +++ b/docs/examples/1.8.x/server-ruby/examples/sites/create.md @@ -13,15 +13,15 @@ sites = Sites.new(client) result = sites.create( site_id: '', name: '', - framework: ::ANALOG, - build_runtime: ::NODE_14_5, + framework: Framework::ANALOG, + build_runtime: BuildRuntime::NODE_14_5, enabled: false, # optional logging: false, # optional timeout: 1, # optional install_command: '', # optional build_command: '', # optional output_directory: '', # optional - adapter: ::STATIC, # optional + adapter: Adapter::STATIC, # optional installation_id: '', # optional fallback_file: '', # optional provider_repository_id: '', # optional diff --git a/docs/examples/1.8.x/server-ruby/examples/sites/get-deployment-download.md b/docs/examples/1.8.x/server-ruby/examples/sites/get-deployment-download.md index 85162626ba..c82ab98879 100644 --- a/docs/examples/1.8.x/server-ruby/examples/sites/get-deployment-download.md +++ b/docs/examples/1.8.x/server-ruby/examples/sites/get-deployment-download.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums client = Client.new .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-ruby/examples/sites/update.md b/docs/examples/1.8.x/server-ruby/examples/sites/update.md index 922255ab65..0d73293124 100644 --- a/docs/examples/1.8.x/server-ruby/examples/sites/update.md +++ b/docs/examples/1.8.x/server-ruby/examples/sites/update.md @@ -13,15 +13,15 @@ sites = Sites.new(client) result = sites.update( site_id: '', name: '', - framework: ::ANALOG, + framework: Framework::ANALOG, enabled: false, # optional logging: false, # optional timeout: 1, # optional install_command: '', # optional build_command: '', # optional output_directory: '', # optional - build_runtime: ::NODE_14_5, # optional - adapter: ::STATIC, # optional + build_runtime: BuildRuntime::NODE_14_5, # optional + adapter: Adapter::STATIC, # optional fallback_file: '', # optional installation_id: '', # optional provider_repository_id: '', # optional diff --git a/docs/examples/1.8.x/server-ruby/examples/storage/create-bucket.md b/docs/examples/1.8.x/server-ruby/examples/storage/create-bucket.md index 4a12518fb7..3db21e2a35 100644 --- a/docs/examples/1.8.x/server-ruby/examples/storage/create-bucket.md +++ b/docs/examples/1.8.x/server-ruby/examples/storage/create-bucket.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums include Appwrite::Permission include Appwrite::Role @@ -19,7 +20,7 @@ result = storage.create_bucket( enabled: false, # optional maximum_file_size: 1, # optional allowed_file_extensions: [], # optional - compression: ::NONE, # optional + compression: Compression::NONE, # optional encryption: false, # optional antivirus: false # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/storage/get-file-preview.md b/docs/examples/1.8.x/server-ruby/examples/storage/get-file-preview.md index 23254615d3..4b154c772d 100644 --- a/docs/examples/1.8.x/server-ruby/examples/storage/get-file-preview.md +++ b/docs/examples/1.8.x/server-ruby/examples/storage/get-file-preview.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums client = Client.new .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-ruby/examples/storage/update-bucket.md b/docs/examples/1.8.x/server-ruby/examples/storage/update-bucket.md index 2e44aad536..0eaecbe0d7 100644 --- a/docs/examples/1.8.x/server-ruby/examples/storage/update-bucket.md +++ b/docs/examples/1.8.x/server-ruby/examples/storage/update-bucket.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums include Appwrite::Permission include Appwrite::Role @@ -19,7 +20,7 @@ result = storage.update_bucket( enabled: false, # optional maximum_file_size: 1, # optional allowed_file_extensions: [], # optional - compression: ::NONE, # optional + compression: Compression::NONE, # optional encryption: false, # optional antivirus: false # optional ) diff --git a/docs/examples/1.8.x/server-ruby/examples/tablesdb/update-relationship-column.md b/docs/examples/1.8.x/server-ruby/examples/tablesdb/update-relationship-column.md index 3951cbc047..81de2d7897 100644 --- a/docs/examples/1.8.x/server-ruby/examples/tablesdb/update-relationship-column.md +++ b/docs/examples/1.8.x/server-ruby/examples/tablesdb/update-relationship-column.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums client = Client.new .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.8.x/server-ruby/examples/users/create-sha-user.md b/docs/examples/1.8.x/server-ruby/examples/users/create-sha-user.md index f3951d9c80..d19db05324 100644 --- a/docs/examples/1.8.x/server-ruby/examples/users/create-sha-user.md +++ b/docs/examples/1.8.x/server-ruby/examples/users/create-sha-user.md @@ -1,6 +1,7 @@ require 'appwrite' include Appwrite +include Appwrite::Enums client = Client.new .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint From 20221cd6b6ed44d8ee2e873e3a9749c796ce82b6 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 18 Nov 2025 11:43:27 +0530 Subject: [PATCH 65/77] sync composer --- composer.json | 2 +- composer.lock | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index 0a4e347d7f..1cff497d08 100644 --- a/composer.json +++ b/composer.json @@ -88,7 +88,7 @@ }, "require-dev": { "ext-fileinfo": "*", - "appwrite/sdk-generator": "dev-fix-enum-rendering", + "appwrite/sdk-generator": "*", "phpunit/phpunit": "9.*", "swoole/ide-helper": "5.1.2", "phpstan/phpstan": "1.8.*", diff --git a/composer.lock b/composer.lock index f173903669..163bdb5bd9 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": "bc877cc8bf639e146710e0d7656adbec", + "content-hash": "3b502f78f5e31f2ea7b4c69e3301283a", "packages": [ { "name": "adhocore/jwt", @@ -5383,16 +5383,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "dev-fix-enum-rendering", + "version": "1.5.7", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "3f39061b0db19057219bab6352afa2201306eedf" + "reference": "dc6720ba92ed98e2c62b2a319d4371f167ccc808" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/3f39061b0db19057219bab6352afa2201306eedf", - "reference": "3f39061b0db19057219bab6352afa2201306eedf", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/dc6720ba92ed98e2c62b2a319d4371f167ccc808", + "reference": "dc6720ba92ed98e2c62b2a319d4371f167ccc808", "shasum": "" }, "require": { @@ -5428,9 +5428,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/fix-enum-rendering" + "source": "https://github.com/appwrite/sdk-generator/tree/1.5.7" }, - "time": "2025-11-18T05:35:14+00:00" + "time": "2025-11-18T05:57:01+00:00" }, { "name": "doctrine/annotations", @@ -8897,9 +8897,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "appwrite/sdk-generator": 20 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From c2645be4e1159e733a18ef2dfe54e802b79dcda4 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 18 Nov 2025 12:47:39 +0530 Subject: [PATCH 66/77] chore: custom format instance in specs --- src/Appwrite/Platform/Tasks/Specs.php | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/Specs.php b/src/Appwrite/Platform/Tasks/Specs.php index 53cbced174..c69558d096 100644 --- a/src/Appwrite/Platform/Tasks/Specs.php +++ b/src/Appwrite/Platform/Tasks/Specs.php @@ -43,6 +43,15 @@ class Specs extends Action return new AppwriteResponse(new SwooleResponse()); } + protected function getFormatInstance(string $format, array $arguments) + { + return match ($format) { + 'swagger2' => new Swagger2(...$arguments), + 'open-api3' => new OpenAPI3(...$arguments), + default => throw new Exception('Format not found: ' . $format) + }; + } + public function __construct() { $this @@ -288,12 +297,7 @@ class Specs extends Action ]; foreach (['swagger2', 'open-api3'] as $format) { - $formatInstance = match ($format) { - 'swagger2' => new Swagger2(...$arguments), - 'open-api3' => new OpenAPI3(...$arguments), - default => throw new Exception('Format not found: ' . $format) - }; - + $formatInstance = $this->getFormatInstance($format, $arguments); $specs = new Specification($formatInstance); $endpoint = System::getEnv('_APP_HOME', '[HOSTNAME]'); $email = System::getEnv('_APP_SYSTEM_TEAM_EMAIL', APP_EMAIL_TEAM); From 5a8a900b1881f9e898750afd36d6aa77b1c53821 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 18 Nov 2025 12:50:22 +0530 Subject: [PATCH 67/77] format --- src/Appwrite/Platform/Tasks/Specs.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/Specs.php b/src/Appwrite/Platform/Tasks/Specs.php index c69558d096..edb1fc56ed 100644 --- a/src/Appwrite/Platform/Tasks/Specs.php +++ b/src/Appwrite/Platform/Tasks/Specs.php @@ -44,13 +44,13 @@ class Specs extends Action } protected function getFormatInstance(string $format, array $arguments) - { - return match ($format) { - 'swagger2' => new Swagger2(...$arguments), - 'open-api3' => new OpenAPI3(...$arguments), - default => throw new Exception('Format not found: ' . $format) - }; - } + { + return match ($format) { + 'swagger2' => new Swagger2(...$arguments), + 'open-api3' => new OpenAPI3(...$arguments), + default => throw new Exception('Format not found: ' . $format) + }; + } public function __construct() { From ce2f2d0ebcdc2439c87ff00b5a394a0b82f8fc06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 18 Nov 2025 16:35:02 +0100 Subject: [PATCH 68/77] Use config library for dotenv adapter --- app/controllers/api/vcs.php | 26 +++++++------ app/init/configs.php | 75 +++++++++++++++++++------------------ composer.json | 2 +- composer.lock | 55 ++++++++++++++------------- 4 files changed, 84 insertions(+), 74 deletions(-) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 4703e3a296..82f23cf6b5 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -17,7 +17,9 @@ use Appwrite\Vcs\Comment; use Swoole\Coroutine\WaitGroup; use Utopia\App; use Utopia\CLI\Console; +use Utopia\Config\Adapters\PHP as ConfigPHP; use Utopia\Config\Config; +use Utopia\Config\Exceptions\Parse; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; @@ -978,14 +980,14 @@ App::post('/v1/vcs/github/installations/:installationId/detections') $contentResponse = $github->getRepositoryContent($owner, $repositoryName, \rtrim($providerRootDirectory, '/') . '/' . $file); $envFile = $contentResponse['content'] ?? ''; - $envLines = \explode("\n", $envFile); - foreach ($envLines as $line) { - $parts = \explode('=', $line, 2); - $envName = \trim($parts[0] ?? ''); - $envValue = \trim($parts[1] ?? ''); - if (!empty($envName)) { + $configAdapter = new ConfigPHP(); + try { + $envObject = $configAdapter->parse($envFile); + foreach ($envObject as $envName => $envValue) { $envs[$envName] = $envValue; } + } catch (Parse $err) { + // Silence error, so rest of endpoint can return } } finally { $wg->done(); @@ -1192,14 +1194,14 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') $contentResponse = $github->getRepositoryContent($repo['organization'], $repo['name'], $file); $envFile = $contentResponse['content'] ?? ''; - $envLines = \explode("\n", $envFile); - foreach ($envLines as $line) { - $parts = \explode('=', $line, 2); - $envName = \trim($parts[0] ?? ''); - $envValue = \trim($parts[1] ?? ''); - if (!empty($envName)) { + $configAdapter = new ConfigPHP(); + try { + $envObject = $configAdapter->parse($envFile); + foreach ($envObject as $envName => $envValue) { $envs[$envName] = $envValue; } + } catch (Parse) { + // Silence error, so rest of endpoint can return } } finally { $wg->done(); diff --git a/app/init/configs.php b/app/init/configs.php index 7572302919..9519c757b3 100644 --- a/app/init/configs.php +++ b/app/init/configs.php @@ -1,42 +1,45 @@ =7.3" + "ext-yaml": "*", + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3", - "vimeo/psalm": "4.0.1" + "laravel/pint": "1.2.*", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^9.3" }, "type": "library", "autoload": { @@ -3774,12 +3776,6 @@ "license": [ "MIT" ], - "authors": [ - { - "name": "Eldad Fux", - "email": "eldad@appwrite.io" - } - ], "description": "A simple Config library to managing application config variables", "keywords": [ "config", @@ -3790,9 +3786,9 @@ ], "support": { "issues": "https://github.com/utopia-php/config/issues", - "source": "https://github.com/utopia-php/config/tree/0.2.2" + "source": "https://github.com/utopia-php/config/tree/feat-config-adapters" }, - "time": "2020-10-24T09:49:09+00:00" + "time": "2025-11-18T14:59:26+00:00" }, { "name": "utopia-php/console", @@ -4212,16 +4208,16 @@ }, { "name": "utopia-php/framework", - "version": "0.33.29", + "version": "0.33.30", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "6e63939fdb33b847f92839499cd6e8df626c278d" + "reference": "07cf699a7c47bd1a03b4da1812f1719a66b3c924" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/6e63939fdb33b847f92839499cd6e8df626c278d", - "reference": "6e63939fdb33b847f92839499cd6e8df626c278d", + "url": "https://api.github.com/repos/utopia-php/http/zipball/07cf699a7c47bd1a03b4da1812f1719a66b3c924", + "reference": "07cf699a7c47bd1a03b4da1812f1719a66b3c924", "shasum": "" }, "require": { @@ -4253,9 +4249,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.29" + "source": "https://github.com/utopia-php/http/tree/0.33.30" }, - "time": "2025-11-14T06:33:29+00:00" + "time": "2025-11-18T12:18:00+00:00" }, { "name": "utopia-php/image", @@ -8895,9 +8891,18 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/config", + "version": "dev-feat-config-adapters", + "alias": "1.0.0", + "alias_normalized": "1.0.0.0" + } + ], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "utopia-php/config": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8921,5 +8926,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.3.0" } From e3ee7241782f688e992640c5f59e5c99bb2531f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 18 Nov 2025 16:42:57 +0100 Subject: [PATCH 69/77] Fix during QA --- app/controllers/api/vcs.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 82f23cf6b5..05bd2f83e5 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -17,7 +17,7 @@ use Appwrite\Vcs\Comment; use Swoole\Coroutine\WaitGroup; use Utopia\App; use Utopia\CLI\Console; -use Utopia\Config\Adapters\PHP as ConfigPHP; +use Utopia\Config\Adapters\Dotenv as ConfigDotenv; use Utopia\Config\Config; use Utopia\Config\Exceptions\Parse; use Utopia\Database\Database; @@ -980,7 +980,7 @@ App::post('/v1/vcs/github/installations/:installationId/detections') $contentResponse = $github->getRepositoryContent($owner, $repositoryName, \rtrim($providerRootDirectory, '/') . '/' . $file); $envFile = $contentResponse['content'] ?? ''; - $configAdapter = new ConfigPHP(); + $configAdapter = new ConfigDotenv(); try { $envObject = $configAdapter->parse($envFile); foreach ($envObject as $envName => $envValue) { @@ -1194,7 +1194,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') $contentResponse = $github->getRepositoryContent($repo['organization'], $repo['name'], $file); $envFile = $contentResponse['content'] ?? ''; - $configAdapter = new ConfigPHP(); + $configAdapter = new ConfigDotenv(); try { $envObject = $configAdapter->parse($envFile); foreach ($envObject as $envName => $envValue) { From 8765d5650a7ca2babc6a5e920f7498175ed953a3 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 19 Nov 2025 16:21:06 +1300 Subject: [PATCH 70/77] Revert "Merge pull request #10682 from appwrite/refactor-auth-single-instance" This reverts commit 919b01a1b164c12438e313a848a5c47aad4fe347, reversing changes made to deb503935244006b0f16da65d4d6fd6f09c92d7d. --- app/cli.php | 28 +-- app/config/storage/resource_limits.php | 4 +- app/controllers/api/account.php | 139 +++++------- app/controllers/api/avatars.php | 29 ++- app/controllers/api/graphql.php | 5 +- app/controllers/api/messaging.php | 65 +++--- app/controllers/api/migrations.php | 34 +-- app/controllers/api/project.php | 9 +- app/controllers/api/storage.php | 202 +++++++++--------- app/controllers/api/teams.php | 138 ++++++------ app/controllers/api/users.php | 6 +- app/controllers/api/vcs.php | 60 +++--- app/controllers/general.php | 62 +++--- app/controllers/shared/api.php | 53 +++-- app/controllers/shared/api/auth.php | 7 +- app/http.php | 28 +-- app/init/database/filters.php | 15 +- app/init/resources.php | 96 ++++----- app/realtime.php | 23 +- app/worker.php | 49 ++--- composer.json | 2 +- composer.lock | 42 ++-- src/Appwrite/Auth/Auth.php | 4 +- src/Appwrite/Databases/TransactionState.php | 10 +- src/Appwrite/Migration/Migration.php | 6 +- .../Platform/Modules/Compute/Base.php | 8 +- .../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 | 12 -- .../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/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 | 8 +- .../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 | 8 +- .../Http/Deployments/Duplicate/Create.php | 6 +- .../Http/Deployments/Template/Create.php | 7 +- .../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 | 6 +- src/Appwrite/Platform/Workers/Deletes.php | 7 +- src/Appwrite/Platform/Workers/Functions.php | 2 + src/Appwrite/Platform/Workers/Migrations.php | 12 +- src/Appwrite/Utopia/Request.php | 9 +- src/Appwrite/Utopia/Request/Filter.php | 2 +- src/Appwrite/Utopia/Request/Filters/V20.php | 7 +- src/Appwrite/Utopia/Response.php | 9 +- .../DatabasesPermissionsGuestTest.php | 25 +-- .../DatabasesPermissionsGuestTest.php | 25 +-- .../Health/HealthCustomServerTest.php | 1 + tests/e2e/Services/Tokens/TokensBase.php | 8 +- tests/unit/Auth/AuthTest.php | 36 +--- .../unit/Messaging/MessagingChannelsTest.php | 18 +- 180 files changed, 868 insertions(+), 1248 deletions(-) diff --git a/app/cli.php b/app/cli.php index 0900926346..71b6464cb9 100644 --- a/app/cli.php +++ b/app/cli.php @@ -40,6 +40,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) { @@ -57,13 +59,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; @@ -77,7 +73,6 @@ CLI::setResource('dbForPlatform', function ($pools, $cache, $authorization) { $dbForPlatform = new Database($adapter, $cache); $dbForPlatform - ->setAuthorization($authorization) ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console'); @@ -102,7 +97,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')); @@ -113,10 +108,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; } @@ -149,7 +144,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', '')); @@ -166,18 +160,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; @@ -187,7 +180,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) @@ -200,7 +192,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 b6e1ebcc61..b7959bb6a9 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -192,10 +192,10 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, Doc ; -$createSession = function (string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Authorization $authorization) { +$createSession = function (string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails) { /** @var Utopia\Database\Document $user */ - $userFromRequest = $authorization->skip(fn () => $dbForProject->getDocument('users', $userId)); + $userFromRequest = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); if ($userFromRequest->isEmpty()) { throw new Exception(Exception::USER_INVALID_TOKEN); @@ -241,7 +241,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', [ @@ -250,7 +250,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 @@ -346,9 +346,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()) { @@ -439,9 +438,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())), @@ -467,9 +466,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) @@ -930,8 +929,7 @@ App::post('/v1/account/sessions/email') ->inject('queueForEvents') ->inject('queueForMails') ->inject('hooks') - ->inject('authorization') - ->action(function (string $email, string $password, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks, Authorization $authorization) { + ->action(function (string $email, string $password, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks) { $email = \strtolower($email); $protocol = $request->getProtocol(); @@ -974,7 +972,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') !== Auth::DEFAULT_ALGO) { @@ -1066,8 +1064,7 @@ App::post('/v1/account/sessions/anonymous') ->inject('dbForProject') ->inject('geodb') ->inject('queueForEvents') - ->inject('authorization') - ->action(function (Request $request, Response $response, Locale $locale, Document $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents, Authorization $authorization) { + ->action(function (Request $request, Response $response, Locale $locale, Document $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents) { $protocol = $request->getProtocol(); if ('console' === $project->getId()) { @@ -1112,7 +1109,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'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; @@ -1138,7 +1135,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())), @@ -1211,7 +1208,6 @@ App::post('/v1/account/sessions/token') ->inject('geodb') ->inject('queueForEvents') ->inject('queueForMails') - ->inject('authorization') ->action($createSession); App::get('/v1/account/sessions/oauth2/:provider') @@ -1404,8 +1400,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') ->inject('dbForProject') ->inject('geodb') ->inject('queueForEvents') - ->inject('authorization') - ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, array $platforms, Document $devKey, Document $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Authorization $authorization) use ($oauthDefaultSuccess) { + ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, array $platforms, Document $devKey, Document $user, Database $dbForProject, Reader $geodb, Event $queueForEvents) use ($oauthDefaultSuccess) { $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $port = $request->getPort(); $callbackBase = $protocol . '://' . $request->getHostname(); @@ -1658,7 +1653,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())), @@ -1677,8 +1672,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 @@ -1749,7 +1744,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']); @@ -1771,7 +1766,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', [ @@ -1998,8 +1993,7 @@ App::post('/v1/account/tokens/magic-url') ->inject('locale') ->inject('queueForEvents') ->inject('queueForMails') - ->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, Authorization $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) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -2072,7 +2066,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)); } $tokenSecret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_MAGIC_URL); @@ -2089,7 +2083,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', [ @@ -2262,8 +2256,7 @@ App::post('/v1/account/tokens/email') ->inject('locale') ->inject('queueForEvents') ->inject('queueForMails') - ->inject('authorization') - ->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, Authorization $authorization) { + ->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -2332,9 +2325,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())), @@ -2372,7 +2365,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', [ @@ -2553,7 +2546,6 @@ App::put('/v1/account/sessions/magic-url') ->inject('geodb') ->inject('queueForEvents') ->inject('queueForMails') - ->inject('authorization') ->action($createSession); App::put('/v1/account/sessions/phone') @@ -2595,7 +2587,6 @@ App::put('/v1/account/sessions/phone') ->inject('geodb') ->inject('queueForEvents') ->inject('queueForMails') - ->inject('authorization') ->action($createSession); App::post('/v1/account/tokens/phone') @@ -2636,8 +2627,7 @@ App::post('/v1/account/tokens/phone') ->inject('timelimit') ->inject('queueForStatsUsage') ->inject('plan') - ->inject('authorization') - ->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Authorization $authorization) { + ->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -2687,9 +2677,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())), @@ -2735,7 +2725,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', [ @@ -3121,8 +3111,7 @@ App::patch('/v1/account/email') ->inject('queueForEvents') ->inject('project') ->inject('hooks') - ->inject('authorization') - ->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, Authorization $authorization) { + ->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks) { // passwordUpdate will be empty if the user has never set a password $passwordUpdate = $user->getAttribute('passwordUpdate'); @@ -3172,7 +3161,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]), ])); @@ -3188,7 +3177,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) { @@ -3230,8 +3219,7 @@ App::patch('/v1/account/phone') ->inject('queueForEvents') ->inject('project') ->inject('hooks') - ->inject('authorization') - ->action(function (string $phone, string $password, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, Authorization $authorization) { + ->action(function (string $phone, string $password, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks) { // passwordUpdate will be empty if the user has never set a password $passwordUpdate = $user->getAttribute('passwordUpdate'); @@ -3244,7 +3232,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]), ])); @@ -3275,7 +3263,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) { @@ -3409,8 +3397,7 @@ App::post('/v1/account/recovery') ->inject('locale') ->inject('queueForMails') ->inject('queueForEvents') - ->inject('authorization') - ->action(function (string $email, string $url, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Mail $queueForMails, Event $queueForEvents, Authorization $authorization) { + ->action(function (string $email, string $url, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Mail $queueForMails, Event $queueForEvents) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); @@ -3446,7 +3433,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', [ @@ -3588,8 +3575,7 @@ App::put('/v1/account/recovery') ->inject('project') ->inject('queueForEvents') ->inject('hooks') - ->inject('authorization') - ->action(function (string $userId, string $secret, string $password, Response $response, Document $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks, Authorization $authorization) { + ->action(function (string $userId, string $secret, string $password, Response $response, Document $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks) { $profile = $dbForProject->getDocument('users', $userId); if ($profile->isEmpty()) { @@ -3603,7 +3589,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 = Auth::passwordHash($password, Auth::DEFAULT_ALGO, Auth::DEFAULT_ALGO_OPTIONS); @@ -3701,8 +3687,7 @@ App::post('/v1/account/verifications/email') ->inject('locale') ->inject('queueForEvents') ->inject('queueForMails') - ->inject('authorization') - ->action(function (string $url, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, Authorization $authorization) { + ->action(function (string $url, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); @@ -3731,7 +3716,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', [ @@ -3914,10 +3899,9 @@ App::put('/v1/account/verifications/email') ->inject('user') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') - ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Authorization $authorization) { + ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { - $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); @@ -3930,7 +3914,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)); @@ -3989,8 +3973,7 @@ App::post('/v1/account/verifications/phone') ->inject('timelimit') ->inject('queueForStatsUsage') ->inject('plan') - ->inject('authorization') - ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Authorization $authorization) { + ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -4029,7 +4012,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', [ @@ -4134,10 +4117,9 @@ App::put('/v1/account/verifications/phone') ->inject('user') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('authorization') - ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Authorization $authorization) { + ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { - $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); @@ -4149,7 +4131,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)); @@ -5137,13 +5119,12 @@ App::post('/v1/account/targets/push') ->inject('request') ->inject('response') ->inject('dbForProject') - ->inject('authorization') - ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject, Authorization $authorization) { + ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject) { $targetId = $targetId == 'unique()' ? ID::unique() : $targetId; - $provider = $authorization->skip(fn () => $dbForProject->getDocument('providers', $providerId)); + $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); @@ -5218,10 +5199,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); @@ -5284,9 +5264,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/avatars.php b/app/controllers/api/avatars.php index 544e22a0fa..d0cb3e554c 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, Authorization $authorization, ?Logger $logger) { +$getUserGitHub = function (string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?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,9 +841,8 @@ App::get('/v1/cards/cloud') ->inject('contributors') ->inject('employees') ->inject('logger') - ->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)); + ->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)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -854,7 +853,7 @@ App::get('/v1/cards/cloud') $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); + $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; @@ -1049,9 +1048,8 @@ App::get('/v1/cards/cloud-back') ->inject('contributors') ->inject('employees') ->inject('logger') - ->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)); + ->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)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -1061,7 +1059,7 @@ App::get('/v1/cards/cloud-back') $userId = $user->getId(); $email = $user->getAttribute('email', ''); - $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); + $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); $githubId = $gitHub['id'] ?? ''; $isHero = \array_key_exists($email, $heroes); @@ -1128,9 +1126,8 @@ App::get('/v1/cards/cloud-og') ->inject('contributors') ->inject('employees') ->inject('logger') - ->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)); + ->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)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -1145,7 +1142,7 @@ App::get('/v1/cards/cloud-og') $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger, $authorization); + $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/app/controllers/api/graphql.php b/app/controllers/api/graphql.php index d0480225da..482b38d698 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'] - && !(Auth::isPrivilegedUser($authorization->getRoles()) || Auth::isAppUser($authorization->getRoles())) + && !(Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index dbbc667c94..58a0ffe42f 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; @@ -1071,9 +1070,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) { @@ -1099,7 +1097,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."); @@ -2479,9 +2477,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) { @@ -2507,7 +2504,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."); @@ -2783,27 +2780,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, @@ -2836,7 +2835,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, @@ -2881,9 +2880,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) { @@ -2894,7 +2892,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 +2915,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 +2929,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, @@ -3704,9 +3700,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) { @@ -3732,7 +3727,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 f9d134db05..41b98ab333 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -1,6 +1,5 @@ inject('response') ->inject('dbForProject') ->inject('dbForPlatform') - ->inject('authorization') ->inject('project') ->inject('deviceForFiles') ->inject('deviceForMigrations') ->inject('queueForEvents') ->inject('queueForMigrations') - ->action(function (string $bucketId, string $fileId, string $resourceId, bool $internalFile, Response $response, Database $dbForProject, Database $dbForPlatform, Authorization $authorization, Document $project, Device $deviceForFiles, Device $deviceForMigrations, Event $queueForEvents, Migration $queueForMigrations) { - $isAPIKey = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); - if ($internalFile && !$isPrivilegedUser) { - throw new Exception(Exception::USER_UNAUTHORIZED); - } - $bucket = $authorization->skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) { + ->action(function ( + string $bucketId, + string $fileId, + string $resourceId, + bool $internalFile, + Response $response, + Database $dbForProject, + Database $dbForPlatform, + Document $project, + Device $deviceForFiles, + Device $deviceForMigrations, + Event $queueForEvents, + Migration $queueForMigrations + ) { + $bucket = Authorization::skip(function () use ($internalFile, $dbForPlatform, $dbForProject, $bucketId) { if ($internalFile) { return $dbForPlatform->getDocument('buckets', 'default'); } @@ -358,7 +364,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); } @@ -474,7 +480,6 @@ App::post('/v1/migrations/csv/exports') ->inject('response') ->inject('dbForProject') ->inject('dbForPlatform') - ->inject('authorization') ->inject('project') ->inject('queueForEvents') ->inject('queueForMigrations') @@ -492,7 +497,6 @@ App::post('/v1/migrations/csv/exports') Response $response, Database $dbForProject, Database $dbForPlatform, - Authorization $authorization, Document $project, Event $queueForEvents, Migration $queueForMigrations @@ -503,7 +507,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); } @@ -516,12 +520,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/storage.php b/app/controllers/api/storage.php index c2adc1e195..10fcbdb3d3 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -32,7 +32,6 @@ use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Authorization\Input; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; @@ -434,20 +433,20 @@ App::post('/v1/storage/buckets/:bucketId/files') ->inject('mode') ->inject('deviceForFiles') ->inject('deviceForLocal') - ->inject('authorization') - ->action(function (string $bucketId, string $fileId, mixed $file, ?array $permissions, Request $request, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, string $mode, Device $deviceForFiles, Device $deviceForLocal, Authorization $authorization) { + ->action(function (string $bucketId, string $fileId, mixed $file, ?array $permissions, Request $request, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, string $mode, Device $deviceForFiles, Device $deviceForLocal) { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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(Database::PERMISSION_CREATE); + if (!$validator->isValid($bucket->getCreate())) { + throw new Exception(Exception::USER_UNAUTHORIZED); } $allowedPermissions = [ @@ -470,7 +469,7 @@ App::post('/v1/storage/buckets/:bucketId/files') } // Users can only manage their own roles, API keys and Admin users can manage any - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -483,7 +482,7 @@ App::post('/v1/storage/buckets/:bucketId/files') $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) . ')'); } } @@ -703,10 +702,11 @@ App::post('/v1/storage/buckets/:bucketId/files') * 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()))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + $validator = new Authorization(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)); } } else { if ($file->isEmpty()) { @@ -745,12 +745,13 @@ App::post('/v1/storage/buckets/:bucketId/files') * 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()))) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + $validator = new Authorization(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); } @@ -794,22 +795,22 @@ App::get('/v1/storage/buckets/:bucketId/files') ->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') ->inject('mode') - ->action(function (string $bucketId, array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject, Authorization $authorization, string $mode) { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + ->action(function (string $bucketId, array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject, string $mode) { + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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); } $queries = Query::parseQueries($queries); @@ -838,7 +839,7 @@ App::get('/v1/storage/buckets/:bucketId/files') 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()) { @@ -848,13 +849,15 @@ App::get('/v1/storage/buckets/:bucketId/files') $cursor->setValue($cursorDocument); } + $filterQueries = Query::groupByType($queries)['filters']; + try { if ($fileSecurity && !$valid) { $files = $dbForProject->find('bucket_' . $bucket->getSequence(), $queries); - $total = $includeTotal ? $dbForProject->count('bucket_' . $bucket->getSequence(), $queries, APP_LIMIT_COUNT) : 0; + $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(), $queries, 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); @@ -893,28 +896,28 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId') ->param('fileId', '', new UID(), 'File ID.') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->inject('mode') - ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, Authorization $authorization, string $mode) { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, string $mode) { + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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()) { @@ -970,18 +973,17 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') ->inject('deviceForFiles') ->inject('deviceForLocal') ->inject('project') - ->inject('authorization') - ->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, ?string $token, Request $request, Response $response, Database $dbForProject, Document $resourceToken, Device $deviceForFiles, Device $deviceForLocal, Document $project, Authorization $authorization) { + ->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, ?string $token, Request $request, Response $response, Database $dbForProject, Document $resourceToken, Device $deviceForFiles, Device $deviceForLocal, Document $project) { if (!\extension_loaded('imagick')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing'); } /* @type Document $bucket */ - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -993,20 +995,21 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $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()) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } if ($file->isEmpty()) { @@ -1124,11 +1127,11 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; //Do not update transformedAt if it's a console user - if (!Auth::isPrivilegedUser($authorization->getRoles())) { + if (!Auth::isPrivilegedUser(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)); } } @@ -1168,16 +1171,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') ->inject('request') ->inject('response') ->inject('dbForProject') - ->inject('authorization') ->inject('mode') ->inject('resourceToken') ->inject('deviceForFiles') - ->action(function (string $bucketId, string $fileId, ?string $token, Request $request, Response $response, Database $dbForProject, Authorization $authorization, string $mode, Document $resourceToken, Device $deviceForFiles) { + ->action(function (string $bucketId, string $fileId, ?string $token, Request $request, Response $response, Database $dbForProject, string $mode, Document $resourceToken, Device $deviceForFiles) { /* @type Document $bucket */ - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -1185,20 +1187,21 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') $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()) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } if ($file->isEmpty()) { @@ -1332,13 +1335,12 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') ->inject('mode') ->inject('resourceToken') ->inject('deviceForFiles') - ->inject('authorization') - ->action(function (string $bucketId, string $fileId, ?string $token, Response $response, Request $request, Database $dbForProject, string $mode, Document $resourceToken, Device $deviceForFiles, Authorization $authorization) { + ->action(function (string $bucketId, string $fileId, ?string $token, Response $response, Request $request, Database $dbForProject, string $mode, Document $resourceToken, Device $deviceForFiles) { /* @type Document $bucket */ - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -1346,20 +1348,21 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $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()) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } if ($file->isEmpty()) { @@ -1488,14 +1491,13 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') ->inject('project') ->inject('mode') ->inject('deviceForFiles') - ->inject('authorization') - ->action(function (string $bucketId, string $fileId, string $jwt, Response $response, Request $request, Database $dbForProject, Database $dbForPlatform, Document $project, string $mode, Device $deviceForFiles, Authorization $authorization) { + ->action(function (string $bucketId, string $fileId, string $jwt, Response $response, Request $request, Database $dbForProject, Database $dbForPlatform, Document $project, string $mode, Device $deviceForFiles) { $decoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); try { $decoded = $decoder->decode($jwt); } catch (JWTException) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } if ( @@ -1503,21 +1505,21 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') $decoded['bucketId'] !== $bucketId || $decoded['fileId'] !== $fileId ) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + throw new Exception(Exception::USER_UNAUTHORIZED); } $isInternal = $decoded['internal'] ?? false; $dbForProject = $isInternal ? $dbForPlatform : $dbForProject; - $isAPIKey = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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); } @@ -1525,6 +1527,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') $mimes = Config::getParam('storage-mimes'); $path = $file->getAttribute('path', ''); + if (!$deviceForFiles->exists($path)) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in ' . $path); } @@ -1661,26 +1664,26 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') ->inject('user') ->inject('mode') ->inject('queueForEvents') - ->inject('authorization') - ->action(function (string $bucketId, string $fileId, ?string $name, ?array $permissions, Response $response, Database $dbForProject, Document $user, string $mode, Event $queueForEvents, Authorization $authorization) { + ->action(function (string $bucketId, string $fileId, ?string $name, ?array $permissions, Response $response, Database $dbForProject, Document $user, string $mode, Event $queueForEvents) { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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); @@ -1694,7 +1697,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') ]); // Users can only manage their own roles, API keys and Admin users can manage any - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles) && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { @@ -1707,7 +1710,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') $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) . ')'); } } @@ -1728,7 +1731,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') 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); @@ -1776,34 +1779,33 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') ->inject('mode') ->inject('deviceForFiles') ->inject('queueForDeletes') - ->inject('authorization') - ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, Event $queueForEvents, string $mode, Device $deviceForFiles, Delete $queueForDeletes, Authorization $authorization) { - $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + ->action(function (string $bucketId, string $fileId, Response $response, Database $dbForProject, Event $queueForEvents, string $mode, Device $deviceForFiles, Delete $queueForDeletes) { + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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 - $validFile = $authorization->isValid(new Input(Database::PERMISSION_DELETE, $file->getDelete())); - if ($fileSecurity && !$valid && !$validFile) { - throw new Exception(Exception::USER_UNAUTHORIZED, $authorization->getDescription()); + if ($fileSecurity && !$valid && !$validator->isValid($file->getDelete())) { + throw new Exception(Exception::USER_UNAUTHORIZED); } $deviceDeleted = false; @@ -1827,7 +1829,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') 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); @@ -1872,8 +1874,7 @@ App::get('/v1/storage/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) { + ->action(function (string $range, Response $response, Database $dbForProject) { $periods = Config::getParam('usage', []); $stats = $usage = []; @@ -1885,7 +1886,7 @@ App::get('/v1/storage/usage') ]; $total = []; - $authorization->skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) { + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) { foreach ($metrics as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), @@ -1963,8 +1964,7 @@ App::get('/v1/storage/:bucketId/usage') ->inject('project') ->inject('dbForProject') ->inject('getLogsDB') - ->inject('authorization') - ->action(function (string $bucketId, string $range, Response $response, Document $project, Database $dbForProject, callable $getLogsDB, Authorization $authorization) { + ->action(function (string $bucketId, string $range, Response $response, Document $project, Database $dbForProject, callable $getLogsDB) { $dbForLogs = call_user_func($getLogsDB, $project); $bucket = $dbForProject->getDocument('buckets', $bucketId); @@ -1982,7 +1982,7 @@ App::get('/v1/storage/:bucketId/usage') 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/app/controllers/api/teams.php b/app/controllers/api/teams.php index 4b8c543e5d..554ef6f4fe 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -84,17 +84,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 = Auth::isPrivilegedUser($authorization->getRoles()); - $isAppUser = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAppUser = Auth::isAppUser(Authorization::getRoles()); $teamId = $teamId == 'unique()' ? ID::unique() : $teamId; try { - $team = $authorization->skip(fn () => $dbForProject->createDocument('teams', new Document([ + $team = Authorization::skip(fn () => $dbForProject->createDocument('teams', new Document([ '$id' => $teamId, '$permissions' => [ Permission::read(Role::team($teamId)), @@ -490,7 +489,6 @@ App::post('/v1/teams/:teamId/memberships') ->inject('project') ->inject('user') ->inject('dbForProject') - ->inject('authorization') ->inject('locale') ->inject('queueForMails') ->inject('queueForMessaging') @@ -498,9 +496,9 @@ App::post('/v1/teams/:teamId/memberships') ->inject('timelimit') ->inject('queueForStatsUsage') ->inject('plan') - ->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) { - $isAppUser = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($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) { + $isAppUser = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); $url = htmlentities($url); if (empty($url)) { @@ -575,50 +573,53 @@ App::post('/v1/teams/:teamId/memberships') $emailCanonical = null; } + $userId = ID::unique(); + + $userDocument = new Document([ + '$id' => $userId, + '$permissions' => [ + Permission::read(Role::any()), + Permission::read(Role::user($userId)), + Permission::update(Role::user($userId)), + Permission::delete(Role::user($userId)), + ], + 'email' => empty($email) ? null : $email, + 'phone' => empty($phone) ? null : $phone, + 'emailVerification' => false, + 'status' => true, + // TODO: Set password empty? + 'password' => Auth::passwordHash(Auth::passwordGenerator(), Auth::DEFAULT_ALGO, Auth::DEFAULT_ALGO_OPTIONS), + 'hash' => Auth::DEFAULT_ALGO, + 'hashOptions' => Auth::DEFAULT_ALGO_OPTIONS, + /** + * Set the password update time to 0 for users created using + * team invite and OAuth to allow password updates without an + * old password + */ + 'passwordUpdate' => null, + 'registration' => DateTime::now(), + 'reset' => false, + 'name' => $name, + 'prefs' => new \stdClass(), + 'sessions' => null, + 'tokens' => null, + 'memberships' => null, + 'search' => implode(' ', [$userId, $email, $name]), + 'emailCanonical' => $emailCanonical?->getCanonical(), + 'emailIsCanonical' => $emailCanonical?->isCanonicalSupported(), + 'emailIsCorporate' => $emailCanonical?->isCorporate(), + 'emailIsDisposable' => $emailCanonical?->isDisposable(), + 'emailIsFree' => $emailCanonical?->isFree(), + ]); + try { - $userId = ID::unique(); - $invitee = $authorization->skip(fn () => $dbForProject->createDocument('users', new Document([ - '$id' => $userId, - '$permissions' => [ - Permission::read(Role::any()), - Permission::read(Role::user($userId)), - Permission::update(Role::user($userId)), - Permission::delete(Role::user($userId)), - ], - 'email' => empty($email) ? null : $email, - 'phone' => empty($phone) ? null : $phone, - 'emailVerification' => false, - 'status' => true, - // TODO: Set password empty? - 'password' => Auth::passwordHash(Auth::passwordGenerator(), Auth::DEFAULT_ALGO, Auth::DEFAULT_ALGO_OPTIONS), - 'hash' => Auth::DEFAULT_ALGO, - 'hashOptions' => Auth::DEFAULT_ALGO_OPTIONS, - /** - * Set the password update time to 0 for users created using - * team invite and OAuth to allow password updates without an - * old password - */ - 'passwordUpdate' => null, - 'registration' => DateTime::now(), - 'reset' => false, - 'name' => $name, - 'prefs' => new \stdClass(), - 'sessions' => null, - 'tokens' => null, - 'memberships' => null, - 'search' => implode(' ', [$userId, $email, $name]), - 'emailCanonical' => $emailCanonical?->getCanonical(), - 'emailIsCanonical' => $emailCanonical?->isCanonicalSupported(), - 'emailIsCorporate' => $emailCanonical?->isCorporate(), - 'emailIsDisposable' => $emailCanonical?->isDisposable(), - 'emailIsFree' => $emailCanonical?->isFree(), - ]))); + $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'); @@ -654,11 +655,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) { @@ -671,7 +672,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); @@ -858,8 +859,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()) { @@ -929,7 +929,7 @@ App::get('/v1/teams/:teamId/memberships') 'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true, ]; - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); @@ -1000,8 +1000,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); @@ -1021,7 +1020,7 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') 'mfa' => $project->getAttribute('auths', [])['membershipsMfa'] ?? true, ]; - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); @@ -1100,9 +1099,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()) { @@ -1119,9 +1117,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') throw new Exception(Exception::USER_NOT_FOUND); } - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); - $isAppUser = Auth::isAppUser($authorization->getRoles()); - $isOwner = $authorization->hasRole('team:' . $team->getId() . '/owner'); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAppUser = Auth::isAppUser(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 @@ -1202,11 +1200,10 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->inject('response') ->inject('user') ->inject('dbForProject') - ->inject('authorization') ->inject('project') ->inject('geodb') ->inject('queueForEvents') - ->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Authorization $authorization, Document $project, Reader $geodb, Event $queueForEvents) { + ->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Reader $geodb, Event $queueForEvents) { $protocol = $request->getProtocol(); $membership = $dbForProject->getDocument('memberships', $membershipId); @@ -1215,7 +1212,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); @@ -1251,11 +1248,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()); @@ -1283,7 +1280,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()); if (!Config::getParam('domainVerification')) { $response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); @@ -1316,7 +1313,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()) @@ -1360,9 +1357,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); @@ -1420,7 +1416,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 3fd570b03f..a8570c3079 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -2647,8 +2647,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 = []; @@ -2658,7 +2658,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 4703e3a296..2ac6cd0b26 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -72,7 +72,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) { +$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, Request $request) { $errors = []; foreach ($repositories as $repository) { try { @@ -83,12 +83,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(); @@ -137,7 +137,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'), @@ -176,7 +176,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 { @@ -187,7 +187,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))), @@ -208,7 +208,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'), @@ -247,7 +247,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)); } } } @@ -290,7 +290,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()), @@ -330,7 +330,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(); @@ -340,7 +340,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(), @@ -373,7 +373,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(), @@ -404,7 +404,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(), @@ -456,7 +456,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', '')) : ''; @@ -468,7 +468,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)); } } } @@ -1462,11 +1462,10 @@ App::post('/v1/vcs/github/events') ->inject('request') ->inject('response') ->inject('dbForPlatform') - ->inject('authorization') ->inject('getProjectDB') ->inject('queueForBuilds') ->action( - function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, Authorization $authorization, callable $getProjectDB, Build $queueForBuilds) use ($createGitDeployments) { + function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds) use ($createGitDeployments) { $payload = $request->getRawPayload(); $signatureRemote = $request->getHeader('x-hub-signature-256', ''); $signatureLocal = System::getEnv('_APP_VCS_GITHUB_WEBHOOK_SECRET', ''); @@ -1502,14 +1501,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); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthorName, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $queueForBuilds, $getProjectDB, $request); } } elseif ($event == $github::EVENT_INSTALLATION) { if ($parsedPayload["action"] == "deleted") { @@ -1522,16 +1521,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) { @@ -1560,12 +1559,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); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForPlatform, $queueForBuilds, $getProjectDB, $request); } elseif ($parsedPayload["action"] == "closed") { // Allowed external contributions cleanup @@ -1574,7 +1573,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') ])); @@ -1585,7 +1584,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)); } } } @@ -1773,17 +1772,16 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor ->inject('response') ->inject('project') ->inject('dbForPlatform') - ->inject('authorization') ->inject('getProjectDB') ->inject('queueForBuilds') - ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Request $request, Response $response, Document $project, Database $dbForPlatform, Authorization $authorization, callable $getProjectDB, Build $queueForBuilds) use ($createGitDeployments) { + ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Request $request, Response $response, Document $project, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds) use ($createGitDeployments) { $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); } - $repository = $authorization->skip(fn () => $dbForPlatform->getDocument('repositories', $repositoryId, [ + $repository = Authorization::skip(fn () => $dbForPlatform->getDocument('repositories', $repositoryId, [ Query::equal('projectInternalId', [$project->getSequence()]) ])); @@ -1800,7 +1798,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'); @@ -1824,7 +1822,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor $providerBranch = \explode(':', $pullRequestResponse['head']['label'])[1] ?? ''; $providerCommitHash = $pullRequestResponse['head']['sha'] ?? ''; - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, '', '', '', '', $providerCommitHash, '', '', '', '', $providerPullRequestId, true, $dbForPlatform, $authorization, $queueForBuilds, $getProjectDB, $request); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerCommitHash, $providerPullRequestId, true, $dbForPlatform, $queueForBuilds, $getProjectDB, $request); $response->noContent(); }); diff --git a/app/controllers/general.php b/app/controllers/general.php index 6790d3c67d..e0435cd499 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -57,7 +57,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, 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, string $previewHostname, ?Key $apiKey) { $host = $request->getHostname() ?? ''; if (!empty($previewHostname)) { @@ -66,9 +66,9 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw // TODO: @christyjacob remove once we migrate the rules in 1.7.x if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { - $rule = $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($host))); + $rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($host))); } else { - $rule = $authorization->skip( + $rule = Authorization::skip( fn () => $dbForPlatform->find('rules', [ Query::equal('domain', [$host]), Query::limit(1) @@ -109,7 +109,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) ); @@ -117,7 +117,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)); } /** @@ -156,7 +156,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 @@ -170,15 +170,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') { @@ -197,8 +197,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'); @@ -240,7 +240,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; } @@ -253,7 +253,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'); @@ -864,8 +864,7 @@ App::init() ->inject('apiKey') ->inject('httpReferrer') ->inject('httpReferrerSafe') - ->inject('authorization') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $platforms, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, Executor $executor, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, string $httpReferrer, string $httpReferrerSafe, Authorization $authorization) { + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $platforms, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, Executor $executor, callable $isResourceBlocked, string $previewHostname, Document $devKey, ?Key $apiKey, string $httpReferrer, string $httpReferrerSafe) { /* * Appwrite Router */ @@ -873,7 +872,7 @@ App::init() $mainDomain = System::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain || !empty($previewHostname)) { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $authorization, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -924,7 +923,7 @@ App::init() } elseif (str_starts_with($request->getURI(), '/.well-known/acme-challenge')) { Console::warning('Skipping SSL certificates generation on ACME challenge.'); } else { - $authorization->disable(); + Authorization::disable(); $envDomain = System::getEnv('_APP_DOMAIN', ''); $mainDomain = null; @@ -994,7 +993,7 @@ App::init() } $domains[$domain->get()] = true; - $authorization->reset(); // ensure authorization is re-enabled + Authorization::reset(); // ensure authorization is re-enabled } Config::setParam('domains', $domains); } @@ -1130,8 +1129,7 @@ App::options() ->inject('project') ->inject('devKey') ->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, string $previewHostname, Document $project, Document $devKey, ?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, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey) { /* * Appwrite Router */ @@ -1139,7 +1137,7 @@ App::options() $mainDomain = System::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain if ($host !== $mainDomain || !empty($previewHostname)) { - if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $authorization, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1180,8 +1178,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); @@ -1263,7 +1260,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 (!Auth::isPrivilegedUser($authorization->getRoles())) { + if (!Auth::isPrivilegedUser(Authorization::getRoles())) { $fileSize = 0; $file = $request->getFiles('file'); if (!empty($file)) { @@ -1325,7 +1322,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)) { @@ -1448,8 +1445,7 @@ App::get('/robots.txt') ->inject('isResourceBlocked') ->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, 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, string $previewHostname, ?Key $apiKey) { $host = $request->getHostname() ?? ''; $consoleDomain = System::getEnv('_APP_CONSOLE_DOMAIN', ''); $mainDomain = System::getEnv('_APP_DOMAIN', ''); @@ -1458,7 +1454,7 @@ App::get('/robots.txt') $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, $previewHostname, $authorization, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1483,8 +1479,7 @@ App::get('/humans.txt') ->inject('isResourceBlocked') ->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, 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, string $previewHostname, ?Key $apiKey) { $host = $request->getHostname() ?? ''; $consoleDomain = System::getEnv('_APP_CONSOLE_DOMAIN', ''); $mainDomain = System::getEnv('_APP_DOMAIN', ''); @@ -1493,7 +1488,7 @@ App::get('/humans.txt') $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, $previewHostname, $authorization, $apiKey)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $log, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { $utopia->getRoute()?->label('router', true); } } @@ -1577,8 +1572,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); } @@ -1590,7 +1584,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 911c8b110d..6a146f2bdc 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -29,7 +29,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; @@ -233,8 +232,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, Document $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey) { $route = $utopia->getRoute(); if (System::getEnv('_APP_EDITION', 'self-hosted') === 'self-hosted' && str_starts_with($route->getPath(), '/v1/backups')) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Database Backups are available on Appwrite Cloud'); @@ -266,7 +264,7 @@ App::init() if ($apiKey->getRole() === Auth::USER_ROLE_APPS) { // Disable authorization checks for API keys - $authorization->setDefaultStatus(false); + Authorization::setDefaultStatus(false); $user = new Document([ '$id' => '', @@ -339,14 +337,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 (Auth::getRoles($user, $authorization) as $authRole) { - $authorization->addRole($authRole); + Authorization::setRole($role); + foreach (Auth::getRoles($user) as $authRole) { + Authorization::setRole($authRole); } // Update project last activity @@ -354,7 +352,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)); } } @@ -389,7 +387,7 @@ App::init() if ( array_key_exists($namespace, $project->getAttribute('services', [])) && !$project->getAttribute('services', [])[$namespace] - && !(Auth::isPrivilegedUser($authorization->getRoles()) || Auth::isAppUser($authorization->getRoles())) + && !(Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles())) ) { throw new Exception(Exception::GENERAL_SERVICE_DISABLED); } @@ -449,15 +447,14 @@ App::init() ->inject('plan') ->inject('devKey') ->inject('telemetry') - ->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, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, 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, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry) use ($usageDatabaseListener, $eventDatabaseListener) { $route = $utopia->getRoute(); if ( array_key_exists('rest', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['rest'] - && !(Auth::isPrivilegedUser($authorization->getRoles()) || Auth::isAppUser($authorization->getRoles())) + && !(Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -487,7 +484,7 @@ App::init() $closestLimit = null; - $roles = $authorization->getRoles(); + $roles = Authorization::getRoles(); $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); @@ -587,10 +584,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 && !Auth::isPrivilegedUser($authorization->getRoles()); + $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !Auth::isPrivilegedUser(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()) ); @@ -607,10 +604,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 = Auth::isPrivilegedUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAppUser && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -621,7 +618,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); } @@ -632,7 +630,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()) { @@ -643,11 +641,11 @@ App::init() throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } //Do not update transformedAt if it's a console user - if (!Auth::isPrivilegedUser($authorization->getRoles())) { + if (!Auth::isPrivilegedUser(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)); } } } @@ -743,8 +741,7 @@ App::shutdown() ->inject('queueForWebhooks') ->inject('queueForRealtime') ->inject('dbForProject') - ->inject('authorization') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $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) use ($parseLabel) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $queueForEvents, Audit $queueForAudits, StatsUsage $queueForStatsUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject) use ($parseLabel) { $responsePayload = $response->getPayload(); @@ -870,11 +867,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, @@ -884,7 +881,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']); } @@ -896,7 +893,7 @@ App::shutdown() } if ($project->getId() !== 'console') { - if (!Auth::isPrivilegedUser($authorization->getRoles())) { + if (!Auth::isPrivilegedUser(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 0e3c89c19a..ecabc641ec 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 = Auth::isPrivilegedUser($authorization->getRoles()); - $isAppUser = Auth::isAppUser($authorization->getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $isAppUser = Auth::isAppUser(Authorization::getRoles()); if ($isAppUser || $isPrivilegedUser) { // Skip limits for app and console devs return; diff --git a/app/http.php b/app/http.php index 568571fad2..1bd3e97e69 100644 --- a/app/http.php +++ b/app/http.php @@ -25,6 +25,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; @@ -258,9 +259,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(Audit::COLLECTION)->isEmpty()) { $audit = new Audit($dbForPlatform); $audit->setup(); @@ -319,9 +318,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', @@ -336,7 +335,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'] ?? []; @@ -364,7 +363,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)); } }); @@ -455,12 +454,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) { @@ -502,7 +497,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); @@ -561,7 +556,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; @@ -578,8 +573,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 c065bf0d82..c4cfd1ac81 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( @@ -175,7 +176,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), ])); @@ -188,7 +189,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), @@ -202,7 +203,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), @@ -216,7 +217,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), @@ -230,7 +231,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), @@ -330,7 +331,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) @@ -344,7 +345,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 8b111e950c..0892da8a82 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -152,7 +152,7 @@ App::setResource('queueForMigrations', function (Publisher $publisher) { App::setResource('queueForStatsResources', function (Publisher $publisher) { return new StatsResources($publisher); }, ['publisher']); -App::setResource('platforms', function (Request $request, Document $console, Document $project, Database $dbForPlatform, Authorization $authorization) { +App::setResource('platforms', function (Request $request, Document $console, Document $project, Database $dbForPlatform) { $console->setAttribute('platforms', [ // Always allow current host '$collection' => ID::custom('platforms'), 'name' => 'Current Host', @@ -200,9 +200,9 @@ App::setResource('platforms', function (Request $request, Document $console, Doc // Safe if rule with same project ID exists if (!empty($origin)) { if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { - $rule = $authorization->skip(fn () => $dbForPlatform->getDocument('rules', md5($origin ?? ''))); + $rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($origin ?? ''))); } else { - $rule = $authorization->skip( + $rule = Authorization::skip( fn () => $dbForPlatform->find('rules', [ Query::equal('domain', [$origin]), Query::limit(1) @@ -224,18 +224,17 @@ App::setResource('platforms', function (Request $request, Document $console, Doc ...$console->getAttribute('platforms', []), ...$project->getAttribute('platforms', []), ]; -}, ['request', 'console', 'project', 'dbForPlatform', 'authorization']); +}, ['request', 'console', 'project', 'dbForPlatform']); -App::setResource('user', function ($mode, $project, $console, $request, $response, $dbForProject, $dbForPlatform, $authorization) { +App::setResource('user', function ($mode, $project, $console, $request, $response, $dbForProject, $dbForPlatform) { /** @var Appwrite\Utopia\Request $request */ /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Document $project */ /** @var Utopia\Database\Database $dbForProject */ /** @var Utopia\Database\Database $dbForPlatform */ - /** @var Utopia\Database\Authorization $authorization */ /** @var string $mode */ - $authorization->setDefaultStatus(true); + Authorization::setDefaultStatus(true); Auth::setCookieName('a_session_' . $project->getId()); @@ -299,7 +298,7 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons // 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([]); // } @@ -337,9 +336,9 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons $dbForPlatform->setMetadata('user', $user->getId()); return $user; -}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform', 'authorization']); +}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform']); -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 */ @@ -350,10 +349,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 (Document $user) { if ($user->isEmpty()) { @@ -380,11 +379,7 @@ 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; } @@ -400,7 +395,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) @@ -421,15 +415,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') @@ -437,12 +429,12 @@ App::setResource('dbForPlatform', function (Group $pools, Cache $cache, Authoriz ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); 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; } @@ -454,9 +446,8 @@ 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) @@ -490,12 +481,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; @@ -505,7 +496,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) @@ -518,7 +508,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache, Authorizatio return $database; }; -}, ['pools', 'cache', 'authorization']); +}, ['pools', 'cache']); App::setResource('telemetry', fn () => new NoTelemetry()); @@ -712,7 +702,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'] ?? []); @@ -722,8 +712,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), ])); @@ -797,7 +787,7 @@ App::setResource('schema', function ($utopia, $dbForProject, $authorization) { $urls, $params, ); -}, ['utopia', 'dbForProject', 'authorization']); +}, ['utopia', 'dbForProject']); App::setResource('contributors', function () { $path = 'app/config/contributors.json'; @@ -843,7 +833,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 @@ -862,7 +852,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()); } @@ -879,14 +869,14 @@ 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', ''); @@ -896,7 +886,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', ''); @@ -905,7 +895,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; } } @@ -914,14 +904,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', @@ -959,7 +949,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 @@ -976,7 +966,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([]); @@ -994,7 +984,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')); @@ -1005,7 +995,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([ @@ -1020,7 +1010,7 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request, A }; } return new Document([]); -}, ['project', 'dbForProject', 'request', 'authorization']); +}, ['project', 'dbForProject', 'request']); App::setResource('httpReferrer', function (Request $request): string { $referrer = $request->getReferer(); @@ -1053,6 +1043,6 @@ App::setResource('httpReferrerSafe', function (Request $request, string $httpRef return $referrer; }, ['request', 'httpReferrer', 'platforms', 'dbForPlatform', 'project', 'utopia']); -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 75aa625348..e18ab8e10d 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -28,6 +28,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; @@ -298,7 +299,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})..."); @@ -328,7 +329,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"); } @@ -359,7 +360,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)), ])); @@ -453,11 +454,12 @@ $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); $user = $database->getDocument('users', $userId); - $roles = Auth::getRoles($user, $database->getAuthorization()); + + $roles = Auth::getRoles($user); $channels = $realtime->connections[$connection]['channels']; $realtime->unsubscribe($connection); @@ -513,7 +515,6 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, try { /** @var Document $project */ $project = $app->getResource('project'); - $authorization = $app->getResource('authorization'); /* * Project Check @@ -525,7 +526,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, if ( array_key_exists('realtime', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['realtime'] - && !(Auth::isPrivilegedUser($authorization->getRoles()) || Auth::isAppUser($authorization->getRoles())) + && !(Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -562,7 +563,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, throw new Exception(Exception::REALTIME_POLICY_VIOLATION, $originValidator->getDescription()); } - $roles = Auth::getRoles($user, $authorization); + $roles = Auth::getRoles($user); $channels = Realtime::convertChannels($request->getQuery('channels', []), $user->getId()); @@ -636,8 +637,8 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re $database = getConsoleDB(); if ($projectId !== 'console') { - $project = $database->getAuthorization()->skip(fn () => $database->getDocument('projects', $projectId)); - $database = getProjectDB($project, $database->getAuthorization()); + $project = Authorization::skip(fn () => $database->getDocument('projects', $projectId)); + $database = getProjectDB($project); } else { $project = null; } @@ -691,7 +692,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re throw new Exception(Exception::REALTIME_MESSAGE_FORMAT_INVALID, 'Session is not valid.'); } - $roles = Auth::getRoles($user, $database->getAuthorization()); + $roles = Auth::getRoles($user); $channels = Realtime::convertChannels(array_flip($realtime->connections[$connection]['channels']), $user->getId()); $realtime->subscribe($realtime->connections[$connection]['projectId'], $connection, $roles, $channels); diff --git a/app/worker.php b/app/worker.php index ef04ffec05..60f44ab33f 100644 --- a/app/worker.php +++ b/app/worker.php @@ -45,28 +45,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'); - + $dbForPlatform->setNamespace('_console'); return $dbForPlatform; -}, ['cache', 'register', 'authorization']); +}, ['cache', 'register']); Server::setResource('project', function (Message $message, Database $dbForPlatform) { $payload = $message->getPayload() ?? []; @@ -79,7 +70,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; } @@ -110,17 +101,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; } @@ -134,7 +123,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)) { @@ -171,17 +160,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; @@ -191,7 +178,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) @@ -204,7 +190,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 @@ -492,8 +478,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) { @@ -509,7 +494,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 1cff497d08..62abce9ca2 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "utopia-php/cache": "0.13.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "4.*", + "utopia-php/database": "3.*", "utopia-php/detector": "0.2.*", "utopia-php/domains": "0.9.*", "utopia-php/emails": "0.6.*", diff --git a/composer.lock b/composer.lock index 163bdb5bd9..b29b19c3bf 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": "3b502f78f5e31f2ea7b4c69e3301283a", + "content-hash": "ad28b7155175986191bd19bbcd13d623", "packages": [ { "name": "adhocore/jwt", @@ -3551,21 +3551,21 @@ }, { "name": "utopia-php/audit", - "version": "1.0.3", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "15656acfddb9d6f03c395b73673fc66c793c10a5" + "reference": "8c17065c2473d4ca799f65585ca74eb53e1be211" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/15656acfddb9d6f03c395b73673fc66c793c10a5", - "reference": "15656acfddb9d6f03c395b73673fc66c793c10a5", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/8c17065c2473d4ca799f65585ca74eb53e1be211", + "reference": "8c17065c2473d4ca799f65585ca74eb53e1be211", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "4.*" + "utopia-php/database": "*" }, "require-dev": { "laravel/pint": "1.*", @@ -3592,9 +3592,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/1.0.3" + "source": "https://github.com/utopia-php/audit/tree/1.0.2" }, - "time": "2025-11-04T11:27:42+00:00" + "time": "2025-10-20T07:14:26+00:00" }, { "name": "utopia-php/cache", @@ -3844,16 +3844,16 @@ }, { "name": "utopia-php/database", - "version": "4.3.0", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "fe7a1326ad623609e65587fe8c01a630a7075fee" + "reference": "e10b4faa4f3a3ef30a5f6d76acdb605469924aec" }, "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/e10b4faa4f3a3ef30a5f6d76acdb605469924aec", + "reference": "e10b4faa4f3a3ef30a5f6d76acdb605469924aec", "shasum": "" }, "require": { @@ -3896,9 +3896,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/3.4.0" }, - "time": "2025-11-14T03:43:10+00:00" + "time": "2025-11-13T06:34:20+00:00" }, { "name": "utopia-php/detector", @@ -4460,16 +4460,16 @@ }, { "name": "utopia-php/migration", - "version": "1.3.4", + "version": "1.3.3", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "81e1be6ff3257d4768aa7483cf64628836244a09" + "reference": "731b3a963c58c30e0b2368695d57a7e8fcb7455c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/81e1be6ff3257d4768aa7483cf64628836244a09", - "reference": "81e1be6ff3257d4768aa7483cf64628836244a09", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/731b3a963c58c30e0b2368695d57a7e8fcb7455c", + "reference": "731b3a963c58c30e0b2368695d57a7e8fcb7455c", "shasum": "" }, "require": { @@ -4478,7 +4478,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.*" }, @@ -4509,9 +4509,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/1.3.4" + "source": "https://github.com/utopia-php/migration/tree/1.3.3" }, - "time": "2025-11-04T11:28:50+00:00" + "time": "2025-10-28T04:02:08+00:00" }, { "name": "utopia-php/mongo", diff --git a/src/Appwrite/Auth/Auth.php b/src/Appwrite/Auth/Auth.php index b6676a2843..9af5045fa4 100644 --- a/src/Appwrite/Auth/Auth.php +++ b/src/Appwrite/Auth/Auth.php @@ -453,11 +453,11 @@ class Auth * @param Document $user * @return array */ - public static function getRoles(Document $user, Authorization $authorization): array + public static function getRoles(Document $user): array { $roles = []; - if (!self::isPrivilegedUser($authorization->getRoles()) && !self::isAppUser($authorization->getRoles())) { + if (!self::isPrivilegedUser(Authorization::getRoles()) && !self::isAppUser(Authorization::getRoles())) { if ($user->getId()) { $roles[] = Role::user($user->getId())->toString(); $roles[] = Role::users()->toString(); 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 4d2db6a3dc..588b193df4 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -99,6 +99,8 @@ abstract class Migration public function __construct() { + Authorization::disable(); + Authorization::setDefaultStatus(false); $this->collections = Config::getParam('collections', []); @@ -126,7 +128,6 @@ abstract class Migration Document $project, Database $dbForProject, Database $dbForPlatform, - Authorization $authorization, ?callable $getProjectDB = null ): self { $this->project = $project; @@ -134,9 +135,6 @@ 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 8ff5d88dd4..a538eb1497 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -142,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', ''); @@ -238,7 +238,7 @@ class Base extends Action // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -264,7 +264,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(), @@ -301,7 +301,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(), diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php index a0f8e9421e..b67a42adb1 100644 --- a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -59,7 +59,6 @@ class Get extends Action ->param('type', '', new WhiteList(['rules']), 'Resource type.') ->inject('response') ->inject('dbForPlatform') - ->inject('authorization') ->callback($this->action(...)); } @@ -67,8 +66,7 @@ class Get extends Action string $value, string $type, Response $response, - Database $dbForPlatform, - Authorization $authorization + Database $dbForPlatform ) { if ($type === 'rules') { $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); @@ -126,7 +124,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 6c5305f299..48124e2a11 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()); } - $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); @@ -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); 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 4f233fcdb4..8dfe80a390 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 27a3622fe2..ddb01ff011 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 d96314855c..d0f45dc664 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 bdf38a5087..1a30a09867 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 07ab604a5a..eb51044323 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); } 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 eed105e583..9f4c38d490 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 d9cbb5ba80..59a0490e6f 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 fb82dfd478..d2ccf9f972 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 31984d5f43..560107dd38 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 6cd158631f..f48348c192 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 6d7d22caf8..99ac992b9e 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 d31b17667e..91fa3582f7 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); } 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 9c5e3707d5..af3ed99bdf 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 2ee0f1a35b..a757ed47d1 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 99492c6950..5e147c771d 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 419f09a4b3..6d3858992b 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 7a92b3e13d..f691fc29cf 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 904209443f..8ef2f96ec2 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 9aff7cba34..aae715ba1e 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 55cadc4ca8..62f35ad2a7 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 bc3dd75ace..6fbbd46d2c 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 1dcca49d99..dba83d44d5 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 30c49911b0..6fc27a9836 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,15 @@ 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; $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); } @@ -151,7 +150,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 8623f7cb17..f9f1d6f3ab 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 0712b9f2e5..88cb161505 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 096481198c..6687178cb1 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 31b012754d..2d3b0c6168 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 46f2ec3acd..ebaea9e61d 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 be61b260b3..c2af3ac945 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -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); } 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 93812585ea..922cc45428 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Create.php @@ -78,13 +78,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, 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); 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 67f53fa33a..d124a47289 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); } 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 14b09777a8..08eea88e19 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 158a44c1b3..fb5925c291 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 = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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); } - $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()); } @@ -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 9045954789..5172890046 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 = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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); } - $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()); } @@ -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 ec3db59668..1320a0c9bc 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 = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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); } - $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()); } @@ -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); @@ -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 93ad7dc2a8..194bf27816 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 = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { 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() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException()); @@ -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); @@ -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 fa89d5fa32..c92a487697 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 = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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); } - $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()); @@ -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 68fd41221d..241b0c4ede 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 @@ -73,13 +73,12 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $documentId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): 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); } 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 0aca4a08c3..ecdbc738a1 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 = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { 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() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception($this->getParentNotFoundException()); @@ -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); @@ -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 5ec455b947..7901865b62 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 = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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); } - $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()); } @@ -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); @@ -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 a5a3ac0eb4..630170a031 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 = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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); } - $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()); } @@ -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 725b53ff9e..89739570c7 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); 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 6afc29a265..9fb438d577 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); 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 89d79ef353..2bccfdfb52 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); 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 27e0767f88..3d118d1922 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); 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 d6e59dc4fa..88b3a32e0b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -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); @@ -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 f193c15299..b202120bad 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 @@ -72,13 +72,12 @@ class XList extends Action ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->inject('authorization') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject, Locale $locale, Reader $geodb): 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); @@ -116,9 +115,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'], @@ -126,20 +125,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 c26a68c068..7575c9803b 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); } 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 beca779bf6..9cf7b85267 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 11b60e35a7..286e48420a 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); 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 41d3f3022a..c4c5bf8b51 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 98a0708f66..bd94c1c7eb 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 = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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); @@ -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); } $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); @@ -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 ec5f0e4c04..899c2b3eaf 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 = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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); @@ -138,12 +137,12 @@ class Update extends Action $databaseOperations = []; try { - $dbForProject->withTransaction(function () use ($dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, $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, $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), @@ -166,7 +165,7 @@ class Update extends Action } if (!isset($collections[$collectionId])) { - $collections[$collectionId] = $authorization->skip( + $collections[$collectionId] = Authorization::skip( fn () => $dbForProject->getCollection($collectionId) ); } @@ -231,7 +230,7 @@ class Update extends Action } } - $transaction = $authorization->skip(fn () => $dbForProject->updateDocument( + $transaction = Authorization::skip(fn () => $dbForProject->updateDocument( 'transactions', $transactionId, new Document(['status' => 'committed']) @@ -243,32 +242,32 @@ class Update extends Action }); } 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); } 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()); @@ -296,11 +295,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]) ])); @@ -392,7 +391,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 7668ad0a79..c9de9d5217 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 44674b68ca..d9dfc15ca8 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 b3643b0e18..3b83e71c12 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 5a5970c3bb..69d6bd2b4b 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 08bb04b4e5..255abf00bf 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 62152453fe..26f4ffa898 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 050e031591..58ea459d0f 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 c58257c8e1..0105345555 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 cc2c109f6a..8ab8019626 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 bdb32de1ab..968c84c56b 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 acc82f406b..21e855d912 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 f53cd711e0..6a479ea266 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 0e7e079a02..c20ef58a39 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 804ebc6e14..08912ebb56 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 e600c0a349..9df9f573a2 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 1980234536..eb9230f48f 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 cbf574010c..6c707f1655 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 469fb6851f..4aa173707b 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 b6a1336c00..fd7d200eb3 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 715348e1f4..b8ae563def 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 c0c4c10689..8b8dd7b66c 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 38c9eaf284..e0a2cf32cd 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 12d6b95a72..c49351fc59 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 84c2123f4d..cccc61beaa 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 b87fc3d33a..5953d600f8 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 02a04a2da0..8d37c9011b 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 9270d7d7c7..43083616ba 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 051e8cbbbb..3fd6f1e463 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 8854e701ef..64dfdfbf69 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 950d38f8a7..1e0b641b32 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php @@ -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 5b598b1a12..68d3e772ec 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Create.php @@ -63,7 +63,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 79b9e7beef..de068d5b29 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 e264ec0411..be6ec5d9e7 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 165f014320..3802ee32b8 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 @@ -2,8 +2,6 @@ namespace Appwrite\Platform\Modules\Databases\Http\TablesDB\Tables\Indexes; -use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Event; use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Indexes\Create as IndexCreate; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; @@ -11,7 +9,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,15 +66,6 @@ class Create extends IndexCreate ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('authorization') ->callback($this->action(...)); } - - public function action(string $databaseId, string $tableId, string $key, string $type, array $columns, array $orders, array $lengths, UtopiaResponse $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Authorization $authorization): void - { - // Map TablesDB parameters to Collections API parameters - // tableId -> collectionId - // columns -> attributes - parent::action($databaseId, $tableId, $key, $type, $columns, $orders, $lengths, $response, $dbForProject, $queueForDatabase, $queueForEvents, $authorization); - } } 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 cb552a086c..57ab466ee8 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 3c01f1b64d..271d842631 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 a6206f06dd..0ea52eaf1b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php @@ -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 f9111287c3..0680649544 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') ->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 e3bf1f9eef..856f17ed10 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 4fe7c2f9f6..d657e5596b 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 d76a907186..4c8b599c8c 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 ebc751a8e6..f355ebb9e6 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 5117e77ea9..5f1efa2953 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') ->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 6265451b57..8f3786b8cf 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 105750ddbd..d4cd61cfdd 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 9486a8abeb..cd6141a6b4 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 aea590168d..a4bfb5bf23 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 eafb291037..5e8fcfc3c8 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 1c6f0f95ca..bc79b86ca3 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 2e3b73e395..5a98f22f37 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 250c9e0bc4..4d55af93a4 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/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index 593c3dde55..a699c0f097 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -27,7 +27,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; @@ -95,7 +94,6 @@ class Create extends Base ->inject('queueForFunctions') ->inject('geodb') ->inject('executor') - ->inject('authorization') ->callback($this->action(...)); } @@ -117,8 +115,7 @@ class Create extends Base StatsUsage $queueForStatsUsage, Func $queueForFunctions, Reader $geodb, - Executor $executor, - Authorization $authorization + Executor $executor ) { $async = \strval($async) === 'true' || \strval($async) === '1'; @@ -156,10 +153,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 = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); @@ -175,7 +172,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'); @@ -189,8 +186,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 @@ -288,7 +287,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) @@ -329,7 +328,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 @@ -482,7 +481,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 ccf345dbb5..666cb8310c 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 69c4080f8a..42d78f8ca8 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 = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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 52562aadf8..3d5ec06ace 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 = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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 182f39e274..ec2a4baac5 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, @@ -367,7 +365,7 @@ class Create extends Base // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? 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 6c9c9c3c6f..72d5589252 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 b913848a13..8846329d27 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 d182bb67ea..318c2a2032 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 ae74bfa98a..815d364dad 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 dcb80e4c8c..35f9618edb 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 959e2608d4..95fd235e4b 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 0a7a35d2e8..22b302f26e 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -27,6 +27,7 @@ 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; @@ -924,11 +925,11 @@ class Builds extends Action ->trigger(); try { - $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()]), - ]); + ])); if ($rule->isEmpty()) { throw new \Exception("Rule for build not found"); @@ -938,7 +939,7 @@ class Builds extends Action $client->setTimeout(\intval($resource->getAttribute('timeout', '15'))); $client->addHeader('content-type', FetchClient::CONTENT_TYPE_APPLICATION_JSON); - $bucket = $dbForPlatform->getDocument('buckets', 'screenshots'); + $bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); $configs = [ 'screenshotLight' => [ @@ -1060,7 +1061,7 @@ class Builds extends Action 'metadata' => ['content_type' => $mimeType], ]); - $dbForPlatform->createDocument('bucket_' . $bucket->getSequence(), $file); + Authorization::skip(fn () => $dbForPlatform->createDocument('bucket_' . $bucket->getSequence(), $file)); $deployment->setAttribute($key, $fileId); } @@ -1283,7 +1284,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'); @@ -1490,6 +1491,7 @@ class Builds extends Action * @return void * @throws Structure * @throws \Utopia\Database\Exception + * @throws Authorization * @throws Conflict * @throws Restricted */ @@ -1577,11 +1579,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 107c7b1389..aa622d8d84 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'; @@ -277,7 +275,7 @@ class Create extends Action // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); - $authorization->skip( + Authorization::skip( fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), @@ -342,7 +340,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(), 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 21f86aea35..065dd13e88 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); @@ -148,7 +146,7 @@ class Create extends Action // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? 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 4da3e9b34f..dc7d4c4ace 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 @@ -191,7 +188,7 @@ class Create extends Base // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? 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/Vcs/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php index 09dc4a1618..ddad5d793a 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 e3cab865a9..bb6bd4f632 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/Tokens/Http/Tokens/Buckets/Files/Action.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php index e05418b90d..5708f1b83b 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\Auth\Auth; use Appwrite\Extend\Exception; 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 = Auth::isAppUser($authorization->getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser($authorization->getRoles()); + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(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 4760fef97f..e4de4c1380 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 33a01346a8..e9a0e1d333 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -9,6 +9,7 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception; 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 +62,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 87d4858351..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; /** @@ -44,7 +45,6 @@ class StatsResources extends Action ->inject('dbForPlatform') ->inject('logError') ->inject('queueForStatsResources') - ->inject('authorization') ->callback($this->action(...)); } @@ -61,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/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 808adabb24..7df2770ac6 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; @@ -199,6 +201,7 @@ class Deletes extends Action * @param string $datetime * @param Document|null $document * @return void + * @throws Authorization * @throws Conflict * @throws Restricted * @throws Structure @@ -989,14 +992,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 8ed95ac2fc..df1833ad33 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; @@ -325,6 +326,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 08782fd825..0bd5c50e04 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -84,7 +84,6 @@ class Migrations extends Action ->inject('deviceForFiles') ->inject('queueForMails') ->inject('plan') - ->inject('authorization') ->callback($this->action(...)); } @@ -102,7 +101,6 @@ class Migrations extends Action Device $deviceForFiles, Mail $queueForMails, array $plan, - Authorization $authorization, ): void { $payload = $message->getPayload() ?? []; $this->deviceForMigrations = $deviceForMigrations; @@ -129,7 +127,7 @@ class Migrations extends Action return; } - $this->processMigration($migration, $queueForRealtime, $queueForMails, $authorization); + $this->processMigration($migration, $queueForRealtime, $queueForMails); } /** @@ -298,7 +296,6 @@ class Migrations extends Action Document $migration, Realtime $queueForRealtime, Mail $queueForMails, - Authorization $authorization, ): void { $project = $this->dbForPlatform->getDocument('projects', $this->project->getId()); $tempAPIKey = $this->generateAPIKey($project); @@ -414,7 +411,7 @@ class Migrations extends Action $source?->success(); if ($migration->getAttribute('destination') === DestinationCSV::getName()) { - $this->handleCSVExportComplete($project, $migration, $queueForMails, $authorization); + $this->handleCSVExportComplete($project, $migration, $queueForMails); } } } @@ -435,8 +432,7 @@ class Migrations extends Action protected function handleCSVExportComplete( Document $project, Document $migration, - Mail $queueForMails, - Authorization $authorization, + Mail $queueForMails ): void { $options = $migration->getAttribute('options', []); $bucketId = 'default'; // Always use platform default bucket @@ -450,7 +446,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/Request.php b/src/Appwrite/Utopia/Request.php index 76d87e2012..558f0cdf09 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -210,7 +210,7 @@ class Request extends UtopiaRequest { $forwardedUserAgent = $this->getHeader('x-forwarded-user-agent'); if (!empty($forwardedUserAgent)) { - $roles = $this->authorization->getRoles() ?? []; + $roles = Authorization::getRoles(); $isAppUser = Auth::isAppUser($roles); if ($isAppUser) { @@ -233,11 +233,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 e130178083..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,10 +150,10 @@ class V20 extends Filter } try { - $collection = $dbForProject->getDocument( + $collection = Authorization::skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence(), $collectionId - ); + )); if ($collection->isEmpty()) { return []; } diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 962ac37aa9..19a451e2c0 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -812,7 +812,7 @@ class Response extends SwooleResponse } if ($rule['sensitive']) { - $roles = $this->authorization->getRoles() ?? []; + $roles = Authorization::getRoles(); $isPrivilegedUser = Auth::isPrivilegedUser($roles); $isAppUser = Auth::isAppUser($roles); @@ -980,11 +980,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/Health/HealthCustomServerTest.php b/tests/e2e/Services/Health/HealthCustomServerTest.php index 63516f624d..4b7062dc22 100644 --- a/tests/e2e/Services/Health/HealthCustomServerTest.php +++ b/tests/e2e/Services/Health/HealthCustomServerTest.php @@ -40,6 +40,7 @@ class HealthCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); + $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals('pass', $response['body']['statuses'][0]['status']); $this->assertIsInt($response['body']['statuses'][0]['ping']); 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/Auth/AuthTest.php b/tests/unit/Auth/AuthTest.php index 5e883bf924..705da42879 100644 --- a/tests/unit/Auth/AuthTest.php +++ b/tests/unit/Auth/AuthTest.php @@ -13,27 +13,13 @@ use Utopia\Database\Validator\Roles; class AuthTest 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 setUp(): void + public function tearDown(): void { - $this->getAuthorization()->cleanRoles(); - $this->getAuthorization()->addRole(Role::any()->toString()); + Authorization::cleanRoles(); + Authorization::setRole(Role::any()->toString()); } public function testCookieName(): void @@ -361,7 +347,7 @@ class AuthTest extends TestCase '$id' => '' ]); - $roles = Auth::getRoles($user, new Authorization()); + $roles = Auth::getRoles($user); $this->assertCount(1, $roles); $this->assertContains(Role::guests()->toString(), $roles); } @@ -397,7 +383,7 @@ class AuthTest extends TestCase ] ]); - $roles = Auth::getRoles($user, $this->getAuthorization()); + $roles = Auth::getRoles($user); $this->assertCount(13, $roles); $this->assertContains(Role::users()->toString(), $roles); @@ -418,21 +404,21 @@ class AuthTest extends TestCase $user['emailVerification'] = false; $user['phoneVerification'] = false; - $roles = Auth::getRoles($user, $this->getAuthorization()); + $roles = Auth::getRoles($user); $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 = Auth::getRoles($user, $this->getAuthorization()); + $roles = Auth::getRoles($user); $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(Auth::USER_ROLE_OWNER); + Authorization::setRole(Auth::USER_ROLE_OWNER); $user = new Document([ '$id' => ID::custom('123'), 'emailVerification' => true, @@ -458,7 +444,7 @@ class AuthTest extends TestCase ] ]); - $roles = Auth::getRoles($user, $this->getAuthorization()); + $roles = Auth::getRoles($user); $this->assertCount(7, $roles); $this->assertNotContains(Role::users()->toString(), $roles); @@ -476,7 +462,7 @@ class AuthTest extends TestCase public function testAppUserRoles(): void { - $this->getAuthorization()->addRole(Auth::USER_ROLE_APPS); + Authorization::setRole(Auth::USER_ROLE_APPS); $user = new Document([ '$id' => ID::custom('123'), 'memberships' => [ @@ -500,7 +486,7 @@ class AuthTest extends TestCase ] ]); - $roles = Auth::getRoles($user, $this->getAuthorization()); + $roles = Auth::getRoles($user); $this->assertCount(7, $roles); $this->assertNotContains(Role::users()->toString(), $roles); diff --git a/tests/unit/Messaging/MessagingChannelsTest.php b/tests/unit/Messaging/MessagingChannelsTest.php index 8fb7f3f666..8ba0374093 100644 --- a/tests/unit/Messaging/MessagingChannelsTest.php +++ b/tests/unit/Messaging/MessagingChannelsTest.php @@ -8,7 +8,6 @@ use PHPUnit\Framework\TestCase; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; -use Utopia\Database\Validator\Authorization; class MessagingChannelsTest extends TestCase { @@ -35,19 +34,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 { /** @@ -80,7 +66,7 @@ class MessagingChannelsTest extends TestCase ] ]); - $roles = Auth::getRoles($user, $this->getAuthorization()); + $roles = Auth::getRoles($user); $parsedChannels = Realtime::convertChannels([0 => $channel], $user->getId()); @@ -104,7 +90,7 @@ class MessagingChannelsTest extends TestCase '$id' => '' ]); - $roles = Auth::getRoles($user, $this->getAuthorization()); + $roles = Auth::getRoles($user); $parsedChannels = Realtime::convertChannels([0 => $channel], $user->getId()); From 150d09f656534065b277916523fc2b9cf6f9c897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 19 Nov 2025 09:27:53 +0100 Subject: [PATCH 71/77] Update composer.lock --- composer.lock | 69 ++++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 39 deletions(-) diff --git a/composer.lock b/composer.lock index 5856a5f2eb..d66945e3fc 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": "1042498bc589543427184b001fef3a1e", + "content-hash": "dc4eb1888275a24d596468924e272e25", "packages": [ { "name": "adhocore/jwt", @@ -3551,21 +3551,21 @@ }, { "name": "utopia-php/audit", - "version": "1.0.3", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "15656acfddb9d6f03c395b73673fc66c793c10a5" + "reference": "8c17065c2473d4ca799f65585ca74eb53e1be211" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/15656acfddb9d6f03c395b73673fc66c793c10a5", - "reference": "15656acfddb9d6f03c395b73673fc66c793c10a5", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/8c17065c2473d4ca799f65585ca74eb53e1be211", + "reference": "8c17065c2473d4ca799f65585ca74eb53e1be211", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "4.*" + "utopia-php/database": "*" }, "require-dev": { "laravel/pint": "1.*", @@ -3592,9 +3592,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/1.0.3" + "source": "https://github.com/utopia-php/audit/tree/1.0.2" }, - "time": "2025-11-04T11:27:42+00:00" + "time": "2025-10-20T07:14:26+00:00" }, { "name": "utopia-php/cache", @@ -3745,21 +3745,21 @@ }, { "name": "utopia-php/config", - "version": "dev-feat-config-adapters", + "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/utopia-php/config.git", - "reference": "02232da489a94576be0d8fb63c326003ccb6e337" + "reference": "6672bf6c1b54ba608593570cbef31bef75f17dd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/config/zipball/02232da489a94576be0d8fb63c326003ccb6e337", - "reference": "02232da489a94576be0d8fb63c326003ccb6e337", + "url": "https://api.github.com/repos/utopia-php/config/zipball/6672bf6c1b54ba608593570cbef31bef75f17dd8", + "reference": "6672bf6c1b54ba608593570cbef31bef75f17dd8", "shasum": "" }, "require": { "ext-yaml": "*", - "php": ">=8.1" + "php": ">=8.0" }, "require-dev": { "laravel/pint": "1.2.*", @@ -3786,9 +3786,9 @@ ], "support": { "issues": "https://github.com/utopia-php/config/issues", - "source": "https://github.com/utopia-php/config/tree/feat-config-adapters" + "source": "https://github.com/utopia-php/config/tree/1.0.0" }, - "time": "2025-11-18T14:59:26+00:00" + "time": "2025-11-18T17:02:00+00:00" }, { "name": "utopia-php/console", @@ -3840,16 +3840,16 @@ }, { "name": "utopia-php/database", - "version": "4.3.0", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "fe7a1326ad623609e65587fe8c01a630a7075fee" + "reference": "5da71b65a6123ce2e78795522b05b7458aabfbd7" }, "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/5da71b65a6123ce2e78795522b05b7458aabfbd7", + "reference": "5da71b65a6123ce2e78795522b05b7458aabfbd7", "shasum": "" }, "require": { @@ -3892,9 +3892,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/3.5.0" }, - "time": "2025-11-14T03:43:10+00:00" + "time": "2025-11-18T08:11:01+00:00" }, { "name": "utopia-php/detector", @@ -4456,16 +4456,16 @@ }, { "name": "utopia-php/migration", - "version": "1.3.4", + "version": "1.3.3", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "81e1be6ff3257d4768aa7483cf64628836244a09" + "reference": "731b3a963c58c30e0b2368695d57a7e8fcb7455c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/81e1be6ff3257d4768aa7483cf64628836244a09", - "reference": "81e1be6ff3257d4768aa7483cf64628836244a09", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/731b3a963c58c30e0b2368695d57a7e8fcb7455c", + "reference": "731b3a963c58c30e0b2368695d57a7e8fcb7455c", "shasum": "" }, "require": { @@ -4474,7 +4474,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.*" }, @@ -4505,9 +4505,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/1.3.4" + "source": "https://github.com/utopia-php/migration/tree/1.3.3" }, - "time": "2025-11-04T11:28:50+00:00" + "time": "2025-10-28T04:02:08+00:00" }, { "name": "utopia-php/mongo", @@ -8891,18 +8891,9 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [ - { - "package": "utopia-php/config", - "version": "dev-feat-config-adapters", - "alias": "1.0.0", - "alias_normalized": "1.0.0.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/config": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From 61f8c99da7579897bb3da20cc04451ff37f32df1 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Wed, 19 Nov 2025 14:11:40 +0530 Subject: [PATCH 72/77] chore: release flutter 20.3.2 --- app/config/platforms.php | 2 +- docker-compose.override.yml | 7 ------- docs/sdks/flutter/CHANGELOG.md | 4 ++++ 3 files changed, 5 insertions(+), 8 deletions(-) delete mode 100644 docker-compose.override.yml diff --git a/app/config/platforms.php b/app/config/platforms.php index 2b5c107648..ce60b2f6c2 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -60,7 +60,7 @@ return [ [ 'key' => 'flutter', 'name' => 'Flutter', - 'version' => '20.3.1', + 'version' => '20.3.2', 'url' => 'https://github.com/appwrite/sdk-for-flutter', 'package' => 'https://pub.dev/packages/appwrite', 'enabled' => true, diff --git a/docker-compose.override.yml b/docker-compose.override.yml deleted file mode 100644 index 52c5058ab9..0000000000 --- a/docker-compose.override.yml +++ /dev/null @@ -1,7 +0,0 @@ -services: - appwrite: - # volumes: - # - ~/.ssh:/root/.ssh - environment: - - GH_TOKEN= - - GIT_EMAIL= diff --git a/docs/sdks/flutter/CHANGELOG.md b/docs/sdks/flutter/CHANGELOG.md index 2f26f34edd..40f703903f 100644 --- a/docs/sdks/flutter/CHANGELOG.md +++ b/docs/sdks/flutter/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 20.3.2 + +* Fix OAuth2 browser infinite redirect issue + ## 20.3.1 * Fix passing of `null` values and stripping only non-nullable optional parameters from the request body From 0974e1335f6b0f20102b7d1e4955196ba3ed3358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 19 Nov 2025 10:38:32 +0100 Subject: [PATCH 73/77] Cleanup --- app/init/configs.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/init/configs.php b/app/init/configs.php index 9519c757b3..9ecbe6114d 100644 --- a/app/init/configs.php +++ b/app/init/configs.php @@ -5,8 +5,6 @@ use Utopia\Config\Config; require_once __DIR__ . '/../config/storage/resource_limits.php'; -$configAdapter = new PHP(); - Config::load('template-runtimes', __DIR__ . '/../config/template-runtimes.php', new PHP()); Config::load('events', __DIR__ . '/../config/events.php', new PHP()); Config::load('auth', __DIR__ . '/../config/auth.php', new PHP()); From bdbe94b56ffb4cc44ac31745da1e1da5e2382043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 19 Nov 2025 11:02:29 +0100 Subject: [PATCH 74/77] Improce codeQL --- app/init/configs.php | 74 +++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/app/init/configs.php b/app/init/configs.php index 9ecbe6114d..51242af578 100644 --- a/app/init/configs.php +++ b/app/init/configs.php @@ -5,39 +5,41 @@ use Utopia\Config\Config; require_once __DIR__ . '/../config/storage/resource_limits.php'; -Config::load('template-runtimes', __DIR__ . '/../config/template-runtimes.php', new PHP()); -Config::load('events', __DIR__ . '/../config/events.php', new PHP()); -Config::load('auth', __DIR__ . '/../config/auth.php', new PHP()); -Config::load('apis', __DIR__ . '/../config/apis.php', new PHP()); // List of APIs -Config::load('errors', __DIR__ . '/../config/errors.php', new PHP()); -Config::load('oAuthProviders', __DIR__ . '/../config/oAuthProviders.php', new PHP()); -Config::load('platforms', __DIR__ . '/../config/platforms.php', new PHP()); -Config::load('console', __DIR__ . '/../config/console.php', new PHP()); -Config::load('collections', __DIR__ . '/../config/collections.php', new PHP()); -Config::load('frameworks', __DIR__ . '/../config/frameworks.php', new PHP()); -Config::load('runtimes', __DIR__ . '/../config/runtimes.php', new PHP()); -Config::load('runtimes-v2', __DIR__ . '/../config/runtimes-v2.php', new PHP()); -Config::load('usage', __DIR__ . '/../config/usage.php', new PHP()); -Config::load('roles', __DIR__ . '/../config/roles.php', new PHP()); // User roles and scopes -Config::load('scopes', __DIR__ . '/../config/scopes.php', new PHP()); // User roles and scopes -Config::load('services', __DIR__ . '/../config/services.php', new PHP()); // List of services -Config::load('variables', __DIR__ . '/../config/variables.php', new PHP()); // List of env variables -Config::load('regions', __DIR__ . '/../config/regions.php', new PHP()); // List of available regions -Config::load('avatar-browsers', __DIR__ . '/../config/avatars/browsers.php', new PHP()); -Config::load('avatar-credit-cards', __DIR__ . '/../config/avatars/credit-cards.php', new PHP()); -Config::load('avatar-flags', __DIR__ . '/../config/avatars/flags.php', new PHP()); -Config::load('locale-codes', __DIR__ . '/../config/locale/codes.php', new PHP()); -Config::load('locale-currencies', __DIR__ . '/../config/locale/currencies.php', new PHP()); -Config::load('locale-eu', __DIR__ . '/../config/locale/eu.php', new PHP()); -Config::load('locale-languages', __DIR__ . '/../config/locale/languages.php', new PHP()); -Config::load('locale-phones', __DIR__ . '/../config/locale/phones.php', new PHP()); -Config::load('locale-countries', __DIR__ . '/../config/locale/countries.php', new PHP()); -Config::load('locale-continents', __DIR__ . '/../config/locale/continents.php', new PHP()); -Config::load('locale-templates', __DIR__ . '/../config/locale/templates.php', new PHP()); -Config::load('storage-logos', __DIR__ . '/../config/storage/logos.php', new PHP()); -Config::load('storage-mimes', __DIR__ . '/../config/storage/mimes.php', new PHP()); -Config::load('storage-inputs', __DIR__ . '/../config/storage/inputs.php', new PHP()); -Config::load('storage-outputs', __DIR__ . '/../config/storage/outputs.php', new PHP()); -Config::load('specifications', __DIR__ . '/../config/specifications.php', new PHP()); -Config::load('templates-function', __DIR__ . '/../config/templates/function.php', new PHP()); -Config::load('templates-site', __DIR__ . '/../config/templates/site.php', new PHP()); +$configAdapter = new PHP(); + +Config::load('template-runtimes', __DIR__ . '/../config/template-runtimes.php', $configAdapter); +Config::load('events', __DIR__ . '/../config/events.php', $configAdapter); +Config::load('auth', __DIR__ . '/../config/auth.php', $configAdapter); +Config::load('apis', __DIR__ . '/../config/apis.php', $configAdapter); // List of APIs +Config::load('errors', __DIR__ . '/../config/errors.php', $configAdapter); +Config::load('oAuthProviders', __DIR__ . '/../config/oAuthProviders.php', $configAdapter); +Config::load('platforms', __DIR__ . '/../config/platforms.php', $configAdapter); +Config::load('console', __DIR__ . '/../config/console.php', $configAdapter); +Config::load('collections', __DIR__ . '/../config/collections.php', $configAdapter); +Config::load('frameworks', __DIR__ . '/../config/frameworks.php', $configAdapter); +Config::load('runtimes', __DIR__ . '/../config/runtimes.php', $configAdapter); +Config::load('runtimes-v2', __DIR__ . '/../config/runtimes-v2.php', $configAdapter); +Config::load('usage', __DIR__ . '/../config/usage.php', $configAdapter); +Config::load('roles', __DIR__ . '/../config/roles.php', $configAdapter); // User roles and scopes +Config::load('scopes', __DIR__ . '/../config/scopes.php', $configAdapter); // User roles and scopes +Config::load('services', __DIR__ . '/../config/services.php', $configAdapter); // List of services +Config::load('variables', __DIR__ . '/../config/variables.php', $configAdapter); // List of env variables +Config::load('regions', __DIR__ . '/../config/regions.php', $configAdapter); // List of available regions +Config::load('avatar-browsers', __DIR__ . '/../config/avatars/browsers.php', $configAdapter); +Config::load('avatar-credit-cards', __DIR__ . '/../config/avatars/credit-cards.php', $configAdapter); +Config::load('avatar-flags', __DIR__ . '/../config/avatars/flags.php', $configAdapter); +Config::load('locale-codes', __DIR__ . '/../config/locale/codes.php', $configAdapter); +Config::load('locale-currencies', __DIR__ . '/../config/locale/currencies.php', $configAdapter); +Config::load('locale-eu', __DIR__ . '/../config/locale/eu.php', $configAdapter); +Config::load('locale-languages', __DIR__ . '/../config/locale/languages.php', $configAdapter); +Config::load('locale-phones', __DIR__ . '/../config/locale/phones.php', $configAdapter); +Config::load('locale-countries', __DIR__ . '/../config/locale/countries.php', $configAdapter); +Config::load('locale-continents', __DIR__ . '/../config/locale/continents.php', $configAdapter); +Config::load('locale-templates', __DIR__ . '/../config/locale/templates.php', $configAdapter); +Config::load('storage-logos', __DIR__ . '/../config/storage/logos.php', $configAdapter); +Config::load('storage-mimes', __DIR__ . '/../config/storage/mimes.php', $configAdapter); +Config::load('storage-inputs', __DIR__ . '/../config/storage/inputs.php', $configAdapter); +Config::load('storage-outputs', __DIR__ . '/../config/storage/outputs.php', $configAdapter); +Config::load('specifications', __DIR__ . '/../config/specifications.php', $configAdapter); +Config::load('templates-function', __DIR__ . '/../config/templates/function.php', $configAdapter); +Config::load('templates-site', __DIR__ . '/../config/templates/site.php', $configAdapter); From 553fe15ba9ec1e48480243d90516dd53cea71066 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Wed, 19 Nov 2025 20:01:02 +0530 Subject: [PATCH 75/77] resolved merge conflicts --- composer.lock | 55 ++++++++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/composer.lock b/composer.lock index 89ca7ee6e3..a095a570e3 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": "ac15c526599e0b27ecdfb5a90dcfffeb", + "content-hash": "fd23f533058976f75c6da390654d0eff", "packages": [ { "name": "adhocore/jwt", @@ -957,19 +957,15 @@ { "name": "mongodb/mongodb", "version": "2.1.2", - "version": "2.1.2", "source": { "type": "git", "url": "https://github.com/mongodb/mongo-php-library.git", "reference": "0a2472ba9cbb932f7e43a8770aedb2fc30612a67" - "reference": "0a2472ba9cbb932f7e43a8770aedb2fc30612a67" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/mongodb/mongo-php-library/zipball/0a2472ba9cbb932f7e43a8770aedb2fc30612a67", "reference": "0a2472ba9cbb932f7e43a8770aedb2fc30612a67", - "url": "https://api.github.com/repos/mongodb/mongo-php-library/zipball/0a2472ba9cbb932f7e43a8770aedb2fc30612a67", - "reference": "0a2472ba9cbb932f7e43a8770aedb2fc30612a67", "shasum": "" }, "require": { @@ -986,7 +982,6 @@ "doctrine/coding-standard": "^12.0", "phpunit/phpunit": "^10.5.35", "rector/rector": "^2.1.4", - "rector/rector": "^2.1.4", "squizlabs/php_codesniffer": "^3.7", "vimeo/psalm": "6.5.*" }, @@ -1033,10 +1028,8 @@ "support": { "issues": "https://github.com/mongodb/mongo-php-library/issues", "source": "https://github.com/mongodb/mongo-php-library/tree/2.1.2" - "source": "https://github.com/mongodb/mongo-php-library/tree/2.1.2" }, "time": "2025-10-06T12:12:40+00:00" - "time": "2025-10-06T12:12:40+00:00" }, { "name": "mustangostang/spyc", @@ -4210,16 +4203,16 @@ }, { "name": "utopia-php/framework", - "version": "0.33.29", + "version": "0.33.30", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "6e63939fdb33b847f92839499cd6e8df626c278d" + "reference": "07cf699a7c47bd1a03b4da1812f1719a66b3c924" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/6e63939fdb33b847f92839499cd6e8df626c278d", - "reference": "6e63939fdb33b847f92839499cd6e8df626c278d", + "url": "https://api.github.com/repos/utopia-php/http/zipball/07cf699a7c47bd1a03b4da1812f1719a66b3c924", + "reference": "07cf699a7c47bd1a03b4da1812f1719a66b3c924", "shasum": "" }, "require": { @@ -4251,9 +4244,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.29" + "source": "https://github.com/utopia-php/http/tree/0.33.30" }, - "time": "2025-11-14T06:33:29+00:00" + "time": "2025-11-18T12:18:00+00:00" }, { "name": "utopia-php/image", @@ -4462,12 +4455,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "f5e175fa8da4bee6211dbeb4fe693a3eedb87672" + "reference": "105b48dcf2bc8a1a969497813f3d7d06231770e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/f5e175fa8da4bee6211dbeb4fe693a3eedb87672", - "reference": "f5e175fa8da4bee6211dbeb4fe693a3eedb87672", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/105b48dcf2bc8a1a969497813f3d7d06231770e6", + "reference": "105b48dcf2bc8a1a969497813f3d7d06231770e6", "shasum": "" }, "require": { @@ -4509,7 +4502,7 @@ "issues": "https://github.com/utopia-php/migration/issues", "source": "https://github.com/utopia-php/migration/tree/feat-documents-db" }, - "time": "2025-11-13T11:11:30+00:00" + "time": "2025-11-19T12:47:12+00:00" }, { "name": "utopia-php/mongo", @@ -5381,16 +5374,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.5.5", + "version": "1.5.7", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "1f3686e41a2d10829220b74f54c80a770e9f968a" + "reference": "dc6720ba92ed98e2c62b2a319d4371f167ccc808" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/1f3686e41a2d10829220b74f54c80a770e9f968a", - "reference": "1f3686e41a2d10829220b74f54c80a770e9f968a", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/dc6720ba92ed98e2c62b2a319d4371f167ccc808", + "reference": "dc6720ba92ed98e2c62b2a319d4371f167ccc808", "shasum": "" }, "require": { @@ -5426,9 +5419,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.5.5" + "source": "https://github.com/appwrite/sdk-generator/tree/1.5.7" }, - "time": "2025-11-14T05:56:33+00:00" + "time": "2025-11-18T05:57:01+00:00" }, { "name": "doctrine/annotations", @@ -8716,16 +8709,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.3.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb" + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/d74205c497bfbca49f34d4bc4c19c17e22db4ebb", - "reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { @@ -8754,7 +8747,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.3.0" + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { @@ -8762,7 +8755,7 @@ "type": "github" } ], - "time": "2025-11-13T13:44:09+00:00" + "time": "2025-11-17T20:03:58+00:00" }, { "name": "twig/twig", @@ -8928,5 +8921,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } From a9e749a81ffe149289743c5e64b0f625ac727c62 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Thu, 20 Nov 2025 14:06:42 +0530 Subject: [PATCH 76/77] updated migration service extractor for csv import/export --- app/controllers/api/migrations.php | 30 ++++++++++++++++++++++++++++-- app/init/constants.php | 8 ++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 2d9890dcbb..be61b1d3e3 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -43,6 +43,14 @@ use Utopia\Validator\WhiteList; include_once __DIR__ . '/../shared/api.php'; +function getDatabaseTransferResourceServices(string $databaseType) +{ + return match($databaseType) { + DATABASE_LEGACY_TYPE, + DATABASE_TABLESDB_TYPE => Transfer::GROUP_DATABASES_TABLES_DB + }; +} + App::post('/v1/migrations/appwrite') ->groups(['api', 'migrations']) ->desc('Create Appwrite migration') @@ -415,8 +423,16 @@ App::post('/v1/migrations/csv/imports') throw new \Exception('Unable to copy file'); } + // getting databasetype + $resources = explode(':', $resourceId); + $databaseId = $resources[0]; + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $databaseType = $database->getAttribute('type'); + if (!in_array($databaseType, CSV_ALLOWED_DATABASE_TYPES)) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Database type not supported for csv'); + } $fileSize = $deviceForMigrations->getFileSize($newPath); - $resources = Transfer::extractServices([Transfer::GROUP_DATABASES]); + $resources = Transfer::extractServices([getDatabaseTransferResourceServices($databaseType)]); $migration = $dbForProject->createDocument('migrations', new Document([ '$id' => $migrationId, @@ -540,13 +556,23 @@ App::post('/v1/migrations/csv/exports') throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); } + // getting databasetype + $resources = explode(':', $resourceId); + $databaseId = $resources[0]; + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + $databaseType = $database->getAttribute('type'); + if (!in_array($databaseType, CSV_ALLOWED_DATABASE_TYPES)) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Database type not supported for csv'); + } + $resources = Transfer::extractServices([getDatabaseTransferResourceServices($databaseType)]); + $migration = $dbForProject->createDocument('migrations', new Document([ '$id' => ID::unique(), 'status' => 'pending', 'stage' => 'init', 'source' => Appwrite::getName(), 'destination' => CSV::getName(), - 'resources' => Transfer::extractServices([Transfer::GROUP_DATABASES]), + 'resources' => $resources, 'resourceId' => $resourceId, 'resourceType' => Resource::TYPE_DATABASE, 'statusCounters' => '{}', diff --git a/app/init/constants.php b/app/init/constants.php index e11fdf9a54..4bb4fbf99f 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -297,3 +297,11 @@ const TOKENS_RESOURCE_TYPE_DATABASES = 'databases'; const SCHEDULE_RESOURCE_TYPE_EXECUTION = 'execution'; const SCHEDULE_RESOURCE_TYPE_FUNCTION = 'function'; const SCHEDULE_RESOURCE_TYPE_MESSAGE = 'message'; + +// Database types +const DATABASE_LEGACY_TYPE = 'legacy'; +const DATABASE_TABLESDB_TYPE = 'tablesdb'; +const DATABASE_DOCUMENTSDB_TYPE = 'documentsdb'; + +// CSV import/export allowed database types +const CSV_ALLOWED_DATABASE_TYPES = [DATABASE_LEGACY_TYPE, DATABASE_LEGACY_TYPE]; From 1004435e9e182d846fbfb28560de6c49a5a1cddc Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Thu, 20 Nov 2025 14:07:05 +0530 Subject: [PATCH 77/77] skipped operator tests for mongodb --- tests/e2e/Services/Databases/Legacy/DatabasesBase.php | 6 ++++++ tests/e2e/Services/Databases/TablesDB/DatabasesBase.php | 6 ++++++ .../Databases/TablesDB/Transactions/TransactionsBase.php | 9 +++++++++ 3 files changed, 21 insertions(+) diff --git a/tests/e2e/Services/Databases/Legacy/DatabasesBase.php b/tests/e2e/Services/Databases/Legacy/DatabasesBase.php index 8f449af2dc..e7ad75d03b 100644 --- a/tests/e2e/Services/Databases/Legacy/DatabasesBase.php +++ b/tests/e2e/Services/Databases/Legacy/DatabasesBase.php @@ -3160,6 +3160,9 @@ trait DatabasesBase public function testOperators(): void { + if ($this->isMongoDB()) { + $this->markTestSkipped('MongoDB is not supported for this test'); + } // Create database $database = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', @@ -3408,6 +3411,9 @@ trait DatabasesBase public function testBulkOperators(): void { + if ($this->isMongoDB()) { + $this->markTestSkipped('MongoDB is not supported for this test'); + } // Create database $database = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', diff --git a/tests/e2e/Services/Databases/TablesDB/DatabasesBase.php b/tests/e2e/Services/Databases/TablesDB/DatabasesBase.php index 1b3bfb0a05..9757b525df 100644 --- a/tests/e2e/Services/Databases/TablesDB/DatabasesBase.php +++ b/tests/e2e/Services/Databases/TablesDB/DatabasesBase.php @@ -3049,6 +3049,9 @@ trait DatabasesBase public function testOperators(): void { + if ($this->isMongoDB()) { + $this->markTestSkipped('MongoDB is not supported for this test'); + } // Create database $database = $this->client->call(Client::METHOD_POST, '/tablesdb', [ 'content-type' => 'application/json', @@ -3297,6 +3300,9 @@ trait DatabasesBase public function testBulkOperators(): void { + if ($this->isMongoDB()) { + $this->markTestSkipped('MongoDB is not supported for this test'); + } // Create database $database = $this->client->call(Client::METHOD_POST, '/tablesdb', [ 'content-type' => 'application/json', diff --git a/tests/e2e/Services/Databases/TablesDB/Transactions/TransactionsBase.php b/tests/e2e/Services/Databases/TablesDB/Transactions/TransactionsBase.php index 488dc60239..7f5b4bcf68 100644 --- a/tests/e2e/Services/Databases/TablesDB/Transactions/TransactionsBase.php +++ b/tests/e2e/Services/Databases/TablesDB/Transactions/TransactionsBase.php @@ -5569,6 +5569,9 @@ trait TransactionsBase */ public function testArrayOperatorsWithUpdateRow(): void { + if ($this->isMongoDB()) { + $this->markTestSkipped('MongoDB is not supported for this test'); + } // Create database $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ 'content-type' => 'application/json', @@ -5693,6 +5696,9 @@ trait TransactionsBase */ public function testArrayOperatorsWithCreateOperations(): void { + if ($this->isMongoDB()) { + $this->markTestSkipped('MongoDB is not supported for this test'); + } // Create database $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ 'content-type' => 'application/json', @@ -5820,6 +5826,9 @@ trait TransactionsBase */ public function testMultipleArrayOperators(): void { + if ($this->isMongoDB()) { + $this->markTestSkipped('MongoDB is not supported for this test'); + } // Create database $database = $this->client->call(Client::METHOD_POST, '/tablesdb', array_merge([ 'content-type' => 'application/json',