77# See https://aboutcode.org for more information about nexB OSS projects.
88#
99import logging
10- from datetime import datetime
10+ from itertools import groupby
11+ from operator import attrgetter
1112
1213from cvss .exceptions import CVSS2MalformedError
1314from cvss .exceptions import CVSS3MalformedError
@@ -197,36 +198,7 @@ def get_context_data(self, **kwargs):
197198 if s .value :
198199 severity_values .add (s .value )
199200
200- sorted_affected_packages = sorted (self .object .affected_packages .all (), key = purl_sort_key )
201- sorted_fixed_by_packages = sorted (self .object .fixed_by_packages .all (), key = purl_sort_key )
202-
203- all_affected_fixed_by_matches = []
204- for sorted_affected_package in sorted_affected_packages :
205- affected_fixed_by_matches = {}
206- affected_fixed_by_matches ["affected_package" ] = sorted_affected_package
207- matched_fixed_by_packages = []
208- for fixed_by_package in sorted_fixed_by_packages :
209-
210- # Ghost Package can't fix vulnerability.
211- if fixed_by_package .is_ghost :
212- continue
213-
214- sorted_affected_version_class = get_purl_version_class (sorted_affected_package )
215- fixed_by_version_class = get_purl_version_class (fixed_by_package )
216- if (
217- (fixed_by_package .type == sorted_affected_package .type )
218- and (fixed_by_package .namespace == sorted_affected_package .namespace )
219- and (fixed_by_package .name == sorted_affected_package .name )
220- and (fixed_by_package .qualifiers == sorted_affected_package .qualifiers )
221- and (fixed_by_package .subpath == sorted_affected_package .subpath )
222- and (
223- fixed_by_version_class (fixed_by_package .version )
224- > sorted_affected_version_class (sorted_affected_package .version )
225- )
226- ):
227- matched_fixed_by_packages .append (fixed_by_package .purl )
228- affected_fixed_by_matches ["matched_fixed_by_packages" ] = matched_fixed_by_packages
229- all_affected_fixed_by_matches .append (affected_fixed_by_matches )
201+ sorted_fixed_by_packages , sorted_affected_packages , all_affected_fixed_by_matches = self .aggregate_fixed_and_affected_packages ()
230202
231203 context .update (
232204 {
@@ -247,6 +219,57 @@ def get_context_data(self, **kwargs):
247219 )
248220 return context
249221
222+ def aggregate_fixed_and_affected_packages (self ):
223+ sorted_fixed_by_packages = self .object .fixed_by_packages .filter (is_ghost = False ).order_by (
224+ "type" , "namespace" , "name" , "qualifiers" , "subpath"
225+ )
226+
227+ sorted_affected_packages = self .object .affected_packages .all ()
228+
229+ grouped_fixed_by_packages = {
230+ key : list (group )
231+ for key , group in groupby (
232+ sorted_fixed_by_packages ,
233+ key = attrgetter ("type" , "namespace" , "name" , "qualifiers" , "subpath" ),
234+ )
235+ }
236+
237+ all_affected_fixed_by_matches = []
238+
239+ for sorted_affected_package in sorted_affected_packages :
240+ affected_fixed_by_matches = {
241+ "affected_package" : sorted_affected_package ,
242+ "matched_fixed_by_packages" : [],
243+ }
244+
245+ # Build the key to find matching group
246+ key = (
247+ sorted_affected_package .type ,
248+ sorted_affected_package .namespace ,
249+ sorted_affected_package .name ,
250+ sorted_affected_package .qualifiers ,
251+ sorted_affected_package .subpath ,
252+ )
253+
254+ # Get matching group from pre-grouped fixed_by_packages
255+ matching_fixed_packages = grouped_fixed_by_packages .get (key , [])
256+
257+ # Get version classes for comparison
258+ affected_version_class = get_purl_version_class (sorted_affected_package )
259+ affected_version = affected_version_class (sorted_affected_package .version )
260+
261+ # Compare versions and filter valid matches
262+ matched_fixed_by_packages = [
263+ fixed_by_package .purl
264+ for fixed_by_package in matching_fixed_packages
265+ if get_purl_version_class (fixed_by_package )(fixed_by_package .version )
266+ > affected_version
267+ ]
268+
269+ affected_fixed_by_matches ["matched_fixed_by_packages" ] = matched_fixed_by_packages
270+ all_affected_fixed_by_matches .append (affected_fixed_by_matches )
271+ return sorted_fixed_by_packages ,sorted_affected_packages ,all_affected_fixed_by_matches
272+
250273
251274class HomePage (View ):
252275 template_name = "index.html"
0 commit comments