From 3bdefc62117fa98c2a634e91cc7d1c2c185ff020 Mon Sep 17 00:00:00 2001 From: Tushar Goel Date: Wed, 15 Jan 2025 15:49:45 +0530 Subject: [PATCH] Separate views Signed-off-by: Tushar Goel --- vulnerabilities/views.py | 99 +++++++++++++++++++++------------------- vulnerablecode/urls.py | 7 ++- 2 files changed, 57 insertions(+), 49 deletions(-) diff --git a/vulnerabilities/views.py b/vulnerabilities/views.py index 4a128e9e8..03a7428c1 100644 --- a/vulnerabilities/views.py +++ b/vulnerabilities/views.py @@ -159,13 +159,13 @@ def get_queryset(self): "exploits", Prefetch( "affecting_packages", - queryset=models.Vulnerability.objects.only( + queryset=models.Package.objects.only( "type", "namespace", "name", "version" ), ), Prefetch( "fixed_by_packages", - queryset=models.Vulnerability.objects.only( + queryset=models.Package.objects.only( "type", "namespace", "name", "version" ), ), @@ -185,15 +185,6 @@ def get_context_data(self, **kwargs): weakness_object for weakness_object in vulnerability.weaknesses.all() if weakness_object.weakness ] - - # Cache aggregated packages - ( - sorted_fixed_by_packages, - sorted_affected_packages, - all_affected_fixed_by_matches, - ) = vulnerability.aggregate_fixed_and_affected_packages() - - severity_vectors, severity_values = self.get_severity_vectors_and_values(vulnerability) context.update( { @@ -201,52 +192,15 @@ def get_context_data(self, **kwargs): "vulnerability_search_form": VulnerabilitySearchForm(self.request.GET), "severities": list(vulnerability.severities.all()), "severity_score_range": "", - "severity_vectors": severity_vectors, "references": list(vulnerability.references.all()), "aliases": list(vulnerability.aliases.all()), - "affected_packages": sorted_affected_packages, - "fixed_by_packages": sorted_fixed_by_packages, "weaknesses": weaknesses_present_in_db, "status": vulnerability.get_status_label, "history": vulnerability.history, - "all_affected_fixed_by_matches": all_affected_fixed_by_matches, } ) return context - def get_severity_vectors_and_values(self, vulnerability): - """ - Collect severity vectors and values, excluding EPSS scoring systems efficiently. - """ - severity_vectors = [] - severity_values = set() - - # Use prefetch data if available - valid_scoring_severities = getattr(vulnerability, "prefetched_valid_severities", []) - - for severity in valid_scoring_severities: - try: - vector_values = SCORING_SYSTEMS[severity.scoring_system].get( - severity.scoring_elements - ) - if vector_values: - severity_vectors.append(vector_values) - except ( - CVSS2MalformedError, - CVSS3MalformedError, - CVSS4MalformedError, - NotImplementedError, - ) as e: - logging.error(f"CVSSMalformedError for {severity.scoring_elements}: {e}") - - # Collect valid values using a pre-filtered queryset - severity_values.update( - vulnerability.severities.exclude(value__isnull=True).exclude(value="").values_list("value", flat=True) - ) - - return severity_vectors, severity_values - - class HomePage(View): template_name = "index.html" @@ -314,3 +268,52 @@ def form_valid(self, form): def get_success_url(self): return reverse_lazy("api_user_request") + + +class VulnerabilityPackagesDetails(DetailView): + """ + View to display all packages affected by or fixing a specific vulnerability. + URL: /vulnerabilities/{vulnerability_id}/packages + """ + + model = models.Vulnerability + template_name = "vulnerability_package_details.html" + slug_url_kwarg = "vulnerability_id" + slug_field = "vulnerability_id" + + def get_queryset(self): + """ + Prefetch and optimize related data to minimize database hits. + """ + return super().get_queryset().prefetch_related( + Prefetch( + "affecting_packages", + queryset=models.Package.objects.only( + "type", "namespace", "name", "version" + ), + ), + Prefetch( + "fixed_by_packages", + queryset=models.Package.objects.only( + "type", "namespace", "name", "version" + ), + ), + ) + + def get_context_data(self, **kwargs): + """ + Build context with preloaded QuerySets and minimize redundant queries. + """ + context = super().get_context_data(**kwargs) + vulnerability = self.object + ( + sorted_fixed_by_packages, + sorted_affected_packages, + all_affected_fixed_by_matches, + ) = vulnerability.aggregate_fixed_and_affected_packages() + context.update({ + "affected_packages": sorted_affected_packages, + "fixed_by_packages": sorted_fixed_by_packages, + "all_affected_fixed_by_matches": all_affected_fixed_by_matches, + }) + return context diff --git a/vulnerablecode/urls.py b/vulnerablecode/urls.py index 10f7db13f..d1c1a56bc 100644 --- a/vulnerablecode/urls.py +++ b/vulnerablecode/urls.py @@ -26,7 +26,7 @@ from vulnerabilities.views import HomePage from vulnerabilities.views import PackageDetails from vulnerabilities.views import PackageSearch -from vulnerabilities.views import VulnerabilityDetails +from vulnerabilities.views import VulnerabilityDetails, VulnerabilityPackagesDetails from vulnerabilities.views import VulnerabilitySearch from vulnerablecode.settings import DEBUG_TOOLBAR @@ -80,6 +80,11 @@ def __init__(self, *args, **kwargs): VulnerabilityDetails.as_view(), name="vulnerability_details", ), + path( + "vulnerabilities//packages", + VulnerabilityPackagesDetails.as_view(), + name="vulnerability_package_details", + ), path( "api/", include(api_router.urls),