Skip to content

Commit 79d9198

Browse files
committed
Enhance permission checks to support multiple primary key attributes in post requests
1 parent bc5a18c commit 79d9198

1 file changed

Lines changed: 39 additions & 26 deletions

File tree

dojo/api_v2/permissions.py

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import re
2+
from collections.abc import Iterable
23

4+
from django.db.models import Model
35
from django.shortcuts import get_object_or_404
46
from rest_framework import permissions, serializers
57
from rest_framework.exceptions import (
68
ParseError,
79
PermissionDenied,
810
ValidationError,
911
)
12+
from rest_framework.request import Request
1013

1114
from dojo.authorization.authorization import (
1215
user_has_configuration_permission,
@@ -29,24 +32,34 @@
2932
)
3033

3134

32-
def check_post_permission(request, post_model, post_pk, post_permission):
35+
def check_post_permission(request: Request, post_model: Model, post_pk: str | Iterable[str], post_permission: int) -> bool:
3336
if request.method == "POST":
34-
if request.data.get(post_pk) is None:
35-
msg = f"Unable to check for permissions: Attribute '{post_pk}' is required"
37+
eligible_post_pk = None
38+
# Support both single PK string and list of PK strings
39+
searchable_post_pks = post_pk if isinstance(post_pk, Iterable) else [post_pk]
40+
# Iterate until we find a matching PK in the request data
41+
for pk in searchable_post_pks:
42+
if request.data.get(pk) is not None:
43+
eligible_post_pk = pk
44+
break
45+
# Raise an error if we never find anything
46+
if eligible_post_pk is None:
47+
msg = f"Unable to check for permissions: No valid attribute in '{post_pk}' is required"
3648
raise ParseError(msg)
37-
obj = get_object_or_404(post_model, pk=request.data.get(post_pk))
49+
# Attempt to get the object
50+
obj = get_object_or_404(post_model, pk=request.data.get(eligible_post_pk))
3851
return user_has_permission(request.user, obj, post_permission)
3952
return True
4053

4154

4255
def check_object_permission(
43-
request,
44-
obj,
45-
get_permission,
46-
put_permission,
47-
delete_permission,
48-
post_permission=None,
49-
):
56+
request: Request,
57+
obj: Model,
58+
get_permission: int,
59+
put_permission: int,
60+
delete_permission: int,
61+
post_permission: int | None = None,
62+
) -> bool:
5063
if request.method == "GET":
5164
return user_has_permission(request.user, obj, get_permission)
5265
if request.method in {"PUT", "PATCH"}:
@@ -61,7 +74,7 @@ def check_object_permission(
6174
class UserHasAppAnalysisPermission(permissions.BasePermission):
6275
def has_permission(self, request, view):
6376
return check_post_permission(
64-
request, Product, "product", Permissions.Technology_Add,
77+
request, Product, ["product", "asset"], Permissions.Technology_Add,
6578
)
6679

6780
def has_object_permission(self, request, view, obj):
@@ -78,7 +91,7 @@ class UserHasCredentialPermission(permissions.BasePermission):
7891
def has_permission(self, request, view):
7992
if request.data.get("product") is not None:
8093
return check_post_permission(
81-
request, Cred_Mapping, "product", Permissions.Credential_Add,
94+
request, Cred_Mapping, ["product", "asset"], Permissions.Credential_Add,
8295
)
8396
if request.data.get("engagement") is not None:
8497
return check_post_permission(
@@ -93,7 +106,7 @@ def has_permission(self, request, view):
93106
request, Cred_Mapping, "finding", Permissions.Credential_Add,
94107
)
95108
return check_post_permission(
96-
request, Cred_Mapping, "product", Permissions.Credential_Add,
109+
request, Cred_Mapping, ["product", "asset"], Permissions.Credential_Add,
97110
)
98111

99112
def has_object_permission(self, request, view, obj):
@@ -231,7 +244,7 @@ def has_object_permission(self, request, view, obj):
231244
class UserHasToolProductSettingsPermission(permissions.BasePermission):
232245
def has_permission(self, request, view):
233246
return check_post_permission(
234-
request, Product, "product", Permissions.Product_Edit,
247+
request, Product, ["product", "asset"], Permissions.Product_Edit,
235248
)
236249

237250
def has_object_permission(self, request, view, obj):
@@ -247,7 +260,7 @@ def has_object_permission(self, request, view, obj):
247260
class UserHasEndpointPermission(permissions.BasePermission):
248261
def has_permission(self, request, view):
249262
return check_post_permission(
250-
request, Product, "product", Permissions.Endpoint_Add,
263+
request, Product, ["product", "asset"], Permissions.Endpoint_Add,
251264
)
252265

253266
def has_object_permission(self, request, view, obj):
@@ -287,7 +300,7 @@ def has_permission(self, request, view):
287300
request.path,
288301
) or UserHasEngagementPermission.path_engagement.match(request.path):
289302
return check_post_permission(
290-
request, Product, "product", Permissions.Engagement_Add,
303+
request, Product, ["product", "asset"], Permissions.Engagement_Add,
291304
)
292305
# related object only need object permission
293306
return True
@@ -326,7 +339,7 @@ def has_permission(self, request, view):
326339
request.path,
327340
):
328341
return check_post_permission(
329-
request, Product, "product", Permissions.Risk_Acceptance,
342+
request, Product, ["product", "asset"], Permissions.Risk_Acceptance,
330343
)
331344
# related object only need object permission
332345
return True
@@ -493,7 +506,7 @@ def has_permission(self, request, view):
493506
return check_post_permission(
494507
request,
495508
Product_Type,
496-
"prod_type",
509+
["prod_type", "organization"],
497510
Permissions.Product_Type_Add_Product,
498511
)
499512

