Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions dojo/api_v2/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1535,6 +1535,13 @@ def create(self, validated_data):
instance = super().create(validated_data)
user = getattr(self.context.get("request", None), "user", None)
ra_helper.add_findings_to_risk_acceptance(user, instance, instance.accepted_findings.all())

# Add risk acceptance to engagement
# This is fine as Pro has its own model + relationshop to track links with engagements.
if instance.accepted_findings.exists():
engagement = instance.accepted_findings.first().test.engagement
engagement.risk_acceptance.add(instance)

return instance

def update(self, instance, validated_data):
Expand All @@ -1554,6 +1561,13 @@ def update(self, instance, validated_data):
# Remove the ones that were not present in the payload
for finding in findings_to_remove:
ra_helper.remove_finding_from_risk_acceptance(user, instance, finding)

# Handle orphaned risk acceptances: link to engagement if it now has findings
# This is fine as Pro has its own model + relationshop to track links with engagements.
if instance.accepted_findings.exists() and not instance.engagement:
engagement = instance.accepted_findings.first().test.engagement
engagement.risk_acceptance.add(instance)

return instance

@extend_schema_field(serializers.CharField())
Expand Down Expand Up @@ -1590,16 +1604,32 @@ def validate_findings_have_same_engagement(finding_objects: list[Finding]):
findings = data.get("accepted_findings", [])
findings_ids = [x.id for x in findings]
finding_objects = Finding.objects.filter(id__in=findings_ids)
authed_findings = get_authorized_findings(Permissions.Finding_Edit).filter(id__in=findings_ids)
authed_findings = get_authorized_findings(Permissions.Risk_Acceptance).filter(id__in=findings_ids)
if len(findings) != len(authed_findings):
msg = "You are not permitted to add one or more selected findings to this risk acceptance"
raise PermissionDenied(msg)
if self.context["request"].method == "POST":
validate_findings_have_same_engagement(finding_objects)

# Validate product allows full risk acceptance BEFORE creating instance
if finding_objects.exists():
engagement = finding_objects.first().test.engagement
if not engagement.product.enable_full_risk_acceptance:
msg = "Full risk acceptance is not enabled for this product"
raise PermissionDenied(msg)
elif self.context["request"].method in {"PATCH", "PUT"}:
existing_findings = Finding.objects.filter(risk_acceptance=self.instance.id)
# Use the reverse relation instead of filtering
existing_findings = self.instance.accepted_findings.all()
existing_and_new_findings = existing_findings | finding_objects
validate_findings_have_same_engagement(existing_and_new_findings)

# Explicit check to prevent engagement switching
risk_acceptance_engagement = self.instance.engagement
if risk_acceptance_engagement and finding_objects.exists():
new_findings_engagement = finding_objects.first().test.engagement
if risk_acceptance_engagement.id != new_findings_engagement.id:
msg = f"Risk Acceptance belongs to engagement {risk_acceptance_engagement.id}. Cannot add findings from engagement {new_findings_engagement.id}"
raise ValidationError(msg)
return data

class Meta:
Expand Down
Loading