Skip to content
Open
11 changes: 11 additions & 0 deletions vulnerabilities/api_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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)
Expand All @@ -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="")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need this?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the UI, (and likely also in the API), I would welcome an option to filter only vulnerable or non vulnerable packages when doing a search for packages.

the issue description quotes if the same thing can be implemented in the API so I have added it in the API as well.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I get that we need filter in the API, but what I'm trying to understand is whether we need this queryset = queryset.exclude(version="").

return queryset.with_is_vulnerable()

def list(self, request, *args, **kwargs):
Expand Down
8 changes: 8 additions & 0 deletions vulnerabilities/templates/packages.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@
<div>
{{ page_obj.paginator.count|intcomma }} results
</div>
<form method="get" style="display: inline;">
{% if search %}<input type="hidden" name="search" value="{{ search }}">{% endif %}
<select name="vulnerable_only" class="select" id="vulnerable-select" onchange="this.form.submit()">
<option value="">All Packages</option>
<option value="true" {% if request.GET.vulnerable_only == 'true' %}selected{% endif %}>Vulnerable Only</option>
<option value="false" {% if request.GET.vulnerable_only == 'false' %}selected{% endif %}>Non-Vulnerable Only</option>
</select>
</form>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is how we want to have filters, how about a filter icon to the left with drop-down with All, Non-vulnerable, Vulnerable options.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure would add that as well.

{% if is_paginated %}
{% include 'includes/pagination.html' with page_obj=page_obj %}
{% endif %}
Expand Down
8 changes: 7 additions & 1 deletion vulnerabilities/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be much cleaner to use a form instead?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes It would be clean as well as safer from XSS attacks.. would handle it from form.

if vulnerable_only in ["true", "false"]:
queryset = queryset.with_is_vulnerable()
queryset = queryset.filter(is_vulnerable=vulnerable_only == "true")
return queryset


class VulnerabilitySearch(ListView):
Expand Down