Skip to content

Commit 6a4097f

Browse files
committed
Fix paths
1 parent ec21f6a commit 6a4097f

21 files changed

+99
-91
lines changed

dojo/api_v2/serializers.py

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
save_vulnerability_ids,
3232
save_vulnerability_ids_template,
3333
)
34-
from dojo.finding.queries import get_authorized_findings
3534
from dojo.group.utils import get_auth_group_name
3635
from dojo.importers.auto_create_context import AutoCreateContextManager
3736
from dojo.importers.base_importer import BaseImporter
@@ -117,6 +116,7 @@
117116
LargeScanSizeProductAnnouncement,
118117
ScanTypeProductAnnouncement,
119118
)
119+
from dojo.risk_acceptance.helper import validate_findings_engagement
120120
from dojo.tools.factory import (
121121
get_choices_sorted,
122122
requires_file,
@@ -1564,33 +1564,39 @@ def get_path(self, obj):
15641564
path = "No proof has been supplied"
15651565
if obj.filename() is not None:
15661566
path = reverse(
1567-
"download_risk_acceptance", args=(obj.engagement.id, obj.id),
1567+
"download_risk_acceptance", args=(obj.id, ),
15681568
)
15691569
request = self.context.get("request")
15701570
if request:
15711571
path = request.build_absolute_uri(path)
15721572
return path
15731573

15741574
def validate(self, data):
1575-
def validate_findings_have_same_engagement(finding_objects: list[Finding]): # TODO: check
1576-
engagements = finding_objects.values_list("test__engagement__id", flat=True).distinct().count()
1577-
if engagements > 1:
1578-
msg = "You are not permitted to add findings from multiple engagements" # TODO: same is missing for UI
1579-
raise PermissionDenied(msg)
1580-
1581-
findings = data.get("accepted_findings", [])
1582-
findings_ids = [x.id for x in findings]
1583-
finding_objects = Finding.objects.filter(id__in=findings_ids)
1584-
authed_findings = get_authorized_findings(Permissions.Finding_Edit).filter(id__in=findings_ids)
1585-
if len(findings) != len(authed_findings):
1586-
msg = "You are not permitted to add one or more selected findings to this risk acceptance"
1587-
raise PermissionDenied(msg)
1588-
if self.context["request"].method == "POST":
1589-
validate_findings_have_same_engagement(finding_objects)
1590-
elif self.context["request"].method in {"PATCH", "PUT"}:
1591-
existing_findings = Finding.objects.filter(risk_acceptance=self.instance.id)
1592-
existing_and_new_findings = existing_findings | finding_objects
1593-
validate_findings_have_same_engagement(existing_and_new_findings)
1575+
1576+
findings = data.get("accepted_findings", self.instance.accepted_findings.all() if self.instance else None)
1577+
engagement = data.get("engagement", self.instance.engagement if self.instance else None)
1578+
validate_findings_engagement(engagement, findings)
1579+
return data
1580+
1581+
# def validate_findings_have_same_engagement(finding_objects: list[Finding]): # TODO: check
1582+
# engagements = finding_objects.values_list("test__engagement__id", flat=True).distinct().count()
1583+
# if engagements > 1:
1584+
# msg = "You are not permitted to add findings from multiple engagements" # TODO: same is missing for UI
1585+
# raise PermissionDenied(msg)
1586+
1587+
# findings = data.get("accepted_findings", [])
1588+
# findings_ids = [x.id for x in findings]
1589+
# finding_objects = Finding.objects.filter(id__in=findings_ids)
1590+
# authed_findings = get_authorized_findings(Permissions.Finding_Edit).filter(id__in=findings_ids)
1591+
# if len(findings) != len(authed_findings):
1592+
# msg = "You are not permitted to add one or more selected findings to this risk acceptance"
1593+
# raise PermissionDenied(msg)
1594+
# if self.context["request"].method == "POST":
1595+
# validate_findings_have_same_engagement(finding_objects)
1596+
# elif self.context["request"].method in {"PATCH", "PUT"}:
1597+
# existing_findings = Finding.objects.filter(risk_acceptance=self.instance.id)
1598+
# existing_and_new_findings = existing_findings | finding_objects
1599+
# validate_findings_have_same_engagement(existing_and_new_findings)
15941600
return data
15951601

15961602
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
@@ -36,17 +36,17 @@
3636
views.add_risk_acceptance, name="add_risk_acceptance"),
3737
re_path(r"^engagement/(?P<eid>\d+)/risk_acceptance/add/(?P<fid>\d+)$",
3838
views.add_risk_acceptance, name="add_risk_acceptance"),
39-
re_path(r"^engagement/(?P<eid>\d+)/risk_acceptance/(?P<raid>\d+)$",
39+
re_path(r"^engagement/risk_acceptance/(?P<raid>\d+)$",
4040
views.view_risk_acceptance, name="view_risk_acceptance"),
41-
re_path(r"^engagement/(?P<eid>\d+)/risk_acceptance/(?P<raid>\d+)/edit$",
41+
re_path(r"^engagement/risk_acceptance/(?P<raid>\d+)/edit$",
4242
views.edit_risk_acceptance, name="edit_risk_acceptance"),
43-
re_path(r"^engagement/(?P<eid>\d+)/risk_acceptance/(?P<raid>\d+)/expire$",
43+
re_path(r"^engagement/risk_acceptance/(?P<raid>\d+)/expire$",
4444
views.expire_risk_acceptance, name="expire_risk_acceptance"),
45-
re_path(r"^engagement/(?P<eid>\d+)/risk_acceptance/(?P<raid>\d+)/reinstate$",
45+
re_path(r"^engagement/risk_acceptance/(?P<raid>\d+)/reinstate$",
4646
views.reinstate_risk_acceptance, name="reinstate_risk_acceptance"),
47-
re_path(r"^engagement/(?P<eid>\d+)/risk_acceptance/(?P<raid>\d+)/delete$",
47+
re_path(r"^engagement/risk_acceptance/(?P<raid>\d+)/delete$",
4848
views.delete_risk_acceptance, name="delete_risk_acceptance"),
49-
re_path(r"^engagement/(?P<eid>\d+)/risk_acceptance/(?P<raid>\d+)/download$",
49+
re_path(r"^engagement/risk_acceptance/(?P<raid>\d+)/download$",
5050
views.download_risk_acceptance, name="download_risk_acceptance"),
5151
re_path(r"^engagement/(?P<eid>\d+)/threatmodel$", views.view_threatmodel,
5252
name="view_threatmodel"),

dojo/engagement/views.py

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

12611261

1262-
@user_is_authorized(Engagement, Permissions.Engagement_View, "eid")
1263-
def view_risk_acceptance(request, eid, raid):
1264-
return view_edit_risk_acceptance(request, eid=eid, raid=raid, edit_mode=False)
1262+
@user_is_authorized(Risk_Acceptance, Permissions.Engagement_View, "raid")
1263+
def view_risk_acceptance(request, raid):
1264+
return view_edit_risk_acceptance(request, raid=raid, edit_mode=False)
12651265

12661266

1267-
@user_is_authorized(Engagement, Permissions.Risk_Acceptance, "eid")
1268-
def edit_risk_acceptance(request, eid, raid):
1269-
return view_edit_risk_acceptance(request, eid=eid, raid=raid, edit_mode=True)
1267+
@user_is_authorized(Risk_Acceptance, Permissions.Risk_Acceptance, "raid")
1268+
def edit_risk_acceptance(request, raid):
1269+
return view_edit_risk_acceptance(request, raid=raid, edit_mode=True)
12701270

12711271

12721272
# will only be called by view_risk_acceptance and edit_risk_acceptance
1273-
def view_edit_risk_acceptance(request, eid, raid, *, edit_mode=False):
1273+
def view_edit_risk_acceptance(request, raid, *, edit_mode=False):
12741274
risk_acceptance = get_object_or_404(Risk_Acceptance, pk=raid)
1275-
eng = get_object_or_404(Engagement, pk=eid)
1275+
eng = risk_acceptance.engagement
12761276

12771277
if edit_mode and not eng.product.enable_full_risk_acceptance:
12781278
raise PermissionDenied
@@ -1381,7 +1381,7 @@ def view_edit_risk_acceptance(request, eid, raid, *, edit_mode=False):
13811381
extra_tags="alert-success")
13821382
if not errors:
13831383
logger.debug("redirecting to return_url")
1384-
return redirect_to_return_url_or_else(request, reverse("view_risk_acceptance", args=(eid, raid)))
1384+
return redirect_to_return_url_or_else(request, reverse("view_risk_acceptance", args=(raid, )))
13851385
logger.error("errors found")
13861386

13871387
elif edit_mode:
@@ -1433,34 +1433,32 @@ def view_edit_risk_acceptance(request, eid, raid, *, edit_mode=False):
14331433
})
14341434

14351435

1436-
@user_is_authorized(Engagement, Permissions.Risk_Acceptance, "eid")
1437-
def expire_risk_acceptance(request, eid, raid):
1436+
@user_is_authorized(Risk_Acceptance, Permissions.Risk_Acceptance, "raid")
1437+
def expire_risk_acceptance(request, raid):
14381438
risk_acceptance = get_object_or_404(prefetch_for_expiration(Risk_Acceptance.objects.all()), pk=raid)
1439-
# Validate the engagement ID exists before moving forward
1440-
get_object_or_404(Engagement, pk=eid)
14411439

14421440
ra_helper.expire_now(risk_acceptance)
14431441

1444-
return redirect_to_return_url_or_else(request, reverse("view_risk_acceptance", args=(eid, raid)))
1442+
return redirect_to_return_url_or_else(request, reverse("view_risk_acceptance", args=(raid, )))
14451443

14461444

1447-
@user_is_authorized(Engagement, Permissions.Risk_Acceptance, "eid")
1448-
def reinstate_risk_acceptance(request, eid, raid):
1445+
@user_is_authorized(Risk_Acceptance, Permissions.Risk_Acceptance, "raid")
1446+
def reinstate_risk_acceptance(request, raid):
14491447
risk_acceptance = get_object_or_404(prefetch_for_expiration(Risk_Acceptance.objects.all()), pk=raid)
1450-
eng = get_object_or_404(Engagement, pk=eid)
1448+
eng = risk_acceptance.engagement
14511449

14521450
if not eng.product.enable_full_risk_acceptance:
14531451
raise PermissionDenied
14541452

14551453
ra_helper.reinstate(risk_acceptance, risk_acceptance.expiration_date)
14561454

1457-
return redirect_to_return_url_or_else(request, reverse("view_risk_acceptance", args=(eid, raid)))
1455+
return redirect_to_return_url_or_else(request, reverse("view_risk_acceptance", args=(raid, )))
14581456

14591457

1460-
@user_is_authorized(Engagement, Permissions.Risk_Acceptance, "eid")
1461-
def delete_risk_acceptance(request, eid, raid):
1458+
@user_is_authorized(Risk_Acceptance, Permissions.Risk_Acceptance, "raid")
1459+
def delete_risk_acceptance(request, raid):
14621460
risk_acceptance = get_object_or_404(Risk_Acceptance, pk=raid)
1463-
eng = get_object_or_404(Engagement, pk=eid)
1461+
eng = risk_acceptance.engagement
14641462

14651463
ra_helper.delete(eng, risk_acceptance)
14661464

@@ -1472,13 +1470,10 @@ def delete_risk_acceptance(request, eid, raid):
14721470
return HttpResponseRedirect(reverse("view_engagement", args=(eng.id, )))
14731471

14741472

1475-
@user_is_authorized(Engagement, Permissions.Engagement_View, "eid")
1476-
def download_risk_acceptance(request, eid, raid):
1473+
@user_is_authorized(Risk_Acceptance, Permissions.Risk_Acceptance, "raid")
1474+
def download_risk_acceptance(request, raid):
14771475
mimetypes.init()
14781476
risk_acceptance = get_object_or_404(Risk_Acceptance, pk=raid)
1479-
# Ensure the risk acceptance is under the supplied engagement
1480-
if not Engagement.objects.filter(risk_acceptance=risk_acceptance, id=eid).exists():
1481-
raise PermissionDenied
14821477
response = StreamingHttpResponse(
14831478
FileIterWrapper(
14841479
(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

@@ -50,7 +50,7 @@ def expire_now(risk_acceptance):
5050
create_notification(event="risk_acceptance_expiration", title=title, risk_acceptance=risk_acceptance, accepted_findings=accepted_findings,
5151
reactivated_findings=reactivated_findings, engagement=risk_acceptance.engagement,
5252
product=risk_acceptance.engagement.product,
53-
url=reverse("view_risk_acceptance", args=(risk_acceptance.engagement.id, risk_acceptance.id)))
53+
url=reverse("view_risk_acceptance", args=(risk_acceptance.id, )))
5454

5555

5656
def reinstate(risk_acceptance, old_expiration_date):
@@ -184,7 +184,7 @@ def expiration_handler(*args, **kwargs):
184184
create_notification(event="risk_acceptance_expiration", title=notification_title, risk_acceptance=risk_acceptance,
185185
accepted_findings=risk_acceptance.accepted_findings.all(), engagement=risk_acceptance.engagement,
186186
product=risk_acceptance.engagement.product,
187-
url=reverse("view_risk_acceptance", args=(risk_acceptance.engagement.id, risk_acceptance.id)))
187+
url=reverse("view_risk_acceptance", args=(risk_acceptance.id, )))
188188

189189
post_jira_comments(risk_acceptance, risk_acceptance.accepted_findings.all(), expiration_warning_message_creator, heads_up_days)
190190

@@ -197,45 +197,45 @@ def get_view_risk_acceptance(risk_acceptance: Risk_Acceptance) -> str:
197197
# Suppressing this error because it does not happen under most circumstances that a risk acceptance does not have engagement
198198
with suppress(AttributeError):
199199
get_full_url(
200-
reverse("view_risk_acceptance", args=(risk_acceptance.engagement.id, risk_acceptance.id)),
200+
reverse("view_risk_acceptance", args=(risk_acceptance.id, )),
201201
)
202202
return ""
203203

204204

205205
def expiration_message_creator(risk_acceptance, heads_up_days=0):
206206
return "Risk acceptance [({})|{}] with {} findings has expired".format(
207207
escape_for_jira(risk_acceptance.name),
208-
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.engagement.id, risk_acceptance.id))),
208+
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.id,))),
209209
len(risk_acceptance.accepted_findings.all()))
210210

