Skip to content

Commit 7c1c775

Browse files
committed
Add views and routes for inisghts
Signed-off-by: Sampurna Pyne <sampurnapyne1710@gmail.com>
1 parent 228f1d1 commit 7c1c775

2 files changed

Lines changed: 130 additions & 0 deletions

File tree

insights/urls.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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+
10+
from django.urls import path
11+
12+
from insights import views
13+
14+
urlpatterns = [
15+
path("", views.insights_dashboard, name="insights-dashboard"),
16+
path("<str:panel_id>/", views.insights_dashboard, name="insights-panel"),
17+
]

insights/views.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
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

Comments
 (0)