diff options
Diffstat (limited to 'rpkid')
-rw-r--r-- | rpkid/rpki/gui/app/templates/app/child_detail.html | 1 | ||||
-rw-r--r-- | rpkid/rpki/gui/app/templates/app/object_detail.html | 2 | ||||
-rw-r--r-- | rpkid/rpki/gui/app/templates/app/parent_detail.html | 12 | ||||
-rw-r--r-- | rpkid/rpki/gui/app/templates/app/repository_detail.html | 28 | ||||
-rw-r--r-- | rpkid/rpki/gui/app/urls.py | 40 | ||||
-rw-r--r-- | rpkid/rpki/gui/app/views.py | 113 |
6 files changed, 110 insertions, 86 deletions
diff --git a/rpkid/rpki/gui/app/templates/app/child_detail.html b/rpkid/rpki/gui/app/templates/app/child_detail.html index 7a6918eb..8c242d04 100644 --- a/rpkid/rpki/gui/app/templates/app/child_detail.html +++ b/rpkid/rpki/gui/app/templates/app/child_detail.html @@ -49,4 +49,5 @@ {% block actions %} <a class='btn' href="{{ object.get_absolute_url }}/add_asn">Delegate AS</a> <a class='btn' href="{{ object.get_absolute_url }}/add_address">Delegate Prefix</a> +<a class='btn' href="{{ object.get_absolute_url }}/export">Export Response</a> {% endblock actions %} diff --git a/rpkid/rpki/gui/app/templates/app/object_detail.html b/rpkid/rpki/gui/app/templates/app/object_detail.html index 7def9a61..44c1a797 100644 --- a/rpkid/rpki/gui/app/templates/app/object_detail.html +++ b/rpkid/rpki/gui/app/templates/app/object_detail.html @@ -26,7 +26,7 @@ {% if can_edit %} <a class='btn' href='{{ object.get_absolute_url }}/edit'>Edit</a> {% endif %} - <a class='btn danger' href='{{ object.get_absolute_url }}/delete'>Delete</a> + <a class='btn danger' href='{{ object.get_absolute_url }}/delete' title='permanently delete this object'>Delete</a> {% block actions %}{% endblock actions %} </div> {% endif %} diff --git a/rpkid/rpki/gui/app/templates/app/parent_detail.html b/rpkid/rpki/gui/app/templates/app/parent_detail.html index 850d5499..58aa8050 100644 --- a/rpkid/rpki/gui/app/templates/app/parent_detail.html +++ b/rpkid/rpki/gui/app/templates/app/parent_detail.html @@ -1,13 +1,11 @@ {% extends "app/object_detail.html" %} {% block object_detail %} - <h2>{{ object.handle }}</h2> - <div class='row'> <div class='span8'> <h3>Delegated Addresses</h3> - <ul> + <ul class='unstyled'> {% for c in object.certs.all %} {% for a in c.address_ranges.all %} <li>{{ a }}</li> @@ -18,10 +16,9 @@ {% endfor %} </ul> </div> - <div class='span8'> <h3>Delegated ASNs</h3> - <ul> + <ul class='unstyled'> {% for c in object.certs.all %} {% for a in c.asn_ranges.all %} <li>{{ a }}</li> @@ -30,7 +27,8 @@ </ul> </div> </div><!-- /row --> - {% endblock object_detail %} -<!-- vim: set sw=2: --> +{% block actions %} +<a class='btn' href='{{ object.get_absolute_url }}/export' title='Export XML repository request'>Export</a> +{% endblock actions %} diff --git a/rpkid/rpki/gui/app/templates/app/repository_detail.html b/rpkid/rpki/gui/app/templates/app/repository_detail.html index 2044abb6..4ef6a63f 100644 --- a/rpkid/rpki/gui/app/templates/app/repository_detail.html +++ b/rpkid/rpki/gui/app/templates/app/repository_detail.html @@ -1,16 +1,20 @@ {% extends "app/object_detail.html" %} {% block object_detail %} -<table style='condensed-table'> - <tr> - <th>Name</th> - <td>{{ object.handle }}</td> - </tr> - <tr> - <th>SIA</th> - <td>{{ object.sia_base }}</td> - </tr> -</table> +<div class='row'> + <div class='span2'> + <p><strong>Name</strong> + </div> + <div class='span14'> + <p>{{ object.handle }} + </div> +</div> +<div class='row'> + <div class='span2'> + <p><strong>SIA</strong> + </div> + <div class='span14'> + <p>{{ object.sia_base }}</td> + </div> +</div> {% endblock object_detail %} - -<!-- vim:set sw=2: --> diff --git a/rpkid/rpki/gui/app/urls.py b/rpkid/rpki/gui/app/urls.py index e111b8c9..b2e30b12 100644 --- a/rpkid/rpki/gui/app/urls.py +++ b/rpkid/rpki/gui/app/urls.py @@ -1,20 +1,19 @@ -# $Id$ -""" -Copyright (C) 2010, 2011 SPARTA, Inc. dba Cobham Analytic Solutions -Copyright (C) 2012 SPARTA, Inc. a Parsons Company +# Copyright (C) 2010, 2011 SPARTA, Inc. dba Cobham Analytic Solutions +# Copyright (C) 2012 SPARTA, Inc. a Parsons Company +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND SPARTA DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL SPARTA BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND SPARTA DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL SPARTA BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. -""" +__version__ = '$Id$' from django.conf.urls.defaults import * from rpki.gui.app import views @@ -26,8 +25,9 @@ urlpatterns = patterns('', (r'^conf/select$', views.conf_select), (r'^parent/$', views.parent_list), (r'^parent/import$', views.parent_import), - (r'^parent/(?P<pk>\d+)$', views.parent_view), + (r'^parent/(?P<pk>\d+)$', views.parent_detail), (r'^parent/(?P<pk>\d+)/delete$', views.parent_delete), + (r'^parent/(?P<pk>\d+)/export$', views.parent_export), (r'^child/$', views.child_list), (r'^child/import$', views.child_import), (r'^child/(?P<pk>\d+)$', views.child_view), @@ -35,8 +35,7 @@ urlpatterns = patterns('', (r'^child/(?P<pk>\d+)/add_address/$', views.child_add_address), (r'^child/(?P<pk>\d+)/delete$', views.child_delete), (r'^child/(?P<pk>\d+)/edit$', views.child_edit), - (r'^child/(?P<pk>\d+)/export$', views.export_child_response), - (r'^child/(?P<pk>\d+)/export_repo$', views.export_child_repo_response), + (r'^child/(?P<pk>\d+)/export$', views.child_response), (r'^child/(?P<pk>\d+)/destroy$', views.destroy_handle), (r'^gbr/$', views.ghostbuster_list), (r'^gbr/create$', views.ghostbuster_create), @@ -48,6 +47,7 @@ urlpatterns = patterns('', (r'^client/import$', views.client_import), (r'^client/(?P<pk>\d+)$', views.client_detail), (r'^client/(?P<pk>\d+)/delete$', views.client_delete), + (r'^client/(?P<pk>\d+)/export$', views.client_export), (r'^repo/$', views.repository_list), (r'^repo/import$', views.repository_import), (r'^repo/(?P<pk>\d+)$', views.repository_detail), @@ -60,5 +60,3 @@ urlpatterns = patterns('', (r'^child_wizard$', views.child_wizard), (r'^update_bpki', views.update_bpki), ) - -# vim:sw=4 ts=8 expandtab diff --git a/rpkid/rpki/gui/app/views.py b/rpkid/rpki/gui/app/views.py index 57439aa6..d238be55 100644 --- a/rpkid/rpki/gui/app/views.py +++ b/rpkid/rpki/gui/app/views.py @@ -40,6 +40,7 @@ from rpki.gui.app import models, forms, glue, range_list from rpki.resource_set import (resource_range_as, resource_range_ipv4, resource_range_ipv6, roa_prefix_ipv4) from rpki.exceptions import BadIPResource +from rpki import sundial import rpki.gui.cacheview.models import rpki.gui.routeview.models @@ -138,9 +139,15 @@ def generic_import(request, queryset, configure, form_class=None, tmpf.write(form.cleaned_data['xml'].read()) tmpf.close() z = Zookeeper(handle=conf.handle) + handle = form.cleaned_data.get('handle') + # CharField uses an empty string for the empty value, rather than + # None. Convert to none in this case, since configure_child/parent + # expects it. + if handle == '': + handle = None # configure_repository returns None, so can't use tuple expansion # here. Unpack the tuple below if post_import_redirect is None. - r = configure(z, tmpf.name, form.cleaned_data.get('handle')) + r = configure(z, tmpf.name, handle) os.remove(tmpf.name) if post_import_redirect: url = post_import_redirect @@ -157,7 +164,6 @@ def generic_import(request, queryset, configure, form_class=None, @handle_required def dashboard(request): - conf = request.session['handle'] used_asns = range_list.RangeList() @@ -244,6 +250,14 @@ def conf_select(request): def serve_xml(content, basename): + """ + Generate a HttpResponse object with the content type set to XML. + + `content` is a string. + + `basename` is the prefix to specify for the XML filename. + + """ resp = http.HttpResponse(content, mimetype='application/xml') resp['Content-Disposition'] = 'attachment; filename=%s.xml' % (basename, ) return resp @@ -251,18 +265,18 @@ def serve_xml(content, basename): @handle_required def conf_export(request): - """Return the identity.xml for the current handle. + """Return the identity.xml for the current handle.""" - """ - handle = request.session['handle'] - return serve_xml(glue.read_identity(handle.handle), 'identity') + conf = request.session['handle'] + z = Zookeeper(handle=conf.handle) + xml = z.generate_identity() + return serve_xml(str(xml), '%s.identity' % conf.handle) @handle_required def parent_import(request): conf = request.session['handle'] - return generic_import(request, conf.parents, - Zookeeper.configure_parent) + return generic_import(request, conf.parents, Zookeeper.configure_parent) @handle_required @@ -270,17 +284,15 @@ def parent_list(request): """List view for parent objects.""" conf = request.session['handle'] return object_list(request, queryset=conf.parents.all(), - extra_context={ - 'create_url': reverse(parent_import), - 'create_label': 'Import'}) + extra_context={'create_url': reverse(parent_import), + 'create_label': 'Import'}) @handle_required -def parent_view(request, pk): +def parent_detail(request, pk): """Detail view for a particular parent.""" - handle = request.session['handle'] - qs = handle.parents.all() - return object_detail(request, qs, object_id=pk) + conf = request.session['handle'] + return object_detail(request, conf.parents.all(), object_id=pk) @handle_required @@ -288,21 +300,30 @@ def parent_delete(request, pk): conf = request.session['handle'] get_object_or_404(conf.parents, pk=pk) # confirm permission return delete_object(request, model=models.Parent, object_id=pk, - post_delete_redirect=reverse(parent_list), - template_name='app/parent_detail.html', - extra_context={'confirm_delete': True}) + post_delete_redirect=reverse(parent_list), + template_name='app/parent_detail.html', + extra_context={'confirm_delete': True}) + + +@handle_required +def parent_export(request, pk): + """Export XML repository request for a given parent.""" + conf = request.session['handle'] + parent = get_object_or_404(conf.parents, pk=pk) + z = Zookeeper(handle=conf.handle) + xml = z.generate_repository_request(parent) + return serve_xml(str(xml), '%s.repository' % parent.handle) @handle_required def child_import(request): conf = request.session['handle'] - return generic_import(request, conf.children, Zookeeper.configure_child, - post_import_redirect=reverse(child_list)) + return generic_import(request, conf.children, Zookeeper.configure_child) @handle_required def child_list(request): - """List view for child objects.""" + """List of children for current user.""" conf = request.session['handle'] return object_list(request, queryset=conf.children.all(), template_name='app/child_list.html', @@ -383,7 +404,7 @@ def child_edit(request, pk): if request.method == 'POST': form = form_class(request.POST, request.FILES) if form.is_valid(): - child.valid_until = form.cleaned_data.get('valid_until') + child.valid_until = sundial.datetime.fromdatetime(form.cleaned_data.get('valid_until')) child.save() # remove AS & prefixes that are not selected in the form models.ChildASN.objects.filter(child=child).exclude(pk__in=form.cleaned_data.get('as_ranges')).delete() @@ -488,8 +509,8 @@ def roa_delete(request, pk): """ conf = request.session['handle'] - obj = get_object_or_404(models.ROARequestPrefix.objects, roa_request__issuer=conf, - pk=pk) + obj = get_object_or_404(models.ROARequestPrefix.objects, + roa_request__issuer=conf, pk=pk) if request.method == 'POST': roa = obj.roa_request @@ -656,29 +677,18 @@ def child_wizard(request): @handle_required -def export_child_response(request, child_handle): - """ - Export the XML file containing the output of the configure_child - to send back to the client. - - """ - conf = request.session['handle'] - log = request.META['wsgi.errors'] - return serve_xml(glue.read_child_response(log, conf, child_handle), - child_handle) - - -@handle_required -def export_child_repo_response(request, child_handle): +def child_response(request, pk): """ Export the XML file containing the output of the configure_child to send back to the client. """ conf = request.session['handle'] - log = request.META['wsgi.errors'] - return serve_xml(glue.read_child_repo_response(log, conf, child_handle), - child_handle) + child = get_object_or_404(models.Child, issuer=conf, pk=pk) + z = Zookeeper(handle=conf.handle) + xml = z.generate_parental_response(child) + resp = serve_xml(str(xml), child.handle) + return resp @handle_required @@ -816,7 +826,7 @@ def route_view(request): ts = dict((attr['name'], attr['ts']) for attr in models.Timestamp.objects.values()) return render(request, 'app/routes_view.html', {'routes': routes, 'timestamp': ts}) - + @handle_required def repository_list(request): @@ -848,14 +858,15 @@ def repository_delete(request, pk): extra_context={'confirm_delete': True}) -@superuser_required +@handle_required def repository_import(request): + """Import XML response file from repository operator.""" return generic_import(request, models.Repository.objects, Zookeeper.configure_repository, - form_class=forms.ImportClientForm, + form_class=forms.ImportRepositoryForm, post_import_redirect=reverse(repository_list)) - + @superuser_required def client_list(request): @@ -884,3 +895,15 @@ def client_import(request): Zookeeper.configure_publication_client, form_class=forms.ImportClientForm, post_import_redirect=reverse(client_list)) + + +@superuser_required +def client_export(request, pk): + """Return the XML file resulting from a configure_publication_client + request. + + """ + client = get_object_or_404(models.Client, pk=pk) + z = Zookeeper() + xml = z.generate_repository_response(client) + return serve_xml(str(xml), '%s.repo' % z.handle) |