Skip to content

Commit fba4d77

Browse files
authored
Merge pull request #286 from Xpirix/security_scan_visibility
Add security scan status indicators in the plugins details page
2 parents ad0cd09 + 5ab83eb commit fba4d77

File tree

2 files changed

+162
-2
lines changed

2 files changed

+162
-2
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
from django.core.management.base import BaseCommand
2+
3+
from plugins.models import Plugin
4+
from plugins.security_utils import run_security_scan
5+
6+
7+
class Command(BaseCommand):
8+
help = (
9+
"Run security scan on the latest version of each plugin "
10+
"if a scan result does not already exist."
11+
)
12+
13+
def handle(self, *args, **options):
14+
plugins = Plugin.objects.all()
15+
scanned = 0
16+
skipped = 0
17+
failed = 0
18+
19+
for plugin in plugins.iterator():
20+
latest_version = (
21+
plugin.pluginversion_set.order_by("-created_on").first()
22+
)
23+
24+
if latest_version is None:
25+
self.stdout.write(
26+
self.style.WARNING(
27+
f" {plugin.package_name}: no approved version, skipping."
28+
)
29+
)
30+
skipped += 1
31+
continue
32+
33+
if hasattr(latest_version, "security_scan"):
34+
self.stdout.write(
35+
f" {plugin.package_name} v{latest_version.version}: "
36+
"already scanned, skipping."
37+
)
38+
skipped += 1
39+
continue
40+
41+
self.stdout.write(
42+
f" Scanning {plugin.package_name} v{latest_version.version} ..."
43+
)
44+
result = run_security_scan(latest_version)
45+
46+
if result is not None:
47+
self.stdout.write(
48+
self.style.SUCCESS(
49+
f" {plugin.package_name} v{latest_version.version}: "
50+
f"scan complete (status: {result.overall_status})."
51+
)
52+
)
53+
scanned += 1
54+
else:
55+
self.stdout.write(
56+
self.style.ERROR(
57+
f" {plugin.package_name} v{latest_version.version}: "
58+
"scan failed."
59+
)
60+
)
61+
failed += 1
62+
63+
self.stdout.write(
64+
self.style.SUCCESS(
65+
f"\nDone. Scanned: {scanned}, Skipped: {skipped}, Failed: {failed}."
66+
)
67+
)

