Skip to content

Commit 9de782b

Browse files
committed
Move fixed_packages to vulnerabilities in packages endpoint #809
Reference: #809 Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
1 parent 2670b03 commit 9de782b

3 files changed

Lines changed: 76 additions & 53 deletions

File tree

vulnerabilities/api.py

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,15 @@ class VulnSerializerRefsAndSummary(serializers.HyperlinkedModelSerializer):
5656
Used for nesting inside package focused APIs.
5757
"""
5858

59+
fixed_packages = MinimalPackageSerializer(
60+
many=True, source="filtered_fixed_packages", read_only=True
61+
)
62+
5963
references = VulnerabilityReferenceSerializer(many=True, source="vulnerabilityreference_set")
6064

6165
class Meta:
6266
model = Vulnerability
63-
fields = ["url", "vulnerability_id", "summary", "references"]
67+
fields = ["url", "vulnerability_id", "summary", "references", "fixed_packages"]
6468

6569

6670
class MinimalVulnerabilitySerializer(serializers.HyperlinkedModelSerializer):
@@ -73,21 +77,6 @@ class Meta:
7377
fields = ["url", "vulnerability_id"]
7478

7579

76-
class PackageSerializerFixedVulns(serializers.HyperlinkedModelSerializer):
77-
"""
78-
Used for nesting inside vulnerability focused APIs.
79-
"""
80-
81-
purl = serializers.CharField(source="package_url")
82-
fixing_vulnerabilities = MinimalVulnerabilitySerializer(
83-
many=True, source="resolved_to", read_only=True
84-
)
85-
86-
class Meta:
87-
model = Package
88-
fields = ["url", "purl", "fixing_vulnerabilities"]
89-
90-
9180
class AliasSerializer(serializers.HyperlinkedModelSerializer):
9281
"""
9382
Used for nesting inside package focused APIs.
@@ -128,13 +117,52 @@ def to_representation(self, instance):
128117
return data
129118

130119
purl = serializers.CharField(source="package_url")
131-
affected_by_vulnerabilities = VulnSerializerRefsAndSummary(
132-
many=True, source="vulnerable_to", read_only=True
133-
)
134-
fixing_vulnerabilities = VulnSerializerRefsAndSummary(
135-
many=True, source="resolved_to", read_only=True
136-
)
137-
fixed_packages = PackageSerializerFixedVulns(many=True, read_only=True)
120+
121+
affected_by_vulnerabilities = serializers.SerializerMethodField("get_affected_vulnerabilities")
122+
123+
fixing_vulnerabilities = serializers.SerializerMethodField("get_fixed_vulnerabilities")
124+
125+
def get_fixed_packages(self, package):
126+
return Package.objects.filter(
127+
name=package.name,
128+
namespace=package.namespace,
129+
type=package.type,
130+
qualifiers=package.qualifiers,
131+
subpath=package.subpath,
132+
packagerelatedvulnerability__fix=True,
133+
).distinct()
134+
135+
def get_affected_vulnerabilities(self, package):
136+
fixed_packages = self.get_fixed_packages(package=package)
137+
qs = package.vulnerabilities.filter(packagerelatedvulnerability__fix=False)
138+
qs = qs.prefetch_related(
139+
Prefetch(
140+
"packages",
141+
queryset=fixed_packages,
142+
to_attr="filtered_fixed_packages",
143+
)
144+
)
145+
return VulnSerializerRefsAndSummary(
146+
instance=qs,
147+
many=True,
148+
context={"request": self.context["request"]},
149+
).data
150+
151+
def get_fixed_vulnerabilities(self, package):
152+
fixed_packages = self.get_fixed_packages(package=package)
153+
qs = package.vulnerabilities.filter(packagerelatedvulnerability__fix=True)
154+
qs = qs.prefetch_related(
155+
Prefetch(
156+
"packages",
157+
queryset=fixed_packages,
158+
to_attr="filtered_fixed_packages",
159+
)
160+
)
161+
return VulnSerializerRefsAndSummary(
162+
instance=qs,
163+
many=True,
164+
context={"request": self.context["request"]},
165+
).data
138166

139167
class Meta:
140168
model = Package
@@ -148,7 +176,6 @@ class Meta:
148176
"qualifiers",
149177
"subpath",
150178
"affected_by_vulnerabilities",
151-
"fixed_packages",
152179
"fixing_vulnerabilities",
153180
]
154181

