Skip to content

Commit 31f9767

Browse files
authored
Add notes management to RiskAcceptanceViewSet (#14173)
* Add notes management to RiskAcceptanceViewSet with GET and POST actions * Fix ruff
1 parent a8fdafe commit 31f9767

2 files changed

Lines changed: 80 additions & 0 deletions

File tree

dojo/api_v2/serializers.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,6 +1607,13 @@ class Meta:
16071607
fields = "__all__"
16081608

16091609

1610+
class RiskAcceptanceToNotesSerializer(serializers.Serializer):
1611+
risk_acceptance_id = serializers.PrimaryKeyRelatedField(
1612+
queryset=Risk_Acceptance.objects.all(), many=False, allow_null=True,
1613+
)
1614+
notes = NoteSerializer(many=True)
1615+
1616+
16101617
class FindingMetaSerializer(serializers.ModelSerializer):
16111618
class Meta:
16121619
model = DojoMeta

dojo/api_v2/views.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,79 @@ def download_proof(self, request, pk=None):
762762

763763
return response
764764

765+
@extend_schema(
766+
methods=["GET"],
767+
responses={
768+
status.HTTP_200_OK: serializers.RiskAcceptanceToNotesSerializer,
769+
},
770+
)
771+
@extend_schema(
772+
methods=["POST"],
773+
request=serializers.AddNewNoteOptionSerializer,
774+
responses={status.HTTP_201_CREATED: serializers.NoteSerializer},
775+
)
776+
@action(detail=True, methods=["get", "post"], permission_classes=[IsAuthenticated, permissions.UserHasRiskAcceptanceRelatedObjectPermission])
777+
def notes(self, request, pk=None):
778+
risk_acceptance = self.get_object()
779+
if request.method == "POST":
780+
new_note = serializers.AddNewNoteOptionSerializer(
781+
data=request.data,
782+
)
783+
if new_note.is_valid():
784+
entry = new_note.validated_data["entry"]
785+
private = new_note.validated_data.get("private", False)
786+
note_type = new_note.validated_data.get("note_type", None)
787+
else:
788+
return Response(
789+
new_note.errors, status=status.HTTP_400_BAD_REQUEST,
790+
)
791+
792+
notes = risk_acceptance.notes.filter(note_type=note_type).first()
793+
if notes and note_type and note_type.is_single:
794+
return Response("Only one instance of this note_type allowed on a risk acceptance.", status=status.HTTP_400_BAD_REQUEST)
795+
796+
author = request.user
797+
note = Notes(
798+
entry=entry,
799+
author=author,
800+
private=private,
801+
note_type=note_type,
802+
)
803+
note.save()
804+
risk_acceptance.notes.add(note)
805+
# Attempt to get a link to the risk acceptance
806+
if hasattr(risk_acceptance, "engagement") and risk_acceptance.engagement is not None:
807+
risk_acceptance_url = request.build_absolute_uri(
808+
reverse("view_risk_acceptance", args=(risk_acceptance.engagement.id, risk_acceptance.id)),
809+
)
810+
# Attempt to intuit the engagement from the findings
811+
elif (finding := risk_acceptance.accepted_findings.first()) is not None:
812+
risk_acceptance_url = request.build_absolute_uri(
813+
reverse("view_risk_acceptance", args=(finding.test.engagement.id, risk_acceptance.id)),
814+
)
815+
else:
816+
# Not much we can do here...
817+
risk_acceptance_url = "/"
818+
# Determine if we need to send any notifications for user mentioned
819+
process_tag_notifications(
820+
request=request,
821+
note=note,
822+
parent_url=risk_acceptance_url,
823+
parent_title=f"Risk Acceptance: {risk_acceptance.name}",
824+
)
825+
826+
serialized_note = serializers.NoteSerializer(
827+
{"author": author, "entry": entry, "private": private},
828+
)
829+
return Response(
830+
serialized_note.data, status=status.HTTP_201_CREATED,
831+
)
832+
notes = risk_acceptance.notes.all()
833+
serialized_notes = serializers.RiskAcceptanceToNotesSerializer(
834+
{"risk_acceptance_id": risk_acceptance, "notes": notes},
835+
)
836+
return Response(serialized_notes.data, status=status.HTTP_200_OK)
837+
765838

766839
# These are technologies in the UI and the API!
767840
# Authorization: object-based

0 commit comments

Comments
 (0)