211211

212212
def expiration_warning_message_creator(risk_acceptance, heads_up_days=0):
213213
return "Risk acceptance [({})|{}] with {} findings will expire in {} days".format(
214214
escape_for_jira(risk_acceptance.name),
215-
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.engagement.id, risk_acceptance.id))),
215+
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.id, ))),
216216
len(risk_acceptance.accepted_findings.all()), heads_up_days)
217217

218218

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

225225

226226
def accepted_message_creator(risk_acceptance, heads_up_days=0):
227227
if risk_acceptance:
228228
return "Finding has been added to risk acceptance [({})|{}] with {} findings (expires on {})".format(
229229
escape_for_jira(risk_acceptance.name),
230-
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.engagement.id, risk_acceptance.id))),
230+
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.id, ))),
231231
len(risk_acceptance.accepted_findings.all()), timezone.localtime(risk_acceptance.expiration_date).strftime("%b %d, %Y"))
232232
return "Finding has been risk accepted"
233233

234234

235235
def unaccepted_message_creator(risk_acceptance, heads_up_days=0):
236236
if risk_acceptance:
237237
return "finding was unaccepted/deleted from risk acceptance [({})|{}]".format(escape_for_jira(risk_acceptance.name),
238-
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.engagement.id, risk_acceptance.id))))
238+
get_full_url(reverse("view_risk_acceptance", args=(risk_acceptance.id, ))))
239239
return "Finding is no longer risk accepted"
240240

241241

@@ -370,3 +370,10 @@ def update_endpoint_statuses(finding: Finding, *, accept_risk: bool) -> None:
370370
status.risk_accepted = False
371371
status.last_modified = timezone.now()
372372
status.save()
373+
374+
375+
def validate_findings_engagement(engagement, findings):
376+
invalid = [f.id for f in findings if f.test.engagement.id != engagement.id]
377+
if invalid:
378+
msg = f"Findings with IDs {invalid} do not belong to engagement {engagement.id}."
379+
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)