Skip to content

Commit 30bd9e7

Browse files
committed
Fix paths
1 parent e038e11 commit 30bd9e7

22 files changed

Lines changed: 109 additions & 101 deletions

dojo/api_v2/serializers.py

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
save_vulnerability_ids,
3333
save_vulnerability_ids_template,
3434
)
35-
from dojo.finding.queries import get_authorized_findings
3635
from dojo.group.utils import get_auth_group_name
3736
from dojo.importers.auto_create_context import AutoCreateContextManager
3837
from dojo.importers.base_importer import BaseImporter
@@ -118,6 +117,7 @@
118117
LargeScanSizeProductAnnouncement,
119118
ScanTypeProductAnnouncement,
120119
)
120+
from dojo.risk_acceptance.helper import validate_findings_engagement
121121
from dojo.tools.factory import (
122122
get_choices_sorted,
123123
requires_file,
@@ -1537,33 +1537,39 @@ def get_path(self, obj):
15371537
path = "No proof has been supplied"
15381538
if obj.filename() is not None:
15391539
path = reverse(
1540-
"download_risk_acceptance", args=(obj.engagement.id, obj.id),
1540+
"download_risk_acceptance", args=(obj.id, ),
15411541
)
15421542
request = self.context.get("request")
15431543
if request:
15441544
path = request.build_absolute_uri(path)
15451545
return path
15461546

15471547
def validate(self, data):
1548-
def validate_findings_have_same_engagement(finding_objects: list[Finding]): # TODO: check
1549-
engagements = finding_objects.values_list("test__engagement__id", flat=True).distinct().count()
1550-
if engagements > 1:
1551-
msg = "You are not permitted to add findings from multiple engagements" # TODO: same is missing for UI
1552-
raise PermissionDenied(msg)
1553-
1554-
findings = data.get("accepted_findings", [])
1555-
findings_ids = [x.id for x in findings]
1556-
finding_objects = Finding.objects.filter(id__in=findings_ids)
1557-
authed_findings = get_authorized_findings(Permissions.Finding_Edit).filter(id__in=findings_ids)
1558-
if len(findings) != len(authed_findings):
1559-
msg = "You are not permitted to add one or more selected findings to this risk acceptance"
1560-
raise PermissionDenied(msg)
1561-
if self.context["request"].method == "POST":
1562-
validate_findings_have_same_engagement(finding_objects)
1563-
elif self.context["request"].method in {"PATCH", "PUT"}:
1564-
existing_findings = Finding.objects.filter(risk_acceptance=self.instance.id)
1565-
existing_and_new_findings = existing_findings | finding_objects
1566-
validate_findings_have_same_engagement(existing_and_new_findings)
1548+
1549+
findings = data.get("accepted_findings", self.instance.accepted_findings.all() if self.instance else None)
1550+
engagement = data.get("engagement", self.instance.engagement if self.instance else None)
1551+
validate_findings_engagement(engagement, findings)
1552+
return data
1553+
1554+
# def validate_findings_have_same_engagement(finding_objects: list[Finding]): # TODO: check
1555+
# engagements = finding_objects.values_list("test__engagement__id", flat=True).distinct().count()
1556+
# if engagements > 1:
1557+
# msg = "You are not permitted to add findings from multiple engagements" # TODO: same is missing for UI
1558+
# raise PermissionDenied(msg)
1559+
1560+
# findings = data.get("accepted_findings", [])
1561+
# findings_ids = [x.id for x in findings]
1562+
# finding_objects = Finding.objects.filter(id__in=findings_ids)
1563+
# authed_findings = get_authorized_findings(Permissions.Finding_Edit).filter(id__in=findings_ids)
1564+
# if len(findings) != len(authed_findings):
1565+
# msg = "You are not permitted to add one or more selected findings to this risk acceptance"
1566+
# raise PermissionDenied(msg)
1567+
# if self.context["request"].method == "POST":
1568+
# validate_findings_have_same_engagement(finding_objects)
1569+
# elif self.context["request"].method in {"PATCH", "PUT"}:
1570+
# existing_findings = Finding.objects.filter(risk_acceptance=self.instance.id)
1571+
# existing_and_new_findings = existing_findings | finding_objects
1572+
# validate_findings_have_same_engagement(existing_and_new_findings)
15671573
return data
15681574

15691575
class Meta:

dojo/authorization/authorization.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
Product_Type,
2424
Product_Type_Group,
2525
Product_Type_Member,
26+
Risk_Acceptance,
2627
Stub_Finding,
2728
Test,
2829
)
@@ -92,6 +93,11 @@ def user_has_permission(user, obj, permission):
9293
and permission in Permissions.get_engagement_permissions()
9394
):
9495
return user_has_permission(user, obj.product, permission)
96+
if (
97+
isinstance(obj, Risk_Acceptance)
98+
and permission in Permissions.get_engagement_permissions()
99+
):
100+
return user_has_permission(user, obj.engagement, permission)
95101
if (
96102
isinstance(obj, Test)
97103
and permission in Permissions.get_test_permissions()

dojo/engagement/urls.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,17 @@
3838
views.add_risk_acceptance, name="add_risk_acceptance"),
3939
re_path(r"^engagement/(?P<eid>\d+)/risk_acceptance/add/(?P<fid>\d+)$",
4040
views.add_risk_acceptance, name="add_risk_acceptance"),
41-
re_path(r"^engagement/(?P<eid>\d+)/risk_acceptance/(?P<raid>\d+)$",
41+
re_path(r"^engagement/risk_acceptance/(?P<raid>\d+)$",
4242
views.view_risk_acceptance, name="view_risk_acceptance"),
43-
re_path(r"^engagement/(?P<eid>\d+)/risk_acceptance/(?P<raid>\d+)/edit$",
43+
re_path(r"^engagement/risk_acceptance/(?P<raid>\d+)/edit$",
4444
views.edit_risk_acceptance, name="edit_risk_acceptance"),
45-
re_path(r"^engagement/(?P<eid>\d+)/risk_acceptance/(?P<raid>\d+)/expire$",
45+
re_path(r"^engagement/risk_acceptance/(?P<raid>\d+)/expire$",
4646
views.expire_risk_acceptance, name="expire_risk_acceptance"),
47-
re_path(r"^engagement/(?P<eid>\d+)/risk_acceptance/(?P<raid>\d+)/reinstate$",
47+
re_path(r"^engagement/risk_acceptance/(?P<raid>\d+)/reinstate$",
4848
views.reinstate_risk_acceptance, name="reinstate_risk_acceptance"),
49-
re_path(r"^engagement/(?P<eid>\d+)/risk_acceptance/(?P<raid>\d+)/delete$",
49+
re_path(r"^engagement/risk_acceptance/(?P<raid>\d+)/delete$",
5050
views.delete_risk_acceptance, name="delete_risk_acceptance"),
51-
re_path(r"^engagement/(?P<eid>\d+)/risk_acceptance/(?P<raid>\d+)/download$",
51+
re_path(r"^engagement/risk_acceptance/(?P<raid>\d+)/download$",
5252
views.download_risk_acceptance, name="download_risk_acceptance"),
5353
re_path(r"^engagement/(?P<eid>\d+)/threatmodel$", views.view_threatmodel,
5454
name="view_threatmodel"),

dojo/engagement/views.py

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,20 +1313,20 @@ def add_risk_acceptance(request, eid, fid=None):
13131313
})
13141314

13151315

1316-
@user_is_authorized(Engagement, Permissions.Engagement_View, "eid")
1317-
def view_risk_acceptance(request, eid, raid):
1318-
return view_edit_risk_acceptance(request, eid=eid, raid=raid, edit_mode=False)
1316+
@user_is_authorized(Risk_Acceptance, Permissions.Engagement_View, "raid")
1317+
def view_risk_acceptance(request, raid):
1318+
return view_edit_risk_acceptance(request, raid=raid, edit_mode=False)
13191319

13201320

1321-
@user_is_authorized(Engagement, Permissions.Risk_Acceptance, "eid")
1322-
def edit_risk_acceptance(request, eid, raid):
1323-
return view_edit_risk_acceptance(request, eid=eid, raid=raid, edit_mode=True)
1321+
@user_is_authorized(Risk_Acceptance, Permissions.Risk_Acceptance, "raid")
1322+
def edit_risk_acceptance(request, raid):
1323+
return view_edit_risk_acceptance(request, raid=raid, edit_mode=True)
13241324

13251325

13261326
# will only be called by view_risk_acceptance and edit_risk_acceptance
1327-
def view_edit_risk_acceptance(request, eid, raid, *, edit_mode=False):
1327+
def view_edit_risk_acceptance(request, raid, *, edit_mode=False):
13281328
risk_acceptance = get_object_or_404(Risk_Acceptance, pk=raid)
1329-
eng = get_object_or_404(Engagement, pk=eid)
1329+
eng = risk_acceptance.engagement
13301330

13311331
if edit_mode and not eng.product.enable_full_risk_acceptance:
13321332
raise PermissionDenied
@@ -1435,7 +1435,7 @@ def view_edit_risk_acceptance(request, eid, raid, *, edit_mode=False):
14351435
extra_tags="alert-success")
14361436
if not errors:
14371437
logger.debug("redirecting to return_url")
1438-
return redirect_to_return_url_or_else(request, reverse("view_risk_acceptance", args=(eid, raid)))
1438+
return redirect_to_return_url_or_else(request, reverse("view_risk_acceptance", args=(raid, )))
14391439
logger.error("errors found")
14401440

14411441
elif edit_mode:
@@ -1487,34 +1487,32 @@ def view_edit_risk_acceptance(request, eid, raid, *, edit_mode=False):
14871487
})
14881488

14891489

1490-
@user_is_authorized(Engagement, Permissions.Risk_Acceptance, "eid")
1491-
def expire_risk_acceptance(request, eid, raid):
1490+
@user_is_authorized(Risk_Acceptance, Permissions.Risk_Acceptance, "raid")
1491+
def expire_risk_acceptance(request, raid):
14921492
risk_acceptance = get_object_or_404(prefetch_for_expiration(Risk_Acceptance.objects.all()), pk=raid)
1493-
# Validate the engagement ID exists before moving forward
1494-
get_object_or_404(Engagement, pk=eid)
14951493

14961494
ra_helper.expire_now(risk_acceptance)
14971495

1498-
return redirect_to_return_url_or_else(request, reverse("view_risk_acceptance", args=(eid, raid)))
1496+
return redirect_to_return_url_or_else(request, reverse("view_risk_acceptance", args=(raid, )))
14991497

15001498

1501-
@user_is_authorized(Engagement, Permissions.Risk_Acceptance, "eid")
1502-
def reinstate_risk_acceptance(request, eid, raid):
1499+
@user_is_authorized(Risk_Acceptance, Permissions.Risk_Acceptance, "raid")
1500+
def reinstate_risk_acceptance(request, raid):
15031501
risk_acceptance = get_object_or_404(prefetch_for_expiration(Risk_Acceptance.objects.all()), pk=raid)
1504-
eng = get_object_or_404(Engagement, pk=eid)
1502+
eng = risk_acceptance.engagement
15051503

15061504
if not eng.product.enable_full_risk_acceptance:
15071505
raise PermissionDenied
15081506

15091507
ra_helper.reinstate(risk_acceptance, risk_acceptance.expiration_date)
15101508

1511-
return redirect_to_return_url_or_else(request, reverse("view_risk_acceptance", args=(eid, raid)))
1509+
return redirect_to_return_url_or_else(request, reverse("view_risk_acceptance", args=(raid, )))
15121510

15131511

1514-
@user_is_authorized(Engagement, Permissions.Risk_Acceptance, "eid")
1515-
def delete_risk_acceptance(request, eid, raid):
1512+
@user_is_authorized(Risk_Acceptance, Permissions.Risk_Acceptance, "raid")
1513+
def delete_risk_acceptance(request, raid):
15161514
risk_acceptance = get_object_or_404(Risk_Acceptance, pk=raid)
1517-
eng = get_object_or_404(Engagement, pk=eid)
1515+
eng = risk_acceptance.engagement
15181516

15191517
ra_helper.delete(eng, risk_acceptance)
15201518

@@ -1526,13 +1524,10 @@ def delete_risk_acceptance(request, eid, raid):
15261524
return HttpResponseRedirect(reverse("view_engagement", args=(eng.id, )))
15271525

15281526

1529-
@user_is_authorized(Engagement, Permissions.Engagement_View, "eid")
1530-
def download_risk_acceptance(request, eid, raid):
1527+
@user_is_authorized(Risk_Acceptance, Permissions.Risk_Acceptance, "raid")
1528+
def download_risk_acceptance(request, raid):
15311529
mimetypes.init()
15321530
risk_acceptance = get_object_or_404(Risk_Acceptance, pk=raid)
1533-
# Ensure the risk acceptance is under the supplied engagement
1534-
if not Engagement.objects.filter(risk_acceptance=risk_acceptance, id=eid).exists():
1535-
raise PermissionDenied
15361531
response = StreamingHttpResponse(
15371532
FileIterWrapper(
15381533
(Path(settings.MEDIA_ROOT) / "risk_acceptance.path.name").open(mode="rb")))

dojo/risk_acceptance/helper.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from contextlib import suppress
33

44
from dateutil.relativedelta import relativedelta
5-
from django.core.exceptions import PermissionDenied
5+
from django.core.exceptions import PermissionDenied, ValidationError
66
from django.urls import reverse
77
from django.utils import timezone
88

@@ -56,7 +56,7 @@ def expire_now(risk_acceptance):
5656
create_notification(event="risk_acceptance_expiration", title=title, risk_acceptance=risk_acceptance, accepted_findings=accepted_findings,
5757
reactivated_findings=reactivated_findings, engagement=risk_acceptance.engagement,
5858
product=risk_acceptance.engagement.product,
59-
url=reverse("view_risk_acceptance", args=(risk_acceptance.engagement.id, risk_acceptance.id)))
59+
url=reverse("view_risk_acceptance", args=(risk_acceptance.id, )))
6060

