1212from urllib .parse import urlencode
1313
1414from django .db .models import Exists
15+ from django .db .models import Max
1516from django .db .models import OuterRef
1617from django .db .models import Prefetch
1718from django_filters import rest_framework as filters
@@ -226,8 +227,7 @@ def get_affected_by_vulnerabilities(self, package):
226227
227228 for adv in advisories :
228229 fixed = impact_map .get (adv ["avid" ])
229- if not fixed :
230- continue
230+ adv .pop ("avid" , None )
231231
232232 result .append (
233233 {
@@ -294,12 +294,9 @@ def get_affected_by_vulnerabilities(self, package):
294294 return self .return_advisories_data (package , advisories_qs , advisories )
295295
296296 def get_fixing_vulnerabilities (self , package ):
297- fixing_advisories = AdvisorySet .objects .filter (
298- package = package , relation_type = "fixing"
299- ).values_list ("primary_advisory__advisory_id" , flat = True )
300-
301- if fixing_advisories :
302- return [{"advisory_id" : adv_id .split ("/" )[- 1 ]} for adv_id in fixing_advisories ]
297+ advisories = self .context ["fixing_advisory_map" ].get (package .id , [])
298+ if advisories :
299+ return advisories
303300
304301 advisories_qs = AdvisoryV2 .objects .latest_fixed_by_advisories_for_purl (package .package_url )
305302
@@ -326,6 +323,8 @@ def get_fixing_vulnerabilities(self, package):
326323 "impacted_packages__affecting_packages" ,
327324 "impacted_packages__fixed_by_packages" ,
328325 )
326+ if not advisories_qs .exists ():
327+ return []
329328 advisories : List [GroupedAdvisory ] = merge_and_save_grouped_advisories (
330329 package , advisories_qs , "fixing"
331330 )
@@ -454,12 +453,13 @@ def create(self, request, *args, **kwargs):
454453 query = PackageV2 .objects .filter (package_url__in = purls ).order_by ("package_url" )
455454
456455 page = self .paginate_queryset (query )
457- advisory_map = get_grouped_advisories_bulk (page )
456+ affected_advisory_map = get_affected_advisories_bulk (page )
457+ fixing_advisory_map = get_fixing_advisories_bulk (page )
458458 impact_map = get_impacts_bulk (page )
459459 serializer = self .get_serializer (
460460 page ,
461461 many = True ,
462- context = {"request" : request , "advisory_map" : advisory_map , "impact_map" : impact_map },
462+ context = {"request" : request , "advisory_map" : affected_advisory_map , "impact_map" : impact_map , "fixing_advisory_map" : fixing_advisory_map },
463463 )
464464 return self .get_paginated_response (serializer .data )
465465
@@ -562,41 +562,35 @@ class AffectedByAdvisoriesViewSet(PackageAdvisoriesViewSet):
562562 serializer_class = AffectedByAdvisoryV3Serializer
563563
564564
565- def get_grouped_advisories_bulk (packages ):
565+ def get_affected_advisories_bulk (packages ):
566566 package_ids = [p .id for p in packages ]
567567
568568 advisory_sets = list (
569569 AdvisorySet .objects .filter (
570570 package_id__in = package_ids ,
571571 relation_type = "affecting" ,
572572 )
573- .select_related ("primary_advisory" , "package" )
574- .prefetch_related (
575- Prefetch ("aliases" , queryset = AdvisoryAlias .objects .only ("alias" )),
576- Prefetch (
577- "members" ,
578- queryset = AdvisorySetMember .objects .filter (is_primary = False )
579- .select_related ("advisory" )
580- .only (
581- "advisory__avid" ,
582- "advisory__weighted_severity" ,
583- "advisory__exploitability" ,
584- ),
585- to_attr = "secondary_members" ,
573+ .select_related ("primary_advisory" )
574+ .prefetch_related (Prefetch ("aliases" , queryset = AdvisoryAlias .objects .only ("alias" )))
575+ .annotate (
576+ max_severity = Max (
577+ "members__advisory__weighted_severity" ,
578+ ),
579+ max_exploitability = Max (
580+ "members__advisory__exploitability" ,
586581 ),
587582 )
588583 .only (
589584 "id" ,
590585 "package_id" ,
591586 "primary_advisory__avid" ,
592587 "primary_advisory__summary" ,
593- "primary_advisory__weighted_severity" ,
594- "primary_advisory__exploitability" ,
595588 "primary_advisory__advisory_id" ,
596589 )
597590 )
598591
599592 package_map = defaultdict (list )
593+
600594 for adv in advisory_sets :
601595 adv ._aliases_cache = [a .alias for a in adv .aliases .all ()]
602596 package_map [adv .package_id ].append (adv )
@@ -609,23 +603,14 @@ def get_grouped_advisories_bulk(packages):
609603
610604 for adv in groups :
611605 primary = adv .primary_advisory
612- secondaries = [m .advisory for m in adv .secondary_members ]
613606
614- max_sev = primary .weighted_severity or 0.0
615- max_exp = primary .exploitability or 0.0
616-
617- for sec in secondaries :
618- if sec .weighted_severity :
619- max_sev = max (max_sev , sec .weighted_severity )
620- if sec .exploitability :
621- max_exp = max (max_exp , sec .exploitability )
607+ max_sev = adv .max_severity or 0.0
608+ max_exp = adv .max_exploitability or 0.0
622609
623610 weighted_severity = round (max_sev , 1 ) if max_sev else None
624611 exploitability = max_exp or None
625612
626- risk_score = None
627- if exploitability and weighted_severity :
628- risk_score = round (min (exploitability * weighted_severity , 10.0 ), 1 )
613+ risk_score = round (min (max_exp * max_sev , 10.0 ), 1 ) if max_exp and max_sev else None
629614
630615 identifier = primary .advisory_id .split ("/" )[- 1 ]
631616
@@ -681,3 +666,39 @@ def get_impacts_bulk(packages):
681666 impact_map [impact .package_id ][avid ] = fixed_cache [ip .id ]
682667
683668 return impact_map
669+
670+
671+ def get_fixing_advisories_bulk (packages ):
672+ package_ids = [p .id for p in packages ]
673+
674+ advisory_sets = list (
675+ AdvisorySet .objects .filter (
676+ package_id__in = package_ids ,
677+ relation_type = "fixing" ,
678+ )
679+ .only (
680+ "id" ,
681+ "package_id" ,
682+ "primary_advisory__advisory_id" ,
683+ )
684+ )
685+
686+ package_map = defaultdict (list )
687+
688+ for adv in advisory_sets :
689+ package_map [adv .package_id ].append (adv .primary_advisory .advisory_id )
690+
691+ result = {}
692+
693+ for package in packages :
694+ groups = package_map .get (package .id , [])
695+ grouped = []
696+
697+ for adv_id in groups :
698+ grouped .append (
699+ {"advisory_id" : adv_id .split ("/" )[- 1 ]}
700+ )
701+
702+ result [package .id ] = grouped
703+
704+ return result
0 commit comments