Skip to content

Commit 05f1ba1

Browse files
committed
Add V2 API endpoints
Reference: #1572 Signed-off-by: Tushar Goel <[email protected]>
1 parent 5cdca84 commit 05f1ba1

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

vulnerabilities/api.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,3 +691,112 @@ class AliasViewSet(VulnerabilityViewSet):
691691
"""
692692

693693
filterset_class = AliasFilterSet
694+
695+
class WeaknessV2Serializer(serializers.ModelSerializer):
696+
cwe_id = serializers.CharField()
697+
name = serializers.CharField()
698+
description = serializers.CharField()
699+
700+
class Meta:
701+
model = Weakness
702+
fields = ["cwe_id", "name", "description"]
703+
704+
705+
class VulnerabilityReferenceV2Serializer(serializers.ModelSerializer):
706+
url = serializers.CharField()
707+
reference_type = serializers.CharField()
708+
reference_id = serializers.CharField()
709+
710+
class Meta:
711+
model = VulnerabilityReference
712+
fields = ["url", "reference_type", "reference_id"]
713+
714+
class VulnerabilityV2Serializer(serializers.ModelSerializer):
715+
aliases = serializers.SerializerMethodField()
716+
severities = serializers.SerializerMethodField()
717+
weaknesses = WeaknessV2Serializer(many=True)
718+
references = VulnerabilityReferenceV2Serializer(many=True, source='vulnerabilityreference_set')
719+
720+
class Meta:
721+
model = Vulnerability
722+
fields = [
723+
"vulnerability_id",
724+
"aliases",
725+
"summary",
726+
"severities",
727+
"weaknesses",
728+
"references",
729+
]
730+
731+
def get_aliases(self, obj):
732+
return [alias.alias for alias in obj.aliases.all()]
733+
734+
def get_severities(self, obj):
735+
#TODO: Need data model changes
736+
return []
737+
738+
739+
class VulnerabilityV2ViewSet(viewsets.ReadOnlyModelViewSet):
740+
queryset = Vulnerability.objects.all()
741+
serializer_class = VulnerabilityV2Serializer
742+
743+
def list(self, request, *args, **kwargs):
744+
queryset = self.get_queryset()
745+
# Apply pagination
746+
page = self.paginate_queryset(queryset)
747+
if page is not None:
748+
serializer = self.get_serializer(page, many=True)
749+
data = serializer.data
750+
vulnerabilities = {item['vulnerability_id']: item for item in data}
751+
# Use 'self.get_paginated_response' to include pagination data
752+
return self.get_paginated_response({'vulnerabilities': vulnerabilities})
753+
754+
# If pagination is not applied
755+
serializer = self.get_serializer(queryset, many=True)
756+
data = serializer.data
757+
vulnerabilities = {item['vulnerability_id']: item for item in data}
758+
return Response({'vulnerabilities': vulnerabilities})
759+
760+
761+
class PackageV2Serializer(serializers.ModelSerializer):
762+
purl = serializers.CharField(source='package_url')
763+
affected_by_vulnerabilities = serializers.SerializerMethodField()
764+
fixing_vulnerabilities = serializers.SerializerMethodField()
765+
next_non_vulnerable_version = serializers.CharField(read_only=True)
766+
latest_non_vulnerable_version = serializers.CharField(read_only=True)
767+
768+
class Meta:
769+
model = Package
770+
fields = [
771+
'purl',
772+
'affected_by_vulnerabilities',
773+
'fixing_vulnerabilities',
774+
'next_non_vulnerable_version',
775+
'latest_non_vulnerable_version',
776+
]
777+
778+
def get_affected_by_vulnerabilities(self, obj):
779+
return [vuln.vulnerability_id for vuln in obj.affected_by_vulnerabilities.all()]
780+
781+
def get_fixing_vulnerabilities(self, obj):
782+
return [vuln.vulnerability_id for vuln in obj.fixing_vulnerabilities.all()]
783+
784+
785+
class PackageV2ViewSet(viewsets.ReadOnlyModelViewSet):
786+
queryset = Package.objects.all()
787+
serializer_class = PackageV2Serializer
788+
789+
def list(self, request, *args, **kwargs):
790+
queryset = self.get_queryset().with_is_vulnerable()
791+
# Apply pagination
792+
page = self.paginate_queryset(queryset)
793+
if page is not None:
794+
serializer = self.get_serializer(page, many=True)
795+
data = serializer.data
796+
# Use 'self.get_paginated_response' to include pagination data
797+
return self.get_paginated_response({'purls': data})
798+
799+
# If pagination is not applied
800+
serializer = self.get_serializer(queryset, many=True)
801+
data = serializer.data
802+
return Response({'purls': data})

vulnerablecode/urls.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
from vulnerabilities.api import CPEViewSet
2121
from vulnerabilities.api import PackageViewSet
2222
from vulnerabilities.api import VulnerabilityViewSet
23+
from vulnerabilities.api import PackageV2ViewSet
24+
from vulnerabilities.api import VulnerabilityV2ViewSet
2325
from vulnerabilities.views import ApiUserCreateView
2426
from vulnerabilities.views import HomePage
2527
from vulnerabilities.views import PackageDetails
@@ -43,6 +45,10 @@ def __init__(self, *args, **kwargs):
4345
api_router.register("cpes", CPEViewSet, basename="cpe")
4446
api_router.register("aliases", AliasViewSet, basename="alias")
4547

48+
api_v2_router = OptionalSlashRouter()
49+
api_v2_router.register("vulnerabilities", VulnerabilityV2ViewSet, basename="vulnerability-v2")
50+
api_v2_router.register("packages", PackageV2ViewSet, basename="package-v2")
51+
4652
urlpatterns = [
4753
path(
4854
"robots.txt",
@@ -98,6 +104,7 @@ def __init__(self, *args, **kwargs):
98104
TemplateView.as_view(template_name="tos.html"),
99105
name="api_tos",
100106
),
107+
path('api/v2/', include(api_v2_router.urls)),
101108
path(
102109
"admin/",
103110
admin.site.urls,

0 commit comments

Comments
 (0)