|
| 1 | +# |
| 2 | +# Copyright (c) nexB Inc. and others. All rights reserved. |
| 3 | +# VulnerableCode is a trademark of nexB Inc. |
| 4 | +# SPDX-License-Identifier: Apache-2.0 |
| 5 | +# See http://www.apache.org/licenses/LICENSE-2.0 for the license text. |
| 6 | +# See https://github.com/aboutcode-org/vulnerablecode for support or download. |
| 7 | +# See https://aboutcode.org for more information about nexB OSS projects. |
| 8 | +# |
| 9 | +from django.db.models import Count |
| 10 | +from django.shortcuts import redirect |
| 11 | +from django.shortcuts import render |
| 12 | + |
| 13 | +from insights.graphs import GRAPHS |
| 14 | +from insights.graphs import PANEL_LABELS |
| 15 | +from insights.graphs import PANEL_LAYOUTS |
| 16 | +from insights.graphs import PANELS |
| 17 | +from insights.graphs.package_panel import build_cwe_chart_columns |
| 18 | +from insights.graphs.package_panel import compute_top_cwes |
| 19 | +from insights.graphs.severity_panel import aggregate_severity_buckets |
| 20 | +from insights.graphs.severity_panel import format_severity_chart_data |
| 21 | +from insights.models import DailySnapshot |
| 22 | +from vulnerabilities.models import AdvisoryV2 |
| 23 | +from vulnerabilities.models import PackageV2 |
| 24 | + |
| 25 | + |
| 26 | +def _severity_search(search_query): |
| 27 | + """Executes a severity search for a given PUrl""" |
| 28 | + packages = PackageV2.objects.search(search_query) |
| 29 | + error = None |
| 30 | + |
| 31 | + if packages.exists(): |
| 32 | + severities = ( |
| 33 | + AdvisoryV2.objects.filter( |
| 34 | + impacted_packages__affecting_packages__in=packages, |
| 35 | + severities__isnull=False, |
| 36 | + severities__scoring_system__icontains="cvss", |
| 37 | + ) |
| 38 | + .values("severities__value") |
| 39 | + .annotate(sev_count=Count("id", distinct=True)) |
| 40 | + ) |
| 41 | + buckets = aggregate_severity_buckets(severities, "sev_count") |
| 42 | + else: |
| 43 | + buckets = [0] * 10 |
| 44 | + error = "No data available for this query." |
| 45 | + |
| 46 | + return format_severity_chart_data(buckets), error |
| 47 | + |
| 48 | + |
| 49 | +def _cwe_search(search_query): |
| 50 | + """Executes a CWE search for a given PUrl""" |
| 51 | + packages = PackageV2.objects.search(search_query) |
| 52 | + error = None |
| 53 | + |
| 54 | + if packages.exists(): |
| 55 | + cwe_counts = compute_top_cwes(packages) |
| 56 | + chart_data = build_cwe_chart_columns(cwe_counts) |
| 57 | + else: |
| 58 | + chart_data = {} |
| 59 | + error = "No packages found for this query." |
| 60 | + |
| 61 | + return {"pkg-cwe-bar": chart_data}, error |
| 62 | + |
| 63 | + |
| 64 | +def insights_dashboard(request, panel_id=None): |
| 65 | + """Dashboard view to display insights.""" |
| 66 | + |
| 67 | + if not panel_id or panel_id not in PANELS: |
| 68 | + return redirect("insights-panel", panel_id=PANELS[0]) |
| 69 | + |
| 70 | + panels = [] |
| 71 | + for panel_key in PANELS: |
| 72 | + panel_graphs = [graph for graph in GRAPHS.values() if graph.panel == panel_key] |
| 73 | + panels.append( |
| 74 | + { |
| 75 | + "id": panel_key, |
| 76 | + "label": PANEL_LABELS[panel_key], |
| 77 | + "layout": PANEL_LAYOUTS.get(panel_key, "standard"), |
| 78 | + "graphs": panel_graphs, |
| 79 | + } |
| 80 | + ) |
| 81 | + |
| 82 | + try: |
| 83 | + snapshot = DailySnapshot.objects.latest() |
| 84 | + last_time = snapshot.created_at |
| 85 | + |
| 86 | + snapshot_data = {} |
| 87 | + for graph_id, graph_def in GRAPHS.items(): |
| 88 | + if graph_def.data_fn: |
| 89 | + snapshot_data[graph_id] = graph_def.data_fn(snapshot) |
| 90 | + except DailySnapshot.DoesNotExist: |
| 91 | + last_time = None |
| 92 | + snapshot_data = {} |
| 93 | + |
| 94 | + search_query = request.GET.get("q", "").strip() |
| 95 | + search_results_dict = None |
| 96 | + search_error = None |
| 97 | + |
| 98 | + if search_query: |
| 99 | + if panel_id == "severity_panel": |
| 100 | + search_results_dict, search_error = _severity_search(search_query) |
| 101 | + elif panel_id == "package_panel": |
| 102 | + search_results_dict, search_error = _cwe_search(search_query) |
| 103 | + |
| 104 | + context = { |
| 105 | + "panels": panels, |
| 106 | + "current_panel_id": panel_id, |
| 107 | + "last_snapshot_time": last_time, |
| 108 | + "snapshot_dict": {"snapshot_data": snapshot_data}, |
| 109 | + "search_query": search_query, |
| 110 | + "search_results_dict": search_results_dict, |
| 111 | + "search_error": search_error, |
| 112 | + } |
| 113 | + return render(request, "insights/dashboard.html", context) |
0 commit comments