11"""
2- Legacy authorization checks .
2+ OS authorization: is_superuser / is_staff / authorized_users .
33
4- The hierarchical RBAC role system has been replaced with the simpler
5- pre-2020 model: a user is authorized for an action on an object iff
4+ The hierarchical RBAC role system has been moved out of OS to the dojo-pro
5+ plugin. OS-only deployments authorize an action on an object iff
66
77 * the user is a superuser, or
8- * the user is staff and the action is non-destructive
9- (View / Edit / Add / Import; Delete and member-management require explicit
10- staff confirmation but legacy treats every staff user as eligible), or
8+ * the user is staff and the action is non-destructive (legacy treats
9+ every staff user as eligible for staff-only and delete actions), or
1110 * the user is in the relevant ``authorized_users`` ManyToMany
1211 (climbing the Product_Type → Product → Engagement → Test → Finding
1312 hierarchy until an explicit membership is found).
1413
1514Per-product role granularity (Reader / Writer / Maintainer / Owner),
16- group-level authorization, and configuration permissions per add/edit/delete
17- codename are not present in this model. Deployments that need that fidelity
18- should run the dojo-pro plugin, which keeps the RBAC layer alive and shadows
19- this module's symbols at startup so the same code paths route through Pro.
20-
21- The public surface (function names + signatures) is preserved so existing
22- callers in dojo/views.py, dojo/forms.py, etc. keep compiling. Track B step
23- #13 simplifies callers to pass action strings directly; until that lands,
24- the existing ``Permissions.X`` enum members are still accepted and reduced
25- to a legacy Action via ``permission_to_action()``.
15+ group-level authorization, and Member/Group/Role tables are not consulted
16+ in this model. Deployments that need that fidelity should run the
17+ dojo-pro plugin, which keeps the RBAC layer alive and shadows this
18+ module's symbols at startup so the same code paths route through Pro.
2619"""
2720from django .core .exceptions import PermissionDenied
28- from django .db .models import Model , QuerySet
29-
30- from dojo .authorization .models import (
31- Dojo_Group_Member ,
32- Product_Group ,
33- Product_Member ,
34- Product_Type_Group ,
35- Product_Type_Member ,
36- )
21+ from django .db .models import Model
22+
3723from dojo .authorization .roles_permissions import (
3824 Action ,
3925 permission_to_action ,
4228from dojo .models import (
4329 App_Analysis ,
4430 Cred_Mapping ,
45- Dojo_Group ,
4631 Dojo_User ,
4732 Endpoint ,
4833 Engagement ,
@@ -106,10 +91,8 @@ def user_has_permission(user: Dojo_User, obj: Model, permission) -> bool:
10691 dojo/user/helper.py at commit e7805aa14~ for the historical
10792 reference.
10893
109- The Member / Group / Cred_Mapping / etc. carrier objects don't expose
110- authorized_users themselves; they delegate to their wrapped product
111- or product type, except for self-removal (a user is always allowed to
112- delete their own membership row).
94+ Cred_Mapping and other carrier objects don't expose authorized_users
95+ themselves; they delegate to their wrapped product or product type.
11396 """
11497 if not user or getattr (user , "is_anonymous" , False ):
11598 return False
@@ -124,10 +107,6 @@ def user_has_permission(user: Dojo_User, obj: Model, permission) -> bool:
124107 if action in {Action .StaffOnly , Action .Delete }:
125108 return bool (user .is_staff )
126109
127- # Member/group self-deletion: any user can remove their own membership
128- if isinstance (obj , Product_Type_Member | Product_Member | Dojo_Group_Member ) and obj .user_id == user .id :
129- return True
130-
131110 return _user_authorized_for (user , obj , action )
132111
133112
@@ -181,16 +160,6 @@ def _user_authorized_for(user: Dojo_User, obj: Model, action: Action) -> bool:
181160 if isinstance (obj , Endpoint | Languages | App_Analysis | Product_API_Scan_Configuration ):
182161 return _user_authorized_for (user , obj .product , action )
183162
184- if isinstance (obj , Product_Type_Member | Product_Type_Group ):
185- return _user_authorized_for (user , obj .product_type , action )
186-
187- if isinstance (obj , Product_Member | Product_Group ):
188- return _user_authorized_for (user , obj .product , action )
189-
190- if isinstance (obj , Dojo_Group | Dojo_Group_Member ):
191- # Group authorization is staff-only in legacy; non-staff already filtered out.
192- return bool (user .is_staff )
193-
194163 if isinstance (obj , Cred_Mapping ):
195164 if obj .product_id :
196165 return _user_authorized_for (user , obj .product , action )
@@ -244,25 +213,6 @@ def user_has_global_permission_or_403(user: Dojo_User, permission) -> None:
244213 raise PermissionDenied
245214
246215
247- # ---------------------------------------------------------------------------
248- # Backward-compat shims for the role hierarchy. Legacy authorization does not
249- # branch on roles, but call sites still import these symbols. Returning empty
250- # results keeps them harmless until Track B step #13 simplifies the callers.
251- # ---------------------------------------------------------------------------
252-
253-
254- def get_roles_for_permission (permission ) -> set [int ]:
255- return set ()
256-
257-
258- def role_has_permission (role : int , permission ) -> bool :
259- return False
260-
261-
262- def role_has_global_permission (role : int , permission ) -> bool :
263- return False
264-
265-
266216class NoAuthorizationImplementedError (Exception ):
267217 def __init__ (self , message ):
268218 self .message = message
@@ -276,56 +226,3 @@ def __init__(self, message):
276226class RoleDoesNotExistError (Exception ):
277227 def __init__ (self , message ):
278228 self .message = message
279-
280-
281- # ---------------------------------------------------------------------------
282- # RBAC member / group lookup helpers. These return empty/None under legacy —
283- # the underlying tables (Product_Member, Product_Type_Member, etc.) still
284- # exist in the database, but legacy authorization does not consult them.
285- # Track B step #13 will remove call sites; until then these stubs prevent
286- # AttributeError / TypeError in transitional code.
287- # ---------------------------------------------------------------------------
288-
289-
290- def get_product_member (user : Dojo_User , product : Product ) -> Product_Member | None :
291- return None
292-
293-
294- def get_product_member_dict (user : Dojo_User ) -> dict [int , Product_Member ]:
295- return {}
296-
297-
298- def get_product_type_member (user : Dojo_User , product_type : Product_Type ) -> Product_Type_Member | None :
299- return None
300-
301-
302- def get_product_type_member_dict (user : Dojo_User ) -> dict [int , Product_Type_Member ]:
303- return {}
304-
305-
306- def get_product_groups (user : Dojo_User , product : Product ) -> list [Product_Group ]:
307- return []
308-
309-
310- def get_product_groups_dict (user : Dojo_User ) -> dict [int , list [Product_Group ]]:
311- return {}
312-
313-
314- def get_product_type_groups (user : Dojo_User , product_type : Product_Type ) -> list [Product_Type_Group ]:
315- return []
316-
317-
318- def get_product_type_groups_dict (user : Dojo_User ) -> dict [int , list [Product_Type_Group ]]:
319- return {}
320-
321-
322- def get_groups (user : Dojo_User ) -> QuerySet [Dojo_Group ]:
323- return Dojo_Group .objects .none ()
324-
325-
326- def get_group_member (user : Dojo_User , group : Dojo_Group ) -> Dojo_Group_Member | None :
327- return None
328-
329-
330- def get_group_members_dict (user : Dojo_User ) -> dict [int , Dojo_Group_Member ]:
331- return {}
0 commit comments