diff --git a/component_catalog/urls.py b/component_catalog/urls.py index 50e87277..1c3deddb 100644 --- a/component_catalog/urls.py +++ b/component_catalog/urls.py @@ -21,7 +21,6 @@ from component_catalog.views import PackageTabScanView from component_catalog.views import PackageUpdateView from component_catalog.views import ScanListView -from component_catalog.views import VulnerabilityListView from component_catalog.views import component_create_ajax_view from component_catalog.views import delete_scan_view from component_catalog.views import package_create_ajax_view @@ -149,17 +148,9 @@ ), ] -vulnerabilities_patterns = [ - path( - "vulnerabilities/", - VulnerabilityListView.as_view(), - name="vulnerability_list", - ), -] - # WARNING: we moved the components/ patterns from the include to the following -# since we need the packages/ and scans/ to be register on the root "/" +# since we need the packages/ and scans/ to be registered on the root "/" def component_path(path_segment, view): @@ -248,4 +239,4 @@ def component_path(path_segment, view): ] -urlpatterns = packages_patterns + component_patterns + scans_patterns + vulnerabilities_patterns +urlpatterns = packages_patterns + component_patterns + scans_patterns diff --git a/component_catalog/views.py b/component_catalog/views.py index bc03434e..f64332a8 100644 --- a/component_catalog/views.py +++ b/component_catalog/views.py @@ -2479,57 +2479,3 @@ def get_tab_fields(self): tab_fields.extend(get_purldb_tab_fields(purldb_entry, user.dataspace)) return {"fields": tab_fields} - - -class VulnerabilityListView( - LoginRequiredMixin, - DataspacedFilterView, -): - model = Vulnerability - filterset_class = VulnerabilityFilterSet - template_name = "component_catalog/vulnerability_list.html" - template_list_table = "component_catalog/tables/vulnerability_list_table.html" - table_headers = ( - Header("vulnerability_id", _("Vulnerability")), - Header("aliases", _("Aliases")), - # Keep `max_score` to enable column sorting - Header("max_score", _("Score"), help_text="Severity score range", filter="max_score"), - Header("summary", _("Summary")), - Header("affected_products_count", _("Affected products"), help_text="Affected products"), - Header("affected_packages_count", _("Affected packages"), help_text="Affected packages"), - Header("fixed_packages_count", _("Fixed by"), help_text="Fixed by packages"), - ) - - def get_queryset(self): - return ( - super() - .get_queryset() - .only( - "uuid", - "vulnerability_id", - "aliases", - "summary", - "fixed_packages_count", - "max_score", - "min_score", - "created_date", - "last_modified_date", - "dataspace", - ) - .with_affected_products_count() - .with_affected_packages_count() - .order_by( - F("max_score").desc(nulls_last=True), - "-min_score", - ) - ) - - def get_context_data(self, **kwargs): - context_data = super().get_context_data(**kwargs) - - if not self.dataspace.enable_vulnerablecodedb_access: - raise Http404("VulnerableCode access is not enabled.") - - vulnerablecode = VulnerableCode(self.dataspace) - context_data["vulnerablecode_url"] = vulnerablecode.service_url - return context_data diff --git a/dejacode/urls.py b/dejacode/urls.py index 8bfabfe8..e7f862e3 100644 --- a/dejacode/urls.py +++ b/dejacode/urls.py @@ -142,6 +142,7 @@ path("owners/", include(("organization.urls", "organization"))), path("requests/", include(("workflow.urls", "workflow"))), path("reports/", include(("reporting.urls", "reporting"))), + path("vulnerabilities/", include(("vulnerabilities.urls", "vulnerabilities"))), path("global_search/", GlobalSearchListView.as_view(), name="global_search"), ] diff --git a/vulnerabilities/management/__init__.py b/vulnerabilities/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/vulnerabilities/management/commands/__init__.py b/vulnerabilities/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/component_catalog/management/commands/fetchvulnerabilities.py b/vulnerabilities/management/commands/fetchvulnerabilities.py similarity index 100% rename from component_catalog/management/commands/fetchvulnerabilities.py rename to vulnerabilities/management/commands/fetchvulnerabilities.py diff --git a/vulnerabilities/urls.py b/vulnerabilities/urls.py new file mode 100644 index 00000000..f3d4a0fd --- /dev/null +++ b/vulnerabilities/urls.py @@ -0,0 +1,15 @@ +# +# Copyright (c) nexB Inc. and others. All rights reserved. +# DejaCode is a trademark of nexB Inc. +# SPDX-License-Identifier: AGPL-3.0-only +# See https://github.com/aboutcode-org/dejacode for support or download. +# See https://aboutcode.org for more information about AboutCode FOSS projects. +# + +from django.urls import path +from vulnerabilities.views import VulnerabilityListView + + +urlpatterns = [ + path("", VulnerabilityListView.as_view(), name="vulnerability_list"), +] diff --git a/vulnerabilities/views.py b/vulnerabilities/views.py new file mode 100644 index 00000000..f991ebc4 --- /dev/null +++ b/vulnerabilities/views.py @@ -0,0 +1,71 @@ +# +# Copyright (c) nexB Inc. and others. All rights reserved. +# DejaCode is a trademark of nexB Inc. +# SPDX-License-Identifier: AGPL-3.0-only +# See https://github.com/aboutcode-org/dejacode for support or download. +# See https://aboutcode.org for more information about AboutCode FOSS projects. +# + +from django.contrib.auth.mixins import LoginRequiredMixin +from django.db.models import F +from django.http import Http404 +from django.utils.translation import gettext_lazy as _ +from component_catalog.filters import VulnerabilityFilterSet +from dejacode_toolkit.vulnerablecode import VulnerableCode +from dje.views import DataspacedFilterView +from dje.views import Header +from vulnerabilities.models import Vulnerability + + +class VulnerabilityListView( + LoginRequiredMixin, + DataspacedFilterView, +): + model = Vulnerability + filterset_class = VulnerabilityFilterSet + template_name = "component_catalog/vulnerability_list.html" + template_list_table = "component_catalog/tables/vulnerability_list_table.html" + table_headers = ( + Header("vulnerability_id", _("Vulnerability")), + Header("aliases", _("Aliases")), + # Keep `max_score` to enable column sorting + Header("max_score", _("Score"), help_text="Severity score range", filter="max_score"), + Header("summary", _("Summary")), + Header("affected_products_count", _("Affected products"), help_text="Affected products"), + Header("affected_packages_count", _("Affected packages"), help_text="Affected packages"), + Header("fixed_packages_count", _("Fixed by"), help_text="Fixed by packages"), + ) + + def get_queryset(self): + return ( + super() + .get_queryset() + .only( + "uuid", + "vulnerability_id", + "aliases", + "summary", + "fixed_packages_count", + "max_score", + "min_score", + "created_date", + "last_modified_date", + "dataspace", + ) + .with_affected_products_count() + .with_affected_packages_count() + .order_by( + F("max_score").desc(nulls_last=True), + "-min_score", + ) + ) + + def get_context_data(self, **kwargs): + context_data = super().get_context_data(**kwargs) + + if not self.dataspace.enable_vulnerablecodedb_access: + raise Http404("VulnerableCode access is not enabled.") + + vulnerablecode = VulnerableCode(self.dataspace) + context_data["vulnerablecode_url"] = vulnerablecode.service_url + return context_data