fix: use User type hint instead of Document for $user parameter

PHPStan correctly flagged that Document::isPrivileged() doesn't exist.
Changed type hints from Document $user to User $user in all action
signatures where $user::isPrivileged() is called, since the runtime
instance is always a User (or subclass).

https://claude.ai/code/session_01JLPDurUgyj7qViA8JqQFTH
This commit is contained in:
Claude
2026-03-16 02:35:03 +00:00
parent 6041468fc4
commit 82d7926c4b
31 changed files with 38 additions and 35 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ Http::init()
->inject('project')
->inject('user')
->inject('authorization')
->action(function (Document $project, Document $user, Authorization $authorization) {
->action(function (Document $project, User $user, Authorization $authorization) {
if (
array_key_exists('graphql', $project->getAttribute('apis', []))
&& !$project->getAttribute('apis', [])['graphql']
+3 -2
View File
@@ -1272,8 +1272,9 @@ Http::error()
if (!$publish && $project->getId() !== 'console') {
$userClass = DBUser::class;
try {
$user = $utopia->getResource('user');
$userClass = $user::class;
/** @var DBUser $errorUser */
$errorUser = $utopia->getResource('user');
$userClass = $errorUser::class;
} catch (\Throwable) {
// User resource may not be available in error context
}
+2 -2
View File
@@ -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();
/**
@@ -483,7 +483,7 @@ 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);
+1 -1
View File
@@ -38,7 +38,7 @@ Http::init()
->inject('geodb')
->inject('user')
->inject('authorization')
->action(function (Http $utopia, Request $request, Document $project, Reader $geodb, Document $user, 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);
@@ -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)
@@ -103,7 +103,7 @@ class Delete extends Action
TransactionState $transactionState,
array $plan,
Authorization $authorization,
Document $user
User $user
): void {
$database = $authorization->skip(fn () => $dbForProject->getDocument('databases', $databaseId));
@@ -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
@@ -83,7 +83,7 @@ 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());
@@ -69,7 +69,7 @@ class Create extends Action
->callback($this->action(...));
}
public function action(string $transactionId, array $operations, UtopiaResponse $response, Database $dbForProject, TransactionState $transactionState, array $plan, Authorization $authorization, Document $user): 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');
@@ -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');
@@ -119,7 +119,7 @@ class Create extends Base
Document $project,
Database $dbForProject,
Database $dbForPlatform,
Document $user,
User $user,
Event $queueForEvents,
Context $usage,
Func $queueForFunctions,
@@ -64,7 +64,7 @@ class Get extends Base
Response $response,
Database $dbForProject,
Authorization $authorization,
Document $user
User $user
) {
$function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId));
@@ -73,7 +73,7 @@ class XList extends Base
Response $response,
Database $dbForProject,
Authorization $authorization,
Document $user
User $user
) {
$function = $authorization->skip(fn () => $dbForProject->getDocument('functions', $functionId));
@@ -103,7 +103,7 @@ class Create extends Action
Request $request,
Response $response,
Database $dbForProject,
Document $user,
User $user,
Event $queueForEvents,
string $mode,
Device $deviceForFiles,
@@ -80,7 +80,7 @@ class Delete extends Action
Device $deviceForFiles,
DeleteEvent $queueForDeletes,
Authorization $authorization,
Document $user
User $user
) {
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
@@ -85,7 +85,7 @@ class Get extends Action
Document $resourceToken,
Device $deviceForFiles,
Authorization $authorization,
Document $user,
User $user,
) {
/* @type Document $bucket */
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
@@ -62,7 +62,7 @@ class Get extends Action
Response $response,
Database $dbForProject,
Authorization $authorization,
Document $user
User $user
) {
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
@@ -119,7 +119,7 @@ class Get extends Action
Device $deviceForLocal,
Document $project,
Authorization $authorization,
Document $user
User $user
) {
if (!\extension_loaded('imagick')) {
@@ -68,7 +68,7 @@ class Get extends Action
string $mode,
Device $deviceForFiles,
Authorization $authorization,
Document $user
User $user
) {
$decoder = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0);
@@ -78,7 +78,7 @@ class Update extends Action
Database $dbForProject,
Event $queueForEvents,
Authorization $authorization,
Document $user
User $user
) {
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
@@ -86,7 +86,7 @@ class Get extends Action
Document $resourceToken,
Device $deviceForFiles,
Authorization $authorization,
Document $user
User $user
) {
/* @type Document $bucket */
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
@@ -76,7 +76,7 @@ class XList extends Action
Database $dbForProject,
string $mode,
Authorization $authorization,
Document $user
User $user
) {
$bucket = $authorization->skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
@@ -98,7 +98,7 @@ 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());
@@ -56,7 +56,7 @@ class Get extends Action
->callback($this->action(...));
}
public function action(string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject, Authorization $authorization, Document $user)
public function action(string $teamId, string $membershipId, Response $response, Document $project, Database $dbForProject, Authorization $authorization, User $user)
{
$team = $dbForProject->getDocument('teams', $teamId);
@@ -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()) {
@@ -65,7 +65,7 @@ class XList extends Action
->callback($this->action(...));
}
public function action(string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject, Authorization $authorization, Document $user)
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);
@@ -68,7 +68,7 @@ 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());
@@ -12,7 +12,7 @@ use Utopia\Platform\Action as UtopiaAction;
class Action extends UtopiaAction
{
protected function getFileAndBucket(Database $dbForProject, Authorization $authorization, Document $user, 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));
@@ -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;
@@ -71,7 +72,7 @@ class Create extends Action
->callback($this->action(...));
}
public function action(string $bucketId, string $fileId, ?string $expire, Response $response, Document $user, 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
@@ -8,6 +8,7 @@ use Appwrite\SDK\ContentType;
use Appwrite\SDK\Method;
use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Database\Validator\Queries\FileTokens;
use Appwrite\Utopia\Database\Documents\User;
use Appwrite\Utopia\Response;
use Utopia\Database\Database;
use Utopia\Database\Document;
@@ -63,7 +64,7 @@ class XList extends Action
->callback($this->action(...));
}
public function action(string $bucketId, string $fileId, array $queries, bool $includeTotal, Response $response, Document $user, 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, $user, $bucketId, $fileId);
+2 -2
View File
@@ -675,14 +675,14 @@ class Response extends SwooleResponse
}
private ?Authorization $authorization = null;
private ?Document $user = null;
private ?DBUser $user = null;
public function setAuthorization(Authorization $authorization): void
{
$this->authorization = $authorization;
}
public function setUser(Document $user): void
public function setUser(DBUser $user): void
{
$this->user = $user;
}