qgis-app/plugins/templates/plugins/plugin_detail.html

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,50 @@ <h2>
223223
</div>
224224
<p class="plugin-details-description">{{ object.description|linebreaksbr }}</p>
225225
<div id="rating"> (<span id="votes">{% firstof votes '0' %}</span>) {% trans "votes" %}&nbsp;<span id="loading" style="display:none">Loading...</span><span id="vote-message" style="display:none"></span></div>
226-
226+
<div>
227+
{% with release=object.stable|default:object.experimental %}
228+
{% if release %}
229+
{% with security_scan=release.security_scan %}
230+
{% if security_scan.overall_status == 'passed' %}
231+
<a {% if user.is_staff or user in object.editors %}href="{{ release.get_absolute_url }}#security-tab"{% endif %} class="button is-small is-rounded is-success">
232+
<span class="icon is-small">
233+
<i class="fas fa-shield-halved"></i>
234+
</span>
235+
<span>{% trans "Security scan passed (latest)" %}</span>
236+
</a>
237+
{% elif security_scan.overall_status == 'critical' %}
238+
<a {% if user.is_staff or user in object.editors %}href="{{ release.get_absolute_url }}#security-tab"{% endif %} class="button is-small is-rounded is-danger">
239+
<span class="icon is-small">
240+
<i class="fas fa-triangle-exclamation"></i>
241+
</span>
242+
<span>{% trans "Security issue detected (latest)" %}</span>
243+
</a>
244+
{% elif security_scan.overall_status == 'warning' %}
245+
<a {% if user.is_staff or user in object.editors %}href="{{ release.get_absolute_url }}#security-tab"{% endif %} class="button is-small is-rounded is-warning">
246+
<span class="icon is-small">
247+
<i class="fas fa-circle-exclamation"></i>
248+
</span>
249+
<span>{% trans "Potential security issue (latest)" %}</span>
250+
</a>
251+
{% elif security_scan.overall_status == 'info' %}
252+
<a {% if user.is_staff or user in object.editors %}href="{{ release.get_absolute_url }}#security-tab"{% endif %} class="button is-small is-rounded is-info">
253+
<span class="icon is-small">
254+
<i class="fas fa-info"></i>
255+
</span>
256+
<span>{% trans "Scanned with informational items (latest)" %}</span>
257+
</a>
258+
{% else %}
259+
<a {% if user.is_staff or user in object.editors %}href="{{ release.get_absolute_url }}#security-tab"{% endif %} class="button is-small is-rounded is-light">
260+
<span class="icon is-small">
261+
<i class="fas fa-circle-question"></i>
262+
</span>
263+
<span>{% trans "Security status unknown (latest)" %}</span>
264+
</a>
265+
{% endif %}
266+
{% endwith %}
267+
{% endif %}
268+
{% endwith %}
269+
</div>
227270
<a class="button mt-3" href="{% if object.stable %}{{ object.stable.get_download_url }}{% else %}{{ object.experimental.get_download_url }}{% endif %}">
228271
<i class="fas fa-download" style="vertical-align: middle;"></i>&nbsp;{% trans "Download latest" %}
229272
</a>
@@ -565,7 +608,57 @@ <h2>
565608
</td>
566609
<td class="has-text-centered" data-order="{{ version.created_on.isoformat }}">{{ version.created_on|local_timezone }}</td>
567610
{% if user.is_staff or user in version.plugin.approvers or user in version.plugin.editors %}
568-
<td class="has-text-centered" style="min-width: 200px;">
611+
<td class="has-text-centered" style="min-width: 229px;">
612+
{% if user.is_staff or user in object.editors %}
613+
{% with security_scan=version.security_scan %}
614+
{% if security_scan.overall_status == 'passed' %}
615+
<a
616+
href="{{ version.get_absolute_url }}#security-tab"
617+
title="{% trans "Security scan passed (latest)" %}"
618+
class="button is-small is-success">
619+
<span class="icon is-small">
620+
<i class="fas fa-shield-halved"></i>
621+
</span>
622+
</a>
623+
{% elif security_scan.overall_status == 'critical' %}
624+
<a
625+
href="{{ version.get_absolute_url }}#security-tab"
626+
title="{% trans "Critical security issues found (latest)" %}"
627+
class="button is-small is-danger">
628+
<span class="icon is-small">
629+
<i class="fas fa-triangle-exclamation"></i>
630+
</span>
631+
</a>
632+
{% elif security_scan.overall_status == 'warning' %}
633+
<a
634+
href="{{ version.get_absolute_url }}#security-tab"
635+
title="{% trans "Potential security issues found (latest)" %}"
636+
class="button is-small is-warning">
637+
<span class="icon is-small">
638+
<i class="fas fa-circle-exclamation"></i>
639+
</span>
640+
</a>
641+
{% elif security_scan.overall_status == 'info' %}
642+
<a
643+
href="{{ version.get_absolute_url }}#security-tab"
644+
title="{% trans "Scanned with informational items (latest)" %}"
645+
class="button is-small is-info">
646+
<span class="icon is-small">
647+
<i class="fas fa-circle-info"></i>
648+
</span>
649+
</a>
650+
{% else %}
651+
<a
652+
href="{{ version.get_absolute_url }}#security-tab"
653+
title="{% trans "Security status unknown (latest)" %}"
654+
class="button is-small is-outlined">
655+
<span class="icon is-small">
656+
<i class="fas fa-circle-question"></i>
657+
</span>
658+
</a>
659+
{% endif %}
660+
{% endwith %}
661+
{% endif %}
569662
{% if user.is_staff or user in version.plugin.approvers %}
570663
{% if not version.approved %}
571664
<form id="approve-version-{{ version.pk }}" method="post" action="{% url 'version_approve' object.package_name version.version %}" style="display:inline;">

0 commit comments

Comments
 (0)