Skip to content

Commit d3789c0

Browse files
devGregAclaude
andcommitted
fix(authorization): restore is_staff bypass for View
The legacy rewrite had `is_staff and action != Action.View` guards on Product_Type and Product, denying staff users View unless they were in authorized_users. That diverged from the actual pre-2020 model: dojo/user/helper.py at commit e7805aa~ shows is_staff was an absolute bypass for every perm_type (view, change, delete, staff). A pre-2020 customer's staff users could see every product. Without this fix they would suddenly see nothing on /product after the upgrade — a behavior regression, not a faithful re-creation. Drop the carve-out in both the per-object check and the queryset filter. Document the historical reference in the docstring. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 7194e83 commit d3789c0

2 files changed

Lines changed: 15 additions & 8 deletions

File tree

dojo/authorization/authorization.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,13 @@ def user_has_permission(user: Dojo_User, obj: Model, permission) -> bool:
8787
3. action → mapped from Permissions / string / Action via permission_to_action
8888
4. SuperuserOnly action → deny (already handled superuser above)
8989
5. StaffOnly / Delete → require is_staff
90-
6. View / Edit / Add / Import → user.is_staff for non-View, or membership
91-
in the obj.authorized_users chain (climbing Product_Type ←
92-
Product ← Engagement ← Test ← Finding when needed).
90+
6. View / Edit / Add / Import → is_staff bypasses unconditionally,
91+
otherwise check membership in the obj.authorized_users chain
92+
(climbing Product_Type ← Product ← Engagement ← Test ← Finding).
93+
This matches the pre-Auth-V2 (pre-2020) behavior where is_staff
94+
was an absolute bypass on every perm_type — see
95+
dojo/user/helper.py at commit e7805aa14~ for the historical
96+
reference.
9397
9498
The Member / Group / Cred_Mapping / etc. carrier objects don't expose
9599
authorized_users themselves; they delegate to their wrapped product
@@ -125,12 +129,12 @@ def _user_authorized_for(user: Dojo_User, obj: Model, action: Action) -> bool:
125129
return False
126130

127131
if isinstance(obj, Product_Type):
128-
if user.is_staff and action != Action.View:
132+
if user.is_staff:
129133
return True
130134
return obj.authorized_users.filter(pk=user.pk).exists()
131135

132136
if isinstance(obj, Product):
133-
if user.is_staff and action != Action.View:
137+
if user.is_staff:
134138
return True
135139
if obj.authorized_users.filter(pk=user.pk).exists():
136140
return True

dojo/authorization/query_registrations.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
Product_Type_Member,
3030
)
3131
from dojo.authorization.query_filters import register_auth_filter
32-
from dojo.authorization.roles_permissions import Action, permission_to_action
32+
from dojo.authorization.roles_permissions import permission_to_action
3333
from dojo.location.models import Location, LocationFindingReference, LocationProductReference
3434
from dojo.models import (
3535
App_Analysis,
@@ -65,13 +65,16 @@ def _resolve_user(user):
6565
def _is_unrestricted(user, action):
6666
"""
6767
Returns True if the user can see every object regardless of membership.
68-
Superuser always; staff for non-View actions (legacy semantics).
68+
Superuser and staff both bypass — matches pre-2020 behavior where
69+
is_staff was an absolute bypass for every perm_type. The ``action``
70+
arg is retained for callers that may want to gate StaffOnly /
71+
SuperuserOnly differently in the future.
6972
"""
7073
if not user or getattr(user, "is_anonymous", False):
7174
return False
7275
if user.is_superuser:
7376
return True
74-
return bool(user.is_staff and action != Action.View)
77+
return bool(user.is_staff)
7578

7679

7780
def _authorized_product_ids(user):

0 commit comments

Comments
 (0)