@@ -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,56 @@ 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 packages that fixes a vulnerability in the given `package`.
128+ """
129+ return Package .objects .filter (
130+ name = package .name ,
131+ namespace = package .namespace ,
132+ type = package .type ,
133+ qualifiers = package .qualifiers ,
134+ subpath = package .subpath ,
135+ packagerelatedvulnerability__fix = True ,
136+ ).distinct ()
137+
138+ def get_vulnerabilities_for_a_package (self , package , fix ):
139+ """
140+ Return a queryset of vulnerabilities related to the given `package`.
141+ Return vulnerabilities that affects the `package` if given `fix` flag is False,
142+ otherwise return vulnerabilities fixed by the `package`.
143+ """
144+ fixed_packages = self .get_fixed_packages (package = package )
145+ qs = package .vulnerabilities .filter (packagerelatedvulnerability__fix = fix )
146+ qs = qs .prefetch_related (
147+ Prefetch (
148+ "packages" ,
149+ queryset = fixed_packages ,
150+ to_attr = "filtered_fixed_packages" ,
151+ )
152+ )
153+ return VulnSerializerRefsAndSummary (
154+ instance = qs ,
155+ many = True ,
156+ context = {"request" : self .context ["request" ]},
157+ ).data
158+
159+ def get_fixed_vulnerabilities (self , package ):
160+ """
161+ Return a queryset of vulnerabilities fixed in the given `package`.
162+ """
163+ return self .get_vulnerabilities_for_a_package (package = package , fix = True )
164+
165+ def get_affected_vulnerabilities (self , package ):
166+ """
167+ Return a queryset of vulnerabilities that affects the given `package`.
168+ """
169+ return self .get_vulnerabilities_for_a_package (package = package , fix = False )
138170
139171 class Meta :
140172 model = Package
@@ -148,7 +180,6 @@ class Meta:
148180 "qualifiers" ,
149181 "subpath" ,
150182 "affected_by_vulnerabilities" ,
151- "fixed_packages" ,
152183 "fixing_vulnerabilities" ,
153184 ]
154185
0 commit comments