@@ -510,7 +523,7 @@ def has_object_permission(self, request, view, obj):
510523
class UserHasProductMemberPermission(permissions.BasePermission):
511524
def has_permission(self, request, view):
512525
return check_post_permission(
513-
request, Product, "product", Permissions.Product_Manage_Members,
526+
request, Product, ["product", "asset"], Permissions.Product_Manage_Members,
514527
)
515528

516529
def has_object_permission(self, request, view, obj):
@@ -526,7 +539,7 @@ def has_object_permission(self, request, view, obj):
526539
class UserHasProductGroupPermission(permissions.BasePermission):
527540
def has_permission(self, request, view):
528541
return check_post_permission(
529-
request, Product, "product", Permissions.Product_Group_Add,
542+
request, Product, ["product", "asset"], Permissions.Product_Group_Add,
530543
)
531544

532545
def has_object_permission(self, request, view, obj):
@@ -562,7 +575,7 @@ def has_permission(self, request, view):
562575
return check_post_permission(
563576
request,
564577
Product_Type,
565-
"product_type",
578+
["product_type", "organization"],
566579
Permissions.Product_Type_Manage_Members,
567580
)
568581

@@ -581,7 +594,7 @@ def has_permission(self, request, view):
581594
return check_post_permission(
582595
request,
583596
Product_Type,
584-
"product_type",
597+
["product_type", "organization"],
585598
Permissions.Product_Type_Group_Add,
586599
)
587600

@@ -707,7 +720,7 @@ def has_object_permission(self, request, view, obj):
707720
class UserHasLanguagePermission(permissions.BasePermission):
708721
def has_permission(self, request, view):
709722
return check_post_permission(
710-
request, Product, "product", Permissions.Language_Add,
723+
request, Product, ["product", "asset"], Permissions.Language_Add,
711724
)
712725

713726
def has_object_permission(self, request, view, obj):
@@ -725,7 +738,7 @@ def has_permission(self, request, view):
725738
return check_post_permission(
726739
request,
727740
Product,
728-
"product",
741+
["product", "asset"],
729742
Permissions.Product_API_Scan_Configuration_Add,
730743
)
731744

@@ -881,7 +894,7 @@ def has_permission(self, request, view):
881894
class UserHasEngagementPresetPermission(permissions.BasePermission):
882895
def has_permission(self, request, view):
883896
return check_post_permission(
884-
request, Product, "product", Permissions.Product_Edit,
897+
request, Product, ["product", "asset"], Permissions.Product_Edit,
885898
)
886899

887900
def has_object_permission(self, request, view, obj):

0 commit comments

Comments
 (0)