From 9468680e79d34867b04b49bdaf9c8d99b304a4f2 Mon Sep 17 00:00:00 2001 From: Rishi Garg Date: Sun, 16 Feb 2025 11:51:28 +0530 Subject: [PATCH 1/6] Filtering of Non Vulnerable packages added in API v2 Signed-off-by: Rishi Garg --- vulnerabilities/api_v2.py | 11 +++++++++++ vulnerabilities/templates/packages.html | 8 ++++++++ vulnerabilities/views.py | 8 +++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/vulnerabilities/api_v2.py b/vulnerabilities/api_v2.py index 10ffb6d98..31d076b58 100644 --- a/vulnerabilities/api_v2.py +++ b/vulnerabilities/api_v2.py @@ -254,6 +254,10 @@ class PackageV2FilterSet(filters.FilterSet): ) fixing_vulnerability = filters.CharFilter(field_name="fixing_vulnerabilities__vulnerability_id") purl = filters.CharFilter(field_name="package_url") + is_vulnerable = filters.BooleanFilter(method="filter_is_vulnerable") + + def filter_is_vulnerable(self, queryset, name, value): + return queryset.filter(is_vulnerable=value) class PackageV2ViewSet(viewsets.ReadOnlyModelViewSet): @@ -273,6 +277,7 @@ def get_queryset(self): package_purls = self.request.query_params.getlist("purl") affected_by_vulnerability = self.request.query_params.get("affected_by_vulnerability") fixing_vulnerability = self.request.query_params.get("fixing_vulnerability") + is_vulnerable = self.request.query_params.get("is_vulnerable") if package_purls: queryset = queryset.filter(package_url__in=package_purls) @@ -284,6 +289,12 @@ def get_queryset(self): queryset = queryset.filter( fixing_vulnerabilities__vulnerability_id=fixing_vulnerability ) + if is_vulnerable is not None: + queryset = queryset.with_is_vulnerable() + is_vulnerable = is_vulnerable.lower() == "true" + queryset = queryset.filter(is_vulnerable=is_vulnerable) + + queryset = queryset.exclude(version="") return queryset.with_is_vulnerable() def list(self, request, *args, **kwargs): diff --git a/vulnerabilities/templates/packages.html b/vulnerabilities/templates/packages.html index 1f7687429..4c5d4f3f4 100644 --- a/vulnerabilities/templates/packages.html +++ b/vulnerabilities/templates/packages.html @@ -18,6 +18,14 @@
{{ page_obj.paginator.count|intcomma }} results
+
+ {% if search %}{% endif %} + +
{% if is_paginated %} {% include 'includes/pagination.html' with page_obj=page_obj %} {% endif %} diff --git a/vulnerabilities/views.py b/vulnerabilities/views.py index a2df48634..d52523498 100644 --- a/vulnerabilities/views.py +++ b/vulnerabilities/views.py @@ -58,12 +58,18 @@ def get_queryset(self, query=None): on exact purl, partial purl or just name and namespace. """ query = query or self.request.GET.get("search") or "" - return ( + queryset = ( self.model.objects.search(query) .with_vulnerability_counts() .prefetch_related() .order_by("package_url") ) + if hasattr(self, "request"): + vulnerable_only = self.request.GET.get("vulnerable_only", "").lower() + if vulnerable_only in ["true", "false"]: + queryset = queryset.with_is_vulnerable() + queryset = queryset.filter(is_vulnerable=vulnerable_only == "true") + return queryset class VulnerabilitySearch(ListView): From d32ef52deaf0083291e9a37c8337a6e96ccaeb21 Mon Sep 17 00:00:00 2001 From: RISHI GARG <134256793+Rishi-source@users.noreply.github.com> Date: Sun, 20 Apr 2025 09:05:08 +0530 Subject: [PATCH 2/6] Add the filting via forms Signed-off-by: RISHI GARG <134256793+Rishi-source@users.noreply.github.com> --- vulnerabilities/api_v2.py | 2 -- vulnerabilities/forms.py | 8 +++++ vulnerabilities/templates/packages.html | 41 +++++++++++++++++++------ vulnerabilities/views.py | 9 ++++-- 4 files changed, 47 insertions(+), 13 deletions(-) diff --git a/vulnerabilities/api_v2.py b/vulnerabilities/api_v2.py index 31d076b58..ea7666878 100644 --- a/vulnerabilities/api_v2.py +++ b/vulnerabilities/api_v2.py @@ -293,8 +293,6 @@ def get_queryset(self): queryset = queryset.with_is_vulnerable() is_vulnerable = is_vulnerable.lower() == "true" queryset = queryset.filter(is_vulnerable=is_vulnerable) - - queryset = queryset.exclude(version="") return queryset.with_is_vulnerable() def list(self, request, *args, **kwargs): diff --git a/vulnerabilities/forms.py b/vulnerabilities/forms.py index 50511571d..8e8d0abbb 100644 --- a/vulnerabilities/forms.py +++ b/vulnerabilities/forms.py @@ -23,6 +23,14 @@ class PackageSearchForm(forms.Form): attrs={"placeholder": "Package name, purl or purl fragment"}, ), ) + vulnerable_only = forms.ChoiceField( + required=False, + choices=[ + ("", "All Packages"), + ("true", "Vulnerable Only"), + ("false", "Non-Vulnerable Only"), + ], + ) class VulnerabilitySearchForm(forms.Form): diff --git a/vulnerabilities/templates/packages.html b/vulnerabilities/templates/packages.html index 4c5d4f3f4..863868285 100644 --- a/vulnerabilities/templates/packages.html +++ b/vulnerabilities/templates/packages.html @@ -18,14 +18,37 @@
{{ page_obj.paginator.count|intcomma }} results
-
- {% if search %}{% endif %} - -
+ {% if is_paginated %} {% include 'includes/pagination.html' with page_obj=page_obj %} {% endif %} @@ -89,4 +112,4 @@ {% endif %} -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/vulnerabilities/views.py b/vulnerabilities/views.py index d52523498..082dfffda 100644 --- a/vulnerabilities/views.py +++ b/vulnerabilities/views.py @@ -49,6 +49,7 @@ def get_context_data(self, **kwargs): request_query = self.request.GET context["package_search_form"] = PackageSearchForm(request_query) context["search"] = request_query.get("search") + context["vulnerable_only"] = request_query.get("vulnerable_only", "") return context def get_queryset(self, query=None): @@ -57,18 +58,22 @@ def get_queryset(self, query=None): Make a best effort approach to find matching packages either based on exact purl, partial purl or just name and namespace. """ + form = PackageSearchForm(self.request.GET) query = query or self.request.GET.get("search") or "" + queryset = ( self.model.objects.search(query) .with_vulnerability_counts() .prefetch_related() .order_by("package_url") ) - if hasattr(self, "request"): - vulnerable_only = self.request.GET.get("vulnerable_only", "").lower() + + if form.is_valid(): + vulnerable_only = form.cleaned_data.get("vulnerable_only", "") if vulnerable_only in ["true", "false"]: queryset = queryset.with_is_vulnerable() queryset = queryset.filter(is_vulnerable=vulnerable_only == "true") + return queryset From 0d27c7cacda305253da03526a9972e1f0ee14116 Mon Sep 17 00:00:00 2001 From: RISHI GARG <134256793+Rishi-source@users.noreply.github.com> Date: Tue, 22 Apr 2025 15:36:43 +0530 Subject: [PATCH 3/6] Fix: Workflow errors in test_views.py Signed-off-by: RISHI GARG <134256793+Rishi-source@users.noreply.github.com> --- vulnerabilities/templates/packages.html | 6 +++--- vulnerabilities/views.py | 23 +++++++++++++---------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/vulnerabilities/templates/packages.html b/vulnerabilities/templates/packages.html index 863868285..bfc848baf 100644 --- a/vulnerabilities/templates/packages.html +++ b/vulnerabilities/templates/packages.html @@ -21,6 +21,9 @@