aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rpkid/portal-gui/Makefile.in2
-rw-r--r--rpkid/portal-gui/settings.py.in9
-rw-r--r--rpkid/rpki/gui/app/forms.py54
-rw-r--r--rpkid/rpki/gui/app/urls.py12
-rw-r--r--rpkid/rpki/gui/app/views.py161
5 files changed, 106 insertions, 132 deletions
diff --git a/rpkid/portal-gui/Makefile.in b/rpkid/portal-gui/Makefile.in
index e1b8d41c..a453552b 100644
--- a/rpkid/portal-gui/Makefile.in
+++ b/rpkid/portal-gui/Makefile.in
@@ -42,6 +42,7 @@ apache.conf: $(srcdir)/apache.conf.in Makefile
install: $(BUILD)
if test -d $(SYSCONFDIR); then :; else ${INSTALL} -d $(SYSCONFDIR); fi
if test -d $(INSTDIR)/media/css; then :; else ${INSTALL} -d $(INSTDIR)/media/css; fi
+ if test -d $(INSTDIR)/media/img; then :; else ${INSTALL} -d $(INSTDIR)/media/img; fi
if test -d $(INSTDIR)/media/js; then :; else ${INSTALL} -d $(INSTDIR)/media/js; fi
if test -d $(INSTDIR)/wsgi; then :; else ${INSTALL} -d $(INSTDIR)/wsgi; fi
${INSTALL} -m 644 apache.conf $(SYSCONFDIR)/apache.conf
@@ -49,6 +50,7 @@ install: $(BUILD)
${INSTALL} -m 644 $(srcdir)/media/js/jquery-1.8.3.min.js $(INSTDIR)/media/js/jquery.min.js
${INSTALL} -m 644 rpki.wsgi $(INSTDIR)/wsgi/rpki.wsgi
${INSTALL} -m 644 settings.py ${SYSCONFDIR}
+ ${INSTALL} -m 644 -t $(INSTDIR)/media/img $(srcdir)/media/img/*
deinstall uninstall:
rm -rf $(INSTDIR)
diff --git a/rpkid/portal-gui/settings.py.in b/rpkid/portal-gui/settings.py.in
index b03ba284..0c939c28 100644
--- a/rpkid/portal-gui/settings.py.in
+++ b/rpkid/portal-gui/settings.py.in
@@ -1,6 +1,6 @@
#
# Sample Django settings.py for running the RPKI portal gui. This
-# template was written for Django 1.2.
+# template was written for Django 1.3.
#
# DO NOT EDIT! This file is automatically generated from
# settings.py.in
@@ -86,8 +86,8 @@ INSTALLED_APPS = (
#'django.contrib.admin',
#'django.contrib.admindocs',
'django.contrib.contenttypes',
- 'django.contrib.formtools',
'django.contrib.sessions',
+ 'django.contrib.staticfiles',
'rpki.irdb',
'rpki.gui.app',
'rpki.gui.cacheview',
@@ -102,5 +102,8 @@ TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.contrib.messages.context_processors.messages",
- "django.core.context_processors.request"
+ "django.core.context_processors.request",
+ "django.core.context_processors.static"
)
+
+STATIC_URL = '/static/'
diff --git a/rpkid/rpki/gui/app/forms.py b/rpkid/rpki/gui/app/forms.py
index f6b9547d..e7050284 100644
--- a/rpkid/rpki/gui/app/forms.py
+++ b/rpkid/rpki/gui/app/forms.py
@@ -288,41 +288,43 @@ class ROARequestConfirm(forms.Form):
return self.cleaned_data
-def AddASNForm(child):
+class AddASNForm(forms.Form):
"""
Returns a forms.Form subclass which verifies that the entered ASN range
does not overlap with a previous allocation to the specified child, and
that the ASN range is within the range allocated to the parent.
"""
- class _wrapped(forms.Form):
- asns = forms.CharField(
- label='ASNs',
- help_text='single ASN or range',
- widget=forms.TextInput(attrs={'autofocus': 'true'})
- )
- def clean_asns(self):
- try:
- r = resource_range_as.parse_str(self.cleaned_data.get('asns'))
- except:
- raise forms.ValidationError('invalid AS or range')
-
- if not models.ResourceRangeAS.objects.filter(
- cert__conf=child.issuer,
- min__lte=r.min,
- max__gte=r.max).exists():
- raise forms.ValidationError('AS or range is not delegated to you')
-
- # determine if the entered range overlaps with any AS already
- # allocated to this child
- if child.asns.filter(end_as__gte=r.min, start_as__lte=r.max).exists():
- raise forms.ValidationError(
- 'Overlap with previous allocation to this child')
+ asns = forms.CharField(
+ label='ASNs',
+ help_text='single ASN or range',
+ widget=forms.TextInput(attrs={'autofocus': 'true'})
+ )
- return str(r)
+ def __init__(self, *args, **kwargs):
+ self.child = kwargs.pop('child')
+ super(AddASNForm, self).__init__(*args, **kwargs)
- return _wrapped
+ def clean_asns(self):
+ try:
+ r = resource_range_as.parse_str(self.cleaned_data.get('asns'))
+ except:
+ raise forms.ValidationError('invalid AS or range')
+
+ if not models.ResourceRangeAS.objects.filter(
+ cert__conf=self.child.issuer,
+ min__lte=r.min,
+ max__gte=r.max).exists():
+ raise forms.ValidationError('AS or range is not delegated to you')
+
+ # determine if the entered range overlaps with any AS already
+ # allocated to this child
+ if self.child.asns.filter(end_as__gte=r.min, start_as__lte=r.max).exists():
+ raise forms.ValidationError(
+ 'Overlap with previous allocation to this child')
+
+ return str(r)
def AddNetForm(child):
diff --git a/rpkid/rpki/gui/app/urls.py b/rpkid/rpki/gui/app/urls.py
index aa6a9043..aeab2d04 100644
--- a/rpkid/rpki/gui/app/urls.py
+++ b/rpkid/rpki/gui/app/urls.py
@@ -29,9 +29,15 @@ urlpatterns = patterns('',
(r'^parent/(?P<pk>\d+)/export$', views.parent_export),
(r'^child/import$', views.child_import),
(r'^child/(?P<pk>\d+)/$', views.child_view),
- (r'^child/(?P<pk>\d+)/add_asn/$', views.child_add_asn),
- (r'^child/(?P<pk>\d+)/add_address/$', views.child_add_address),
- (r'^child/(?P<pk>\d+)/delete$', views.child_delete),
+ url(r'^child/(?P<pk>\d+)/add_asn/$',
+ views.handle_required(views.ChildAddASN.as_view()),
+ name='child-add-asn'),
+ url(r'^child/(?P<pk>\d+)/add_address/$',
+ views.handle_required(views.ChildAddPrefix.as_view()),
+ name='child-add-prefix'),
+ url(r'^child/(?P<pk>\d+)/delete$',
+ views.handle_required(views.ChildDeleteView.as_view()),
+ name='child-delete'),
(r'^child/(?P<pk>\d+)/edit$', views.child_edit),
(r'^child/(?P<pk>\d+)/export$', views.child_response),
url(r'^gbr/create$',
diff --git a/rpkid/rpki/gui/app/views.py b/rpkid/rpki/gui/app/views.py
index 1d825000..3778e361 100644
--- a/rpkid/rpki/gui/app/views.py
+++ b/rpkid/rpki/gui/app/views.py
@@ -32,9 +32,9 @@ from django import http
from django.views.generic.list_detail import object_detail
from django.core.urlresolvers import reverse, reverse_lazy
from django.contrib.auth.models import User
-from django.contrib.formtools.preview import FormPreview
from django.views.generic import (DetailView, ListView, CreateView, UpdateView,
- DeleteView)
+ DeleteView, FormView)
+from django.views.generic.detail import SingleObjectMixin
from rpki.irdb import Zookeeper, ChildASN, ChildNet
from rpki.gui.app import models, forms, glue, range_list
@@ -296,56 +296,23 @@ def child_import(request):
return generic_import(request, conf.children, Zookeeper.configure_child)
-class ObjectActionPreview(FormPreview):
- """Generic base class for confirming an action of an object.
-
- Subclasses should define:
- - template_name
-
- """
-
- def __init__(self, *args, **kwargs):
- """
- The docstring for FormPreview says we should not redefine this method, but
- I don't see how we can set extra information in this class otherwise.
-
- """
- self.form_object = kwargs.pop('form_object')
- self.logstream = kwargs.pop('logstream')
- # use the same template for both form edit and preview
- self.form_template = self.template_name
- self.preview_template = self.template_name
- super(ObjectActionPreview, self).__init__(*args, **kwargs)
-
- def get_context(self, *args, **kwargs):
- """"
- Override the superclass method to add context variables needed by the
- form template.
-
- """
- d = super(ObjectActionPreview, self).get_context(*args, **kwargs)
- d['object'] = self.form_object
- d['form_label'] = self.form_label
- return d
-
- def process_preview(self, request, form, context):
- # set a boolean flag so that the template knows this is a preview
- context['is_preview'] = True
-
+class ChildAddPrefix(FormView, SingleObjectMixin):
+ form_class = forms.AddNetForm
+ template_name = 'app/app_form.html'
-class ChildAddResourcePreview(ObjectActionPreview):
- """
- Base class for handling preview of AS/Prefix additions to a child.
- Subclasses implement the 'done' method to perform actual work on IRDB.
+ def get_queryset(self):
+ return self.request.session['handle'].children
- """
- template_name = 'app/child_detail.html'
- form_label = 'Add Resource'
+ def get_form_kwargs(self):
+ kwargs = super(ChildAddPrefix, self).get_form_kwargs()
+ kwargs['child'] = self.get_object()
+ return kwargs
+ # FormMixin
+ def form_valid(self, form):
+ r = super(ChildAddPrefix, self).form_valid(form)
-class ChildAddPrefixPreview(ChildAddResourcePreview):
- def done(self, request, cleaned_data):
- address_range = cleaned_data.get('address_range')
+ address_range = form.cleaned_data.get('address_range')
if ':' in address_range:
r = resource_range_ipv6.parse_str(address_range)
version = 'IPv6'
@@ -355,33 +322,35 @@ class ChildAddPrefixPreview(ChildAddResourcePreview):
self.child.address_ranges.create(start_ip=str(r.min), end_ip=str(r.max),
version=version)
Zookeeper(handle=self.child.issuer.handle, logstream=self.logstream).run_rpkid_now()
- return http.HttpResponseRedirect(self.child.get_absolute_url())
+ return r
-@handle_required
-def child_add_address(request, pk):
- logstream = request.META['wsgi.errors']
- conf = request.session['handle']
- child = get_object_or_404(models.Child, issuer=conf, pk=pk)
- form = forms.AddNetForm(child)
- preview = ChildAddPrefixPreview(form, form_object=child, logstream=logstream)
- return preview(request)
-class ChildAddASNPreview(ChildAddResourcePreview):
- def done(self, request, cleaned_data):
- asns = cleaned_data.get('asns')
+
+class ChildAddASN(FormView, SingleObjectMixin):
+ form_class = forms.AddASNForm
+ template_name = 'app/app_form.html'
+
+ def get_queryset(self):
+ return self.request.session['handle'].children
+
+ def get_form_kwargs(self):
+ kwargs = super(ChildAddASN, self).get_form_kwargs()
+ kwargs['child'] = self.get_object()
+ return kwargs
+
+ # FormMixin
+ def form_valid(self, form):
+ resp = super(ChildAddASN, self).form_valid(form)
+
+ asns = form.cleaned_data.get('asns')
r = resource_range_as.parse_str(asns)
- self.child.asns.create(start_as=r.min, end_as=r.max)
- Zookeeper(handle=self.child.issuer.handle, logstream=self.logstream).run_rpkid_now()
- return http.HttpResponseRedirect(self.child.get_absolute_url())
+ self.get_object().asns.create(start_as=r.min, end_as=r.max)
+
+ return resp
+
+ def get_success_url(self):
+ return self.get_object().get_absolute_url()
-@handle_required
-def child_add_asn(request, pk):
- logstream = request.META['wsgi.errors']
- conf = request.session['handle']
- child = get_object_or_404(models.Child, issuer=conf, pk=pk)
- form = forms.AddASNForm(child)
- preview = ChildAddASNPreview(form, form_object=child, logstream=logstream)
- return preview(request)
@handle_required
def child_view(request, pk):
@@ -434,30 +403,30 @@ def child_response(request, pk):
return resp
-class ChildDeletePreview(ObjectActionPreview):
- template_name = 'app/child_detail.html'
- form_label = 'Delete Child'
+class GenericDeleteView(DeleteView):
+ """Subclasses should implement the get_queryset() method.
+
+ """
+ template_name = 'app/object_confirm_delete.html'
+ success_url = reverse_lazy(dashboard)
+
+ def get_context_data(self, **kwargs):
+ context = super(GenericDeleteView, self).get_context_data(**kwargs)
+ context['parent_template'] = 'app/%s_detail.html' % self.object.__class__.__name__.lower()
+ return context
+
- def __init__(self, *args, **kwargs):
- self.conf = kwargs.pop('conf')
- super(ChildDeletePreview, self).__init__(*args, **kwargs)
+class ChildDeleteView(GenericDeleteView):
+ def get_queryset(self):
+ return self.request.session['handle'].children
- def done(self, request, cleaned_data):
- z = Zookeeper(handle=self.conf.handle)
- z.delete_child(self.form_object.handle)
+ # override DeletionMixin.delete()
+ def delete(self, request, *args, **kwargs):
+ z = Zookeeper(handle=request.session['handle'])
+ z.delete_child(self.get_object().handle)
z.synchronize()
- return http.HttpResponseRedirect(reverse(dashboard))
+ return http.HttpResponseRedirect(self.get_success_url())
-@handle_required
-def child_delete(request, pk):
- log = request.META['wsgi.errors']
- conf = request.session['handle']
- # verify this child belongs to the current user
- obj = get_object_or_404(conf.children, pk=pk)
- form_class = forms.UserDeleteForm # FIXME
- preview = ChildDeletePreview(form_class, conf=conf, form_object=obj,
- logstream=log)
- return preview(request)
@handle_required
def roa_create(request):
@@ -609,18 +578,10 @@ class GhostbusterDetailView(DetailView):
return self.request.session['handle'].ghostbusters
-class GhostbusterDeleteView(DeleteView):
- template_name = 'app/object_confirm_delete.html'
- success_url = reverse_lazy(dashboard)
-
+class GhostbusterDeleteView(GenericDeleteView):
def get_queryset(self):
return self.request.session['handle'].ghostbusters
- def get_context_data(self, **kwargs):
- context = super(GhostbusterDeleteView, self).get_context_data(**kwargs)
- context['parent_template'] = 'app/ghostbusterrequest_detail.html'
- return context
-
class GhostbusterCreateView(CreateView):
form_class = forms.GhostbusterRequestForm