summaryrefslogtreecommitdiff
path: root/pgweb/security/admin.py
diff options
context:
space:
mode:
authorMagnus Hagander2018-01-25 20:59:13 +0000
committerMagnus Hagander2018-01-25 20:59:13 +0000
commit0cb56d93554926d087dfb696f608f9b51bfc7cfc (patch)
tree208b180b049bee4ad4b263faa8ebb677d1a4d9be /pgweb/security/admin.py
parentd0aa8ac11910e7352d83dfe281afebb57cfde554 (diff)
Database:ify the list of security patches
This finally moves the patches into the db, which makes it a lot easier to filter patches in the views. It also adds the new way of categorising patches, which is assigning them a CVSSv3 score. For now, there are no public views to this, and the old static pages remain. This is so we can backfill all existing security patches before we make it public.
Diffstat (limited to 'pgweb/security/admin.py')
-rw-r--r--pgweb/security/admin.py69
1 files changed, 69 insertions, 0 deletions
diff --git a/pgweb/security/admin.py b/pgweb/security/admin.py
new file mode 100644
index 00000000..7abe19c7
--- /dev/null
+++ b/pgweb/security/admin.py
@@ -0,0 +1,69 @@
+from django.contrib import admin
+from django import forms
+from django.db import models
+from django.core.validators import ValidationError
+from django.conf import settings
+
+from pgweb.core.models import Version
+from pgweb.news.models import NewsArticle
+from models import SecurityPatch, SecurityPatchVersion
+
+class VersionChoiceField(forms.ModelChoiceField):
+ def label_from_instance(self, obj):
+ return obj.numtree
+
+class SecurityPatchVersionAdminForm(forms.ModelForm):
+ model = SecurityPatchVersion
+ version = VersionChoiceField(queryset=Version.objects.filter(tree__gt=0), required=True)
+
+class SecurityPatchVersionAdmin(admin.TabularInline):
+ model = SecurityPatchVersion
+ extra = 2
+ form = SecurityPatchVersionAdminForm
+
+class SecurityPatchForm(forms.ModelForm):
+ model = SecurityPatch
+ newspost = forms.ModelChoiceField(queryset=NewsArticle.objects.filter(org=settings.PGDG_ORG_ID), required=False)
+
+ def clean(self):
+ d = super(SecurityPatchForm, self).clean()
+ vecs = [v for k,v in d.items() if k.startswith('vector_') and k != 'vector_other']
+ empty = [v for v in vecs if v == '']
+ if len(empty) != len(vecs) and len(empty) != 0:
+ for k in d.keys():
+ if k.startswith('vector_') and k != 'vector_other':
+ self.add_error(k, 'Either specify all vector values or none')
+ if d['vector_other'] and len(empty) > 0:
+ self.add_error('vector_other', 'Cannot specify other vectors without base vectors')
+ return d
+
+class SecurityPatchAdmin(admin.ModelAdmin):
+ form = SecurityPatchForm
+ exclude = ['cvenumber', ]
+ inlines = (SecurityPatchVersionAdmin, )
+ list_display = ('cve', 'public', 'cvssscore', 'legacyscore', 'cvssvector', 'description')
+ actions = ['make_public', 'make_unpublic']
+
+ def cvssvector(self, obj):
+ if not obj.cvssvector:
+ return ''
+ return '<a href="https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector={0}">{0}</a>'.format(
+ obj.cvssvector)
+ cvssvector.allow_tags = True
+ cvssvector.short_description = "CVSS vector link"
+
+ def cvssscore(self, obj):
+ return obj.cvssscore
+ cvssscore.short_description = "CVSS score"
+
+ def make_public(self, request, queryset):
+ self.do_public(queryset, True)
+ def make_unpublic(self, request, queryset):
+ self.do_public(queryset, False)
+ def do_public(self, queryset, val):
+ # Intentionally loop and do manually, so we generate change notices
+ for p in queryset.all():
+ p.public=val
+ p.save()
+
+admin.site.register(SecurityPatch, SecurityPatchAdmin)