6161

6262
def reinstate(risk_acceptance, old_expiration_date):
@@ -201,7 +201,7 @@ def expiration_handler(*args, **kwargs):
201201
create_notification(event="risk_acceptance_expiration", title=notification_title, risk_acceptance=risk_acceptance,
202202
accepted_findings=risk_acceptance.accepted_findings.all(), engagement=risk_acceptance.engagement,
203203
product=risk_acceptance.engagement.product,
204-
url=reverse("view_risk_acceptance", args=(risk_acceptance.engagement.id, risk_acceptance.id)))
204+
url=reverse("view_risk_acceptance", args=(risk_acceptance.id, )))
205205

206206
post_jira_comments(risk_acceptance, risk_acceptance.accepted_findings.all(), expiration_warning_message_creator, heads_up_days)
207207

@@ -214,45 +214,45 @@ def get_view_risk_acceptance(risk_acceptance: Risk_Acceptance) -> str:
214214
# Suppressing this error because it does not happen under most circumstances that a risk acceptance does not have engagement
215215
with suppress(AttributeError):
216216
get_full_url(
217-
reverse("view_risk_acceptance", args=(risk_acceptance.engagement.id, risk_acceptance.id)),
217+
reverse("view_risk_acceptance", args=(risk_acceptance.id, )),
218218
)
219219
return ""
220220

