Skip to content

Commit 84a6f8f

Browse files
authored
Merge pull request #14140 from valentijnscholten/fix/risk-acceptance-api-engagement-link
Fix risk acceptance API to link to engagement and add validations and permission check
2 parents 7cbd455 + e1b4c97 commit 84a6f8f

2 files changed

Lines changed: 392 additions & 2 deletions

File tree

dojo/api_v2/serializers.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,6 +1555,13 @@ def create(self, validated_data):
15551555
instance = super().create(validated_data)
15561556
user = getattr(self.context.get("request", None), "user", None)
15571557
ra_helper.add_findings_to_risk_acceptance(user, instance, instance.accepted_findings.all())
1558+
1559+
# Add risk acceptance to engagement
1560+
# This is fine as Pro has its own model + relationshop to track links with engagements.
1561+
if instance.accepted_findings.exists():
1562+
engagement = instance.accepted_findings.first().test.engagement
1563+
engagement.risk_acceptance.add(instance)
1564+
15581565
return instance
15591566

15601567
def update(self, instance, validated_data):
@@ -1574,6 +1581,13 @@ def update(self, instance, validated_data):
15741581
# Remove the ones that were not present in the payload
15751582
for finding in findings_to_remove:
15761583
ra_helper.remove_finding_from_risk_acceptance(user, instance, finding)
1584+
1585+
# Handle orphaned risk acceptances: link to engagement if it now has findings
1586+
# This is fine as Pro has its own model + relationshop to track links with engagements.
1587+
if instance.accepted_findings.exists() and not instance.engagement:
1588+
engagement = instance.accepted_findings.first().test.engagement
1589+
engagement.risk_acceptance.add(instance)
1590+
15771591
return instance
15781592

15791593
@extend_schema_field(serializers.CharField())
@@ -1610,16 +1624,32 @@ def validate_findings_have_same_engagement(finding_objects: list[Finding]):
16101624
findings = data.get("accepted_findings", [])
16111625
findings_ids = [x.id for x in findings]
16121626
finding_objects = Finding.objects.filter(id__in=findings_ids)
1613-
authed_findings = get_authorized_findings(Permissions.Finding_Edit).filter(id__in=findings_ids)
1627+
authed_findings = get_authorized_findings(Permissions.Risk_Acceptance).filter(id__in=findings_ids)
16141628
if len(findings) != len(authed_findings):
16151629
msg = "You are not permitted to add one or more selected findings to this risk acceptance"
16161630
raise PermissionDenied(msg)
16171631
if self.context["request"].method == "POST":
16181632
validate_findings_have_same_engagement(finding_objects)
1633+
1634+
# Validate product allows full risk acceptance BEFORE creating instance
1635+
if finding_objects.exists():
1636+
engagement = finding_objects.first().test.engagement
1637+
if not engagement.product.enable_full_risk_acceptance:
1638+
msg = "Full risk acceptance is not enabled for this product"
1639+
raise PermissionDenied(msg)
16191640
elif self.context["request"].method in {"PATCH", "PUT"}:
1620-
existing_findings = Finding.objects.filter(risk_acceptance=self.instance.id)
1641+
# Use the reverse relation instead of filtering
1642+
existing_findings = self.instance.accepted_findings.all()
16211643
existing_and_new_findings = existing_findings | finding_objects
16221644
validate_findings_have_same_engagement(existing_and_new_findings)
1645+
1646+
# Explicit check to prevent engagement switching
1647+
risk_acceptance_engagement = self.instance.engagement
1648+
if risk_acceptance_engagement and finding_objects.exists():
1649+
new_findings_engagement = finding_objects.first().test.engagement
1650+
if risk_acceptance_engagement.id != new_findings_engagement.id:
1651+
msg = f"Risk Acceptance belongs to engagement {risk_acceptance_engagement.id}. Cannot add findings from engagement {new_findings_engagement.id}"
1652+
raise ValidationError(msg)
16231653
return data
16241654

16251655
class Meta:

0 commit comments

Comments
 (0)