2020from rest_framework .throttling import AnonRateThrottle
2121
2222from vulnerabilities .models import AdvisoryReference
23+ from vulnerabilities .models import AdvisorySet
2324from vulnerabilities .models import AdvisorySeverity
2425from vulnerabilities .models import AdvisoryV2
2526from vulnerabilities .models import AdvisoryWeakness
2627from vulnerabilities .models import ImpactedPackageAffecting
2728from vulnerabilities .models import PackageV2
2829from vulnerabilities .throttling import PermissionBasedUserRateThrottle
29- from vulnerabilities .utils import group_advisories_by_content
30+ from vulnerabilities .utils import TYPES_WITH_MULTIPLE_IMPORTERS
31+ from vulnerabilities .utils import get_advisories_from_groups
32+ from vulnerabilities .utils import merge_and_save_grouped_advisories
3033
3134
3235class PackageQuerySerializer (serializers .Serializer ):
@@ -210,6 +213,32 @@ def get_affected_by_vulnerabilities(self, package):
210213 """Return a dictionary with advisory as keys and their details, including fixed_by_packages."""
211214 advisories_qs = AdvisoryV2 .objects .latest_affecting_advisories_for_purl (package .package_url )
212215
216+ advisories = []
217+
218+ is_grouped = AdvisorySet .objects .filter (package = package , relation_type = "affecting" ).exists ()
219+
220+ if is_grouped :
221+ affected_by_advisories_qs = AdvisorySet .objects .filter (
222+ package = package , relation_type = "affecting"
223+ ).select_related ("primary_advisory" )
224+
225+ affected_groups = [
226+ (list (adv .aliases .all ()), adv .primary_advisory , "" )
227+ for adv in affected_by_advisories_qs
228+ ]
229+
230+ advisories = get_advisories_from_groups (affected_groups )
231+ return self .return_advisories_data (package , advisories_qs , advisories )
232+
233+ if package .type in TYPES_WITH_MULTIPLE_IMPORTERS :
234+ advisories_qs = advisories_qs .prefetch_related (
235+ "aliases" ,
236+ "impacted_packages__affecting_packages" ,
237+ "impacted_packages__fixed_by_packages" ,
238+ )
239+ advisories = merge_and_save_grouped_advisories (package , advisories_qs , "affecting" )
240+ return self .return_advisories_data (package , advisories_qs , advisories )
241+
213242 advisories_ids = advisories_qs .only ("id" )
214243
215244 advisories_ids = list (advisories_ids [:101 ])
@@ -227,20 +256,19 @@ def get_affected_by_vulnerabilities(self, package):
227256
228257 impact_by_avid = {impact .advisory .avid : impact for impact in impacts }
229258
230- grouped = group_advisories_by_content (advisories_qs )
231-
232259 result = []
233- for entry in grouped . values ():
234- primary = entry [ "primary" ]
235- impact = impact_by_avid .get (primary .avid )
260+
261+ for advisory in advisories_qs :
262+ impact = impact_by_avid .get (advisory .avid )
236263 if not impact :
237264 continue
238265
239266 result .append (
240267 {
241- "advisory_id" : primary .avid ,
268+ "advisory_id" : advisory .advisory_id .split ("/" )[- 1 ],
269+ "aliases" : [alias .alias for alias in advisory .aliases .all ()],
270+ "summary" : advisory .summary ,
242271 "fixed_by_packages" : [pkg .purl for pkg in impact .fixed_by_packages .all ()],
243- "duplicate_advisory_ids" : [a .avid for a in entry ["secondary" ]],
244272 }
245273 )
246274
@@ -249,21 +277,82 @@ def get_affected_by_vulnerabilities(self, package):
249277 def get_fixing_vulnerabilities (self , package ):
250278 advisories_qs = AdvisoryV2 .objects .latest_fixed_by_advisories_for_purl (package .package_url )
251279
280+ advisories = []
281+
282+ is_grouped = AdvisorySet .objects .filter (package = package , relation_type = "fixing" ).exists ()
283+
284+ if is_grouped :
285+ fixing_advisories_qs = AdvisorySet .objects .filter (
286+ package = package , relation_type = "fixing"
287+ ).select_related ("primary_advisory" )
288+
289+ fixing_groups = [
290+ (list (adv .aliases .all ()), adv .primary_advisory , "" ) for adv in fixing_advisories_qs
291+ ]
292+
293+ advisories = get_advisories_from_groups (fixing_groups )
294+ return self .return_fixing_advisories_data (advisories )
295+
296+ if package .type in TYPES_WITH_MULTIPLE_IMPORTERS :
297+ advisories_qs = advisories_qs .prefetch_related (
298+ "aliases" ,
299+ "impacted_packages__affecting_packages" ,
300+ "impacted_packages__fixed_by_packages" ,
301+ )
302+ advisories = merge_and_save_grouped_advisories (package , advisories_qs , "fixing" )
303+ return self .return_fixing_advisories_data (advisories )
304+
252305 advisories_ids = advisories_qs .only ("id" )
253306
254307 advisories_ids = list (advisories_ids [:101 ])
255308 if len (advisories_ids ) > 100 :
256309 return None
257310
258- grouped = group_advisories_by_content ( advisories_qs )
311+ results = []
259312
313+ for advisory in advisories_qs :
314+ results .append (
315+ {
316+ "advisory_id" : advisory .advisory_id .split ("/" )[- 1 ],
317+ }
318+ )
319+ return results
320+
321+ def return_fixing_advisories_data (self , advisories ):
260322 result = []
261- for entry in grouped .values ():
262- primary = entry ["primary" ]
323+ for advisory in advisories :
263324 result .append (
264325 {
265- "advisory_id" : primary .avid ,
266- "duplicate_advisory_ids" : [a .avid for a in entry ["secondary" ]],
326+ "advisory_id" : advisory ["identifier" ],
327+ }
328+ )
329+
330+ return result
331+
332+ def return_advisories_data (self , package , advisories_qs , advisories ):
333+ advisory_by_avid = {adv .avid : adv for adv in advisories_qs }
334+ avids = advisory_by_avid .keys ()
335+
336+ impacts = (
337+ package .affected_in_impacts .filter (advisory__avid__in = avids )
338+ .select_related ("advisory" )
339+ .prefetch_related ("fixed_by_packages" )
340+ )
341+
342+ impact_by_avid = {impact .advisory .avid : impact for impact in impacts }
343+
344+ result = []
345+ for advisory in advisories :
346+ impact = impact_by_avid .get (advisory ["advisory" ].avid )
347+ if not impact :
348+ continue
349+
350+ result .append (
351+ {
352+ "advisory_id" : advisory ["identifier" ],
353+ "aliases" : [alias .alias for alias in advisory ["aliases" ]],
354+ "summary" : advisory ["advisory" ].summary ,
355+ "fixed_by_packages" : [pkg .purl for pkg in impact .fixed_by_packages .all ()],
267356 }
268357 )
269358
0 commit comments