221221

222222
def expiration_message_creator(risk_acceptance, heads_up_days=0):
223223
return "Risk acceptance [({})|{}] with {} findings has expired".format(
224224
escape_for_jira(risk_acceptance.name),
225-
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.engagement.id, risk_acceptance.id))),
225+
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.id,))),
226226
len(risk_acceptance.accepted_findings.all()))
227227

228228

229229
def expiration_warning_message_creator(risk_acceptance, heads_up_days=0):
230230
return "Risk acceptance [({})|{}] with {} findings will expire in {} days".format(
231231
escape_for_jira(risk_acceptance.name),
232-
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.engagement.id, risk_acceptance.id))),
232+
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.id, ))),
233233
len(risk_acceptance.accepted_findings.all()), heads_up_days)
234234

235235

236236
def reinstation_message_creator(risk_acceptance, heads_up_days=0):
237237
return "Risk acceptance [({})|{}] with {} findings has been reinstated (expires on {})".format(
238238
escape_for_jira(risk_acceptance.name),
239-
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.engagement.id, risk_acceptance.id))),
239+
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.id, ))),
240240
len(risk_acceptance.accepted_findings.all()), timezone.localtime(risk_acceptance.expiration_date).strftime("%b %d, %Y"))
241241

242242

243243
def accepted_message_creator(risk_acceptance, heads_up_days=0):
244244
if risk_acceptance:
245245
return "Finding has been added to risk acceptance [({})|{}] with {} findings (expires on {})".format(
246246
escape_for_jira(risk_acceptance.name),
247-
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.engagement.id, risk_acceptance.id))),
247+
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.id, ))),
248248
len(risk_acceptance.accepted_findings.all()), timezone.localtime(risk_acceptance.expiration_date).strftime("%b %d, %Y"))
249249
return "Finding has been risk accepted"
250250

