Skip to content

Commit 3bdefc6

Browse files
committed
Separate views
Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
1 parent 02c503f commit 3bdefc6

File tree

2 files changed

+57
-49
lines changed

2 files changed

+57
-49
lines changed

vulnerabilities/views.py

Lines changed: 51 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,13 @@ def get_queryset(self):
159159
"exploits",
160160
Prefetch(
161161
"affecting_packages",
162-
queryset=models.Vulnerability.objects.only(
162+
queryset=models.Package.objects.only(
163163
"type", "namespace", "name", "version"
164164
),
165165
),
166166
Prefetch(
167167
"fixed_by_packages",
168-
queryset=models.Vulnerability.objects.only(
168+
queryset=models.Package.objects.only(
169169
"type", "namespace", "name", "version"
170170
),
171171
),
@@ -185,68 +185,22 @@ def get_context_data(self, **kwargs):
185185
weakness_object for weakness_object in vulnerability.weaknesses.all()
186186
if weakness_object.weakness
187187
]
188-
189-
# Cache aggregated packages
190-
(
191-
sorted_fixed_by_packages,
192-
sorted_affected_packages,
193-
all_affected_fixed_by_matches,
194-
) = vulnerability.aggregate_fixed_and_affected_packages()
195-
196-
severity_vectors, severity_values = self.get_severity_vectors_and_values(vulnerability)
197188

198189
context.update(
199190
{
200191
"vulnerability": vulnerability,
201192
"vulnerability_search_form": VulnerabilitySearchForm(self.request.GET),
202193
"severities": list(vulnerability.severities.all()),
203194
"severity_score_range": "",
204-
"severity_vectors": severity_vectors,
205195
"references": list(vulnerability.references.all()),
206196
"aliases": list(vulnerability.aliases.all()),
207-
"affected_packages": sorted_affected_packages,
208-
"fixed_by_packages": sorted_fixed_by_packages,
209197
"weaknesses": weaknesses_present_in_db,
210198
"status": vulnerability.get_status_label,
211199
"history": vulnerability.history,
212-
"all_affected_fixed_by_matches": all_affected_fixed_by_matches,
213200
}
214201
)
215202
return context
216203

217-
def get_severity_vectors_and_values(self, vulnerability):
218-
"""
219-
Collect severity vectors and values, excluding EPSS scoring systems efficiently.
220-
"""
221-
severity_vectors = []
222-
severity_values = set()
223-
224-
# Use prefetch data if available
225-
valid_scoring_severities = getattr(vulnerability, "prefetched_valid_severities", [])
226-
227-
for severity in valid_scoring_severities:
228-
try:
229-
vector_values = SCORING_SYSTEMS[severity.scoring_system].get(
230-
severity.scoring_elements
231-
)
232-
if vector_values:
233-
severity_vectors.append(vector_values)
234-
except (
235-
CVSS2MalformedError,
236-
CVSS3MalformedError,
237-
CVSS4MalformedError,
238-
NotImplementedError,
239-
) as e:
240-
logging.error(f"CVSSMalformedError for {severity.scoring_elements}: {e}")
241-
242-
# Collect valid values using a pre-filtered queryset
243-
severity_values.update(
244-
vulnerability.severities.exclude(value__isnull=True).exclude(value="").values_list("value", flat=True)
245-
)
246-
247-
return severity_vectors, severity_values
248-
249-
250204
class HomePage(View):
251205
template_name = "index.html"
252206

@@ -314,3 +268,52 @@ def form_valid(self, form):
314268

315269
def get_success_url(self):
316270
return reverse_lazy("api_user_request")
271+
272+
273+
class VulnerabilityPackagesDetails(DetailView):
274+
"""
275+
View to display all packages affected by or fixing a specific vulnerability.
276+
URL: /vulnerabilities/{vulnerability_id}/packages
277+
"""
278+
279+
model = models.Vulnerability
280+
template_name = "vulnerability_package_details.html"
281+
slug_url_kwarg = "vulnerability_id"
282+
slug_field = "vulnerability_id"
283+
284+
def get_queryset(self):
285+
"""
286+
Prefetch and optimize related data to minimize database hits.
287+
"""
288+
return super().get_queryset().prefetch_related(
289+
Prefetch(
290+
"affecting_packages",
291+
queryset=models.Package.objects.only(
292+
"type", "namespace", "name", "version"
293+
),
294+
),
295+
Prefetch(
296+
"fixed_by_packages",
297+
queryset=models.Package.objects.only(
298+
"type", "namespace", "name", "version"
299+
),
300+
),
301+
)
302+
303+
def get_context_data(self, **kwargs):
304+
"""
305+
Build context with preloaded QuerySets and minimize redundant queries.
306+
"""
307+
context = super().get_context_data(**kwargs)
308+
vulnerability = self.object
309+
(
310+
sorted_fixed_by_packages,
311+
sorted_affected_packages,
312+
all_affected_fixed_by_matches,
313+
) = vulnerability.aggregate_fixed_and_affected_packages()
314+
context.update({
315+
"affected_packages": sorted_affected_packages,
316+
"fixed_by_packages": sorted_fixed_by_packages,
317+
"all_affected_fixed_by_matches": all_affected_fixed_by_matches,
318+
})
319+
return context

vulnerablecode/urls.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from vulnerabilities.views import HomePage
2727
from vulnerabilities.views import PackageDetails
2828
from vulnerabilities.views import PackageSearch
29-
from vulnerabilities.views import VulnerabilityDetails
29+
from vulnerabilities.views import VulnerabilityDetails, VulnerabilityPackagesDetails
3030
from vulnerabilities.views import VulnerabilitySearch
3131
from vulnerablecode.settings import DEBUG_TOOLBAR
3232

@@ -80,6 +80,11 @@ def __init__(self, *args, **kwargs):
8080
VulnerabilityDetails.as_view(),
8181
name="vulnerability_details",
8282
),
83+
path(
84+
"vulnerabilities/<str:vulnerability_id>/packages",
85+
VulnerabilityPackagesDetails.as_view(),
86+
name="vulnerability_package_details",
87+
),
8388
path(
8489
"api/",
8590
include(api_router.urls),

0 commit comments

Comments
 (0)