Skip to content

Commit 823081b

Browse files
committed
Change response of API
Signed-off-by: Tushar Goel <[email protected]>
1 parent e458518 commit 823081b

File tree

1 file changed

+107
-11
lines changed

1 file changed

+107
-11
lines changed

vulnerabilities/api_v2.py

Lines changed: 107 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#
99

1010

11+
from django_filters import rest_framework as filters
1112
from drf_spectacular.utils import OpenApiParameter
1213
from drf_spectacular.utils import extend_schema
1314
from drf_spectacular.utils import extend_schema_view
@@ -19,6 +20,8 @@
1920
from rest_framework.response import Response
2021
from rest_framework.reverse import reverse
2122

23+
from vulnerabilities.api import PackageFilterSet
24+
from vulnerabilities.api import VulnerabilitySeveritySerializer
2225
from vulnerabilities.models import Package
2326
from vulnerabilities.models import Vulnerability
2427
from vulnerabilities.models import VulnerabilityReference
@@ -210,9 +213,19 @@ class LookupRequestSerializer(serializers.Serializer):
210213
)
211214

212215

216+
class PackageV2FilterSet(filters.FilterSet):
217+
affected_by_vulnerability = filters.CharFilter(
218+
field_name="affected_by_vulnerabilities__vulnerability_id"
219+
)
220+
fixing_vulnerability = filters.CharFilter(field_name="fixing_vulnerabilities__vulnerability_id")
221+
purl = filters.CharFilter(field_name="package_url")
222+
223+
213224
class PackageV2ViewSet(viewsets.ReadOnlyModelViewSet):
214225
queryset = Package.objects.all()
215226
serializer_class = PackageV2Serializer
227+
filter_backends = (filters.DjangoFilterBackend,)
228+
filterset_class = PackageV2FilterSet
216229

217230
def get_queryset(self):
218231
queryset = super().get_queryset()
@@ -234,18 +247,45 @@ def get_queryset(self):
234247

235248
def list(self, request, *args, **kwargs):
236249
queryset = self.get_queryset()
250+
237251
# Apply pagination
238252
page = self.paginate_queryset(queryset)
239253
if page is not None:
254+
# Collect only vulnerabilities for packages in the current page
255+
vulnerabilities = set()
256+
for package in page:
257+
vulnerabilities.update(package.affected_by_vulnerabilities.all())
258+
vulnerabilities.update(package.fixing_vulnerabilities.all())
259+
260+
# Serialize the vulnerabilities with vulnerability_id as keys
261+
vulnerability_data = {
262+
vuln.vulnerability_id: VulnerabilityV2Serializer(vuln).data
263+
for vuln in vulnerabilities
264+
}
265+
266+
# Serialize the current page of packages
240267
serializer = self.get_serializer(page, many=True)
241268
data = serializer.data
269+
242270
# Use 'self.get_paginated_response' to include pagination data
243-
return self.get_paginated_response({"packages": data})
271+
return self.get_paginated_response(
272+
{"vulnerabilities": vulnerability_data, "packages": data}
273+
)
274+
275+
# If pagination is not applied, collect vulnerabilities for all packages
276+
vulnerabilities = set()
277+
for package in queryset:
278+
vulnerabilities.update(package.affected_by_vulnerabilities.all())
279+
vulnerabilities.update(package.fixing_vulnerabilities.all())
280+
281+
vulnerability_data = {
282+
vuln.vulnerability_id: VulnerabilityV2Serializer(vuln).data for vuln in vulnerabilities
283+
}
244284

245-
# If pagination is not applied
285+
# Serialize all packages when pagination is not applied
246286
serializer = self.get_serializer(queryset, many=True)
247287
data = serializer.data
248-
return Response({"packages": data})
288+
return Response({"vulnerabilities": vulnerability_data, "packages": data})
249289

250290
@extend_schema(
251291
request=PackageurlListSerializer,
@@ -274,12 +314,32 @@ def bulk_lookup(self, request):
274314
validated_data = serializer.validated_data
275315
purls = validated_data.get("purls")
276316

317+
# Fetch packages matching the provided purls
318+
packages = Package.objects.for_purls(purls).with_is_vulnerable()
319+
320+
# Collect vulnerabilities associated with these packages
321+
vulnerabilities = set()
322+
for package in packages:
323+
vulnerabilities.update(package.affected_by_vulnerabilities.all())
324+
vulnerabilities.update(package.fixing_vulnerabilities.all())
325+
326+
# Serialize vulnerabilities with vulnerability_id as keys
327+
vulnerability_data = {
328+
vuln.vulnerability_id: VulnerabilityV2Serializer(vuln).data for vuln in vulnerabilities
329+
}
330+
331+
# Serialize packages
332+
package_data = PackageV2Serializer(
333+
packages,
334+
many=True,
335+
context={"request": request},
336+
).data
337+
277338
return Response(
278-
PackageV2Serializer(
279-
Package.objects.for_purls(purls).with_is_vulnerable(),
280-
many=True,
281-
context={"request": request},
282-
).data
339+
{
340+
"vulnerabilities": vulnerability_data,
341+
"packages": package_data,
342+
}
283343
)
284344

285345
@extend_schema(
@@ -331,22 +391,58 @@ def bulk_search(self, request):
331391
.with_is_vulnerable()
332392
)
333393

394+
packages = query
395+
396+
# Collect vulnerabilities associated with these packages
397+
vulnerabilities = set()
398+
for package in packages:
399+
vulnerabilities.update(package.affected_by_vulnerabilities.all())
400+
vulnerabilities.update(package.fixing_vulnerabilities.all())
401+
402+
vulnerability_data = {
403+
vuln.vulnerability_id: VulnerabilityV2Serializer(vuln).data
404+
for vuln in vulnerabilities
405+
}
406+
334407
if not purl_only:
408+
package_data = PackageV2Serializer(
409+
packages, many=True, context={"request": request}
410+
).data
335411
return Response(
336-
PackageV2Serializer(query, many=True, context={"request": request}).data
412+
{
413+
"vulnerabilities": vulnerability_data,
414+
"packages": package_data,
415+
}
337416
)
338417

339-
# using order by and distinct because there will be
418+
# Using order by and distinct because there will be
340419
# many fully qualified purl for a single plain purl
341420
vulnerable_purls = query.vulnerable().only("plain_package_url")
342421
vulnerable_purls = [str(package.plain_package_url) for package in vulnerable_purls]
343422
return Response(data=vulnerable_purls)
344423

345424
query = Package.objects.filter(package_url__in=purls).distinct().with_is_vulnerable()
425+
packages = query
426+
427+
# Collect vulnerabilities associated with these packages
428+
vulnerabilities = set()
429+
for package in packages:
430+
vulnerabilities.update(package.affected_by_vulnerabilities.all())
431+
vulnerabilities.update(package.fixing_vulnerabilities.all())
432+
433+
vulnerability_data = {
434+
vuln.vulnerability_id: VulnerabilityV2Serializer(vuln).data for vuln in vulnerabilities
435+
}
346436

347437
if not purl_only:
438+
package_data = PackageV2Serializer(
439+
packages, many=True, context={"request": request}
440+
).data
348441
return Response(
349-
PackageV2Serializer(query, many=True, context={"request": request}).data
442+
{
443+
"vulnerabilities": vulnerability_data,
444+
"packages": package_data,
445+
}
350446
)
351447

352448
vulnerable_purls = query.vulnerable().only("package_url")

0 commit comments

Comments
 (0)