251251

252252
def unaccepted_message_creator(risk_acceptance, heads_up_days=0):
253253
if risk_acceptance:
254254
return "finding was unaccepted/deleted from risk acceptance [({})|{}]".format(escape_for_jira(risk_acceptance.name),
255-
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.engagement.id, risk_acceptance.id))))
255+
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.id, ))))
256256
return "Finding is no longer risk accepted"
257257

258258

@@ -391,3 +391,10 @@ def update_endpoint_statuses(finding: Finding, *, accept_risk: bool) -> None:
391391
status.risk_accepted = False
392392
status.last_modified = timezone.now()
393393
status.save()
394+
395+
396+
def validate_findings_engagement(engagement, findings):
397+
invalid = [f.id for f in findings if f.test.engagement.id != engagement.id]
398+
if invalid:
399+
msg = f"Findings with IDs {invalid} do not belong to engagement {engagement.id}."
400+
raise ValidationError(msg)

dojo/templates/dojo/custom_html_report_endpoint_list.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ <h5 class="report_findings_entry">
8686
<td>
8787
{% comment %} for some reason the font-awesome icons don't work with the report template{% endcomment %}
8888
{% for ra in finding.risk_acceptance_set.all|slice:":5" %}
89-
<a href="{% url 'view_risk_acceptance' finding.test.engagement.id ra.id %}"
89+
<a href="{% url 'view_risk_acceptance' ra.id %}"
9090
class="{% if ra.is_expired %}lightgrey{% endif%}">acceptance</a>&nbsp;
9191
{% endfor %}
9292
</td>

