Skip to content

Commit 44248b5

Browse files
committed
Make bulk search fast
Signed-off-by: Tushar Goel <[email protected]>
1 parent 83b2bc6 commit 44248b5

File tree

4 files changed

+72
-21
lines changed

4 files changed

+72
-21
lines changed

vulnerabilities/api.py

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -238,32 +238,26 @@ 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)
243244
if not purls or not isinstance(purls, list):
244245
return Response(
245246
status=400,
246-
data={"Error": "A non-empty 'purls' list of package URLs is required."},
247+
data={"Error": "A non-empty 'purls' list of PURLs is required."},
247248
)
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)
249+
250+
query = Package.objects.filter(package__in=purls)
251+
252+
if not purl_only:
253+
return Response(
254+
PackageSerializer(query.distinct(), many=True, context={"request": request}).data
255+
)
256+
257+
vulnerable_purls = (
258+
query.filter(packagerelatedvulnerability__fix=False).only("package").distinct()
259+
)
260+
return Response(data=vulnerable_purls)
267261

268262
@action(detail=False, methods=["get"], throttle_scope="vulnerable_packages")
269263
def all(self, request):
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 4.0.7 on 2022-11-25 12:57
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('vulnerabilities', '0033_alter_vulnerabilityseverity_scoring_system'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='package',
15+
name='package',
16+
field=models.CharField(blank=True, help_text='The Package URL for this package.', max_length=255),
17+
),
18+
]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Generated by Django 4.0.7 on 2022-11-25 12:57
2+
3+
from django.db import migrations
4+
from packageurl import PackageURL
5+
6+
class Migration(migrations.Migration):
7+
8+
def save_package(apps, schema_editor):
9+
Package = apps.get_model("vulnerabilities", "Package")
10+
for package in Package.objects.all():
11+
purl = PackageURL(
12+
type=package.type,
13+
namespace=package.namespace,
14+
name=package.name,
15+
version=package.version,
16+
qualifiers=package.qualifiers,
17+
subpath=package.subpath,
18+
)
19+
package.package = str(purl)
20+
package.save()
21+
22+
dependencies = [
23+
('vulnerabilities', '0034_package_package'),
24+
]
25+
26+
operations = [
27+
migrations.RunPython(save_package, reverse_code=migrations.RunPython.noop),
28+
]

vulnerabilities/models.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,8 +531,19 @@ class Package(PackageURLMixin):
531531
to="Vulnerability", through="PackageRelatedVulnerability"
532532
)
533533

534+
package = models.CharField(
535+
max_length=255,
536+
blank=True,
537+
null=False,
538+
help_text="The Package URL for this package.",
539+
)
540+
534541
objects = PackageQuerySet.as_manager()
535542

543+
def save(self, *args, **kwargs):
544+
self.package = self.purl
545+
super().save(*args, **kwargs)
546+
536547
@property
537548
def purl(self):
538549
return self.package_url

0 commit comments

Comments
 (0)