2222# Visit https://github.com/nexB/vulnerablecode/ for support and download.
2323
2424from urllib .parse import unquote
25+ from typing import List
2526
2627from django .db .models import Q
2728from django .urls import reverse
3132from rest_framework import viewsets
3233from rest_framework .decorators import action
3334from rest_framework .response import Response
35+ from drf_spectacular .utils import extend_schema , inline_serializer
36+ from drf_spectacular .types import OpenApiTypes
3437
3538from vulnerabilities .models import Package
3639from vulnerabilities .models import Vulnerability
3740from vulnerabilities .models import VulnerabilityReference
3841
42+ # This serializer is used for the bulk apis, to prevent wrong auto documentation
43+ # TODO: Fix the swagger documentation for bulk apis
44+ placeholder_serializer = inline_serializer (name = "Placeholder" , fields = {})
45+
3946
4047class VulnerabilityReferenceSerializer (serializers .ModelSerializer ):
4148 class Meta :
@@ -63,45 +70,52 @@ class Meta:
6370 fields = ["url" , "vulnerability_id" ]
6471
6572
66- class VulnerabilitySerializer (serializers .HyperlinkedModelSerializer ):
67- references = VulnerabilityReferenceSerializer ( many = True , source = "vulnerabilityreference_set" )
73+ class MinimalVulnerabilitySerializer (serializers .HyperlinkedModelSerializer ):
74+
6875 resolved_packages = HyperLinkedPackageSerializer (
6976 many = True , source = "resolved_to" , read_only = True
7077 )
7178 unresolved_packages = HyperLinkedPackageSerializer (
7279 many = True , source = "vulnerable_to" , read_only = True
7380 )
7481
82+ class Meta :
83+ model = Vulnerability
84+ fields = ["url" , "unresolved_packages" , "resolved_packages" ]
85+
86+
87+ class VulnerabilitySerializer (MinimalVulnerabilitySerializer ):
88+ references = VulnerabilityReferenceSerializer (many = True , source = "vulnerabilityreference_set" )
89+
7590 class Meta :
7691 model = Vulnerability
7792 fields = "__all__"
7893
7994
80- class PackageSerializer (serializers .HyperlinkedModelSerializer ):
95+ class MinimalPackageSerializer (serializers .HyperlinkedModelSerializer ):
8196 unresolved_vulnerabilities = HyperLinkedVulnerabilitySerializer (
8297 many = True , source = "vulnerable_to" , read_only = True
8398 )
8499 resolved_vulnerabilities = HyperLinkedVulnerabilitySerializer (
85100 many = True , source = "resolved_to" , read_only = True
86101 )
87- purl = serializers .CharField (source = "package_url" )
88102
89103 class Meta :
90104 model = Package
91105 fields = [
92- "url" ,
93- "type" ,
94- "namespace" ,
95- "name" ,
96- "version" ,
97- "qualifiers" ,
98- "subpath" ,
99- "purl" ,
100106 "resolved_vulnerabilities" ,
101107 "unresolved_vulnerabilities" ,
102108 ]
103109
104110
111+ class PackageSerializer (MinimalPackageSerializer ):
112+ purl = serializers .CharField (source = "package_url" )
113+
114+ class Meta :
115+ model = Package
116+ exclude = ["vulnerabilities" ]
117+
118+
105119class PackageFilterSet (filters .FilterSet ):
106120 purl = filters .CharFilter (method = "filter_purl" )
107121
@@ -129,8 +143,13 @@ class PackageViewSet(viewsets.ReadOnlyModelViewSet):
129143 filter_backends = (filters .DjangoFilterBackend ,)
130144 filterset_class = PackageFilterSet
131145
146+ # TODO: Fix the swagger documentation for this endpoint
147+ @extend_schema (request = placeholder_serializer , responses = placeholder_serializer )
132148 @action (detail = False , methods = ["post" ])
133149 def bulk_search (self , request ):
150+ """
151+ See https://github.com/nexB/vulnerablecode/pull/303#issuecomment-761801639 for docs
152+ """
134153 filter_list = Q ()
135154 response = {}
136155 if not isinstance (request .data .get ("packages" ), list ):
@@ -152,7 +171,7 @@ def bulk_search(self, request):
152171 response [purl ] = {}
153172 res = Package .objects .filter (filter_list )
154173 for p in res :
155- response [p .package_url ] = PackageSerializer (p , context = {"request" : request }).data
174+ response [p .package_url ] = MinimalPackageSerializer (p , context = {"request" : request }).data
156175
157176 return Response (response )
158177
@@ -172,8 +191,13 @@ class VulnerabilityViewSet(viewsets.ReadOnlyModelViewSet):
172191 filter_backends = (filters .DjangoFilterBackend ,)
173192 filterset_class = VulnerabilityFilterSet
174193
194+ # TODO: Fix the swagger documentation for this endpoint
195+ @extend_schema (request = placeholder_serializer , responses = placeholder_serializer )
175196 @action (detail = False , methods = ["post" ])
176197 def bulk_search (self , request ):
198+ """
199+ See https://github.com/nexB/vulnerablecode/pull/303#issuecomment-761801619 for docs
200+ """
177201 filter_list = []
178202 response = {}
179203 if not isinstance (request .data .get ("vulnerabilities" ), list ):
@@ -190,5 +214,7 @@ def bulk_search(self, request):
190214 response [cve_id ] = {}
191215 res = Vulnerability .objects .filter (cve_id__in = filter_list )
192216 for vuln in res :
193- response [vuln .cve_id ] = VulnerabilitySerializer (vuln , context = {"request" : request }).data
217+ response [vuln .cve_id ] = MinimalVulnerabilitySerializer (
218+ vuln , context = {"request" : request }
219+ ).data
194220 return Response (response )
0 commit comments