dojo/templates/dojo/custom_html_report_finding_list.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ <h5 class="report_findings_entry">
7575
<td>
7676
{% comment %} for some reason the font-awesome icons don't work with the report template{% endcomment %}
7777
{% for ra in finding.risk_acceptance_set.all|slice:":5" %}
78-
<a href="{% url 'view_risk_acceptance' finding.test.engagement.id ra.id %}"
78+
<a href="{% url 'view_risk_acceptance' ra.id %}"
7979
class="{% if ra.is_expired %}lightgrey{% endif%}">acceptance</a>&nbsp;
8080
{% endfor %}
8181
</td>

dojo/templates/dojo/endpoint_pdf_report.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ <h5>
148148
<td>
149149
{% comment %} for some reason the font-awesome icons don't work with the report template{% endcomment %}
150150
{% for ra in finding.risk_acceptance_set.all|slice:":5" %}
151-
<a href="{% url 'view_risk_acceptance' finding.test.engagement.id ra.id %}"
151+
<a href="{% url 'view_risk_acceptance' ra.id %}"
152152
class="{% if ra.is_expired %}lightgrey{% endif%}">acceptance</a>&nbsp;
153153
{% endfor %}
154154
</td>

dojo/templates/dojo/engagement_pdf_report.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ <h5>
283283
<td>
284284
{% comment %} for some reason the font-awesome icons don't work with the report template{% endcomment %}
285285
{% for ra in finding.risk_acceptance_set.all|slice:":5" %}
286-
<a href="{% url 'view_risk_acceptance' finding.test.engagement.id ra.id %}"
286+
<a href="{% url 'view_risk_acceptance' ra.id %}"
287287
class="{% if ra.is_expired %}lightgrey{% endif%}">acceptance</a>&nbsp;
288288
{% endfor %}
289289
</td>

dojo/templates/dojo/finding_pdf_report.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ <h5>
127127
<td>
128128
{% comment %} for some reason the font-awesome icons don't work with the report template{% endcomment %}
129129
{% for ra in finding.risk_acceptance_set.all|slice:":5" %}
130-
<a href="{% url 'view_risk_acceptance' finding.test.engagement.id ra.id %}"
130+
<a href="{% url 'view_risk_acceptance' ra.id %}"
131131
class="{% if ra.is_expired %}lightgrey{% endif%}">acceptance</a>&nbsp;
132132
{% endfor %}
133133
</td>

0 commit comments

Comments
 (0)