Skip to content

Commit cb03445

Browse files
UN-3586 [FIX] Move rotate self-check to has_object_permission (PR review)
Relocate the 'key may rotate only its own key' constraint from has_permission (view-level, via view.kwargs[pk]) to has_object_permission, the idiomatic DRF location for per-object access control — it receives the already-fetched obj. has_permission stays as the coarse session-vs-key gate. Behavior is unchanged (self-rotate 200, cross-key 403): this permission is only used by the rotate detail action, which calls get_object() and so always triggers the object-level check. (Greptile)
1 parent baf9415 commit cb03445

1 file changed

Lines changed: 18 additions & 4 deletions

File tree

backend/platform_api/permissions.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ class CanRotatePlatformApiKey(BasePermission):
3434
enforced upstream (auth middleware + org-scoped queryset); this adds the
3535
intra-org "self only" restriction for key callers.
3636
37+
The "self only" constraint for key callers is enforced object-level in
38+
``has_object_permission`` (the idiomatic DRF location); ``has_permission``
39+
is the coarse session-vs-key gate. This permission is only used by the
40+
detail-route ``rotate`` action, which fetches the row via ``get_object()``
41+
and therefore always triggers the object-level check.
42+
3743
Note: the auth middleware already blocks ``read`` keys from POST, so only
3844
``read_write``/``full_access`` keys can reach rotate.
3945
"""
@@ -46,9 +52,17 @@ class CanRotatePlatformApiKey(BasePermission):
4652
def has_permission(self, request, view):
4753
if not request.user or not request.user.is_authenticated:
4854
return False
49-
platform_key = getattr(request, "platform_api_key", None)
50-
if platform_key is not None:
51-
# Platform API key caller: self-rotation only.
52-
return str(view.kwargs.get("pk")) == str(platform_key.id)
55+
if getattr(request, "platform_api_key", None) is not None:
56+
# Platform API key caller: admitted here; the "own key only"
57+
# constraint is enforced in has_object_permission below.
58+
return True
5359
# Session caller: must be an org admin (may rotate any key in the org).
5460
return IsOrganizationAdmin().has_permission(request, view)
61+
62+
def has_object_permission(self, request, view, obj):
63+
platform_key = getattr(request, "platform_api_key", None)
64+
if platform_key is not None:
65+
# Platform API key may rotate only its own key.
66+
return obj.id == platform_key.id
67+
# Session admins were already gated in has_permission.
68+
return True

0 commit comments

Comments
 (0)