@@ -108,6 +108,8 @@ def get_vulnerability(self, vuln):
108108
109109 purl = serializers .CharField (source = "package_url" )
110110
111+ is_vulnerable = serializers .BooleanField ()
112+
111113 class Meta :
112114 model = Package
113115 fields = ["url" , "purl" , "is_vulnerable" , "affected_by_vulnerabilities" ]
@@ -248,21 +250,27 @@ def get_latest_non_vulnerable(self, package):
248250
249251 affected_by_vulnerabilities = serializers .SerializerMethodField ("get_affected_vulnerabilities" )
250252
251- fixing_vulnerabilities = serializers .SerializerMethodField ("get_fixed_vulnerabilities" )
253+ fixing_vulnerabilities = serializers .SerializerMethodField ("get_fixing_vulnerabilities" )
254+
255+ is_vulnerable = serializers .BooleanField ()
252256
253257 def get_fixed_packages (self , package ):
254258 """
255259 Return a queryset of all packages that fix a vulnerability with
256260 same type, namespace, name, subpath and qualifiers of the `package`
257261 """
258- return Package .objects .filter (
259- name = package .name ,
260- namespace = package .namespace ,
261- type = package .type ,
262- qualifiers = package .qualifiers ,
263- subpath = package .subpath ,
264- packagerelatedvulnerability__fix = True ,
265- ).distinct ()
262+ return (
263+ Package .objects .filter (
264+ name = package .name ,
265+ namespace = package .namespace ,
266+ type = package .type ,
267+ qualifiers = package .qualifiers ,
268+ subpath = package .subpath ,
269+ packagerelatedvulnerability__fix = True ,
270+ )
271+ .with_is_vulnerable ()
272+ .distinct ()
273+ )
266274
267275 def get_vulnerabilities_for_a_package (self , package , fix ) -> dict :
268276 """
@@ -285,7 +293,7 @@ def get_vulnerabilities_for_a_package(self, package, fix) -> dict:
285293 context = {"request" : self .context ["request" ]},
286294 ).data
287295
288- def get_fixed_vulnerabilities (self , package ) -> dict :
296+ def get_fixing_vulnerabilities (self , package ) -> dict :
289297 """
290298 Return a mapping of vulnerabilities fixed in the given `package`.
291299 """
@@ -322,12 +330,15 @@ class Meta:
322330 "version" ,
323331 "qualifiers" ,
324332 "subpath" ,
333+ "is_vulnerable" ,
325334 "next_non_vulnerable_version" ,
326335 "latest_non_vulnerable_version" ,
327336 "affected_by_vulnerabilities" ,
328337 "fixing_vulnerabilities" ,
329338 ]
330339
340+ is_vulnerable = serializers .BooleanField ()
341+
331342
332343class PackageFilterSet (filters .FilterSet ):
333344 purl = filters .CharFilter (method = "filter_purl" )
@@ -390,6 +401,9 @@ class PackageViewSet(viewsets.ReadOnlyModelViewSet):
390401 filterset_class = PackageFilterSet
391402 throttle_classes = [StaffUserRateThrottle , AnonRateThrottle ]
392403
404+ def get_queryset (self ):
405+ return super ().get_queryset ().with_is_vulnerable ()
406+
393407 @extend_schema (
394408 request = PackageBulkSearchRequestSerializer ,
395409 responses = {200 : PackageSerializer (many = True )},
@@ -436,6 +450,7 @@ def bulk_search(self, request):
436450 Package .objects .filter (plain_package_url__in = plain_purls )
437451 .order_by ("plain_package_url" )
438452 .distinct ("plain_package_url" )
453+ .with_is_vulnerable ()
439454 )
440455
441456 if not purl_only :
@@ -449,7 +464,7 @@ def bulk_search(self, request):
449464 vulnerable_purls = [str (package .plain_package_url ) for package in vulnerable_purls ]
450465 return Response (data = vulnerable_purls )
451466
452- query = Package .objects .filter (package_url__in = purls ).distinct ()
467+ query = Package .objects .filter (package_url__in = purls ).distinct (). with_is_vulnerable ()
453468
454469 if not purl_only :
455470 return Response (PackageSerializer (query , many = True , context = {"request" : request }).data )
@@ -463,7 +478,9 @@ def all(self, request):
463478 """
464479 Return the Package URLs of all packages known to be vulnerable.
465480 """
466- vulnerable_packages = Package .objects .vulnerable ().only ("package_url" ).distinct ()
481+ vulnerable_packages = (
482+ Package .objects .vulnerable ().only ("package_url" ).distinct ().with_is_vulnerable ()
483+ )
467484 vulnerable_purls = [str (package .package_url ) for package in vulnerable_packages ]
468485 return Response (vulnerable_purls )
469486
@@ -494,11 +511,8 @@ def lookup(self, request):
494511 validated_data = serializer .validated_data
495512 purl = validated_data .get ("purl" )
496513
497- return Response (
498- PackageSerializer (
499- Package .objects .for_purls ([purl ]), many = True , context = {"request" : request }
500- ).data
501- )
514+ qs = self .get_queryset ().for_purls ([purl ]).with_is_vulnerable ()
515+ return Response (PackageSerializer (qs , many = True , context = {"request" : request }).data )
502516
503517 @extend_schema (
504518 request = PackageurlListSerializer ,
@@ -529,7 +543,7 @@ def bulk_lookup(self, request):
529543
530544 return Response (
531545 PackageSerializer (
532- Package .objects .for_purls (purls ),
546+ Package .objects .for_purls (purls ). with_is_vulnerable () ,
533547 many = True ,
534548 context = {"request" : request },
535549 ).data
@@ -547,33 +561,47 @@ class VulnerabilityViewSet(viewsets.ReadOnlyModelViewSet):
547561 Lookup for vulnerabilities affecting packages.
548562 """
549563
564+ queryset = Vulnerability .objects .all ()
565+
550566 def get_fixed_packages_qs (self ):
551567 """
552568 Filter the packages that fixes a vulnerability
553569 on fields like name, namespace and type.
554570 """
555- package_filter_data = { " packagerelatedvulnerability__fix" : True }
571+ return self . get_packages_qs (). filter ( packagerelatedvulnerability__fix = True )
556572
573+ def get_packages_qs (self ):
574+ """
575+ Filter the packages on type, namespace and name.
576+ """
557577 query_params = self .request .query_params
558- for field_name in [ "name" , "namespace" , "type" ]:
559- value = query_params . get ( field_name )
560- if value :
578+ package_filter_data = {}
579+ for field_name in ( "type" , "namespace" , "name" ):
580+ if value := query_params . get ( field_name ) :
561581 package_filter_data [field_name ] = value
562582
563- return PackageFilterSet (package_filter_data ).qs
583+ return PackageFilterSet (package_filter_data ).qs . with_is_vulnerable ()
564584
565585 def get_queryset (self ):
566586 """
567587 Assign filtered packages queryset from `get_fixed_packages_qs`
568588 to a custom attribute `filtered_fixed_packages`
569589 """
570- return Vulnerability .objects .prefetch_related (
571- "weaknesses" ,
572- Prefetch (
573- "packages" ,
574- queryset = self .get_fixed_packages_qs (),
575- to_attr = "filtered_fixed_packages" ,
576- ),
590+ return (
591+ super ()
592+ .get_queryset ()
593+ .prefetch_related (
594+ Prefetch (
595+ "packages" ,
596+ queryset = self .get_packages_qs (),
597+ ),
598+ "weaknesses" ,
599+ Prefetch (
600+ "packages" ,
601+ queryset = self .get_fixed_packages_qs (),
602+ to_attr = "filtered_fixed_packages" ,
603+ ),
604+ )
577605 )
578606
579607 serializer_class = VulnerabilitySerializer
0 commit comments