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()); }