@@ -1012,6 +1012,54 @@ def normalize_datetime(value):
10121012 return value
10131013
10141014
1015+ def _create_note_if_provided (
1016+ finding ,
1017+ note_entry ,
1018+ * ,
1019+ user = None ,
1020+ note_type = None ,
1021+ note_date = None ,
1022+ ):
1023+ """
1024+ Create a note for the finding when content is provided. Returns the note or None.
1025+ Note author defaults to finding.last_reviewed_by
1026+ """
1027+ if not note_entry :
1028+ return None
1029+
1030+ new_note = Notes .objects .create (
1031+ entry = note_entry ,
1032+ author = user or finding .last_reviewed_by ,
1033+ note_type = note_type ,
1034+ date = note_date ,
1035+ )
1036+ finding .notes .add (new_note )
1037+ return new_note
1038+
1039+
1040+ def _save_finding_with_jira_sync (finding , * , new_note = None ):
1041+ """Persist finding and apply JIRA sync behavior used by finding status actions."""
1042+ push_to_jira = False
1043+ finding_in_group = finding .has_finding_group
1044+ jira_issue_exists = finding .has_jira_issue or (
1045+ finding .finding_group and finding .finding_group .has_jira_issue
1046+ )
1047+ jira_instance = jira_helper .get_jira_instance (finding )
1048+ jira_project = jira_helper .get_jira_project (finding )
1049+
1050+ if jira_issue_exists :
1051+ push_to_jira = (
1052+ jira_helper .is_push_all_issues (finding )
1053+ or (jira_instance and jira_instance .finding_jira_sync )
1054+ )
1055+ if new_note and (getattr (jira_project , "push_notes" , False ) or push_to_jira ) and not finding_in_group :
1056+ jira_helper .add_comment (finding , new_note , force_push = True )
1057+
1058+ finding .save (push_to_jira = (push_to_jira and not finding_in_group ))
1059+ if push_to_jira and finding_in_group :
1060+ jira_helper .push_to_jira (finding .finding_group )
1061+
1062+
10151063def close_finding (
10161064 * ,
10171065 finding ,
@@ -1046,15 +1094,12 @@ def close_finding(
10461094 finding .last_reviewed_by = user
10471095
10481096 # Create note if provided
1049- new_note = None
1050- if note_entry :
1051- new_note = Notes .objects .create (
1052- entry = note_entry ,
1053- author = user ,
1054- note_type = note_type ,
1055- date = mitigated_date ,
1056- )
1057- finding .notes .add (new_note )
1097+ new_note = _create_note_if_provided (
1098+ finding ,
1099+ note_entry ,
1100+ note_type = note_type ,
1101+ note_date = mitigated_date ,
1102+ )
10581103
10591104 if settings .V3_FEATURE_LOCATIONS :
10601105 # Related locations
@@ -1076,26 +1121,7 @@ def close_finding(
10761121 # External issues (best effort)
10771122 close_external_issue (finding .id , "Closed by defectdojo" , "github" )
10781123
1079- # JIRA sync
1080- push_to_jira = False
1081- finding_in_group = finding .has_finding_group
1082- jira_issue_exists = finding .has_jira_issue or (
1083- finding .finding_group and finding .finding_group .has_jira_issue
1084- )
1085- jira_instance = jira_helper .get_jira_instance (finding )
1086- jira_project = jira_helper .get_jira_project (finding )
1087- if jira_issue_exists :
1088- push_to_jira = (
1089- jira_helper .is_push_all_issues (finding )
1090- or (jira_instance and jira_instance .finding_jira_sync )
1091- )
1092- if new_note and (getattr (jira_project , "push_notes" , False ) or push_to_jira ) and not finding_in_group :
1093- jira_helper .add_comment (finding , new_note , force_push = True )
1094-
1095- # Persist and push JIRA if applicable
1096- finding .save (push_to_jira = (push_to_jira and not finding_in_group ))
1097- if push_to_jira and finding_in_group :
1098- jira_helper .push_to_jira (finding .finding_group )
1124+ _save_finding_with_jira_sync (finding , new_note = new_note )
10991125
11001126 # Notification
11011127 create_notification (
@@ -1105,3 +1131,28 @@ def close_finding(
11051131 description = f'The finding "{ finding .title } " was closed by { user } ' ,
11061132 url = reverse ("view_finding" , args = (finding .id ,)),
11071133 )
1134+
1135+
1136+ def verify_finding (
1137+ * ,
1138+ finding ,
1139+ user ,
1140+ note_entry = None ,
1141+ note_type = None ,
1142+ ) -> None :
1143+ """Shared verify logic used by UI and API."""
1144+ verification_time = now ()
1145+
1146+ finding .verified = True
1147+ finding .last_reviewed = verification_time
1148+ finding .last_reviewed_by = user
1149+ finding .last_status_update = verification_time
1150+
1151+ new_note = _create_note_if_provided (
1152+ finding ,
1153+ note_entry ,
1154+ note_type = note_type ,
1155+ note_date = verification_time ,
1156+ )
1157+
1158+ _save_finding_with_jira_sync (finding , new_note = new_note )
0 commit comments