@@ -238,40 +238,62 @@ def bulk_search(self, request):
238238 """
239239 Lookup for vulnerable packages using many Package URLs at once.
240240 """
241- response = []
241+
242242 purls = request .data .get ("purls" , []) or []
243+ purl_only = request .data .get ("purl_only" , False )
244+ plain_purl = request .data .get ("plain_purl" , False )
243245 if not purls or not isinstance (purls , list ):
244246 return Response (
245247 status = 400 ,
246- data = {"Error" : "A non-empty 'purls' list of package URLs is required." },
248+ data = {"Error" : "A non-empty 'purls' list of PURLs is required." },
249+ )
250+
251+ if plain_purl :
252+ purl_objects = [PackageURL .from_string (purl ) for purl in purls ]
253+ plain_purl_objects = [
254+ PackageURL (
255+ type = purl .type ,
256+ namespace = purl .namespace ,
257+ name = purl .name ,
258+ version = purl .version ,
259+ )
260+ for purl in purl_objects
261+ ]
262+ plain_purls = [str (purl ) for purl in plain_purl_objects ]
263+
264+ query = (
265+ Package .objects .filter (plain_package_url__in = plain_purls )
266+ .order_by ("plain_package_url" )
267+ .distinct ("plain_package_url" )
247268 )
248- for purl in request .data ["purls" ]:
249- try :
250- purl_string = purl
251- purl = PackageURL .from_string (purl )
252- except ValueError :
253- return Response (status = 400 , data = {"Error" : f"Invalid Package URL: { purl } " })
254- lookups = get_purl_query_lookups (purl )
255- purl_data = Package .objects .filter (** lookups )
256- purl_response = {}
257- if purl_data :
258- purl_response = PackageSerializer (purl_data [0 ], context = {"request" : request }).data
259- else :
260- purl_response = purl .to_dict ()
261- purl_response ["unresolved_vulnerabilities" ] = []
262- purl_response ["resolved_vulnerabilities" ] = []
263- purl_response ["purl" ] = purl_string
264- response .append (purl_response )
265-
266- return Response (response )
269+
270+ if not purl_only :
271+ return Response (
272+ PackageSerializer (query , many = True , context = {"request" : request }).data
273+ )
274+
275+ # using order by and distinct because there will be
276+ # many fully qualified purl for a single plain purl
277+ vulnerable_purls = query .vulnerable ().only ("plain_package_url" )
278+ vulnerable_purls = [str (package .plain_package_url ) for package in vulnerable_purls ]
279+ return Response (data = vulnerable_purls )
280+
281+ query = Package .objects .filter (package_url__in = purls ).distinct ()
282+
283+ if not purl_only :
284+ return Response (PackageSerializer (query , many = True , context = {"request" : request }).data )
285+
286+ vulnerable_purls = query .vulnerable ().only ("package_url" )
287+ vulnerable_purls = [str (package .package_url ) for package in vulnerable_purls ]
288+ return Response (data = vulnerable_purls )
267289
268290 @action (detail = False , methods = ["get" ], throttle_scope = "vulnerable_packages" )
269291 def all (self , request ):
270292 """
271293 Return the Package URLs of all packages known to be vulnerable.
272294 """
273- vulnerable_packages = Package .objects .vulnerable ().only (* PackageURL . _fields ).distinct ()
274- vulnerable_purls = [str (package .purl ) for package in vulnerable_packages ]
295+ vulnerable_packages = Package .objects .vulnerable ().only ("package_url" ).distinct ()
296+ vulnerable_purls = [str (package .package_url ) for package in vulnerable_packages ]
275297 return Response (vulnerable_purls )
276298
277299
0 commit comments