|
174 | 174 | "fa-exclamation-circle", |
175 | 175 | ) |
176 | 176 |
|
| 177 | +ANALYSIS_STATE_STYLES = { |
| 178 | + "exploitable": "bg-danger-subtle text-danger-emphasis", |
| 179 | + "in_triage": "bg-warning-subtle text-warning-emphasis", |
| 180 | + "resolved": "bg-success-subtle text-success-emphasis", |
| 181 | + "resolved_with_pedigree": "bg-success-subtle text-success-emphasis", |
| 182 | + "not_affected": "bg-secondary-subtle text-secondary-emphasis", |
| 183 | + "false_positive": "bg-secondary-subtle text-secondary-emphasis", |
| 184 | +} |
| 185 | +ANALYSIS_STATE_DEFAULT_STYLE = "bg-secondary-subtle text-secondary-emphasis" |
| 186 | + |
177 | 187 |
|
178 | 188 | class BaseProductViewMixin: |
179 | 189 | model = Product |
@@ -1252,43 +1262,30 @@ class ProductTabVulnerabilitiesView( |
1252 | 1262 | ), |
1253 | 1263 | Header( |
1254 | 1264 | "vulnerability_analyses__state", |
1255 | | - _("Status"), |
1256 | | - help_text=_("Exploitability analysis status"), |
1257 | | - filter="vulnerability_analyses__state", |
1258 | | - ), |
1259 | | - Header( |
1260 | | - "vulnerability_analyses__justification", |
1261 | | - _("Justification"), |
1262 | | - help_text=_("The rationale of why the impact analysis state was asserted."), |
1263 | | - filter="vulnerability_analyses__justification", |
1264 | | - ), |
1265 | | - Header( |
1266 | | - "vulnerability_analyses__responses", |
1267 | | - _("Responses"), |
| 1265 | + _("Analysis"), |
1268 | 1266 | help_text=_( |
1269 | | - "A response to the vulnerability by the manufacturer, supplier, or project " |
1270 | | - "responsible for the affected component or service." |
| 1267 | + "Exploitability analysis: status, justification, responses and reachability." |
1271 | 1268 | ), |
1272 | | - filter="responses", |
1273 | | - ), |
1274 | | - Header( |
1275 | | - "vulnerability_analyses__is_reachable", |
1276 | | - _("Reach"), |
1277 | | - help_text=_( |
1278 | | - "Indicates whether the vulnerability is reachable in the context of " |
1279 | | - "this product package." |
1280 | | - ), |
1281 | | - filter="is_reachable", |
| 1269 | + filter="vulnerability_analyses__state", |
1282 | 1270 | ), |
1283 | 1271 | ) |
1284 | 1272 |
|
1285 | 1273 | def attach_vulnerability_analyses(self, page_obj): |
1286 | 1274 | """Set the matching VulnerabilityAnalysis instance on each prefetched vulnerability.""" |
| 1275 | + response_labels = dict(VulnerabilityAnalysis.Response.choices) |
| 1276 | + |
1287 | 1277 | for product_package in page_obj.object_list: |
1288 | 1278 | for vulnerability in product_package.package.affected_by_vulnerabilities.all(): |
1289 | 1279 | for analysis in vulnerability.vulnerability_analyses.all(): |
1290 | 1280 | if analysis.product_package_id == product_package.id: |
1291 | 1281 | vulnerability.vulnerability_analysis = analysis |
| 1282 | + analysis.state_badge_class = ANALYSIS_STATE_STYLES.get( |
| 1283 | + analysis.state, ANALYSIS_STATE_DEFAULT_STYLE |
| 1284 | + ) |
| 1285 | + analysis.response_labels = [ |
| 1286 | + response_labels.get(response, response) |
| 1287 | + for response in analysis.responses or [] |
| 1288 | + ] |
1292 | 1289 | break |
1293 | 1290 |
|
1294 | 1291 | REACHABILITY_FILTER_MAP = {"yes": True, "no": False, "unknown": None} |
@@ -1384,8 +1381,11 @@ def get_context_data(self, **kwargs): |
1384 | 1381 | risk_threshold = product.get_vulnerabilities_risk_threshold() |
1385 | 1382 |
|
1386 | 1383 | base_productpackage_qs = product.get_vulnerable_productpackages(risk_threshold) |
| 1384 | + vulnerability_analyses_qs = VulnerabilityAnalysis.objects.select_related( |
| 1385 | + "last_modified_by", "applied_by_preset" |
| 1386 | + ) |
1387 | 1387 | vulnerability_qs = Vulnerability.objects.prefetch_related( |
1388 | | - "vulnerability_analyses" |
| 1388 | + Prefetch("vulnerability_analyses", queryset=vulnerability_analyses_qs) |
1389 | 1389 | ).order_by(F("risk_score").desc(nulls_last=True)) |
1390 | 1390 | package_qs = ( |
1391 | 1391 | Package.objects.all() |
|
0 commit comments