@@ -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
6670class 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-
9180class AliasSerializer (serializers .HyperlinkedModelSerializer ):
9281 """
9382 Used for nesting inside package focused APIs.
@@ -128,13 +117,57 @@ 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+ """
127+ Return a queryset of all packages with version that fixes a vulnerability
128+ in the given `package` with same name, version, namespace, subpath and qualifiers.
129+ """
130+ return Package .objects .filter (
131+ name = package .name ,
132+ namespace = package .namespace ,
133+ type = package .type ,
134+ qualifiers = package .qualifiers ,
135+ subpath = package .subpath ,
136+ packagerelatedvulnerability__fix = True ,
137+ ).distinct ()
138+
139+ def get_vulnerabilities_for_a_package (self , package , fix ):
140+ """
141+ Return a queryset of vulnerabilities related to the given `package`.
142+ Return vulnerabilities that affects the `package` if given `fix` flag is False,
143+ otherwise return vulnerabilities fixed by the `package`.
144+ """
145+ fixed_packages = self .get_fixed_packages (package = package )
146+ qs = package .vulnerabilities .filter (packagerelatedvulnerability__fix = fix )
147+ qs = qs .prefetch_related (
148+ Prefetch (
149+ "packages" ,
150+ queryset = fixed_packages ,
151+ to_attr = "filtered_fixed_packages" ,
152+ )
153+ )
154+ return VulnSerializerRefsAndSummary (
155+ instance = qs ,
156+ many = True ,
157+ context = {"request" : self .context ["request" ]},
158+ ).data
159+
160+ def get_fixed_vulnerabilities (self , package ):
161+ """
162+ Return a queryset of vulnerabilities fixed in the given `package`.
163+ """
164+ return self .get_vulnerabilities_for_a_package (package = package , fix = True )
165+
166+ def get_affected_vulnerabilities (self , package ):
167+ """
168+ Return a queryset of vulnerabilities that affects the given `package`.
169+ """
170+ return self .get_vulnerabilities_for_a_package (package = package , fix = False )
138171
139172 class Meta :
140173 model = Package
@@ -148,7 +181,6 @@ class Meta:
148181 "qualifiers" ,
149182 "subpath" ,
150183 "affected_by_vulnerabilities" ,
151- "fixed_packages" ,
152184 "fixing_vulnerabilities" ,
153185 ]
154186
0 commit comments