From fdf4cd0335423891752dffea0d07ef32047e59f5 Mon Sep 17 00:00:00 2001 From: tdruez Date: Wed, 4 Sep 2024 13:15:27 +0400 Subject: [PATCH] Refine the delete event on m2m #95 Signed-off-by: tdruez --- ...mponentaffectedbyvulnerability_and_more.py | 6 +-- vulnerabilities/models.py | 7 +-- vulnerabilities/tests/test_models.py | 52 ++++++++++++------- 3 files changed, 37 insertions(+), 28 deletions(-) diff --git a/component_catalog/migrations/0009_componentaffectedbyvulnerability_and_more.py b/component_catalog/migrations/0009_componentaffectedbyvulnerability_and_more.py index 5f3ec869..ff0f9bd8 100644 --- a/component_catalog/migrations/0009_componentaffectedbyvulnerability_and_more.py +++ b/component_catalog/migrations/0009_componentaffectedbyvulnerability_and_more.py @@ -1,4 +1,4 @@ -# Generated by Django 5.0.6 on 2024-09-04 08:17 +# Generated by Django 5.0.6 on 2024-09-04 09:15 import django.db.models.deletion import uuid @@ -21,7 +21,7 @@ class Migration(migrations.Migration): ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, verbose_name='UUID')), ('component', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='component_catalog.component')), ('dataspace', models.ForeignKey(editable=False, help_text='A Dataspace is an independent, exclusive set of DejaCode data, which can be either nexB master reference data or installation-specific data.', on_delete=django.db.models.deletion.PROTECT, to='dje.dataspace')), - ('vulnerability', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='vulnerabilities.vulnerability')), + ('vulnerability', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='vulnerabilities.vulnerability')), ], options={ 'unique_together': {('component', 'vulnerability'), ('dataspace', 'uuid')}, @@ -39,7 +39,7 @@ class Migration(migrations.Migration): ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, verbose_name='UUID')), ('dataspace', models.ForeignKey(editable=False, help_text='A Dataspace is an independent, exclusive set of DejaCode data, which can be either nexB master reference data or installation-specific data.', on_delete=django.db.models.deletion.PROTECT, to='dje.dataspace')), ('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='component_catalog.package')), - ('vulnerability', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='vulnerabilities.vulnerability')), + ('vulnerability', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='vulnerabilities.vulnerability')), ], options={ 'unique_together': {('dataspace', 'uuid'), ('package', 'vulnerability')}, diff --git a/vulnerabilities/models.py b/vulnerabilities/models.py index 441cca6f..2a156061 100644 --- a/vulnerabilities/models.py +++ b/vulnerabilities/models.py @@ -256,20 +256,15 @@ def as_cyclonedx(self, affected_instances): ) -# TODO: Review cascade class AffectedByVulnerabilityRelationship(DataspacedModel): vulnerability = models.ForeignKey( to="vulnerabilities.Vulnerability", - on_delete=models.PROTECT, + on_delete=models.CASCADE, ) class Meta: abstract = True - def save(self, *args, **kwargs): - self.dataspace = self.vulnerability.dataspace - super().save(*args, **kwargs) - class AffectedByVulnerabilityMixin(models.Model): """Add the `vulnerability` many to many field.""" diff --git a/vulnerabilities/tests/test_models.py b/vulnerabilities/tests/test_models.py index b9114b57..1700c274 100644 --- a/vulnerabilities/tests/test_models.py +++ b/vulnerabilities/tests/test_models.py @@ -13,6 +13,7 @@ from django.test import TestCase from component_catalog.tests import make_component +from component_catalog.models import Package from component_catalog.tests import make_package from dejacode_toolkit.vulnerablecode import VulnerableCode from dje.models import Dataspace @@ -85,35 +86,48 @@ def test_vulnerability_mixin_create_vulnerabilities(self): def test_vulnerability_model_affected_packages_m2m(self): package1 = make_package(self.dataspace) - vulnerablity1 = make_vulnerability(dataspace=self.dataspace, affecting=package1) - self.assertEqual(package1, vulnerablity1.affected_packages.get()) - self.assertEqual(vulnerablity1, package1.affected_by_vulnerabilities.get()) + vulnerability1 = make_vulnerability(dataspace=self.dataspace, affecting=package1) + self.assertEqual(package1, vulnerability1.affected_packages.get()) + self.assertEqual(vulnerability1, package1.affected_by_vulnerabilities.get()) + + def test_vulnerability_model_affected_by_vulnerability_relationship_delete(self): + package1 = make_package(self.dataspace) + vulnerability1 = make_vulnerability(dataspace=self.dataspace, affecting=package1) + package1.delete() + self.assertEqual(vulnerability1, Vulnerability.objects.get()) + self.assertEqual(0, Package.objects.count()) + + package1 = make_package(self.dataspace) + vulnerability1.add_affected(package1) + vulnerability1.delete() + self.assertEqual(package1, Package.objects.get()) + self.assertEqual(0, Vulnerability.objects.count()) def test_vulnerability_model_add_affected(self): - vulnerablity1 = make_vulnerability(dataspace=self.dataspace) + vulnerability1 = make_vulnerability(dataspace=self.dataspace) package1 = make_package(self.dataspace) package2 = make_package(self.dataspace) - vulnerablity1.add_affected(package1) - vulnerablity1.add_affected([package2]) - self.assertEqual(2, vulnerablity1.affected_packages.count()) + vulnerability1.add_affected(package1) + vulnerability1.add_affected([package2]) + self.assertEqual(2, vulnerability1.affected_packages.count()) - vulnerablity2 = make_vulnerability(dataspace=self.dataspace) + vulnerability2 = make_vulnerability(dataspace=self.dataspace) component1 = make_component(self.dataspace) - vulnerablity2.add_affected([component1, package1]) - self.assertQuerySetEqual(vulnerablity2.affected_packages.all(), [package1]) - self.assertQuerySetEqual(vulnerablity2.affected_components.all(), [component1]) + vulnerability2.add_affected([component1, package1]) + self.assertQuerySetEqual(vulnerability2.affected_packages.all(), [package1]) + self.assertQuerySetEqual(vulnerability2.affected_components.all(), [component1]) def test_vulnerability_model_fixed_packages_count_generated_field(self): - vulnerablity1 = make_vulnerability(dataspace=self.dataspace) - self.assertEqual(0, vulnerablity1.fixed_packages_count) + vulnerability1 = make_vulnerability(dataspace=self.dataspace) + self.assertEqual(0, vulnerability1.fixed_packages_count) - vulnerablity1.fixed_packages = [ + vulnerability1.fixed_packages = [ {"purl": "pkg:pypi/gitpython@3.1.41", "is_vulnerable": True}, {"purl": "pkg:pypi/gitpython@3.2", "is_vulnerable": False}, ] - vulnerablity1.save() - vulnerablity1.refresh_from_db() - self.assertEqual(2, vulnerablity1.fixed_packages_count) + vulnerability1.save() + vulnerability1.refresh_from_db() + self.assertEqual(2, vulnerability1.fixed_packages_count) def test_vulnerability_model_create_from_data(self): package1 = make_package(self.dataspace) @@ -164,8 +178,8 @@ def test_vulnerability_model_create_from_data_computed_scores(self): def test_vulnerability_model_queryset_count_methods(self): package1 = make_package(self.dataspace) package2 = make_package(self.dataspace) - vulnerablity1 = make_vulnerability(dataspace=self.dataspace) - vulnerablity1.add_affected([package1, package2]) + vulnerability1 = make_vulnerability(dataspace=self.dataspace) + vulnerability1.add_affected([package1, package2]) make_product(self.dataspace, inventory=[package1, package2]) qs = (