|
7 | 7 | # See https://aboutcode.org for more information about nexB OSS projects. |
8 | 8 | # |
9 | 9 | import logging |
| 10 | +from collections import defaultdict |
10 | 11 |
|
11 | 12 | from cvss.exceptions import CVSS2MalformedError |
12 | 13 | from cvss.exceptions import CVSS3MalformedError |
|
15 | 16 | from django.contrib.auth.views import LoginView |
16 | 17 | from django.core.exceptions import ValidationError |
17 | 18 | from django.core.mail import send_mail |
18 | | -from django.db.models import Count |
19 | | -from django.db.models import F |
| 19 | +from django.db.models import Exists |
| 20 | +from django.db.models import OuterRef |
20 | 21 | from django.db.models import Prefetch |
21 | 22 | from django.http.response import Http404 |
22 | 23 | from django.shortcuts import get_object_or_404 |
@@ -227,48 +228,46 @@ def get_context_data(self, **kwargs): |
227 | 228 | return context |
228 | 229 |
|
229 | 230 | def get_fixed_package_details(self, package): |
230 | | - affected_impacts = package.affected_in_impacts.select_related("advisory").prefetch_related( |
231 | | - Prefetch( |
232 | | - "fixed_by_packages", |
233 | | - queryset=( |
234 | | - models.PackageV2.objects.annotate(affected_count=Count("affected_in_impacts")) |
235 | | - ), |
236 | | - ) |
| 231 | + rows = package.affected_in_impacts.values_list( |
| 232 | + "advisory__avid", |
| 233 | + "fixed_by_packages", |
237 | 234 | ) |
238 | 235 |
|
239 | | - fixed_impacts = package.fixed_in_impacts.select_related("advisory") |
240 | | - |
241 | | - affected_avids = {impact.advisory.avid for impact in affected_impacts if impact.advisory_id} |
| 236 | + pkg_ids = {pkg_id for _, pkg_id in rows if pkg_id} |
242 | 237 |
|
243 | | - fixed_avids = {impact.advisory.avid for impact in fixed_impacts if impact.advisory_id} |
244 | | - |
245 | | - all_avids = affected_avids | fixed_avids |
| 238 | + pkg_map = { |
| 239 | + p.id: p |
| 240 | + for p in models.PackageV2.objects.filter(id__in=pkg_ids).annotate( |
| 241 | + is_vulnerable=Exists( |
| 242 | + models.ImpactedPackage.objects.filter(affecting_packages=OuterRef("pk")) |
| 243 | + ) |
| 244 | + ) |
| 245 | + } |
246 | 246 |
|
247 | | - advisories = models.AdvisoryV2.objects.latest_for_avids(all_avids) |
248 | | - advisory_by_avid = {adv.avid: adv for adv in advisories} |
| 247 | + fixed_pkg_details = defaultdict(list) |
249 | 248 |
|
250 | | - fixed_pkg_details = {} |
| 249 | + for avid, pkg_id in rows: |
| 250 | + if not pkg_id: |
| 251 | + continue |
251 | 252 |
|
252 | | - for impact in affected_impacts: |
253 | | - advisory = advisory_by_avid.get(impact.advisory.avid) |
254 | | - if not advisory: |
| 253 | + pkg = pkg_map.get(pkg_id) |
| 254 | + if not pkg: |
255 | 255 | continue |
256 | 256 |
|
257 | | - fixed_pkg_details.setdefault(impact.advisory.avid, []).extend( |
| 257 | + fixed_pkg_details[avid].append( |
258 | 258 | { |
259 | 259 | "pkg": pkg, |
260 | | - "affected_count": pkg.affected_count, |
| 260 | + "is_vulnerable": pkg.is_vulnerable, |
261 | 261 | } |
262 | | - for pkg in impact.fixed_by_packages.all() |
263 | 262 | ) |
264 | 263 |
|
265 | | - affected_by_advisories = { |
266 | | - advisory_by_avid[avid] for avid in affected_avids if avid in advisory_by_avid |
267 | | - } |
| 264 | + affected_by_advisories = models.AdvisoryV2.objects.latest_affecting_advisories_for_purl( |
| 265 | + package.package_url |
| 266 | + ) |
268 | 267 |
|
269 | | - fixing_advisories = { |
270 | | - advisory_by_avid[avid] for avid in fixed_avids if avid in advisory_by_avid |
271 | | - } |
| 268 | + fixing_advisories = models.AdvisoryV2.objects.latest_fixed_by_advisories_for_purl( |
| 269 | + package.package_url |
| 270 | + ) |
272 | 271 |
|
273 | 272 | return fixed_pkg_details, affected_by_advisories, fixing_advisories |
274 | 273 |
|
|
0 commit comments