aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Elkins <melkins@tislabs.com>2012-01-21 01:42:14 +0000
committerMichael Elkins <melkins@tislabs.com>2012-01-21 01:42:14 +0000
commitcb3e16840ce29c8e46789abd083803f4f9cfd2b5 (patch)
treecf1b7b563d38bf950734a680b90669b59d5dd0ba
parentf25bac0b0473490d84198e6a28185182530550c5 (diff)
require double confirmation for roa creation
display list of matching routes with validation status for second confirmation svn path=/branches/tk161/; revision=4254
-rw-r--r--rpkid/rpki/gui/app/forms.py10
-rw-r--r--rpkid/rpki/gui/app/templates/app/roa_request_confirm_delete.html2
-rw-r--r--rpkid/rpki/gui/app/templates/app/roarequest_form.html42
-rw-r--r--rpkid/rpki/gui/app/views.py45
4 files changed, 80 insertions, 19 deletions
diff --git a/rpkid/rpki/gui/app/forms.py b/rpkid/rpki/gui/app/forms.py
index 375e8e67..69d4b335 100644
--- a/rpkid/rpki/gui/app/forms.py
+++ b/rpkid/rpki/gui/app/forms.py
@@ -151,9 +151,11 @@ class ROARequest(forms.Form):
Handles both IPv4 and IPv6."""
- asn = forms.IntegerField()
+ asn = forms.IntegerField(label='AS')
prefix = forms.CharField(max_length=50)
- max_prefixlen = forms.CharField(required=False)
+ max_prefixlen = forms.CharField(required=False,
+ label='Max Prefix Length')
+ confirmed = forms.BooleanField(widget=forms.HiddenInput, required=False)
def _as_resource_range(self):
prefix = self.cleaned_data.get('prefix')
@@ -192,8 +194,8 @@ class ROARequest(forms.Form):
max_prefixlen = self.cleaned_data.get('max_prefixlen')
max_prefixlen = int(max_prefixlen) if max_prefixlen else r.prefixlen()
if max_prefixlen < r.prefixlen():
- raise (forms.ValidationError,
- 'max prefix length must be greater than or equal to the prefix length')
+ raise forms.ValidationError, \
+ 'max prefix length must be greater than or equal to the prefix length'
if max_prefixlen > r.datum_type.bits:
raise forms.ValidationError, \
'max prefix length (%d) is out of range for IP version (%d)' % (max_prefixlen, r.datum_type.bits)
diff --git a/rpkid/rpki/gui/app/templates/app/roa_request_confirm_delete.html b/rpkid/rpki/gui/app/templates/app/roa_request_confirm_delete.html
index e4bc432b..a0e4b54d 100644
--- a/rpkid/rpki/gui/app/templates/app/roa_request_confirm_delete.html
+++ b/rpkid/rpki/gui/app/templates/app/roa_request_confirm_delete.html
@@ -48,7 +48,7 @@ that are covered by this ROA request will be if this ROA request is deleted:
<tr>
<td>{{ r.get_prefix_display }}</td>
<td>{{ r.asn }}</td>
- <td><span class='label {{ r.status_label }}'>{{ r.status }}</span>
+ <td><span class='label {{ r.status_label }}'>{{ r.status }}</span></td>
</tr>
{% endfor %}
</table>
diff --git a/rpkid/rpki/gui/app/templates/app/roarequest_form.html b/rpkid/rpki/gui/app/templates/app/roarequest_form.html
new file mode 100644
index 00000000..83759120
--- /dev/null
+++ b/rpkid/rpki/gui/app/templates/app/roarequest_form.html
@@ -0,0 +1,42 @@
+{% extends "app/app_base.html" %}
+
+{% block content %}
+
+<div class='page-title'>
+ <h1>Create ROA</h1>
+</div>
+
+<div class='row'>
+ <div class='span8'>
+ <form method='POST' action='{{ request.get_full_path }}'>
+ {% csrf_token %}
+ {% include "app/bootstrap_form.html" %}
+ <div class='actions'>
+ <input class='btn primary' type='submit' value='Create'/>
+ <a class='btn' href='{% url rpki.gui.app.views.roa_list %}'>Cancel</a>
+ </div>
+ </form>
+ </div>
+ <div class='span8 offset8'>
+ <p>Matched Routes
+
+ <table style='zebra-striped condensed-table'>
+ <tr>
+ <th>Prefix</th>
+ <th>Origin AS</th>
+ <th>Validation Status</th>
+ </tr>
+ {% for r in routes %}
+ <tr>
+ <td>{{ r.get_prefix_display }}</td>
+ <td>{{ r.asn }}</td>
+ <td><span class='label {{ r.status_label }}'>{{ r.status }}</span></td>
+ </tr>
+ {% endfor %}
+ </table>
+ </div>
+</div>
+
+{% endblock content %}
+
+{# vim:set sw=2: #}
diff --git a/rpkid/rpki/gui/app/views.py b/rpkid/rpki/gui/app/views.py
index 70696eea..9f7e6df3 100644
--- a/rpkid/rpki/gui/app/views.py
+++ b/rpkid/rpki/gui/app/views.py
@@ -429,29 +429,46 @@ def roa_create(request):
Doesn't use the generic create_object() form because we need to create both
the ROARequest and ROARequestPrefix objects."""
+ routes = []
if request.method == 'POST':
form = forms.ROARequest(request.POST, request.FILES)
if form.is_valid():
asn = form.cleaned_data.get('asn')
conf = request.session['handle']
- roarequests = models.ROARequest.objects.filter(issuer=conf, asn=asn)
- if roarequests:
- # FIXME need to handle the case where there are multiple ROAs
- # for the same AS due to prefixes delegated from different
- # resource certs.
- roa = roarequests[0]
- else:
- roa = models.ROARequest.objects.create(issuer=conf, asn=asn)
rng = form._as_resource_range() # FIXME calling "private" method
max_prefixlen = int(form.cleaned_data.get('max_prefixlen'))
- version = 'IPv4' if isinstance(rng,
- resource_set.resource_range_ipv4) else 'IPv6'
- roa.prefixes.create(version=version, prefix=str(rng.min),
- prefixlen=rng.prefixlen(), max_prefixlen=max_prefixlen)
- return http.HttpResponseRedirect(reverse(roa_list))
+
+ if form.cleaned_data.get('confirmed'):
+ roarequests = models.ROARequest.objects.filter(issuer=conf, asn=asn)
+ if roarequests:
+ # FIXME need to handle the case where there are multiple ROAs
+ # for the same AS due to prefixes delegated from different
+ # resource certs.
+ roa = roarequests[0]
+ else:
+ roa = models.ROARequest.objects.create(issuer=conf, asn=asn)
+ version = 'IPv4' if isinstance(rng,
+ resource_set.resource_range_ipv4) else 'IPv6'
+ roa.prefixes.create(version=version, prefix=str(rng.min),
+ prefixlen=rng.prefixlen(), max_prefixlen=max_prefixlen)
+ return http.HttpResponseRedirect(reverse(roa_list))
+ else:
+ form = forms.ROARequest(initial={
+ 'asn': form.cleaned_data.get('asn'),
+ 'prefix': form.cleaned_data.get('prefix'),
+ 'max_prefixlen': form.cleaned_data.get('max_prefixlen'),
+ 'confirmed': True})
+
+ # find list of matching routes
+ match = roa_match(rng)
+ for route, roas in match:
+ validate_route(route, roas)
+ routes.append(route)
else:
form = forms.ROARequest()
- return render('app/roarequest_form.html', {'form': form}, request)
+
+ return render('app/roarequest_form.html', {'form': form, 'routes': routes},
+ request)
@handle_required