diff --git a/app/controllers/api/graphql.php b/app/controllers/api/graphql.php index 2d0a840bd6..937380b643 100644 --- a/app/controllers/api/graphql.php +++ b/app/controllers/api/graphql.php @@ -28,12 +28,18 @@ use Utopia\Validator\Text; Http::init() ->groups(['graphql']) ->inject('project') + ->inject('user') + ->inject('request') + ->inject('response') ->inject('authorization') - ->action(function (Document $project, Authorization $authorization) { + ->action(function (Document $project, User $user, Request $request, Response $response, Authorization $authorization) { + $response->setUser($user); + $request->setUser($user); + if ( array_key_exists('graphql', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['graphql'] - && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) + && !($user->isPrivileged($authorization->getRoles()) || $user->isApp($authorization->getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } diff --git a/app/controllers/general.php b/app/controllers/general.php index 51cce37fee..79929816d9 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1270,7 +1270,16 @@ Http::error() * If not a publishable error, track usage stats. Publishable errors are >= 500 or those explicitly marked as publish=true in errors.php */ if (!$publish && $project->getId() !== 'console') { - if (!DBUser::isPrivileged($authorization->getRoles())) { + $errorUser = new DBUser(); + try { + $resolvedUser = $utopia->getResource('user'); + if ($resolvedUser instanceof DBUser) { + $errorUser = $resolvedUser; + } + } catch (\Throwable) { + // User resource may not be available in error context + } + if (!$errorUser->isPrivileged($authorization->getRoles())) { $bus->dispatch(new RequestCompleted( project: $project->getArrayCopy(), request: $request, diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index f98b9ed454..5166429e32 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -96,7 +96,7 @@ Http::init() ->inject('team') ->inject('apiKey') ->inject('authorization') - ->action(function (Http $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 (Http $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, User $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey, Authorization $authorization) { $route = $utopia->getRoute(); /** @@ -419,7 +419,7 @@ Http::init() if ( array_key_exists($namespace, $project->getAttribute('services', [])) && ! $project->getAttribute('services', [])[$namespace] - && ! (User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) + && ! ($user->isPrivileged($authorization->getRoles()) || $user->isApp($authorization->getRoles())) ) { throw new Exception(Exception::GENERAL_SERVICE_DISABLED); } @@ -483,7 +483,10 @@ Http::init() ->inject('telemetry') ->inject('platform') ->inject('authorization') - ->action(function (Http $utopia, Request $request, Response $response, Document $project, Document $user, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Context $usage, Func $queueForFunctions, Mail $queueForMails, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform, Authorization $authorization) { + ->action(function (Http $utopia, Request $request, Response $response, Document $project, User $user, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Context $usage, Func $queueForFunctions, Mail $queueForMails, Database $dbForProject, callable $timelimit, Document $resourceToken, string $mode, ?Key $apiKey, array $plan, Document $devKey, Telemetry $telemetry, array $platform, Authorization $authorization) { + + $response->setUser($user); + $request->setUser($user); $route = $utopia->getRoute(); $path = $route->getMatchedPath(); @@ -496,7 +499,7 @@ Http::init() if ( array_key_exists('rest', $project->getAttribute('apis', [])) && ! $project->getAttribute('apis', [])['rest'] - && ! (User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) + && ! ($user->isPrivileged($authorization->getRoles()) || $user->isApp($authorization->getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -528,8 +531,8 @@ Http::init() $closestLimit = null; $roles = $authorization->getRoles(); - $isPrivilegedUser = User::isPrivileged($roles); - $isAppUser = User::isApp($roles); + $isPrivilegedUser = $user->isPrivileged($roles); + $isAppUser = $user->isApp($roles); foreach ($timeLimitArray as $timeLimit) { foreach ($request->getParams() as $key => $value) { // Set request params as potential abuse keys @@ -611,7 +614,7 @@ Http::init() if ($useCache) { $route = $utopia->match($request); $isImageTransformation = $route->getPath() === '/v1/storage/buckets/:bucketId/files/:fileId/preview'; - $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && ! User::isPrivileged($authorization->getRoles()); + $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && ! $user->isPrivileged($authorization->getRoles()); $key = $request->cacheIdentifier(); $cacheLog = $authorization->skip(fn () => $dbForProject->getDocument('cache', $key)); @@ -630,7 +633,7 @@ Http::init() $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); $isToken = ! $resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (! $bucket->getAttribute('enabled') && ! $isAppUser && ! $isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -663,7 +666,7 @@ Http::init() throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } // Do not update transformedAt if it's a console user - if (! User::isPrivileged($authorization->getRoles())) { + if (! $user->isPrivileged($authorization->getRoles())) { $transformedAt = $file->getAttribute('transformedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) { $file->setAttribute('transformedAt', DateTime::now()); @@ -697,7 +700,7 @@ Http::init() ->groups(['session']) ->inject('user') ->inject('request') - ->action(function (Document $user, Request $request) { + ->action(function (User $user, Request $request) { if (\str_contains($request->getURI(), 'oauth2')) { return; } @@ -984,7 +987,7 @@ Http::shutdown() } if ($project->getId() !== 'console') { - if (! User::isPrivileged($authorization->getRoles())) { + if (! $user->isPrivileged($authorization->getRoles())) { $bus->dispatch(new RequestCompleted( project: $project->getArrayCopy(), request: $request, diff --git a/app/controllers/shared/api/auth.php b/app/controllers/shared/api/auth.php index 6e1f9f389f..db98d97bf5 100644 --- a/app/controllers/shared/api/auth.php +++ b/app/controllers/shared/api/auth.php @@ -36,8 +36,9 @@ Http::init() ->inject('request') ->inject('project') ->inject('geodb') + ->inject('user') ->inject('authorization') - ->action(function (Http $utopia, Request $request, Document $project, Reader $geodb, Authorization $authorization) { + ->action(function (Http $utopia, Request $request, Document $project, Reader $geodb, User $user, Authorization $authorization) { $denylist = System::getEnv('_APP_CONSOLE_COUNTRIES_DENYLIST', ''); if (!empty($denylist && $project->getId() === 'console')) { $countries = explode(',', $denylist); @@ -50,8 +51,8 @@ Http::init() $route = $utopia->match($request); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $isAppUser = User::isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); + $isAppUser = $user->isApp($authorization->getRoles()); if ($isAppUser || $isPrivilegedUser) { // Skip limits for app and console devs return; diff --git a/app/init/resources.php b/app/init/resources.php index 9883d6d644..3481e73e0b 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -432,8 +432,10 @@ Http::setResource('user', function (string $mode, Document $project, Document $c $jwtUserId = $payload['userId'] ?? ''; if (! empty($jwtUserId)) { if ($mode === APP_MODE_ADMIN) { + /** @var User $user */ $user = $dbForPlatform->getDocument('users', $jwtUserId); } else { + /** @var User $user */ $user = $dbForProject->getDocument('users', $jwtUserId); } } @@ -453,6 +455,7 @@ Http::setResource('user', function (string $mode, Document $project, Document $c throw new Exception(Exception::USER_API_KEY_AND_SESSION_SET); } + /** @var User $accountKeyUser */ $accountKeyUser = $dbForPlatform->getAuthorization()->skip(fn () => $dbForPlatform->getDocument('users', $accountKeyUserId)); if (! $accountKeyUser->isEmpty()) { $key = $accountKeyUser->find( diff --git a/app/realtime.php b/app/realtime.php index d3305ca7f8..1c453ce05b 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -518,7 +518,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $project = $consoleDatabase->getAuthorization()->skip(fn () => $consoleDatabase->getDocument('projects', $projectId)); $database = getProjectDB($project); - /** @var Appwrite\Utopia\Database\Documents\User $user */ + /** @var User $user */ $user = $database->getDocument('users', $userId); $roles = $user->getRoles($database->getAuthorization()); @@ -642,10 +642,14 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, throw new Exception(Exception::REALTIME_POLICY_VIOLATION, 'Missing or unknown project ID'); } + $timelimit = $app->getResource('timelimit'); + $user = $app->getResource('user'); /** @var User $user */ + $logUser = $user; + if ( array_key_exists('realtime', $project->getAttribute('apis', [])) && !$project->getAttribute('apis', [])['realtime'] - && !(User::isPrivileged($authorization->getRoles()) || User::isApp($authorization->getRoles())) + && !($user->isPrivileged($authorization->getRoles()) || $user->isApp($authorization->getRoles())) ) { throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } @@ -656,10 +660,6 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'Project is not accessible in this region. Please make sure you are using the correct endpoint'); } - $timelimit = $app->getResource('timelimit'); - $user = $app->getResource('user'); /** @var User $user */ - $logUser = $user; - /* * Abuse Check * diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 5e5ab5eef4..37e2579644 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -114,12 +114,6 @@ parameters: count: 1 path: app/controllers/mock.php - - - message: '#^Call to an undefined method Utopia\\Database\\Document\:\:getRoles\(\)\.$#' - identifier: method.notFound - count: 1 - path: app/controllers/shared/api.php - - message: '#^Variable \$register might not be defined\.$#' identifier: variable.undefined 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 8d31e19753..a02eb51aba 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 @@ -87,13 +87,14 @@ class Decrement extends Action ->inject('usage') ->inject('plan') ->inject('authorization') + ->inject('user') ->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, callable $getDatabasesDB, Event $queueForEvents, Context $usage, 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, callable $getDatabasesDB, Event $queueForEvents, Context $usage, array $plan, Authorization $authorization, User $user): void { - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { 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 9de5f83154..305d9b7a8d 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 @@ -87,13 +87,14 @@ class Increment extends Action ->inject('usage') ->inject('plan') ->inject('authorization') + ->inject('user') ->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, callable $getDatabasesDB, Event $queueForEvents, Context $usage, 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, callable $getDatabasesDB, Event $queueForEvents, Context $usage, array $plan, Authorization $authorization, User $user): void { - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { 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 08c3b047be..7f2e895228 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 @@ -139,7 +139,7 @@ class Create extends Action ->inject('eventProcessor') ->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, callable $getDatabasesDB, Document $user, Event $queueForEvents, Context $usage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, Authorization $authorization, EventProcessor $eventProcessor): void + public function action(string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, ?array $documents, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, User $user, Event $queueForEvents, Context $usage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, array $plan, Authorization $authorization, EventProcessor $eventProcessor): void { $data = \is_string($data) ? \json_decode($data, true) @@ -183,8 +183,8 @@ class Create extends Action $documents = [$data]; } - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if ($isBulk && !$isAPIKey && !$isPrivilegedUser) { throw new Exception(Exception::GENERAL_UNAUTHORIZED_SCOPE); 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 9931109c49..ecc5b152ec 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 @@ -85,6 +85,7 @@ class Delete extends Action ->inject('transactionState') ->inject('plan') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } @@ -101,12 +102,13 @@ class Delete extends Action Context $usage, TransactionState $transactionState, array $plan, - Authorization $authorization + Authorization $authorization, + User $user ): void { $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); 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 d84eb75a0f..b48df136ee 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 @@ -72,13 +72,14 @@ class Get extends Action ->inject('usage') ->inject('transactionState') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Context $usage, TransactionState $transactionState, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, string $documentId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Context $usage, TransactionState $transactionState, Authorization $authorization, User $user): void { - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { 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 f006ad7f59..27ccaafc71 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 @@ -89,10 +89,11 @@ class Update extends Action ->inject('transactionState') ->inject('plan') ->inject('authorization') + ->inject('user') ->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, callable $getDatabasesDB, Event $queueForEvents, Context $usage, 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, callable $getDatabasesDB, Event $queueForEvents, Context $usage, TransactionState $transactionState, array $plan, Authorization $authorization, User $user): void { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -102,8 +103,8 @@ class Update extends Action $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::DATABASE_NOT_FOUND, params: [$databaseId]); 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 0dfc64f392..ef89b80e97 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 @@ -96,7 +96,7 @@ class Upsert extends Action ->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, callable $getDatabasesDB, Event $queueForEvents, Context $usage, 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, User $user, Database $dbForProject, callable $getDatabasesDB, Event $queueForEvents, Context $usage, TransactionState $transactionState, array $plan, Authorization $authorization): void { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -108,8 +108,8 @@ class Upsert extends Action throw new Exception($this->getMissingPayloadException()); } - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { 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 bc9d30c6f2..744a4fd922 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 @@ -83,10 +83,10 @@ class XList extends Action ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, int $ttl, UtopiaResponse $response, Database $dbForProject, Document $user, callable $getDatabasesDB, Context $usage, TransactionState $transactionState, Authorization $authorization): void + public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, int $ttl, UtopiaResponse $response, Database $dbForProject, User $user, callable $getDatabasesDB, Context $usage, TransactionState $transactionState, Authorization $authorization): void { - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); $database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { 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 26457cc4a0..30c9b7cb30 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 @@ -65,17 +65,18 @@ class Create extends Action ->inject('transactionState') ->inject('plan') ->inject('authorization') + ->inject('user') ->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, Authorization $authorization, User $user): void { if (empty($operations)) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Operations array cannot be empty'); } - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); // API keys and admins can read any transaction, regular users need permissions $transaction = ($isAPIKey || $isPrivilegedUser) 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 5e88eee500..a5d96d5768 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php @@ -91,7 +91,7 @@ class Update extends Action * @param UtopiaResponse $response * @param Database $dbForProject * @param callable $getDatabasesDB - * @param Document $user + * @param User $user * @param TransactionState $transactionState * @param Delete $queueForDeletes * @param Event $queueForEvents @@ -109,7 +109,7 @@ class Update extends Action * @throws Structure * @throws \Utopia\Http\Exception */ - public function action(string $transactionId, bool $commit, bool $rollback, Document $project, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, Document $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, Context $usage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, Authorization $authorization, EventProcessor $eventProcessor): void + public function action(string $transactionId, bool $commit, bool $rollback, Document $project, UtopiaResponse $response, Database $dbForProject, callable $getDatabasesDB, User $user, TransactionState $transactionState, Delete $queueForDeletes, Event $queueForEvents, Context $usage, Event $queueForRealtime, Event $queueForFunctions, Event $queueForWebhooks, Authorization $authorization, EventProcessor $eventProcessor): void { if (!$commit && !$rollback) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Either commit or rollback must be true'); @@ -118,8 +118,8 @@ class Update extends Action throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Cannot commit and rollback at the same time'); } - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); $transaction = ($isAPIKey || $isPrivilegedUser) ? $authorization->skip(fn () => $dbForProject->getDocument('transactions', $transactionId)) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Attribute/Decrement.php b/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Attribute/Decrement.php index de3acdc96a..6d986fc6b1 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Attribute/Decrement.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Attribute/Decrement.php @@ -68,6 +68,7 @@ class Decrement extends DecrementDocumentAttribute ->inject('usage') ->inject('plan') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Attribute/Increment.php b/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Attribute/Increment.php index 8664bb09ec..09def76941 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Attribute/Increment.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Attribute/Increment.php @@ -68,6 +68,7 @@ class Increment extends IncrementDocumentAttribute ->inject('usage') ->inject('plan') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Delete.php index 86749f8a3d..0253c287aa 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Delete.php @@ -71,6 +71,7 @@ class Delete extends DocumentDelete ->inject('transactionState') ->inject('plan') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Get.php index 4dd1f6f6b3..47d352bf98 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Get.php @@ -59,6 +59,7 @@ class Get extends DocumentGet ->inject('usage') ->inject('transactionState') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Update.php index b5c612c155..9e79bb5464 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Collections/Documents/Update.php @@ -70,6 +70,7 @@ class Update extends DocumentUpdate ->inject('transactionState') ->inject('plan') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Transactions/Operations/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Transactions/Operations/Create.php index bc15d440d1..963af2f43e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Transactions/Operations/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/DocumentsDB/Transactions/Operations/Create.php @@ -55,6 +55,7 @@ class Create extends OperationsCreate ->inject('transactionState') ->inject('plan') ->inject('authorization') + ->inject('user') ->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 2670cc00aa..ea1bfa163d 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 @@ -70,6 +70,7 @@ class Decrement extends DecrementDocumentAttribute ->inject('usage') ->inject('plan') ->inject('authorization') + ->inject('user') ->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 ca6589aa3a..2f8be876d7 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 @@ -70,6 +70,7 @@ class Increment extends IncrementDocumentAttribute ->inject('usage') ->inject('plan') ->inject('authorization') + ->inject('user') ->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 addc87f610..06aee2cb30 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 @@ -73,6 +73,7 @@ class Delete extends DocumentDelete ->inject('transactionState') ->inject('plan') ->inject('authorization') + ->inject('user') ->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 48a24e9ec4..65ae238a1a 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 @@ -61,6 +61,7 @@ class Get extends DocumentGet ->inject('usage') ->inject('transactionState') ->inject('authorization') + ->inject('user') ->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 99599bd169..93ec5d3b58 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 @@ -71,6 +71,7 @@ class Update extends DocumentUpdate ->inject('transactionState') ->inject('plan') ->inject('authorization') + ->inject('user') ->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 818ed70cea..b00b75f270 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 @@ -56,6 +56,7 @@ class Create extends OperationsCreate ->inject('transactionState') ->inject('plan') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Collections/Documents/Delete.php b/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Collections/Documents/Delete.php index eca6049970..e81e34e1e5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Collections/Documents/Delete.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Collections/Documents/Delete.php @@ -71,6 +71,7 @@ class Delete extends DocumentDelete ->inject('transactionState') ->inject('plan') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Collections/Documents/Get.php b/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Collections/Documents/Get.php index 2a7090a01e..73f7a55026 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Collections/Documents/Get.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Collections/Documents/Get.php @@ -59,6 +59,7 @@ class Get extends DocumentGet ->inject('usage') ->inject('transactionState') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Collections/Documents/Update.php index 2624cc82e4..8a8b9d89ae 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Collections/Documents/Update.php @@ -70,6 +70,7 @@ class Update extends DocumentUpdate ->inject('transactionState') ->inject('plan') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Transactions/Operations/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Transactions/Operations/Create.php index 830c0c3fe1..27283cda49 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Transactions/Operations/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Transactions/Operations/Create.php @@ -55,6 +55,7 @@ class Create extends OperationsCreate ->inject('transactionState') ->inject('plan') ->inject('authorization') + ->inject('user') ->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 ee33abe9e1..c6d25a15fc 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -119,7 +119,7 @@ class Create extends Base Document $project, Database $dbForProject, Database $dbForPlatform, - Document $user, + User $user, Event $queueForEvents, Context $usage, Func $queueForFunctions, @@ -171,8 +171,8 @@ class Create extends Base /* @var Document $function */ $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php index 70912cf58c..aec9d56543 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php @@ -53,6 +53,7 @@ class Get extends Base ->inject('response') ->inject('dbForProject') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } @@ -61,12 +62,13 @@ class Get extends Base string $executionId, Response $response, Database $dbForProject, - Authorization $authorization + Authorization $authorization, + User $user ) { $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php index dcc3f6ee9c..b12980b222 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -62,6 +62,7 @@ class XList extends Base ->inject('response') ->inject('dbForProject') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } @@ -71,12 +72,13 @@ class XList extends Base bool $includeTotal, Response $response, Database $dbForProject, - Authorization $authorization + Authorization $authorization, + User $user ) { $function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::FUNCTION_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php index 827dbc8dd9..c67601dae9 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Create.php @@ -103,7 +103,7 @@ class Create extends Action Request $request, Response $response, Database $dbForProject, - Document $user, + User $user, Event $queueForEvents, string $mode, Device $deviceForFiles, @@ -112,8 +112,8 @@ class Create extends Action ) { $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php index ca376842e2..aa7f14d2ed 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Delete.php @@ -66,6 +66,7 @@ class Delete extends Action ->inject('deviceForFiles') ->inject('queueForDeletes') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } @@ -77,12 +78,13 @@ class Delete extends Action Event $queueForEvents, Device $deviceForFiles, DeleteEvent $queueForDeletes, - Authorization $authorization + Authorization $authorization, + User $user ) { $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php index 042ae76565..c876004319 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Download/Get.php @@ -70,6 +70,7 @@ class Get extends Action ->inject('resourceToken') ->inject('deviceForFiles') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } @@ -84,12 +85,13 @@ class Get extends Action Document $resourceToken, Device $deviceForFiles, Authorization $authorization, + User $user, ) { /* @type Document $bucket */ $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php index caaab29efc..c9ce5796eb 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Get.php @@ -51,6 +51,7 @@ class Get extends Action ->inject('response') ->inject('dbForProject') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } @@ -59,12 +60,13 @@ class Get extends Action string $fileId, Response $response, Database $dbForProject, - Authorization $authorization + Authorization $authorization, + User $user ) { $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php index 63a72fc683..a5e48be478 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Preview/Get.php @@ -92,6 +92,7 @@ class Get extends Action ->inject('deviceForLocal') ->inject('project') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } @@ -117,7 +118,8 @@ class Get extends Action Device $deviceForFiles, Device $deviceForLocal, Document $project, - Authorization $authorization + Authorization $authorization, + User $user ) { if (!\extension_loaded('imagick')) { @@ -127,8 +129,8 @@ class Get extends Action /* @type Document $bucket */ $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -271,7 +273,7 @@ class Get extends Action $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; //Do not update transformedAt if it's a console user - if (!User::isPrivileged($authorization->getRoles())) { + if (!$user->isPrivileged($authorization->getRoles())) { $transformedAt = $file->getAttribute('transformedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) { $file->setAttribute('transformedAt', DateTime::now()); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php index c475c53d24..5b3fd02370 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Push/Get.php @@ -52,6 +52,7 @@ class Get extends Action ->inject('mode') ->inject('deviceForFiles') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } @@ -66,7 +67,8 @@ class Get extends Action Document $project, string $mode, Device $deviceForFiles, - Authorization $authorization + Authorization $authorization, + User $user ) { $decoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); @@ -88,8 +90,8 @@ class Get extends Action $disposition = $decoded['disposition'] ?? 'inline'; $dbForProject = $isInternal ? $dbForPlatform : $dbForProject; - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php index 57856c1564..8e69468170 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/Update.php @@ -64,6 +64,7 @@ class Update extends Action ->inject('dbForProject') ->inject('queueForEvents') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } @@ -75,12 +76,13 @@ class Update extends Action Response $response, Database $dbForProject, Event $queueForEvents, - Authorization $authorization + Authorization $authorization, + User $user ) { $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -108,7 +110,7 @@ class Update extends Action // Users can only manage their own roles, API keys and Admin users can manage any $roles = $authorization->getRoles(); - if (!User::isApp($roles) && !User::isPrivileged($roles) && !\is_null($permissions)) { + if (!$user->isApp($roles) && !$user->isPrivileged($roles) && !\is_null($permissions)) { foreach (Database::PERMISSIONS as $type) { foreach ($permissions as $permission) { $permission = Permission::parse($permission); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php index cba6c2fa13..b2f00da6d2 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/View/Get.php @@ -71,6 +71,7 @@ class Get extends Action ->inject('resourceToken') ->inject('deviceForFiles') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } @@ -84,13 +85,14 @@ class Get extends Action string $mode, Document $resourceToken, Device $deviceForFiles, - Authorization $authorization + Authorization $authorization, + User $user ) { /* @type Document $bucket */ $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php index 6de360ae0e..945c4bfd7c 100644 --- a/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Storage/Http/Buckets/Files/XList.php @@ -63,6 +63,7 @@ class XList extends Action ->inject('dbForProject') ->inject('mode') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } @@ -74,12 +75,13 @@ class XList extends Action Response $response, Database $dbForProject, string $mode, - Authorization $authorization + Authorization $authorization, + User $user ) { $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Teams/Http/Memberships/Create.php b/src/Appwrite/Platform/Modules/Teams/Http/Memberships/Create.php index 0632aea3dd..777184f2f2 100644 --- a/src/Appwrite/Platform/Modules/Teams/Http/Memberships/Create.php +++ b/src/Appwrite/Platform/Modules/Teams/Http/Memberships/Create.php @@ -98,10 +98,10 @@ class Create extends Action ->callback($this->action(...)); } - public function action(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, Context $usage, array $plan, Password $proofForPassword, Token $proofForToken) + public function action(string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, User $user, Database $dbForProject, Authorization $authorization, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, Context $usage, array $plan, Password $proofForPassword, Token $proofForToken) { - $isAppUser = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAppUser = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if (empty($url)) { if (! $isAppUser && ! $isPrivilegedUser) { diff --git a/src/Appwrite/Platform/Modules/Teams/Http/Memberships/Get.php b/src/Appwrite/Platform/Modules/Teams/Http/Memberships/Get.php index 9bfbd8528e..f3fd9a4bb9 100644 --- a/src/Appwrite/Platform/Modules/Teams/Http/Memberships/Get.php +++ b/src/Appwrite/Platform/Modules/Teams/Http/Memberships/Get.php @@ -52,10 +52,11 @@ class Get extends Action ->inject('project') ->inject('dbForProject') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } - public function action(string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject, Authorization $authorization) + public function action(string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject, Authorization $authorization, User $user) { $team = $dbForProject->getDocument('teams', $teamId); @@ -76,25 +77,25 @@ class Get extends Action ]; $roles = $authorization->getRoles(); - $isPrivilegedUser = User::isPrivileged($roles); - $isAppUser = User::isApp($roles); + $isPrivilegedUser = $user->isPrivileged($roles); + $isAppUser = $user->isApp($roles); $membershipsPrivacy = array_map(function ($privacy) use ($isPrivilegedUser, $isAppUser) { return $privacy || $isPrivilegedUser || $isAppUser; }, $membershipsPrivacy); - $user = !empty(array_filter($membershipsPrivacy)) + $memberUser = !empty(array_filter($membershipsPrivacy)) ? $dbForProject->getDocument('users', $membership->getAttribute('userId')) : new Document(); if ($membershipsPrivacy['mfa']) { - $mfa = $user->getAttribute('mfa', false); + $mfa = $memberUser->getAttribute('mfa', false); if ($mfa) { - $totp = TOTP::getAuthenticatorFromUser($user); + $totp = TOTP::getAuthenticatorFromUser($memberUser); $totpEnabled = $totp && $totp->getAttribute('verified', false); - $emailEnabled = $user->getAttribute('email', false) && $user->getAttribute('emailVerification', false); - $phoneEnabled = $user->getAttribute('phone', false) && $user->getAttribute('phoneVerification', false); + $emailEnabled = $memberUser->getAttribute('email', false) && $memberUser->getAttribute('emailVerification', false); + $phoneEnabled = $memberUser->getAttribute('phone', false) && $memberUser->getAttribute('phoneVerification', false); if (!$totpEnabled && !$emailEnabled && !$phoneEnabled) { $mfa = false; @@ -105,11 +106,11 @@ class Get extends Action } if ($membershipsPrivacy['userName']) { - $membership->setAttribute('userName', $user->getAttribute('name')); + $membership->setAttribute('userName', $memberUser->getAttribute('name')); } if ($membershipsPrivacy['userEmail']) { - $membership->setAttribute('userEmail', $user->getAttribute('email')); + $membership->setAttribute('userEmail', $memberUser->getAttribute('email')); } $membership->setAttribute('teamName', $team->getAttribute('name')); diff --git a/src/Appwrite/Platform/Modules/Teams/Http/Memberships/Update.php b/src/Appwrite/Platform/Modules/Teams/Http/Memberships/Update.php index a935055163..540dc8a871 100644 --- a/src/Appwrite/Platform/Modules/Teams/Http/Memberships/Update.php +++ b/src/Appwrite/Platform/Modules/Teams/Http/Memberships/Update.php @@ -66,7 +66,7 @@ class Update extends Action ->callback($this->action(...)); } - public function action(string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Authorization $authorization, Event $queueForEvents) + public function action(string $teamId, string $membershipId, array $roles, Request $request, Response $response, User $user, Document $project, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -83,8 +83,8 @@ class Update extends Action throw new Exception(Exception::USER_NOT_FOUND); } - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $isAppUser = User::isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); + $isAppUser = $user->isApp($authorization->getRoles()); $isOwner = $authorization->hasRole('team:' . $team->getId() . '/owner'); if ($project->getId() === 'console') { diff --git a/src/Appwrite/Platform/Modules/Teams/Http/Memberships/XList.php b/src/Appwrite/Platform/Modules/Teams/Http/Memberships/XList.php index ba59f48b43..364f92e1c5 100644 --- a/src/Appwrite/Platform/Modules/Teams/Http/Memberships/XList.php +++ b/src/Appwrite/Platform/Modules/Teams/Http/Memberships/XList.php @@ -61,10 +61,11 @@ class XList extends Action ->inject('project') ->inject('dbForProject') ->inject('authorization') + ->inject('user') ->callback($this->action(...)); } - public function action(string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject, Authorization $authorization) + public function action(string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject, Authorization $authorization, User $user) { $team = $dbForProject->getDocument('teams', $teamId); @@ -129,26 +130,26 @@ class XList extends Action ]; $roles = $authorization->getRoles(); - $isPrivilegedUser = User::isPrivileged($roles); - $isAppUser = User::isApp($roles); + $isPrivilegedUser = $user->isPrivileged($roles); + $isAppUser = $user->isApp($roles); $membershipsPrivacy = array_map(function ($privacy) use ($isPrivilegedUser, $isAppUser) { return $privacy || $isPrivilegedUser || $isAppUser; }, $membershipsPrivacy); $memberships = array_map(function ($membership) use ($dbForProject, $team, $membershipsPrivacy) { - $user = !empty(array_filter($membershipsPrivacy)) + $memberUser = !empty(array_filter($membershipsPrivacy)) ? $dbForProject->getDocument('users', $membership->getAttribute('userId')) : new Document(); if ($membershipsPrivacy['mfa']) { - $mfa = $user->getAttribute('mfa', false); + $mfa = $memberUser->getAttribute('mfa', false); if ($mfa) { - $totp = TOTP::getAuthenticatorFromUser($user); + $totp = TOTP::getAuthenticatorFromUser($memberUser); $totpEnabled = $totp && $totp->getAttribute('verified', false); - $emailEnabled = $user->getAttribute('email', false) && $user->getAttribute('emailVerification', false); - $phoneEnabled = $user->getAttribute('phone', false) && $user->getAttribute('phoneVerification', false); + $emailEnabled = $memberUser->getAttribute('email', false) && $memberUser->getAttribute('emailVerification', false); + $phoneEnabled = $memberUser->getAttribute('phone', false) && $memberUser->getAttribute('phoneVerification', false); if (!$totpEnabled && !$emailEnabled && !$phoneEnabled) { $mfa = false; @@ -159,11 +160,11 @@ class XList extends Action } if ($membershipsPrivacy['userName']) { - $membership->setAttribute('userName', $user->getAttribute('name')); + $membership->setAttribute('userName', $memberUser->getAttribute('name')); } if ($membershipsPrivacy['userEmail']) { - $membership->setAttribute('userEmail', $user->getAttribute('email')); + $membership->setAttribute('userEmail', $memberUser->getAttribute('email')); } $membership->setAttribute('teamName', $team->getAttribute('name')); diff --git a/src/Appwrite/Platform/Modules/Teams/Http/Teams/Create.php b/src/Appwrite/Platform/Modules/Teams/Http/Teams/Create.php index ae20017e76..0d20a58b6b 100644 --- a/src/Appwrite/Platform/Modules/Teams/Http/Teams/Create.php +++ b/src/Appwrite/Platform/Modules/Teams/Http/Teams/Create.php @@ -68,10 +68,10 @@ class Create extends Action ->callback($this->action(...)); } - public function action(string $teamId, string $name, array $roles, Response $response, Document $user, Database $dbForProject, Authorization $authorization, Event $queueForEvents) + public function action(string $teamId, string $name, array $roles, Response $response, User $user, Database $dbForProject, Authorization $authorization, Event $queueForEvents) { - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); - $isAppUser = User::isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); + $isAppUser = $user->isApp($authorization->getRoles()); $teamId = $teamId == 'unique()' ? ID::unique() : $teamId; diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php index 5f1bd55788..934074d3c2 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 @@ -11,12 +11,12 @@ 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, Authorization $authorization, User $user, string $bucketId, string $fileId): array { $bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = User::isApp($authorization->getRoles()); - $isPrivilegedUser = User::isPrivileged($authorization->getRoles()); + $isAPIKey = $user->isApp($authorization->getRoles()); + $isPrivilegedUser = $user->isPrivileged($authorization->getRoles()); if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); 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 10257d3603..1c2bd692ef 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 @@ -8,6 +8,7 @@ use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Database\Documents\User; use Appwrite\Utopia\Response; use Utopia\Auth\Proofs\Token; use Utopia\Database\Database; @@ -64,19 +65,20 @@ class Create extends Action ->param('fileId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'File unique ID.', false, ['dbForProject']) ->param('expire', null, new Nullable(new DatetimeValidator(requireDateInFuture: true)), 'Token expiry date', true) ->inject('response') + ->inject('user') ->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, User $user, Database $dbForProject, Event $queueForEvents, Authorization $authorization): void { /** * @var Document $bucket * @var Document $file */ - ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $bucketId, $fileId); + ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $user, $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 3d7be9bf81..5a93a06f26 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 @@ -7,6 +7,7 @@ use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Database\Documents\User; use Appwrite\Utopia\Database\Validator\Queries\FileTokens; use Appwrite\Utopia\Response; use Utopia\Database\Database; @@ -57,14 +58,15 @@ class XList extends Action ->param('queries', [], new FileTokens(), '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(', ', FileTokens::ALLOWED_ATTRIBUTES), 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('response') + ->inject('user') ->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, User $user, Database $dbForProject, Authorization $authorization) { - ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $bucketId, $fileId); + ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $authorization, $user, $bucketId, $fileId); $queries = Query::parseQueries($queries); $queries[] = Query::equal('resourceType', [TOKENS_RESOURCE_TYPE_FILES]); diff --git a/src/Appwrite/Utopia/Database/Documents/User.php b/src/Appwrite/Utopia/Database/Documents/User.php index bef73b31d9..50e66dac38 100644 --- a/src/Appwrite/Utopia/Database/Documents/User.php +++ b/src/Appwrite/Utopia/Database/Documents/User.php @@ -102,7 +102,7 @@ class User extends Document * * @return bool */ - public static function isPrivileged(array $roles): bool + public function isPrivileged(array $roles): bool { if ( in_array(self::ROLE_OWNER, $roles) || @@ -122,7 +122,7 @@ class User extends Document * * @return bool */ - public static function isApp(array $roles): bool + public function isApp(array $roles): bool { if (in_array(self::ROLE_APPS, $roles)) { return true; @@ -175,7 +175,5 @@ class User extends Document } return false; - - return false; } } diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index a5b3d038bb..9428ff9d88 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -215,7 +215,7 @@ class Request extends UtopiaRequest $forwardedUserAgent = $this->getHeader('x-forwarded-user-agent'); if (!empty($forwardedUserAgent)) { $roles = $this->authorization->getRoles(); - $isAppUser = User::isApp($roles); + $isAppUser = $this->user?->isApp($roles) ?? false; if ($isAppUser) { return $forwardedUserAgent; @@ -239,9 +239,15 @@ class Request extends UtopiaRequest } private ?Authorization $authorization = null; + private ?User $user = null; public function setAuthorization(Authorization $authorization): void { $this->authorization = $authorization; } + + public function setUser(User $user): void + { + $this->user = $user; + } } diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index c2fc520da3..99170a58c9 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -505,8 +505,9 @@ class Response extends SwooleResponse if ($rule['sensitive']) { $roles = $this->authorization->getRoles(); - $isPrivilegedUser = DBUser::isPrivileged($roles); - $isAppUser = DBUser::isApp($roles); + $user = $this->user ?? new DBUser(); + $isPrivilegedUser = $user->isPrivileged($roles); + $isAppUser = $user->isApp($roles); if ((!$isPrivilegedUser && !$isAppUser) && !self::$showSensitive) { $data->setAttribute($key, ''); @@ -674,9 +675,15 @@ class Response extends SwooleResponse } private ?Authorization $authorization = null; + private ?DBUser $user = null; public function setAuthorization(Authorization $authorization): void { $this->authorization = $authorization; } + + public function setUser(DBUser $user): void + { + $this->user = $user; + } } diff --git a/tests/unit/Utopia/Database/Documents/UserTest.php b/tests/unit/Utopia/Database/Documents/UserTest.php index 4094b43246..b3638e7d3a 100644 --- a/tests/unit/Utopia/Database/Documents/UserTest.php +++ b/tests/unit/Utopia/Database/Documents/UserTest.php @@ -171,36 +171,40 @@ class UserTest extends TestCase public function testIsPrivilegedUser(): void { - $this->assertEquals(false, User::isPrivileged([])); - $this->assertEquals(false, User::isPrivileged([Role::guests()->toString()])); - $this->assertEquals(false, User::isPrivileged([Role::users()->toString()])); - $this->assertEquals(true, User::isPrivileged([User::ROLE_ADMIN])); - $this->assertEquals(true, User::isPrivileged([User::ROLE_DEVELOPER])); - $this->assertEquals(true, User::isPrivileged([User::ROLE_OWNER])); - $this->assertEquals(false, User::isPrivileged([User::ROLE_APPS])); - $this->assertEquals(false, User::isPrivileged([User::ROLE_SYSTEM])); + $user = new User(); - $this->assertEquals(false, User::isPrivileged([User::ROLE_APPS, User::ROLE_APPS])); - $this->assertEquals(false, User::isPrivileged([User::ROLE_APPS, Role::guests()->toString()])); - $this->assertEquals(true, User::isPrivileged([User::ROLE_OWNER, Role::guests()->toString()])); - $this->assertEquals(true, User::isPrivileged([User::ROLE_OWNER, User::ROLE_ADMIN, User::ROLE_DEVELOPER])); + $this->assertEquals(false, $user->isPrivileged([])); + $this->assertEquals(false, $user->isPrivileged([Role::guests()->toString()])); + $this->assertEquals(false, $user->isPrivileged([Role::users()->toString()])); + $this->assertEquals(true, $user->isPrivileged([User::ROLE_ADMIN])); + $this->assertEquals(true, $user->isPrivileged([User::ROLE_DEVELOPER])); + $this->assertEquals(true, $user->isPrivileged([User::ROLE_OWNER])); + $this->assertEquals(false, $user->isPrivileged([User::ROLE_APPS])); + $this->assertEquals(false, $user->isPrivileged([User::ROLE_SYSTEM])); + + $this->assertEquals(false, $user->isPrivileged([User::ROLE_APPS, User::ROLE_APPS])); + $this->assertEquals(false, $user->isPrivileged([User::ROLE_APPS, Role::guests()->toString()])); + $this->assertEquals(true, $user->isPrivileged([User::ROLE_OWNER, Role::guests()->toString()])); + $this->assertEquals(true, $user->isPrivileged([User::ROLE_OWNER, User::ROLE_ADMIN, User::ROLE_DEVELOPER])); } public function testIsAppUser(): void { - $this->assertEquals(false, User::isApp([])); - $this->assertEquals(false, User::isApp([Role::guests()->toString()])); - $this->assertEquals(false, User::isApp([Role::users()->toString()])); - $this->assertEquals(false, User::isApp([User::ROLE_ADMIN])); - $this->assertEquals(false, User::isApp([User::ROLE_DEVELOPER])); - $this->assertEquals(false, User::isApp([User::ROLE_OWNER])); - $this->assertEquals(true, User::isApp([User::ROLE_APPS])); - $this->assertEquals(false, User::isApp([User::ROLE_SYSTEM])); + $user = new User(); - $this->assertEquals(true, User::isApp([User::ROLE_APPS, User::ROLE_APPS])); - $this->assertEquals(true, User::isApp([User::ROLE_APPS, Role::guests()->toString()])); - $this->assertEquals(false, User::isApp([User::ROLE_OWNER, Role::guests()->toString()])); - $this->assertEquals(false, User::isApp([User::ROLE_OWNER, User::ROLE_ADMIN, User::ROLE_DEVELOPER])); + $this->assertEquals(false, $user->isApp([])); + $this->assertEquals(false, $user->isApp([Role::guests()->toString()])); + $this->assertEquals(false, $user->isApp([Role::users()->toString()])); + $this->assertEquals(false, $user->isApp([User::ROLE_ADMIN])); + $this->assertEquals(false, $user->isApp([User::ROLE_DEVELOPER])); + $this->assertEquals(false, $user->isApp([User::ROLE_OWNER])); + $this->assertEquals(true, $user->isApp([User::ROLE_APPS])); + $this->assertEquals(false, $user->isApp([User::ROLE_SYSTEM])); + + $this->assertEquals(true, $user->isApp([User::ROLE_APPS, User::ROLE_APPS])); + $this->assertEquals(true, $user->isApp([User::ROLE_APPS, Role::guests()->toString()])); + $this->assertEquals(false, $user->isApp([User::ROLE_OWNER, Role::guests()->toString()])); + $this->assertEquals(false, $user->isApp([User::ROLE_OWNER, User::ROLE_ADMIN, User::ROLE_DEVELOPER])); } public function testGuestRoles(): void