diff options
Diffstat (limited to 'portal-gui/rpkigui/myrpki/views.py')
-rw-r--r-- | portal-gui/rpkigui/myrpki/views.py | 284 |
1 files changed, 213 insertions, 71 deletions
diff --git a/portal-gui/rpkigui/myrpki/views.py b/portal-gui/rpkigui/myrpki/views.py index c7d93779..70c453c1 100644 --- a/portal-gui/rpkigui/myrpki/views.py +++ b/portal-gui/rpkigui/myrpki/views.py @@ -8,13 +8,12 @@ from django.shortcuts import get_object_or_404, render_to_response from django.utils.http import urlquote from django.template import RequestContext from django.db import IntegrityError -from django.db.models import Q from django import http from functools import update_wrapper import models import forms -import settings import glue +from asnset import asnset # For each type of object, we have a detail view, a create view and # an update view. We heavily leverage the generic views, only @@ -24,9 +23,12 @@ def handle_required(f): @login_required def wrapped_fn(request, *args, **kwargs): if 'handle' not in request.session: - conf = models.Conf.objects.all().filter(owner__in=request.user.groups.all()) + if request.user.is_superuser: + conf = models.Conf.objects.all() + else: + conf = models.Conf.objects.filter(owner=request.user) if conf.count() == 1: - handle = conf[ 0 ] + handle = conf[0] elif conf.count() == 0: return http.HttpResponseRedirect('/myrpki/conf/add') else: @@ -174,7 +176,10 @@ def dashboard(request): @login_required def conf_list(request): """Allow the user to select a handle.""" - queryset = models.Conf.objects.filter(owner__in=request.user.groups.all()) + if request.user.is_superuser: + queryset = models.Conf.objects.all() + else: + queryset = models.Conf.objects.filter(owner__in=request.user.groups.all()) return object_list(request, queryset, template_name='myrpki/conf_list.html', template_object_name='conf') @@ -188,11 +193,14 @@ def conf_select(request): if next_url == '': next_url = '/myrpki/' - # since the handle is passed in as a parameter, need to verify that - # the user is actually in the group - conf = models.Conf.objects.filter( - Q(handle__exact=handle) & Q(owner__in=request.user.groups.all())) - if conf.count() > 0: + if request.user.is_superuser: + conf = models.Conf.objects.filter(handle=handle) + else: + # since the handle is passed in as a parameter, need to verify that + # the user is actually in the group + conf = models.Conf.objects.filter(handle=handle, + owner__in=request.user.groups.all()) + if conf: request.session['handle'] = conf[0] return http.HttpResponseRedirect(next_url) @@ -327,90 +335,224 @@ def get_parents_or_404(handle, obj): return handle.parents.filter(pk__in=[c.parent.pk for c in cert_set]) -def resource_view(request, object_type, form_type, pk): - '''view/subdivide an address range.''' +#def resource_view(request, object_type, form_type, pk, resource_type): +# '''view/subdivide an address range.''' +# handle = request.session['handle'] +# obj = get_object_or_404(object_type, pk=pk) +# # ensure this resource range belongs to a parent of the current conf +# parent_set = get_parents_or_404(handle, obj) +# +# if request.method == 'POST': +# form = form_type(handle, obj, request.POST) +# if form.is_valid(): +# if form.cleaned_data['child'] is None: +# hi = form.cleaned_data['hi'] +# lo = form.cleaned_data['lo'] +# print hi, lo +# # if a range is given, create a new object +# if hi and lo: +# subobj = object_type.objects.create( +# lo=lo, hi=hi, parent=obj, allocated=None) +# subobj.save() +# if obj.allocated: +# obj.allocated = None +# obj.save() +# else: +# obj.allocated = form.cleaned_data['child'] +# obj.save() +# +# glue.configure_resources(handle) +# else: +# form = form_type(handle, obj) +# return render('myrpki/resource_view.html', { 'addr': obj, 'form': form, +# 'parent': parent_set, 'resource_type': resource_type }, request) + +@handle_required +def address_view(request, pk): handle = request.session['handle'] - obj = get_object_or_404(object_type, pk=pk) + obj = get_object_or_404(models.AddressRange.objects.all(), pk=pk) # ensure this resource range belongs to a parent of the current conf parent_set = get_parents_or_404(handle, obj) - if request.method == 'POST': - form = form_type(handle, obj, request.POST) - if form.is_valid(): - if form.cleaned_data['child'] is None: - hi = form.cleaned_data['hi'] - lo = form.cleaned_data['lo'] - # if a range is given, create a new object - if hi != '' and lo != '': - subobj = object_type.objects.create( - lo=lo, hi=hi, parent=obj, allocated=None) - subobj.save() - if obj.allocated: - obj.allocated = None - obj.save() - else: - obj.allocated = form.cleaned_data['child'] - obj.save() - - glue.configure_resources(handle) - else: - form = form_type(handle, obj) - return render('myrpki/resource_view.html', { 'addr': obj, 'form': form, - 'parent': parent_set }, request) - -@handle_required -def address_view(request, pk): - '''view/subdivide an address range.''' - return resource_view(request, models.AddressRange, - forms.SubOrAssignAddressForm, pk) + return render('myrpki/prefix_view.html', + { 'addr': obj, 'parent': parent_set }, request) @handle_required def asn_view(request, pk): '''view/subdivide an asn range.''' - return resource_view(request, models.Asn, forms.SubOrAssignAsnForm, pk) + handle = request.session['handle'] + obj = get_object_or_404(models.Asn.objects, pk=pk) + # ensure this resource range belongs to a parent of the current conf + parent_set = get_parents_or_404(handle, obj) + + return render('myrpki/_view.html', + { 'addr': obj, 'parent': parent_set }, request) + +#@handle_required +#def roa_edit(request, pk=None): +# '''Create or edit a ROA.''' +# +# handle = request.session['handle'] +# +# if not pk is None: +# obj = get_object_or_404(models.Roa, pk=pk) +# if obj.conf != handle: +# raise http.Http404 +# else: +# obj = None +# +# if request.method == 'POST': +# form = forms.RoaForm(handle, None, None, None, request.POST) +# if form.is_valid(): +# if not obj: +# obj = models.Roa(conf=handle, asn=form.cleaned_data['asn'], +# comments=form.cleaned_data['comments'], max_len=0) +# else: +# obj.asn = form.cleaned_data['asn'] +# obj.comments = form.cleaned_data['comments'] +# obj.save() +# obj.prefix.clear() +# obj.prefix.add(*form.cleaned_data['prefix']) +# +# glue.configure_resources(handle) +# +# return http.HttpResponseRedirect('/myrpki/') +# else: +# asn = obj.asn if obj else None +# comments = obj.comments if obj else None +# prefix = [o.pk for o in obj.prefix.all()] if obj else [] +# form = forms.RoaForm(handle, asn, comments, prefix) +# return render('myrpki/roaform.html', { 'form': form }, request) @handle_required -def roa_edit(request, pk=None): - '''Create or edit a ROA.''' +def child_view(request, child_handle): + '''Detail view of child for the currently selected handle.''' + handle = request.session['handle'] + child = get_object_or_404(handle.children.all(), handle__exact=child_handle) + + return render('myrpki/child_view.html', { 'child': child }, request) +@handle_required +def prefix_split_view(request, pk): handle = request.session['handle'] + prefix = get_object_or_404(models.AddressRange.objects, pk=pk) + # ensure this resource range belongs to a parent of the current conf + parent_set = get_parents_or_404(handle, prefix) - if not pk is None: - obj = get_object_or_404(models.Roa, pk=pk) - if obj.conf != handle: - raise http.Http404 + if request.method == 'POST': + form = forms.PrefixSplitForm(prefix, request.POST) + if form.is_valid(): + obj = models.AddressRange.create(form.cleaned_data['lo'], form.cleaned_data['hi'], parent=parent) + obj.save() + return http.HttpResponseRedirect(obj.get_absolute_url()) else: - obj = None + form = forms.PrefixSplitForm(prefix) + + return render('myrpki/prefix_view.html', { 'form': form, + 'addr': prefix, 'form': form, 'parent': parent_set }, request) + +@handle_required +def prefix_allocate_view(request, pk): + handle = request.session['handle'] + prefix = get_object_or_404(models.AddressRange.objects, pk=pk) + # ensure this resource range belongs to a parent of the current conf + parent_set = get_parents_or_404(handle, prefix) if request.method == 'POST': - form = forms.RoaForm(handle, None, None, None, request.POST) + form = forms.PrefixAllocateForm(None, handle.children.all(), request.POST) if form.is_valid(): - if not obj: - obj = models.Roa(conf=handle, asn=form.cleaned_data['asn'], - comments=form.cleaned_data['comments'], max_len=0) - else: - obj.asn = form.cleaned_data['asn'] - obj.comments = form.cleaned_data['comments'] - obj.save() - obj.prefix.clear() - obj.prefix.add(*form.cleaned_data['prefix']) + prefix.allocated = form.cleaned_data['child'] + prefix.save() + return http.HttpResponseRedirect(prefix.get_absolute_url()) + else: + form = forms.PrefixAllocateForm(prefix.allocated.pk if prefix.allocated else None, + handle.children.all()) + + return render('myrpki/prefix_view.html', { 'form': form, + 'addr': prefix, 'form': form, 'parent': parent_set }, request) + +def common_cert(prefix, prefix_set): + '''Return true if prefix is derived from the same resource cert + as all the addresses in prefix_set.''' + # list of certs for the target prefix + certs = prefix.from_cert.all() + # all prefixes will have the same cert, so just check the first one + prefix_certs = prefix_set[0].from_cert.all() + # all we need is one match + for c in certs: + if c in prefix_certs: + return True + return False + +def update_roas(handle, prefix): + '''Recompute the required ROAs for the prefix that was changed.''' + # generate the list of ASNs + asns = list(asnset(prefix.asns)) + + print 'updating roas for %s: asns=%r' % (prefix, asns) + + # remove this prefix from any roa not on the updated list + for roa in prefix.from_roa.exclude(asn__in=asns): + print 'removing %s from roa for asn %d' % (prefix, roa.asn) + roa.prefix.remove(prefix) + # if the roa is empty, delete it now + if roa.prefix.all().count() == 0: + print 'deleting roa for asn %d because it is empty' % (roa.asn,) + roa.delete() + + for asid in asns: + for roa in handle.roas.filter(asn=asid): + # determine if this roa includes prefixes from the same + # resource cert as the prefix we just changed + if common_cert(prefix, roa.prefix.all()): + roa.prefix.add(prefix) + break + else: + # no roa is present for this ASN, create a new one + print 'creating new roa for asn %d with %s' % (asid, prefix) + roa = models.Roa.objects.create(asn=asid, conf=handle, active=False) + roa.save() + roa.prefix.add(prefix) - glue.configure_resources(handle) +@handle_required +def prefix_roa_view(request, pk): + handle = request.session['handle'] + obj = get_object_or_404(models.AddressRange.objects, pk=pk) + # ensure this resource range belongs to a parent of the current conf + parent_set = get_parents_or_404(handle, obj) - return http.HttpResponseRedirect('/myrpki/') + if request.method == 'POST': + form = forms.PrefixRoaForm(request.POST) + if form.is_valid(): + obj.asns = form.cleaned_data['asns'] + obj.save() + update_roas(handle, obj) + glue.configure_resources(handle) + return http.HttpResponseRedirect(obj.get_absolute_url()) else: - asn = obj.asn if obj else None - comments = obj.comments if obj else None - prefix = [o.pk for o in obj.prefix.all()] if obj else [] - form = forms.RoaForm(handle, asn, comments, prefix) - return render('myrpki/roaform.html', { 'form': form }, request) + form = forms.PrefixRoaForm(initial={ 'asns': obj.asns }) + + return render('myrpki/prefix_view.html', { 'form': form, + 'addr': obj, 'form': form, 'parent': parent_set }, request) @handle_required -def child_view(request, child_handle): - '''Detail view of child for the currently selected handle.''' +def asn_allocate_view(request, pk): handle = request.session['handle'] - child = get_object_or_404(handle.children.all(), handle__exact=child_handle) + obj = get_object_or_404(models.Asn.objects, pk=pk) + # ensure this resource range belongs to a parent of the current conf + parent_set = get_parents_or_404(handle, obj) - return render('myrpki/child_view.html', { 'child': child }, request) + if request.method == 'POST': + form = forms.PrefixAllocateForm(None, handle.children.all(), request.POST) + if form.is_valid(): + obj.allocated = form.cleaned_data['child'] + obj.save() + return http.HttpResponseRedirect(obj.get_absolute_url()) + else: + form = forms.PrefixAllocateForm(obj.allocated.pk if obj.allocated else None, + handle.children.all()) + + return render('myrpki/asn_view.html', { 'form': form, + 'asn': obj, 'form': form, 'parent': parent_set }, request) # vim:sw=4 ts=8 expandtab |