Skip to content

Commit 54341a9

Browse files
committed
Add package context in vulnerability details view
Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
1 parent ff95e09 commit 54341a9

3 files changed

Lines changed: 30 additions & 27 deletions

File tree

vulnerabilities/models.py

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -341,28 +341,32 @@ class Meta:
341341
ordering = ["vulnerability", "reference"]
342342

343343

344-
def purl_to_dict(purl: PackageURL):
344+
def purl_to_dict(purl: PackageURL, without_version=False):
345345
"""
346346
Return a dict of purl components suitable for use in a queryset.
347347
We need to have specific empty values for using in querysets because of our peculiar model structure.
348348
349349
For example::
350350
>>> purl_to_dict(PackageURL.from_string("pkg:generic/postgres"))
351-
{'type': 'generic', 'namespace': '', 'name': 'postgres', 'version': '', 'qualifiers': {}, 'subpath': ''}
351+
{'type': 'generic', 'namespace': '', 'name': 'postgres', 'qualifiers': {}, 'subpath': '', 'version': ''}
352352
>>> purl_to_dict(PackageURL.from_string("pkg:generic/postgres/postgres@1.2?foo=bar#baz"))
353-
{'type': 'generic', 'namespace': 'postgres', 'name': 'postgres', 'version': '1.2', 'qualifiers': {'foo': 'bar'}, 'subpath': 'baz'}
353+
{'type': 'generic', 'namespace': 'postgres', 'name': 'postgres', 'qualifiers': {'foo': 'bar'}, 'subpath': 'baz', 'version': '1.2'}
354+
>>> purl_to_dict(purl = PackageURL.from_string("pkg:generic/postgres/postgres@1.2?foo=bar#baz"), without_version=True)
355+
{'type': 'generic', 'namespace': 'postgres', 'name': 'postgres', 'qualifiers': {'foo': 'bar'}, 'subpath': 'baz'}
354356
"""
355357
if isinstance(purl, str):
356358
purl = PackageURL.from_string(purl)
357359

358-
return dict(
360+
lookup = dict(
359361
type=purl.type,
360362
namespace=purl.namespace or "",
361363
name=purl.name,
362-
version=purl.version or "",
363364
qualifiers=purl.qualifiers or {},
364365
subpath=purl.subpath or "",
365366
)
367+
if not without_version:
368+
lookup["version"] = purl.version or ""
369+
return lookup
366370

367371

368372
class PackageQuerySet(BaseQuerySet, PackageURLQuerySet):
@@ -416,17 +420,6 @@ def with_vulnerability_counts(self):
416420
),
417421
)
418422

419-
def fixing_packages(self, package, with_qualifiers_and_subpath=True):
420-
"""
421-
Return a queryset of packages that are fixing the vulnerability of
422-
``package``.
423-
"""
424-
425-
return self.match_purl(
426-
purl=package.purl,
427-
with_qualifiers_and_subpath=with_qualifiers_and_subpath,
428-
).fixing()
429-
430423
def search(self, query=None):
431424
"""
432425
Return a Package queryset searching for the ``query``.
@@ -481,6 +474,14 @@ def for_cve(self, cve):
481474
"""
482475
return self.filter(vulnerabilities__vulnerabilityreference__reference_id__exact=cve)
483476

477+
def matching_packages(self, purl):
478+
if not purl:
479+
return self
480+
if isinstance(purl, str):
481+
purl = PackageURL.from_string(purl)
482+
lookups = purl_to_dict(purl=purl, without_version=True)
483+
return self.filter(**lookups)
484+
484485

485486
def get_purl_query_lookups(purl):
486487
"""
@@ -584,13 +585,6 @@ def fixing(self):
584585
# legacy aliases
585586
resolved_to = fixing
586587

587-
@property
588-
def fixed_packages(self):
589-
"""
590-
Return a queryset of packages that are fixed.
591-
"""
592-
return Package.objects.fixing_packages(package=self).distinct()
593-
594588
@property
595589
def is_vulnerable(self) -> bool:
596590
"""

vulnerabilities/templates/package_details.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
{% for vulnerability in affected_by_vulnerabilities %}
5959
<tr>
6060
<td>
61-
<a href="{{ vulnerability.get_absolute_url }}" target="_self">{{ vulnerability.vulnerability_id }}</a>
61+
<a href="{{ vulnerability.get_absolute_url }}?package={{package.purl}}" target="_self">{{ vulnerability.vulnerability_id }}</a>
6262
</td>
6363
<td>
6464
{{ vulnerability.summary }}
@@ -105,7 +105,7 @@
105105
{% for vulnerability in fixing_vulnerabilities %}
106106
<tr>
107107
<td>
108-
<a href="{{ vulnerability.get_absolute_url }}" target="_self">{{ vulnerability.vulnerability_id }}</a>
108+
<a href="{{ vulnerability.get_absolute_url }}?package={{package.purl}}" target="_self">{{ vulnerability.vulnerability_id }}</a>
109109
</td>
110110
<td>
111111
{{ vulnerability.summary }}

vulnerabilities/views.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from django.views import generic
1919
from django.views.generic.detail import DetailView
2020
from django.views.generic.list import ListView
21+
from packageurl import PackageURL
2122

2223
from vulnerabilities import models
2324
from vulnerabilities.forms import ApiUserCreationForm
@@ -116,15 +117,23 @@ def get_queryset(self):
116117

117118
def get_context_data(self, **kwargs):
118119
context = super().get_context_data(**kwargs)
120+
request_query = self.request.GET
121+
package = request_query.get("package")
122+
purl = None
123+
if package:
124+
try:
125+
purl = PackageURL.from_string(package)
126+
except:
127+
purl = None
119128
context.update(
120129
{
121130
"vulnerability": self.object,
122131
"vulnerability_search_form": VulnerabilitySearchForm(self.request.GET),
123132
"severities": list(self.object.severities),
124133
"references": self.object.references.all(),
125134
"aliases": self.object.aliases.all(),
126-
"affected_packages": self.object.affected_packages.all(),
127-
"fixed_by_packages": self.object.fixed_by_packages.all(),
135+
"affected_packages": self.object.affected_packages.matching_packages(purl),
136+
"fixed_by_packages": self.object.fixed_by_packages.matching_packages(purl),
128137
"weaknesses": self.object.weaknesses.all(),
129138
}
130139
)

0 commit comments

Comments
 (0)