From c6e95666a031ea925f3b5d1bf2076670b5db11b5 Mon Sep 17 00:00:00 2001 From: Shivam Sandbhor Date: Wed, 10 Jun 2020 17:48:57 +0530 Subject: [PATCH] Use JSONField instead of CharField to store a Package's qualifers Signed-off-by: Shivam Sandbhor --- vulnerabilities/import_runner.py | 2 +- vulnerabilities/migrations/0001_initial.py | 2 +- vulnerabilities/models.py | 29 ++++++++++++++++++++++ vulnerabilities/tests/test_alpine.py | 2 +- vulnerabilities/tests/test_debian.py | 2 +- 5 files changed, 33 insertions(+), 4 deletions(-) diff --git a/vulnerabilities/import_runner.py b/vulnerabilities/import_runner.py index 4590dee4b..7cf50d2e3 100644 --- a/vulnerabilities/import_runner.py +++ b/vulnerabilities/import_runner.py @@ -172,7 +172,7 @@ def _get_or_create_package(p: PackageURL) -> Tuple[models.Package, bool]: query_kwargs['namespace'] = packageurl.normalize_namespace(p.namespace, p.type, encode=True) if p.qualifiers: - query_kwargs['qualifiers'] = packageurl.normalize_qualifiers(p.qualifiers, encode=True) + query_kwargs['qualifiers'] = packageurl.normalize_qualifiers(p.qualifiers, encode=False) if p.subpath: query_kwargs['subpath'] = packageurl.normalize_subpath(p.subpath, encode=True) diff --git a/vulnerabilities/migrations/0001_initial.py b/vulnerabilities/migrations/0001_initial.py index 1855ad2dd..4df137b21 100644 --- a/vulnerabilities/migrations/0001_initial.py +++ b/vulnerabilities/migrations/0001_initial.py @@ -38,7 +38,7 @@ class Migration(migrations.Migration): ('namespace', models.CharField(blank=True, help_text='Package name prefix, such as Maven groupid, Docker image owner, GitHub user or organization, etc.', max_length=255, null=True)), ('name', models.CharField(blank=True, help_text='Name of the package.', max_length=100, null=True)), ('version', models.CharField(blank=True, help_text='Version of the package.', max_length=100, null=True)), - ('qualifiers', models.CharField(blank=True, help_text='Extra qualifying data for a package such as the name of an OS, architecture, distro, etc.', max_length=1024, null=True)), + ('qualifiers', django.contrib.postgres.fields.jsonb.JSONField(default=dict, null=True, help_text='Extra qualifying data for a package such as the name of an OS, architecture, distro, etc.')), ('subpath', models.CharField(blank=True, help_text='Extra subpath within a package, relative to the package root.', max_length=200, null=True)), ], options={ diff --git a/vulnerabilities/models.py b/vulnerabilities/models.py index 80aa4b92d..5fde0c21b 100644 --- a/vulnerabilities/models.py +++ b/vulnerabilities/models.py @@ -26,8 +26,10 @@ from django.db import models import django.contrib.postgres.fields as pgfields +from django.utils.translation import ugettext_lazy as _ from packageurl.contrib.django_models import PackageURLMixin +from packageurl import PackageURL from vulnerabilities.data_source import DataSource @@ -77,6 +79,33 @@ class Package(PackageURLMixin): class Meta: unique_together = ('name', 'namespace', 'type', 'version', 'qualifiers', 'subpath') + # Remove the `qualifers` and `set_package_url` overrides after + # https://github.com/package-url/packageurl-python/pull/35 gets merged + qualifiers = pgfields.JSONField( + default=dict, + help_text=_( + 'Extra qualifying data for a package such as the name of an OS, ' + 'architecture, distro, etc.' + ), + null=True + ) + + def set_package_url(self, package_url): + """ + Set each field values to the values of the provided `package_url` string + or PackageURL object. Existing values are overwritten including setting + values to None for provided empty values. + """ + if not isinstance(package_url, PackageURL): + package_url = PackageURL.from_string(package_url) + + for field_name, value in package_url.to_dict().items(): + model_field = self._meta.get_field(field_name) + + if value and len(value) > model_field.max_length: + raise ValidationError(_('Value too long for field "{}".'.format(field_name))) + + setattr(self, field_name, value or None) def __str__(self): return self.package_url diff --git a/vulnerabilities/tests/test_alpine.py b/vulnerabilities/tests/test_alpine.py index fd186923f..f2ae746b7 100644 --- a/vulnerabilities/tests/test_alpine.py +++ b/vulnerabilities/tests/test_alpine.py @@ -98,7 +98,7 @@ def assert_for_package(self, name, version, cve_ids=None, vuln_ref=None, arch=No assert qs if arch: - pkg = qs.get(qualifiers__contains=arch) + pkg = qs.get(qualifiers__arch=arch) else: pkg = qs[0] diff --git a/vulnerabilities/tests/test_debian.py b/vulnerabilities/tests/test_debian.py index 0c40d3f82..2b6c5120d 100644 --- a/vulnerabilities/tests/test_debian.py +++ b/vulnerabilities/tests/test_debian.py @@ -84,7 +84,7 @@ def assert_for_package(self, name, version, release, cve_ids=None): type='deb', namespace='debian', ) - qs = qs.filter(qualifiers__contains=release) + qs = qs.filter(qualifiers__distro=release) assert qs if cve_ids: