|
5 | 5 | from django.core.exceptions import ValidationError
|
6 | 6 | from django.core.files.base import ContentFile
|
7 | 7 | from django.core.files.uploadedfile import TemporaryUploadedFile
|
| 8 | +from django.db import IntegrityError |
8 | 9 | from django.urls import reverse
|
9 | 10 | from django.utils.timezone import make_aware
|
10 | 11 |
|
@@ -262,6 +263,13 @@ def determine_process_method(
|
262 | 263 | **kwargs,
|
263 | 264 | )
|
264 | 265 |
|
| 266 | + def determine_deduplication_algorithm(self) -> str: |
| 267 | + """ |
| 268 | + Determines what dedupe algorithm to use for the Test being processed. |
| 269 | + :return: A string representing the dedupe algorithm to use. |
| 270 | + """ |
| 271 | + return self.test.deduplication_algorithm |
| 272 | + |
265 | 273 | def update_test_meta(self):
|
266 | 274 | """
|
267 | 275 | Update the test with some values stored in the kwargs dict. The common
|
@@ -357,53 +365,80 @@ def update_import_history(
|
357 | 365 | commit_hash=self.commit_hash,
|
358 | 366 | type=self.import_type,
|
359 | 367 | )
|
360 |
| - # Define all of the respective import finding actions for the test import object |
361 |
| - test_import_finding_action_list = [] |
| 368 | + |
| 369 | + # Create a history record for each finding |
362 | 370 | 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( |
| 371 | + self.create_import_history_record_safe(Test_Import_Finding_Action( |
365 | 372 | test_import=test_import,
|
366 | 373 | finding=finding,
|
367 | 374 | action=IMPORT_CLOSED_FINDING,
|
368 | 375 | ))
|
369 | 376 | 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( |
| 377 | + self.create_import_history_record_safe(Test_Import_Finding_Action( |
372 | 378 | test_import=test_import,
|
373 | 379 | finding=finding,
|
374 | 380 | action=IMPORT_CREATED_FINDING,
|
375 | 381 | ))
|
376 | 382 | 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( |
| 383 | + self.create_import_history_record_safe(Test_Import_Finding_Action( |
379 | 384 | test_import=test_import,
|
380 | 385 | finding=finding,
|
381 | 386 | action=IMPORT_REACTIVATED_FINDING,
|
382 | 387 | ))
|
383 | 388 | 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( |
| 389 | + self.create_import_history_record_safe(Test_Import_Finding_Action( |
386 | 390 | test_import=test_import,
|
387 | 391 | finding=finding,
|
388 | 392 | action=IMPORT_UNTOUCHED_FINDING,
|
389 | 393 | ))
|
390 |
| - # Bulk create all the defined objects |
391 |
| - Test_Import_Finding_Action.objects.bulk_create(test_import_finding_action_list) |
392 | 394 |
|
393 | 395 | # Add any tags to the findings imported if necessary
|
394 | 396 | if self.apply_tags_to_findings and self.tags:
|
395 | 397 | for finding in test_import.findings_affected.all():
|
396 | 398 | for tag in self.tags:
|
397 |
| - finding.tags.add(tag) |
| 399 | + self.add_tags_safe(finding, tag) |
398 | 400 | # Add any tags to any endpoints of the findings imported if necessary
|
399 | 401 | if self.apply_tags_to_endpoints and self.tags:
|
400 | 402 | for finding in test_import.findings_affected.all():
|
401 | 403 | for endpoint in finding.endpoints.all():
|
402 | 404 | for tag in self.tags:
|
403 |
| - endpoint.tags.add(tag) |
| 405 | + self.add_tags_safe(endpoint, tag) |
404 | 406 |
|
405 | 407 | return test_import
|
406 | 408 |
|
| 409 | + def create_import_history_record_safe( |
| 410 | + self, |
| 411 | + test_import_finding_action, |
| 412 | + ): |
| 413 | + """Creates an import history record, while catching any IntegrityErrors that might happen because of the background job having deleted a finding""" |
| 414 | + logger.debug(f"creating Test_Import_Finding_Action for finding: {test_import_finding_action.finding.id} action: {test_import_finding_action.action}") |
| 415 | + try: |
| 416 | + test_import_finding_action.save() |
| 417 | + except IntegrityError as e: |
| 418 | + # 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 |
| 419 | + logger.warning("Error creating Test_Import_Finding_Action: %s", e) |
| 420 | + logger.debug("Error creating Test_Import_Finding_Action, finding marked as duplicate and deleted ?") |
| 421 | + |
| 422 | + def add_tags_safe( |
| 423 | + self, |
| 424 | + finding_or_endpoint, |
| 425 | + tag, |
| 426 | + ): |
| 427 | + """Adds tags to a finding or endpoint, while catching any IntegrityErrors that might happen because of the background job having deleted a finding""" |
| 428 | + if not isinstance(finding_or_endpoint, Finding) and not isinstance(finding_or_endpoint, Endpoint): |
| 429 | + msg = "finding_or_endpoint must be a Finding or Endpoint object" |
| 430 | + raise TypeError(msg) |
| 431 | + |
| 432 | + msg = "finding" if isinstance(finding_or_endpoint, Finding) else "endpoint" if isinstance(finding_or_endpoint, Endpoint) else "unknown" |
| 433 | + logger.debug(f" adding tag: {tag} to " + msg + f"{finding_or_endpoint.id}") |
| 434 | + |
| 435 | + try: |
| 436 | + finding_or_endpoint.tags.add(tag) |
| 437 | + except IntegrityError as e: |
| 438 | + # 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 |
| 439 | + logger.warning("Error adding tag: %s", e) |
| 440 | + logger.debug("Error adding tag, finding marked as duplicate and deleted ?") |
| 441 | + |
407 | 442 | def construct_imported_message(
|
408 | 443 | self,
|
409 | 444 | finding_count: int = 0,
|
|
0 commit comments