vulnerabilities/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def alias(self):
8383
Returns packages that first received patch against this vulnerability
8484
in their particular version history.
8585
"""
86-
return self.aliases.all()
86+
return self.aliases.all().order_by("-alias")
8787

8888
def __str__(self):
8989
return self.vulnerability_id

vulnerabilities/tests/test_fix_api.py

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
99

10+
from collections import OrderedDict
11+
1012
from django.test import TestCase
1113
from django.utils.http import int_to_base36
1214
from rest_framework import status
@@ -138,30 +140,24 @@ def test_api_with_single_vulnerability_and_fixed_package(self):
138140
"namespace": "nginx",
139141
"name": "test",
140142
"version": "11",
141-
"unresolved_vulnerabilities": [],
142143
"qualifiers": {},
143144
"subpath": "",
144-
"fixed_packages": [
145-
{
146-
"url": f"http://testserver/api/packages/{self.package.id}",
147-
"purl": "pkg:generic/nginx/test@11",
148-
"fixing_vulnerabilities": [
149-
{
150-
"url": f"http://testserver/api/vulnerabilities/{self.vuln.id}",
151-
"vulnerability_id": f"VULCOID-{int_to_base36(self.vuln.id).upper()}",
152-
}
153-
],
154-
}
155-
],
156145
"affected_by_vulnerabilities": [],
157146
"fixing_vulnerabilities": [
158147
{
159148
"url": f"http://testserver/api/vulnerabilities/{self.vuln.id}",
160149
"vulnerability_id": f"VULCOID-{int_to_base36(self.vuln.id).upper()}",
161150
"summary": "test-vuln",
162151
"references": [],
163-
}
152+
"fixed_packages": [
153+
{
154+
"url": f"http://testserver/api/packages/{self.package.id}",
155+
"purl": "pkg:generic/nginx/test@11",
156+
}
157+
],
158+
},
164159
],
160+
"unresolved_vulnerabilities": [],
165161
}
166162

167163
def test_api_with_single_vulnerability_and_vulnerable_package(self):
@@ -173,37 +169,37 @@ def test_api_with_single_vulnerability_and_vulnerable_package(self):
173169
"namespace": "nginx",
174170
"name": "test",
175171
"version": "9",
176-
"unresolved_vulnerabilities": [
172+
"qualifiers": {},
173+
"subpath": "",
174+
"affected_by_vulnerabilities": [
177175
{
178176
"url": f"http://testserver/api/vulnerabilities/{self.vuln.id}",
179177
"vulnerability_id": f"VULCOID-{int_to_base36(self.vuln.id).upper()}",
180178
"summary": "test-vuln",
181179
"references": [],
182-
}
183-
],
184-
"qualifiers": {},
185-
"subpath": "",
186-
"fixed_packages": [
187-
{
188-
"url": f"http://testserver/api/packages/{self.package.id}",
189-
"purl": "pkg:generic/nginx/test@11",
190-
"fixing_vulnerabilities": [
180+
"fixed_packages": [
191181
{
192-
"url": f"http://testserver/api/vulnerabilities/{self.vuln.id}",
193-
"vulnerability_id": f"VULCOID-{int_to_base36(self.vuln.id).upper()}",
182+
"url": f"http://testserver/api/packages/{self.package.id}",
183+
"purl": "pkg:generic/nginx/test@11",
194184
}
195185
],
196186
}
197187
],
198-
"affected_by_vulnerabilities": [
188+
"fixing_vulnerabilities": [],
189+
"unresolved_vulnerabilities": [
199190
{
200191
"url": f"http://testserver/api/vulnerabilities/{self.vuln.id}",
201192
"vulnerability_id": f"VULCOID-{int_to_base36(self.vuln.id).upper()}",
202193
"summary": "test-vuln",
203194
"references": [],
195+
"fixed_packages": [
196+
{
197+
"url": f"http://testserver/api/packages/{self.package.id}",
198+
"purl": "pkg:generic/nginx/test@11",
199+
}
200+
],
204201
}
205202
],
206-
"fixing_vulnerabilities": [],
207203
}
208204

209205

0 commit comments

Comments
 (0)