Skip to content

Commit 7ef2199

Browse files
Add bulk delete findings extension hook and optional cascade context
- Split internal bulk delete implementation from entry point that can delegate via get_custom_method(BULK_DELETE_FINDINGS_METHOD). - Allow callers to pass optional cascade_root alongside chunk_size for downstream use when a custom method is configured.
1 parent 5024e7e commit 7ef2199

2 files changed

Lines changed: 19 additions & 3 deletions

File tree

dojo/finding/helper.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,7 @@ def bulk_clear_finding_m2m(finding_qs):
764764
Notes.objects.filter(id__in=note_ids).delete()
765765

766766

767-
def bulk_delete_findings(finding_qs, chunk_size=1000):
767+
def _bulk_delete_findings_internal(finding_qs, chunk_size=1000):
768768
"""
769769
Delete findings and all related objects efficiently. Including any related object in Dojo-Pro
770770
@@ -799,6 +799,20 @@ def bulk_delete_findings(finding_qs, chunk_size=1000):
799799
)
800800

801801

802+
def bulk_delete_findings(finding_qs, chunk_size=1000, cascade_root=None):
803+
"""Entry point; may delegate to Pro via settings.BULK_DELETE_FINDINGS_METHOD.
804+
805+
cascade_root: optional dict describing the top-level object whose cascade triggered
806+
this bulk delete (e.g. {"model": "dojo.engagement", "pk": 9}). Ignored by OSS
807+
when no custom method is configured.
808+
"""
809+
from dojo.utils import get_custom_method # noqa: PLC0415 circular import
810+
811+
if fn := get_custom_method("BULK_DELETE_FINDINGS_METHOD"):
812+
return fn(finding_qs, chunk_size=chunk_size, cascade_root=cascade_root)
813+
return _bulk_delete_findings_internal(finding_qs, chunk_size=chunk_size)
814+
815+
802816
def fix_loop_duplicates(scope_qs=None):
803817
"""Due to bugs in the past and even currently when under high parallel load, there can be transitive duplicates."""
804818
""" i.e. A -> B -> C. This can lead to problems when deleting findingns, performing deduplication, etc """

dojo/utils.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2024,6 +2024,8 @@ def async_delete_task(obj, **kwargs):
20242024
scope_field = FINDING_SCOPE_FILTERS.get(type(obj))
20252025
if scope_field:
20262026
finding_qs = Finding.objects.filter(**{scope_field: obj})
2027+
# cascade_root is some context we provide to the bulk_delete_findings function
2028+
cascade_root = {"model": obj._meta.label_lower, "pk": obj.pk}
20272029

20282030
# Step 2: Prepare duplicate clusters (must happen before any deletion)
20292031
# When CASCADE_DELETE=True, reconfigure_duplicate_cluster skips reconfiguration —
@@ -2042,10 +2044,10 @@ def async_delete_task(obj, **kwargs):
20422044
outside_count = outside_dupes_qs.count()
20432045
if outside_count:
20442046
logger.info("ASYNC_DELETE: Deleting %d outside-scope duplicates first", outside_count)
2045-
bulk_delete_findings(outside_dupes_qs, chunk_size=chunk_size)
2047+
bulk_delete_findings(outside_dupes_qs, chunk_size=chunk_size, cascade_root=cascade_root)
20462048

20472049
# Step 4: Delete the main scope findings
2048-
bulk_delete_findings(finding_qs, chunk_size=chunk_size)
2050+
bulk_delete_findings(finding_qs, chunk_size=chunk_size, cascade_root=cascade_root)
20492051

20502052
# Step 5: Delete all remaining related objects (Tests, Engagements,
20512053
# Endpoints, etc.) via SQL cascade. Findings are already gone, so

0 commit comments

Comments
 (0)