@@ -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