From d8df5f1ea164bc55a87a3132fd037ec9745b8784 Mon Sep 17 00:00:00 2001 From: eldadfux Date: Fri, 13 Mar 2026 08:21:02 +0100 Subject: [PATCH] Updated comments and docs --- app/controllers/api/users.php | 2 +- app/controllers/shared/api.php | 3 ++- src/Appwrite/Platform/Tasks/Specs.php | 18 +++++++++--------- src/Appwrite/Utopia/Response/Model/Account.php | 2 +- src/Appwrite/Utopia/Response/Model/User.php | 2 +- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index c26738b5e1..a4fac593e2 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -1233,7 +1233,7 @@ Http::patch('/v1/users/:userId/impersonator') ] )) ->param('userId', '', fn (Database $dbForProject) => new UID($dbForProject->getAdapter()->getMaxUIDLength()), 'User ID.', false, ['dbForProject']) - ->param('impersonator', false, new Boolean(true), 'Whether the user can impersonate other users. When true, the user can pass impersonation headers to act as another user.') + ->param('impersonator', false, new Boolean(true), 'Whether the user can impersonate other users. When true, the user can browse project users to choose a target and can pass impersonation headers to act as that user.') ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 1e6598ee4f..c96c28aa14 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -338,7 +338,8 @@ Http::init() $scopes = \array_unique($scopes); - // Impersonators can browse users before and during impersonation. + // Intentional: impersonators get users.read so they can discover a target user + // before impersonation starts, and keep that access while impersonating. if ( !$user->isEmpty() && ( diff --git a/src/Appwrite/Platform/Tasks/Specs.php b/src/Appwrite/Platform/Tasks/Specs.php index 4f8e9dad9e..e030b2eaaf 100644 --- a/src/Appwrite/Platform/Tasks/Specs.php +++ b/src/Appwrite/Platform/Tasks/Specs.php @@ -163,19 +163,19 @@ class Specs extends Action 'ImpersonateUserId' => [ 'type' => 'apiKey', 'name' => 'X-Appwrite-Impersonate-User-Id', - 'description' => 'Impersonate a user by ID. Requires the current user to have impersonator capability.', + 'description' => 'Impersonate a user by ID on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins.', 'in' => 'header', ], 'ImpersonateUserEmail' => [ 'type' => 'apiKey', 'name' => 'X-Appwrite-Impersonate-User-Email', - 'description' => 'Impersonate a user by email. Requires the current user to have impersonator capability.', + 'description' => 'Impersonate a user by email on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins.', 'in' => 'header', ], 'ImpersonateUserPhone' => [ 'type' => 'apiKey', 'name' => 'X-Appwrite-Impersonate-User-Phone', - 'description' => 'Impersonate a user by phone. Requires the current user to have impersonator capability.', + 'description' => 'Impersonate a user by phone on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins.', 'in' => 'header', ], ], @@ -219,19 +219,19 @@ class Specs extends Action 'ImpersonateUserId' => [ 'type' => 'apiKey', 'name' => 'X-Appwrite-Impersonate-User-Id', - 'description' => 'Impersonate a user by ID. Requires the current user to have impersonator capability.', + 'description' => 'Impersonate a user by ID on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins.', 'in' => 'header', ], 'ImpersonateUserEmail' => [ 'type' => 'apiKey', 'name' => 'X-Appwrite-Impersonate-User-Email', - 'description' => 'Impersonate a user by email. Requires the current user to have impersonator capability.', + 'description' => 'Impersonate a user by email on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins.', 'in' => 'header', ], 'ImpersonateUserPhone' => [ 'type' => 'apiKey', 'name' => 'X-Appwrite-Impersonate-User-Phone', - 'description' => 'Impersonate a user by phone. Requires the current user to have impersonator capability.', + 'description' => 'Impersonate a user by phone on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins.', 'in' => 'header', ], ], @@ -275,19 +275,19 @@ class Specs extends Action 'ImpersonateUserId' => [ 'type' => 'apiKey', 'name' => 'X-Appwrite-Impersonate-User-Id', - 'description' => 'Impersonate a user by ID. Requires the current user to have impersonator capability.', + 'description' => 'Impersonate a user by ID on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins.', 'in' => 'header', ], 'ImpersonateUserEmail' => [ 'type' => 'apiKey', 'name' => 'X-Appwrite-Impersonate-User-Email', - 'description' => 'Impersonate a user by email. Requires the current user to have impersonator capability.', + 'description' => 'Impersonate a user by email on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins.', 'in' => 'header', ], 'ImpersonateUserPhone' => [ 'type' => 'apiKey', 'name' => 'X-Appwrite-Impersonate-User-Phone', - 'description' => 'Impersonate a user by phone. Requires the current user to have impersonator capability.', + 'description' => 'Impersonate a user by phone on an already user-authenticated request. Requires the current request to be authenticated as a user with impersonator capability; X-Appwrite-Key alone is not sufficient. Impersonator users are intentionally granted users.read so they can discover a target before impersonation begins.', 'in' => 'header', ], ], diff --git a/src/Appwrite/Utopia/Response/Model/Account.php b/src/Appwrite/Utopia/Response/Model/Account.php index 679d24e3d5..b2656b7f3f 100644 --- a/src/Appwrite/Utopia/Response/Model/Account.php +++ b/src/Appwrite/Utopia/Response/Model/Account.php @@ -118,7 +118,7 @@ class Account extends Model ]) ->addRule('impersonatorUserId', [ 'type' => self::TYPE_STRING, - 'description' => 'When present, the current session is impersonating this user ID. Only set when the request used impersonation headers.', + 'description' => 'ID of the user performing the impersonation. Present only when the current request is impersonating another user.', 'required' => false, 'default' => '', 'example' => '5e5ea5c16897e', diff --git a/src/Appwrite/Utopia/Response/Model/User.php b/src/Appwrite/Utopia/Response/Model/User.php index 18b1419c5b..fb74452029 100644 --- a/src/Appwrite/Utopia/Response/Model/User.php +++ b/src/Appwrite/Utopia/Response/Model/User.php @@ -148,7 +148,7 @@ class User extends Model ]) ->addRule('impersonatorUserId', [ 'type' => self::TYPE_STRING, - 'description' => 'When present, the current session is impersonating this user ID. Only set when the request used impersonation headers.', + 'description' => 'ID of the user performing the impersonation. Present only when the current request is impersonating another user.', 'required' => false, 'default' => '', 'example' => '5e5ea5c16897e',