Skip to content

Commit b483752

Browse files
Duplicate Delete errors: catch IntegrityErrors (A) (#11739)
* option a: catch IntegrityErrors * linting * fix object creation * fix object creation * bugfixing * bugfixing * Update dojo/api_v2/serializers.py
1 parent 7a7e4d8 commit b483752

2 files changed

Lines changed: 43 additions & 15 deletions

File tree

dojo/api_v2/serializers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ class ImportStatisticsSerializer(serializers.Serializer):
167167
)
168168
delta = DeltaStatisticsSerializer(
169169
required=False,
170-
help_text="Finding statistics of modifications made by the reimport. Only available when TRACK_IMPORT_HISTORY hass not disabled.",
170+
help_text="Finding statistics of modifications made by the reimport. Only available when TRACK_IMPORT_HISTORY has not been disabled.",
171171
)
172172
after = SeverityStatusStatisticsSerializer(
173173
help_text="Finding statistics as stored in Defect Dojo after the import",

dojo/importers/base_importer.py

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from django.core.exceptions import ValidationError
66
from django.core.files.base import ContentFile
77
from django.core.files.uploadedfile import TemporaryUploadedFile
8+
from django.db import IntegrityError
89
from django.urls import reverse
910
from django.utils.timezone import make_aware
1011

@@ -357,53 +358,80 @@ def update_import_history(
357358
commit_hash=self.commit_hash,
358359
type=self.import_type,
359360
)
360-
# Define all of the respective import finding actions for the test import object
361-
test_import_finding_action_list = []
361+
362+
# Create a history record for each finding
362363
for finding in closed_findings:
363-
logger.debug(f"preparing Test_Import_Finding_Action for closed finding: {finding.id}")
364-
test_import_finding_action_list.append(Test_Import_Finding_Action(
364+
self.create_import_history_record_safe(Test_Import_Finding_Action(
365365
test_import=test_import,
366366
finding=finding,
367367
action=IMPORT_CLOSED_FINDING,
368368
))
369369
for finding in new_findings:
370-
logger.debug(f"preparing Test_Import_Finding_Action for created finding: {finding.id}")
371-
test_import_finding_action_list.append(Test_Import_Finding_Action(
370+
self.create_import_history_record_safe(Test_Import_Finding_Action(
372371
test_import=test_import,
373372
finding=finding,
374373
action=IMPORT_CREATED_FINDING,
375374
))
376375
for finding in reactivated_findings:
377-
logger.debug(f"preparing Test_Import_Finding_Action for reactivated finding: {finding.id}")
378-
test_import_finding_action_list.append(Test_Import_Finding_Action(
376+
self.create_import_history_record_safe(Test_Import_Finding_Action(
379377
test_import=test_import,
380378
finding=finding,
381379
action=IMPORT_REACTIVATED_FINDING,
382380
))
383381
for finding in untouched_findings:
384-
logger.debug(f"preparing Test_Import_Finding_Action for untouched finding: {finding.id}")
385-
test_import_finding_action_list.append(Test_Import_Finding_Action(
382+
self.create_import_history_record_safe(Test_Import_Finding_Action(
386383
test_import=test_import,
387384
finding=finding,
388385
action=IMPORT_UNTOUCHED_FINDING,
389386
))
390-
# Bulk create all the defined objects
391-
Test_Import_Finding_Action.objects.bulk_create(test_import_finding_action_list)
392387

393388
# Add any tags to the findings imported if necessary
394389
if self.apply_tags_to_findings and self.tags:
395390
for finding in test_import.findings_affected.all():
396391
for tag in self.tags:
397-
finding.tags.add(tag)
392+
self.add_tags_safe(finding, tag)
398393
# Add any tags to any endpoints of the findings imported if necessary
399394
if self.apply_tags_to_endpoints and self.tags:
400395
for finding in test_import.findings_affected.all():
401396
for endpoint in finding.endpoints.all():
402397
for tag in self.tags:
403-
endpoint.tags.add(tag)
398+
self.add_tags_safe(endpoint, tag)
404399

405400
return test_import
406401

402+
def create_import_history_record_safe(
403+
self,
404+
test_import_finding_action,
405+
):
406+
"""Creates an import history record, while catching any IntegrityErrors that might happen because of the background job having deleted a finding"""
407+
logger.debug(f"creating Test_Import_Finding_Action for finding: {test_import_finding_action.finding.id} action: {test_import_finding_action.action}")
408+
try:
409+
test_import_finding_action.save()
410+
except IntegrityError as e:
411+
# This try catch makes us look we don't know what we're doing, but in https://github.com/DefectDojo/django-DefectDojo/issues/6217 we decided that for now this is the best solution
412+
logger.warning("Error creating Test_Import_Finding_Action: %s", e)
413+
logger.debug("Error creating Test_Import_Finding_Action, finding marked as duplicate and deleted ?")
414+
415+
def add_tags_safe(
416+
self,
417+
finding_or_endpoint,
418+
tag,
419+
):
420+
"""Adds tags to a finding or endpoint, while catching any IntegrityErrors that might happen because of the background job having deleted a finding"""
421+
if not isinstance(finding_or_endpoint, Finding) and not isinstance(finding_or_endpoint, Endpoint):
422+
msg = "finding_or_endpoint must be a Finding or Endpoint object"
423+
raise TypeError(msg)
424+
425+
msg = "finding" if isinstance(finding_or_endpoint, Finding) else "endpoint" if isinstance(finding_or_endpoint, Endpoint) else "unknown"
426+
logger.debug(f" adding tag: {tag} to " + msg + f"{finding_or_endpoint.id}")
427+
428+
try:
429+
finding_or_endpoint.tags.add(tag)
430+
except IntegrityError as e:
431+
# This try catch makes us look we don't know what we're doing, but in https://github.com/DefectDojo/django-DefectDojo/issues/6217 we decided that for now this is the best solution
432+
logger.warning("Error adding tag: %s", e)
433+
logger.debug("Error adding tag, finding marked as duplicate and deleted ?")
434+
407435
def construct_imported_message(
408436
self,
409437
finding_count: int = 0,

0 commit comments

Comments
 (0)