aboutsummaryrefslogtreecommitdiff
path: root/rpki/gui/app/templates
diff options
context:
space:
mode:
Diffstat (limited to 'rpki/gui/app/templates')
-rw-r--r--rpki/gui/app/templates/404.html11
-rw-r--r--rpki/gui/app/templates/500.html11
-rw-r--r--rpki/gui/app/templates/app/alert_confirm_clear.html21
-rw-r--r--rpki/gui/app/templates/app/alert_confirm_delete.html17
-rw-r--r--rpki/gui/app/templates/app/alert_detail.html31
-rw-r--r--rpki/gui/app/templates/app/alert_list.html31
-rw-r--r--rpki/gui/app/templates/app/app_base.html31
-rw-r--r--rpki/gui/app/templates/app/app_confirm_delete.html21
-rw-r--r--rpki/gui/app/templates/app/app_form.html19
-rw-r--r--rpki/gui/app/templates/app/bootstrap_form.html26
-rw-r--r--rpki/gui/app/templates/app/child_detail.html48
-rw-r--r--rpki/gui/app/templates/app/client_detail.html25
-rw-r--r--rpki/gui/app/templates/app/client_list.html22
-rw-r--r--rpki/gui/app/templates/app/conf_empty.html17
-rw-r--r--rpki/gui/app/templates/app/conf_list.html17
-rw-r--r--rpki/gui/app/templates/app/dashboard.html230
-rw-r--r--rpki/gui/app/templates/app/ghostbuster_confirm_delete.html20
-rw-r--r--rpki/gui/app/templates/app/ghostbusterrequest_detail.html64
-rw-r--r--rpki/gui/app/templates/app/import_resource_form.html9
-rw-r--r--rpki/gui/app/templates/app/object_confirm_delete.html21
-rw-r--r--rpki/gui/app/templates/app/parent_detail.html67
-rw-r--r--rpki/gui/app/templates/app/pubclient_list.html10
-rw-r--r--rpki/gui/app/templates/app/repository_detail.html19
-rw-r--r--rpki/gui/app/templates/app/resource_holder_list.html37
-rw-r--r--rpki/gui/app/templates/app/roa_detail.html40
-rw-r--r--rpki/gui/app/templates/app/roarequest_confirm_delete.html59
-rw-r--r--rpki/gui/app/templates/app/roarequest_confirm_form.html60
-rw-r--r--rpki/gui/app/templates/app/roarequest_confirm_multi_form.html66
-rw-r--r--rpki/gui/app/templates/app/roarequest_form.html50
-rw-r--r--rpki/gui/app/templates/app/roarequest_multi_form.html28
-rw-r--r--rpki/gui/app/templates/app/route_detail.html58
-rw-r--r--rpki/gui/app/templates/app/routes_view.html55
-rw-r--r--rpki/gui/app/templates/app/user_list.html37
-rw-r--r--rpki/gui/app/templates/base.html63
-rw-r--r--rpki/gui/app/templates/registration/login.html25
35 files changed, 1366 insertions, 0 deletions
diff --git a/rpki/gui/app/templates/404.html b/rpki/gui/app/templates/404.html
new file mode 100644
index 00000000..76ef3aee
--- /dev/null
+++ b/rpki/gui/app/templates/404.html
@@ -0,0 +1,11 @@
+{% extends "base.html" %}
+
+{% block content %}
+<div class="page-header">
+ <h1>Page Not Found</h1>
+</div>
+
+<div class="alert alert-error">
+ <strong>Whoops!</strong> I could not find the page you requested.
+</div>
+{% endblock content %}
diff --git a/rpki/gui/app/templates/500.html b/rpki/gui/app/templates/500.html
new file mode 100644
index 00000000..216fe8ae
--- /dev/null
+++ b/rpki/gui/app/templates/500.html
@@ -0,0 +1,11 @@
+{% extends "base.html" %}
+
+{% block content %}
+<div class="page-header">
+ <h1>Internal Server Error</h1>
+</div>
+
+<div class="alert alert-error">
+ <strong>Whoops!</strong> The administrator has been notified of this error.
+</div>
+{% endblock content %}
diff --git a/rpki/gui/app/templates/app/alert_confirm_clear.html b/rpki/gui/app/templates/app/alert_confirm_clear.html
new file mode 100644
index 00000000..5d7fcf04
--- /dev/null
+++ b/rpki/gui/app/templates/app/alert_confirm_clear.html
@@ -0,0 +1,21 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+
+{% block content %}
+<div class='page-header'>
+ <h1>Delete all alerts</h1>
+</div>
+
+<div class="row-fluid">
+ <div class="alert">
+ Please confirm that you would like to delete all alerts.
+ </div>
+ <form method="POST">
+ {% csrf_token %}
+ <div class="form-actions">
+ <button class="btn btn-danger" type="submit"><i class="icon-trash"></i> Delete All</button>
+ <a class="btn" href="{% url "alert-list" %}">Cancel</a>
+ </div>
+ </form>
+</div>
+{% endblock %}
diff --git a/rpki/gui/app/templates/app/alert_confirm_delete.html b/rpki/gui/app/templates/app/alert_confirm_delete.html
new file mode 100644
index 00000000..78c84917
--- /dev/null
+++ b/rpki/gui/app/templates/app/alert_confirm_delete.html
@@ -0,0 +1,17 @@
+{% extends "app/alert_detail.html" %}
+{% load url from future %}
+
+{% block action %}
+<div class="row-fluid">
+ <div class="alert">
+ Please confirm that you would like to delete this alert.
+ </div>
+ <form method="POST">
+ {% csrf_token %}
+ <div class="form-actions">
+ <button class="btn btn-danger" type="submit"><i class="icon-trash"></i> Delete</button>
+ <a class="btn" href="{{ object.get_absolute_url }}">Cancel</a>
+ </div>
+ </form>
+</div>
+{% endblock action %}
diff --git a/rpki/gui/app/templates/app/alert_detail.html b/rpki/gui/app/templates/app/alert_detail.html
new file mode 100644
index 00000000..b3a73b7e
--- /dev/null
+++ b/rpki/gui/app/templates/app/alert_detail.html
@@ -0,0 +1,31 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+{% load app_extras %}
+
+{% block content %}
+<div class="page-header">
+ <h1>Alert Detail <small>{{ object.subject }}</small></h1>
+</div>
+
+<div class="row-fluid">
+<table class="table">
+ <tr>
+ <th>Date:</th><td> {{ object.when }}</td>
+ </tr>
+ <tr>
+ <th>Severity:</th><td><span class="label {% severity_class object.severity %}">{{ object.get_severity_display }}</span></td>
+ </tr>
+</table>
+
+<p>
+{{ object.text }}
+
+</div>
+
+{% block action %}
+<div class="row-fluid">
+<a class="btn btn-danger" title="delete this alert" href="{% url "alert-delete" object.pk %}"><i class="icon-trash"></i> Delete</a>
+</div>
+{% endblock action %}
+
+{% endblock content %}
diff --git a/rpki/gui/app/templates/app/alert_list.html b/rpki/gui/app/templates/app/alert_list.html
new file mode 100644
index 00000000..dd0530e4
--- /dev/null
+++ b/rpki/gui/app/templates/app/alert_list.html
@@ -0,0 +1,31 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+
+{% block content %}
+<div class="page-header">
+ <h1>Alerts</h1>
+</div>
+
+<table class="table table-striped">
+ <thead>
+ <tr>
+ <th>#</th>
+ <th>Date</th>
+ <th>Subject</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for obj in object_list %}
+ <tr {% if not obj.seen %}style="font-weight: bold" {% endif %}class="{% if obj.severity == 1 %}warning{% endif %} {% if obj.severity == 2 %}error{% endif %}">
+ <td>{# <input type="checkbox"> #}</td>
+ <td>{{ obj.when }}</td>
+ <td><a href="{{ obj.get_absolute_url }}" title="view text of alert">{{ obj.subject }}</a></td>
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+
+<div class='row-fluid'>
+ <a class="btn btn-danger" href="{% url 'alert-clear-all' %}"><i class='icon-trash'></i> Delete All</a>
+</div>
+{% endblock content %}
diff --git a/rpki/gui/app/templates/app/app_base.html b/rpki/gui/app/templates/app/app_base.html
new file mode 100644
index 00000000..4fb5f731
--- /dev/null
+++ b/rpki/gui/app/templates/app/app_base.html
@@ -0,0 +1,31 @@
+{% extends "base.html" %}
+{# this can be removed when django 1.4 is EOL, because it is the default behavior in 1.5 #}
+{% load url from future %}
+{% load app_extras %}
+
+{# This template defines the common structure for the rpki.gui.app application. #}
+
+{% block sidebar %}
+
+<h2>{{ request.session.handle }}</h2>
+
+{# common navigation #}
+
+<ul class='nav nav-list'>
+ {% if request.session.handle %}
+ <li><a href="{% url "rpki.gui.app.views.dashboard" %}">dashboard</a></li>
+ <li><a href="{% url "rpki.gui.app.views.route_view" %}">routes</a></li>
+ <li><a href="{% url "alert-list" %}">alerts {% alert_count request.session.handle %}</a></li>
+ <li class="divider"></li>
+ {% endif %}
+ <li><a href="{% url "rpki.gui.app.views.conf_list" %}" title="select a different resource handle to manage">select identity</a></li>
+{% if request.user.is_superuser %}
+ <li class="divider"></li>
+ <li><a href="{% url "rpki.gui.app.views.user_list" %}" title="manage users"><i class="icon-user"></i> web users</a></li>
+ <li><a href="{% url "rpki.gui.app.views.resource_holder_list" %}" title="manage resource holders"><i class="icon-user"></i> resource holders</a></li>
+ <li><a href="{% url "rpki.gui.app.views.client_list" %}" title="manage repository clients">repository clients</a></li>
+{% endif %}
+{% block sidebar_extra %}{% endblock %}
+</ul>
+
+{% endblock sidebar %}
diff --git a/rpki/gui/app/templates/app/app_confirm_delete.html b/rpki/gui/app/templates/app/app_confirm_delete.html
new file mode 100644
index 00000000..7c35a733
--- /dev/null
+++ b/rpki/gui/app/templates/app/app_confirm_delete.html
@@ -0,0 +1,21 @@
+{% extends "app/app_base.html" %}
+
+{% block content %}
+<div class='page-title'>
+ <h1>{{ form_title }}</h1>
+</div>
+
+<div class='alert alert-block'>
+ <h4>Warning!</h4>
+ <strong>Please confirm</strong> that you would like to delete this object.
+</div>
+
+<form method='POST' action="">
+ {% csrf_token %}
+ {{ form }}
+ <div class="form-actions">
+ <input class='btn btn-danger' value='Delete' type='submit'>
+ <a class='btn' href="{{ cancel_url }}">Cancel</a>
+ </div>
+</form>
+{% endblock content %}
diff --git a/rpki/gui/app/templates/app/app_form.html b/rpki/gui/app/templates/app/app_form.html
new file mode 100644
index 00000000..b6ab60a2
--- /dev/null
+++ b/rpki/gui/app/templates/app/app_form.html
@@ -0,0 +1,19 @@
+{% extends "app/app_base.html" %}
+
+{% block content %}
+<div class="page-header">
+ <h1>{{ form_title }}</h1>
+</div>
+
+{# allow this template to be subclassed to fill in extra information, such as warnings #}
+{% block form_info %}{% endblock form_info %}
+
+<form method="POST" action="" enctype="multipart/form-data" class="form-horizontal">
+ {% csrf_token %}
+ {% include "app/bootstrap_form.html" %}
+ <div class="form-actions">
+ <input class='btn btn-primary' type='submit' value='Save'>
+ <a class='btn' href="{{ cancel_url }}">Cancel</a>
+ </div>
+</form>
+{% endblock %}
diff --git a/rpki/gui/app/templates/app/bootstrap_form.html b/rpki/gui/app/templates/app/bootstrap_form.html
new file mode 100644
index 00000000..c6fd5424
--- /dev/null
+++ b/rpki/gui/app/templates/app/bootstrap_form.html
@@ -0,0 +1,26 @@
+{% if form.non_field_errors %}
+<div class="alert alert-block alert-error">
+ {{ form.non_field_errors }}
+</div>
+{% endif %}
+
+{% for field in form %}
+
+{% if field.is_hidden %}
+{{ field }}
+{% else %}
+<div class="control-group {% if field.errors %}error{% endif %}">
+ <label class="control-label" for="{{ field.html_name }}">{{ field.label }}</label>
+ <div class="controls">
+ {{ field }}
+ {% if field.help_text %}
+ <span class="help-inline">{{ field.help_text }}</span>
+ {% endif %}
+ {% if field.errors %}
+ <span class="help-inline">{{ field.errors }}</span>
+ {% endif %}
+ </div>
+</div>
+{% endif %}
+
+{% endfor %}
diff --git a/rpki/gui/app/templates/app/child_detail.html b/rpki/gui/app/templates/app/child_detail.html
new file mode 100644
index 00000000..8178e179
--- /dev/null
+++ b/rpki/gui/app/templates/app/child_detail.html
@@ -0,0 +1,48 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+
+{% block content %}
+<div class="page-header">
+ <h1>Child: {{ object.handle }}</h1>
+</div>
+
+<div class='row-fluid'>
+ <p><strong>Valid until</strong> {{ object.valid_until }}
+</div>
+
+<div class='row-fluid'>
+ <div class='span6'>
+ <strong>Addresses</strong>
+ {% if object.address_ranges.all %}
+ <ul class='unstyled'>
+ {% for a in object.address_ranges.all %}
+ <li>{{ a.as_resource_range }}</li>
+ {% endfor %}
+ </ul>
+ {% else %}
+ <p style='font-style:italic'>none</p>
+ {% endif %}
+ </div>
+ <div class='span6'>
+ <strong>ASNs</strong>
+ {% if object.asns.all %}
+ <ul class='unstyled'>
+ {% for a in object.asns.all %}
+ <li>{{ a.as_resource_range }}</li>
+ {% endfor %}
+ </ul>
+ {% else %}
+ <p style='font-style:italic'>none</p>
+ {% endif %}
+ </div>
+</div>
+
+{% block action %}
+<a class='btn' href="{% url "rpki.gui.app.views.child_edit" object.pk %}" title='Edit this child'><i class="icon-edit"></i> Edit</a>
+<a class='btn' href="{% url "rpki.gui.app.views.child_add_asn" object.pk %}" title='Delegate an ASN to this child'><i class="icon-plus-sign"></i> AS</a>
+<a class='btn' href="{% url "rpki.gui.app.views.child_add_prefix" object.pk %}" title='Delegate a prefix to this child'><i class="icon-plus-sign"></i> Prefix</a>
+<a class='btn' href="{% url "rpki.gui.app.views.child_response" object.pk %}" title='Download XML file to send to child'><i class="icon-download"></i> Export</a>
+<a class="btn" href="{% url "rpki.gui.app.views.child_delete" object.pk %}" title="Delete this child"><i class="icon-trash"></i> Delete</a>
+{% endblock %}
+
+{% endblock %}
diff --git a/rpki/gui/app/templates/app/client_detail.html b/rpki/gui/app/templates/app/client_detail.html
new file mode 100644
index 00000000..3117e859
--- /dev/null
+++ b/rpki/gui/app/templates/app/client_detail.html
@@ -0,0 +1,25 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+
+{% block content %}
+<div class="page-header">
+ <h1>Repository Client: {{ object.handle }}</h1>
+</div>
+
+<table class="table">
+ <tr>
+ <td>Name</td>
+ <td>{{ object.handle }} </td>
+ </tr>
+ <tr>
+ <td>SIA</td>
+ <td>{{ object.sia_base }}</td>
+ </tr>
+</table>
+
+{% block action %}
+<a class="btn" href="{% url "client-export" object.pk %}" title="Download XML response to send to publication client"><i class="icon-download"></i> Export</a>
+<a class="btn" href="{% url "rpki.gui.app.views.client_delete" object.pk %}"><i class="icon-trash"></i> Delete</a>
+{% endblock action %}
+
+{% endblock content %}
diff --git a/rpki/gui/app/templates/app/client_list.html b/rpki/gui/app/templates/app/client_list.html
new file mode 100644
index 00000000..12987c53
--- /dev/null
+++ b/rpki/gui/app/templates/app/client_list.html
@@ -0,0 +1,22 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+
+{% block content %}
+<div class="page-header">
+ <h1>Repository Clients</h1>
+</div>
+<table class="table table-striped">
+ <thead><tr><th>Handle</th><th>Action</th></tr></thead>
+ <tbody>
+ {% for client in object_list %}
+ <tr>
+ <td><a href="{% url "rpki.gui.app.views.client_detail" client.pk %}">{{ client.handle }}</a></td>
+ <td>
+ <a class="btn btn-mini" href="{% url "rpki.gui.app.views.client_delete" client.pk %}" title="Delete"><i class="icon-trash"></i></a>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+<a class="btn" href="{% url "rpki.gui.app.views.client_import" %}"><i class="icon-upload"></i> Import</a>
+{% endblock content %}
diff --git a/rpki/gui/app/templates/app/conf_empty.html b/rpki/gui/app/templates/app/conf_empty.html
new file mode 100644
index 00000000..efe06f14
--- /dev/null
+++ b/rpki/gui/app/templates/app/conf_empty.html
@@ -0,0 +1,17 @@
+{% extends "base.html" %}
+{% load url from future %}
+
+{% block content %}
+
+{% if request.user.is_superuser %}
+<div class="alert alert-info">
+There are currently no resource holders on this system.
+</div>
+<a class="btn" href="{% url "rpki.gui.app.views.resource_holder_create" %}" title="create a new resource holder"><i class="icon-plus-sign"></i> Create</a>
+{% else %}
+<div class="alert alert-error">
+Your account does not have permission to manage any resource handles on this server. Please contact your portal-gui adminstrator.
+</div>
+{% endif %}
+
+{% endblock %}
diff --git a/rpki/gui/app/templates/app/conf_list.html b/rpki/gui/app/templates/app/conf_list.html
new file mode 100644
index 00000000..dce6d59e
--- /dev/null
+++ b/rpki/gui/app/templates/app/conf_list.html
@@ -0,0 +1,17 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+
+{% block content %}
+<div class="page-header">
+ <h1>Handle List</h1>
+</div>
+
+<p>Please select a handle.</p>
+
+<ul>
+ {% for c in conf_list %}
+ <li><a href="{% url "rpki.gui.app.views.conf_select" %}?handle={{ c.handle }}&next={{ next_url }}">{{ c.handle }}</a></li>
+ {% endfor %}
+</ul>
+
+{% endblock %}
diff --git a/rpki/gui/app/templates/app/dashboard.html b/rpki/gui/app/templates/app/dashboard.html
new file mode 100644
index 00000000..65dbb90f
--- /dev/null
+++ b/rpki/gui/app/templates/app/dashboard.html
@@ -0,0 +1,230 @@
+{% extends "app/app_base.html" %}
+
+{# this can be removed when django 1.4 is EOL, because it is the default behavior in 1.5 #}
+{% load url from future %}
+
+{% block sidebar_extra %}
+ <li class="divider"></li>
+ <li><a href="{% url "rpki.gui.app.views.conf_export" %}" title="download XML identity to send to parent">
+ {#<i class="icon-download"></i> #}export identity</a></li>
+{% endblock sidebar_extra %}
+
+{% block content %}
+<div class='row-fluid'>
+ <div class='span6'>
+ <div class="page-header">
+ <h1>Resources</h1>
+ </div>
+
+ <table class='table table-condensed-table table-striped'>
+ <tr>
+ <th>Resource</th>
+ <th>Valid Until</th>
+ <th>Parent</th>
+ </tr>
+
+ {% for object in asns %}
+ <tr>
+ <td>{{ object }}</td>
+ <td>{{ object.cert.not_after }}</td>
+ <td>
+ {% if object.cert.parent %}
+ <a href="{{ object.cert.parent.get_absolute_url }}">{{ object.cert.parent.handle }}</a>
+ {% endif %}
+ </td>
+ </tr>
+ {% endfor %}
+
+ {% for object in prefixes %}
+ <tr>
+ <td>{{ object.as_resource_range }}</td>
+ <td>{{ object.cert.not_after }}</td>
+ <td>
+ {% if object.cert.parent %}
+ <a href="{{ object.cert.parent.get_absolute_url }}">{{ object.cert.parent.handle }}</a>
+ {% endif %}
+ </td>
+ </tr>
+ {% endfor %}
+
+ {% if prefixes_v6 %}
+ {% for object in prefixes_v6 %}
+ <tr>
+ <td>{{ object.as_resource_range }}</td>
+ <td>{{ object.cert.not_after }}</td>
+ <td>
+ {% if object.cert.parent %}
+ <a href="{{ object.cert.parent.get_absolute_url }}">{{ object.cert.parent.handle }}</a>
+ {% endif %}
+ </td>
+ </tr>
+ {% endfor %}
+ {% endif %}
+ </table>
+ <a class='btn' href="{% url "rpki.gui.app.views.refresh" %}" title="refresh resource list from rpkid"><i class="icon-refresh"></i> refresh</a></li>
+ </div>
+ <div class='span6'>
+ <h2>Unallocated Resources</h2>
+ <p>The following resources have not been allocated to a child, nor appear in a ROA.
+
+ {% if unused_asns %}
+ <h3>ASNs</h3>
+ <ul>
+ {% for asn in unused_asns %}
+ <li>AS{{ asn }}
+ {% endfor %} <!-- ASNs -->
+ </ul>
+ {% endif %}
+
+ {% if unused_prefixes %}
+ <h3>IPv4</h3>
+ <table class="table table-condensed table-striped">
+ <tr><th>Prefix</th><th>Action</th></tr>
+ {% for addr in unused_prefixes %}
+ <tr>
+ <td>{{ addr }}</td>
+ <td>
+ <a class="btn btn-mini" title="Create ROA using this prefix" href="{% url "rpki.gui.app.views.roa_create_multi" %}?roa={{ addr }}"><i class="icon-plus-sign"></i> ROA</a>
+ </td>
+ </tr>
+ {% endfor %} <!-- addrs -->
+ </table>
+ {% endif %}
+
+ {% if unused_prefixes_v6 %}
+ <h3>IPv6</h3>
+ <table class="table table-condensed table-striped">
+ <tr><th>Prefix</th><th></th></tr>
+ {% for addr in unused_prefixes_v6 %}
+ <tr>
+ <td>{{ addr }}</td>
+ <td>
+ <a class="btn btn-mini" title='create roa using this prefix' href="{% url "rpki.gui.app.views.roa_create_multi" %}?roa={{ addr }}"><i class="icon-plus-sign"></i> ROA</a>
+ </td>
+ </tr>
+ {% endfor %} <!-- addrs -->
+ </table>
+ {% endif %}
+
+ </div><!-- /span -->
+</div><!-- /row -->
+
+<div class="row-fluid">
+ <div class="span6">
+<div class="page-header">
+ <h1>ROAs</h1>
+</div>
+<table class="table table-condensed table-striped">
+ <tr><th>Prefix</th><th>Max Length</th><th>AS</th><th></th></tr>
+ {% for roa in conf.roas %}
+ <tr>
+ <!-- each roa request has a single roa request prefix object associated -->
+ <td>{{ roa.prefixes.all.0.as_roa_prefix }}</td>
+ <td>{{ roa.prefixes.all.0.max_prefixlen }}</td>
+ <td>{{ roa.asn }}</td>
+ <td>
+ <a class="btn btn-mini" href="{% url "rpki.gui.app.views.roa_detail" roa.pk %}" title="Detail"><i class="icon-info-sign"></i></a>
+ <a class="btn btn-mini" href="{% url "rpki.gui.app.views.roa_delete" roa.pk %}" title="Delete"><i class="icon-trash"></i></a>
+ <a class="btn btn-mini" href="{% url "roa-clone" roa.pk %}" title="create another ROA for this prefix"><i class="icon-repeat"></i></a>
+ </td>
+ </tr>
+ {% endfor %}
+</table>
+<a class="btn" href="{% url "rpki.gui.app.views.roa_create_multi" %}"><i class="icon-plus-sign"></i> Create</a>
+<a class="btn" href="{% url "roa-import" %}" title="import a CSV file containing ROAs"><i class="icon-upload"></i> Import</a>
+<a class="btn" href="{% url "roa-export" %}" title="download a CSV file containing ROAs"><i class="icon-download"></i> Export</a>
+</div>
+
+ <div class="span6">
+<div class="page-header">
+ <h1>Ghostbusters</h1>
+</div>
+<table class="table table-condensed table-striped">
+ <tr><th>Full Name</th><th>Organization</th><th>Email</th><th>Telephone</th><th></th></tr>
+ {% for gbr in conf.ghostbusters %}
+ <tr>
+ <td>{{ gbr.full_name }}</td>
+ <td>{{ gbr.organization }}</td>
+ <td>{{ gbr.email_address }}</td>
+ <td>{{ gbr.telephone }}</td>
+ <td>
+ <a class="btn btn-mini" href="{% url "gbr-detail" gbr.pk %}" title="View"><i class="icon-info-sign"></i></a>
+ <a class="btn btn-mini" href="{% url "gbr-edit" gbr.pk %}" title="Edit"><i class="icon-edit"></i></a>
+ <a class="btn btn-mini" href="{% url "gbr-delete" gbr.pk %}" title="Delete"><i class="icon-trash"></i></a>
+ </td>
+ </tr>
+ {% endfor %}
+</table>
+<a class="btn" href="{% url "gbr-create" %}"><i class="icon-plus-sign"></i> Create</a>
+</div><!-- /span -->
+</div><!-- /row -->
+
+<div class="row-fluid">
+ <div class="span6">
+ <div class="page-header">
+ <h1>Children</h1>
+ </div>
+<table class="table table-condensed table-striped">
+ <tr><th>Handle</th><th></th>
+ {% for child in conf.children %}
+ <tr>
+ <td><a href="{{ child.get_absolute_url }}">{{ child.handle }}</a></td>
+ <td>
+ <a class="btn btn-mini" href="{% url "rpki.gui.app.views.child_delete" child.pk %}" title="Delete"><i class="icon-trash"></i></a>
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+ <div class="row-fluid">
+ <div class='span6'>
+ <a class="btn" href="{% url "rpki.gui.app.views.child_import" %}" title="Import XML request from Child"><i class="icon-upload"></i> Child</a>
+ <a class="btn" href="{% url "import-asns" %}" title="Import CSV file containing ASN delgations to children"><i class="icon-upload"></i> ASNs</a>
+ <a class="btn" href="{% url "import-prefixes" %}" title="import CSV file containing prefix delgations to children"><i class="icon-upload"></i> Prefixes</a>
+ </div>
+ </div>
+ <div class="row-fluid">
+ <div class='span6'>
+ <a class="btn" href="{% url "export-asns" %}" title="Export CSV file containing ASN delgations to children"><i class="icon-download"></i> ASNs</a>
+ <a class="btn" href="{% url "export-prefixes" %}" title="Export CSV file containing prefix delgations to children"><i class="icon-download"></i> Prefixes</a>
+ </div>
+ </div>
+ </div><!-- /span -->
+ <div class="span6">
+ <div class="page-header">
+ <h1>Parents</h1>
+ </div>
+ <table class="table table-condensed table-striped">
+ <tr><th>Handle</th><th></th></tr>
+ {% for parent in conf.parents %}
+ <tr>
+ <td><a href="{{ parent.get_absolute_url }}">{{ parent.handle }}</a></td>
+ <td>
+ <a class="btn btn-mini" href="{% url "rpki.gui.app.views.parent_delete" parent.pk %}" title="Delete"><i class="icon-trash"></i></a>
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+ <a class="btn" href="{% url "rpki.gui.app.views.parent_import" %}"><i class="icon-upload"></i> Import</a>
+ </div><!-- /span -->
+</div><!-- /row -->
+
+<div class="row-fluid">
+ <div class="span6">
+ <div class="page-header">
+ <h1>Repositories</h1>
+ </div>
+<table class="table table-condensed table-striped">
+ <tr><th>Handle</th><th></th></tr>
+ {% for repo in conf.repositories %}
+ <tr>
+ <td><a href="{{ repo.get_absolute_url }}">{{ repo.handle }}</a></td>
+ <td>
+ <a class="btn btn-mini" href="{% url "rpki.gui.app.views.repository_delete" repo.pk %}" title="Delete"><i class="icon-trash"></i></a>
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+ <a class="btn" href="{% url "rpki.gui.app.views.repository_import" %}"><i class="icon-upload"></i> Import</a>
+ </div><!-- /span -->
+</div><!-- /row -->
+{% endblock %}
diff --git a/rpki/gui/app/templates/app/ghostbuster_confirm_delete.html b/rpki/gui/app/templates/app/ghostbuster_confirm_delete.html
new file mode 100644
index 00000000..76b1d25a
--- /dev/null
+++ b/rpki/gui/app/templates/app/ghostbuster_confirm_delete.html
@@ -0,0 +1,20 @@
+{% extends "app/ghostbuster_detail.html" %}
+
+{% block extra %}
+
+<div class='alert-message block-message warning'>
+ <p>
+ <strong>Please confirm</strong> that you really want to delete by clicking Delete.
+
+ <div class='alert-actions'>
+ <form method='POST' action='{{ request.get_full_path }}'>
+ {% csrf_token %}
+ <input class='btn danger' type='submit' value='Delete' />
+ <a class='btn' href='{{ object.get_absolute_url }}'>Cancel</a>
+ </form>
+ </div>
+</div>
+
+{% endblock %}
+
+<!-- vim:set sw=2: -->
diff --git a/rpki/gui/app/templates/app/ghostbusterrequest_detail.html b/rpki/gui/app/templates/app/ghostbusterrequest_detail.html
new file mode 100644
index 00000000..296f0f16
--- /dev/null
+++ b/rpki/gui/app/templates/app/ghostbusterrequest_detail.html
@@ -0,0 +1,64 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+
+{% block content %}
+<div class="page-header">
+ <h1>Ghostbuster Request</h1>
+</div>
+
+<table class='table table-striped table-condensed'>
+ <tr><td>Full Name</td><td>{{ object.full_name }}</td></tr>
+
+ {% if object.honorific_prefix %}
+ <tr><td >Honorific Prefix</td><td>{{ object.honorific_prefix }}</td></tr>
+ {% endif %}
+
+ {% if object.organization %}
+ <tr><td >Organization</td><td>{{ object.organization }}</td></tr>
+ {% endif %}
+
+ {% if object.telephone %}
+ <tr><td >Telephone</td><td>{{ object.telephone }}</td></tr>
+ {% endif %}
+
+ {% if object.email_address %}
+ <tr><td >Email</td><td>{{ object.email_address }}</td></tr>
+ {% endif %}
+
+ {% if object.box %}
+ <tr><td >P.O. Box</td><td>{{ object.box }}</td></tr>
+ {% endif %}
+
+ {% if object.extended %}
+ <tr><td >Extended Address</td><td>{{ object.extended }}</td></tr>
+ {% endif %}
+
+ {% if object.street %}
+ <tr><td >Street Address</td><td>{{ object.street }}</td></tr>
+ {% endif %}
+
+ {% if object.city %}
+ <tr><td >City</td><td>{{ object.city }}</td></tr>
+ {% endif %}
+
+ {% if object.region %}
+ <tr><td >Region</td><td>{{ object.region }}</td></tr>
+ {% endif %}
+
+ {% if object.code %}
+ <tr><td >Postal Code</td><td>{{ object.code }}</td></tr>
+ {% endif %}
+
+ {% if object.country %}
+ <tr><td >Country</td><td>{{ object.country }}</td></tr>
+ {% endif %}
+
+</table>
+
+{% block action %}
+{# the roarequest_confirm_delete template will override this section #}
+<a class="btn" href="{% url "gbr-edit" object.pk %}"><i class="icon-edit"></i> Edit</a>
+<a class="btn" href="{% url "gbr-delete" object.pk %}"><i class="icon-trash"></i> Delete</a>
+{% endblock action %}
+
+{% endblock content %}
diff --git a/rpki/gui/app/templates/app/import_resource_form.html b/rpki/gui/app/templates/app/import_resource_form.html
new file mode 100644
index 00000000..e446d344
--- /dev/null
+++ b/rpki/gui/app/templates/app/import_resource_form.html
@@ -0,0 +1,9 @@
+{% extends "app/app_form.html" %}
+
+{% block form_info %}
+<div class="alert alert-block alert-warning">
+ <b>Warning!</b> All existing resources of this type currently in the
+ database <b>will be deleted</b> and replaced with the contents of the CSV
+ file you are uploading.
+</div>
+{% endblock form_info %}
diff --git a/rpki/gui/app/templates/app/object_confirm_delete.html b/rpki/gui/app/templates/app/object_confirm_delete.html
new file mode 100644
index 00000000..c4af9b26
--- /dev/null
+++ b/rpki/gui/app/templates/app/object_confirm_delete.html
@@ -0,0 +1,21 @@
+{% extends parent_template %}
+{% comment %}
+Since Django templates do not support multiple inheritance, we simluate it by
+dynamically extending from the *_detail.html template for a concrete object
+type. The *DeleteView classes should set a "parent_template" variable which is
+string specifying the concrete template to inherit from.
+{% endcomment %}
+{% load url from future %}
+
+{% block action %}
+<div class="alert alert-warning alert-block">
+ <h4>Warning!</h4>
+ Please confirm that you would like to delete this object
+</div>
+
+<form action='' method='POST'>
+ {% csrf_token %}
+ <input class='btn btn-danger' type='submit' value='Delete'>
+ <a class='btn' href="{% url "rpki.gui.app.views.dashboard" %}">Cancel</a>
+</form>
+{% endblock %}
diff --git a/rpki/gui/app/templates/app/parent_detail.html b/rpki/gui/app/templates/app/parent_detail.html
new file mode 100644
index 00000000..4dd1842f
--- /dev/null
+++ b/rpki/gui/app/templates/app/parent_detail.html
@@ -0,0 +1,67 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+
+{% block content %}
+<div class="page-header">
+ <h1>Parent: {{ object.handle }}</h1>
+</div>
+
+<table class="table table-striped table-condensed">
+ <tr>
+ <td>service_uri</td>
+ <td>{{ object.service_uri }}</td>
+ </tr>
+ <tr>
+ <td>parent_handle</td>
+ <td>{{ object.parent_handle }}</td>
+ </tr>
+ <tr>
+ <td>child_handle</td>
+ <td>{{ object.child_handle }}</td>
+ </tr>
+ <tr>
+ <td>repository_type</td>
+ <td>{{ object.repository_type }}</td>
+ </tr>
+ <tr>
+ <td>referrer</td>
+ <td>{{ object.referrer }}</td>
+ </tr>
+ <tr>
+ <td>ta validity period</td>
+ <td>{{ object.ta.getNotBefore }} - {{ object.ta.getNotAfter }}</td>
+ </tr>
+</table>
+
+<div class='row-fluid'>
+ <div class='span6'>
+ <h3>Delegated Addresses</h3>
+ <ul class='unstyled'>
+ {% for c in object.certs.all %}
+ {% for a in c.address_ranges.all %}
+ <li>{{ a }}</li>
+ {% endfor %}
+ {% for a in c.address_ranges_v6.all %}
+ <li>{{ a }}</li>
+ {% endfor %}
+ {% endfor %}
+ </ul>
+ </div>
+ <div class='span6'>
+ <h3>Delegated ASNs</h3>
+ <ul class='unstyled'>
+ {% for c in object.certs.all %}
+ {% for a in c.asn_ranges.all %}
+ <li>{{ a }}</li>
+ {% endfor %}
+ {% endfor %}
+ </ul>
+ </div>
+</div>
+
+{% block action %}
+<a class='btn' href='{% url "rpki.gui.app.views.parent_export" object.pk %}' title='Download XML to send to repository operator'><i class="icon-download"></i> Export</a>
+<a class="btn" href="{% url "rpki.gui.app.views.parent_delete" object.pk %}" title="Delete this parent"><i class="icon-trash"></i> Delete</a>
+{% endblock action %}
+
+{% endblock content %}
diff --git a/rpki/gui/app/templates/app/pubclient_list.html b/rpki/gui/app/templates/app/pubclient_list.html
new file mode 100644
index 00000000..1872e005
--- /dev/null
+++ b/rpki/gui/app/templates/app/pubclient_list.html
@@ -0,0 +1,10 @@
+{% extends "app/object_list.html" %}
+{% load url from future %}
+
+{% block actions %}
+<div class='actions'>
+ <a class='btn' href='{% url "rpki.gui.app.views.pubclient_import" %}'>Import</a>
+</div>
+{% endblock actions %}
+
+<!-- vim:set sw=2: -->
diff --git a/rpki/gui/app/templates/app/repository_detail.html b/rpki/gui/app/templates/app/repository_detail.html
new file mode 100644
index 00000000..92a43e54
--- /dev/null
+++ b/rpki/gui/app/templates/app/repository_detail.html
@@ -0,0 +1,19 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+
+{% block content %}
+<div class="page-header">
+ <h1>Repository: {{ object.handle }}</h1>
+</div>
+
+<table class="table">
+ <tr>
+ <td><strong>SIA</strong></td>
+ <td>{{ object.sia_base }}</td>
+ </tr>
+</table>
+
+{% block action %}
+<a class="btn" href="{% url "rpki.gui.app.views.repository_delete" object.pk %}" title="Delete this repository"><i class="icon-trash"></i> Delete</a>
+{% endblock action %}
+{% endblock content %}
diff --git a/rpki/gui/app/templates/app/resource_holder_list.html b/rpki/gui/app/templates/app/resource_holder_list.html
new file mode 100644
index 00000000..6525e74d
--- /dev/null
+++ b/rpki/gui/app/templates/app/resource_holder_list.html
@@ -0,0 +1,37 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+
+{% block content %}
+<div class='page-header'>
+ <h1>Resource Holders</h1>
+</div>
+
+<p>
+This page lists all of the resource holders that are currently managed by this server.
+Note that this is distinct from the
+<a href="{% url "rpki.gui.app.views.user_list" %}">list of web interface users</a>.
+</p>
+
+<table class='table table-striped'>
+ <thead>
+ <tr>
+ <th>Handle</th>
+ <th>Action</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for conf in object_list %}
+ <tr>
+ <td>{{ conf.handle }}</td>
+ <td>
+ <a class='btn btn-small' href='{% url "rpki.gui.app.views.resource_holder_edit" conf.pk %}' title="Edit"><i class="icon-edit"></i></a>
+ <a class='btn btn-small' href='{% url "rpki.gui.app.views.resource_holder_delete" conf.pk %}' title="Delete"><i class="icon-trash"></i></a>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+
+<a class="btn" href="{% url "rpki.gui.app.views.resource_holder_create" %}"><i class="icon-plus-sign"></i> Create</a>
+{% endblock content %}
+{# vim: set ft=htmldjango: #}
diff --git a/rpki/gui/app/templates/app/roa_detail.html b/rpki/gui/app/templates/app/roa_detail.html
new file mode 100644
index 00000000..ec76579d
--- /dev/null
+++ b/rpki/gui/app/templates/app/roa_detail.html
@@ -0,0 +1,40 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+{% load app_extras %}
+
+{% block content %}
+<div class="page-header">
+ <h1>ROA Detail</h1>
+</div>
+
+<div class="row-fluid">
+ <div class="span6 well">
+ <table class="table">
+ <tr><th>Prefix</th><th>Max Length</th><th>AS</th></tr>
+ <tr>
+ <td>{{ object.prefixes.all.0.as_roa_prefix }}</td>
+ <td>{{ object.prefixes.all.0.max_prefixlen }}</td>
+ <td>{{ object.asn }}</td>
+ </tr>
+ </table>
+ </div>
+
+ <div class="span6">
+ <h3>Covered Routes</h3>
+ <p>This table lists currently announced routes which are covered by prefixes included in this ROA.
+ <table class="table">
+ <tr><th>Prefix</th><th>AS</th><th>Validity</th></tr>
+ {% for r in object.routes %}
+ <tr>
+ <td>{{ r.as_resource_range }}</td>
+ <td>{{ r.asn }}</td>
+ <td>{% validity_label r.status %}</td>
+ <td><a href="{{ r.get_absolute_url }}" title="view route detail"><i class="icon-info-sign"></i></a></td>
+ </tr>
+ {% endfor %}
+ </table>
+ </div>
+</div>
+
+<a class="btn" href="{% url "rpki.gui.app.views.roa_delete" object.pk %}"><i class="icon-trash"></i> Delete</a>
+{% endblock content %}
diff --git a/rpki/gui/app/templates/app/roarequest_confirm_delete.html b/rpki/gui/app/templates/app/roarequest_confirm_delete.html
new file mode 100644
index 00000000..7dc3ec2b
--- /dev/null
+++ b/rpki/gui/app/templates/app/roarequest_confirm_delete.html
@@ -0,0 +1,59 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+{% load app_extras %}
+
+{% block content %}
+<div class='page-header'>
+ <h1>Delete ROA Request</h1>
+</div>
+
+<div class='row-fluid'>
+ <div class='span6'>
+ <div class='alert alert-block alert-warning'>
+ <p><strong>Please confirm</strong> that you would like to delete the
+ following ROA Request. The table to the right indicates how validation
+ status for matching routes may change.
+ </div>
+
+ <table class='table'>
+ <tr>
+ <th>Prefix</th>
+ <td>{{ object.prefixes.all.0.as_roa_prefix }}</td>
+ </tr>
+ <tr>
+ <th>Max Length</th>
+ <td>{{ object.prefixes.all.0.max_prefixlen }}</td>
+ </tr>
+ <tr>
+ <th>AS</th>
+ <td>{{ object.asn }}</td>
+ </tr>
+ </table>
+
+ <form method='POST' action='{{ request.get_full_path }}'>
+ {% csrf_token %}
+ <input class='btn btn-danger' type='submit' value='Delete'/>
+ <a class='btn' href="{% url "rpki.gui.app.views.dashboard" %}">Cancel</a>
+ </form>
+ </div>
+
+ <div class='span6'>
+ <h2>Matching Routes</h2>
+
+ <table class='table table-striped table-condensed'>
+ <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>{% validity_label r.newstatus %}</td>
+ </tr>
+ {% endfor %}
+ </table>
+ </div><!-- /span8 -->
+</div><!-- /row -->
+{% endblock content %}
diff --git a/rpki/gui/app/templates/app/roarequest_confirm_form.html b/rpki/gui/app/templates/app/roarequest_confirm_form.html
new file mode 100644
index 00000000..446bb6a4
--- /dev/null
+++ b/rpki/gui/app/templates/app/roarequest_confirm_form.html
@@ -0,0 +1,60 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+
+{% block content %}
+<div class='page-title'>
+ <h1>Confirm ROA Request</h1>
+</div>
+
+<div class='row-fluid'>
+ <div class='span6'>
+ <div class='alert alert-block-message alert-warning'>
+ <p><strong>Please confirm</strong> that you would like to create the following ROA.
+ The accompanying table indicates how the validation status may change as a result.
+ </div>
+
+ <table class='table table-condensed table-striped'>
+ <tr>
+ <th>AS</th>
+ <th>Prefix</th>
+ <th>Max Length</th>
+ </tr>
+ <tr>
+ <td>{{ asn }}</td>
+ <td>{{ prefix }}</td>
+ <td>{{ max_prefixlen }}</td>
+ </tr>
+ </table>
+
+ <form method='POST' action='{% url "rpki.gui.app.views.roa_create_confirm" %}'>
+ {% csrf_token %}
+ {% include "app/bootstrap_form.html" %}
+
+ <div class='form-actions'>
+ <input class='btn btn-primary' type='submit' value='Create'/>
+ <a class='btn' href='{% url "rpki.gui.app.views.dashboard" %}'>Cancel</a>
+ </div>
+ </form>
+ </div>
+
+ <div class='span6'>
+ <h2>Matched Routes</h2>
+
+ <table class='table table-striped table-condensed'>
+ <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 %}
diff --git a/rpki/gui/app/templates/app/roarequest_confirm_multi_form.html b/rpki/gui/app/templates/app/roarequest_confirm_multi_form.html
new file mode 100644
index 00000000..4a06a4aa
--- /dev/null
+++ b/rpki/gui/app/templates/app/roarequest_confirm_multi_form.html
@@ -0,0 +1,66 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+{% load app_extras %}
+
+{% block content %}
+<div class='page-title'>
+ <h1>Confirm ROA Requests</h1>
+</div>
+
+<div class='row-fluid'>
+ <div class='span6'>
+ <div class='alert alert-block-message alert-warning'>
+ <p><strong>Please confirm</strong> that you would like to create the following ROA(s).
+ The accompanying table indicates how the validation status may change as a result.
+ </div>
+
+ <table class='table table-condensed table-striped'>
+ <tr>
+ <th>Prefix</th>
+ <th>Max Length</th>
+ <th>AS</th>
+ </tr>
+ {% for roa in roas %}
+ <tr>
+ <td>{{ roa.prefix }}</td>
+ <td>{{ roa.max_prefixlen }}</td>
+ <td>{{ roa.asn }}</td>
+ </tr>
+ {% endfor %}
+ </table>
+
+ <form method='POST' action='{% url "rpki.gui.app.views.roa_create_multi_confirm" %}'>
+ {% csrf_token %}
+ {{ formset.management_form }}
+ {% for form in formset %}
+ {% include "app/bootstrap_form.html" %}
+ {% endfor %}
+
+ <div class='form-actions'>
+ <input class='btn btn-primary' type='submit' value='Create'/>
+ <a class='btn' href='{% url "rpki.gui.app.views.dashboard" %}'>Cancel</a>
+ </div>
+ </form>
+ </div>
+
+ <div class='span6'>
+ <h2>Matched Routes</h2>
+
+ <table class='table table-striped table-condensed'>
+ <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>{% validity_label r.newstatus %}</td>
+ </tr>
+ {% endfor %}
+ </table>
+ </div>
+
+</div>
+{% endblock content %}
diff --git a/rpki/gui/app/templates/app/roarequest_form.html b/rpki/gui/app/templates/app/roarequest_form.html
new file mode 100644
index 00000000..3a29131d
--- /dev/null
+++ b/rpki/gui/app/templates/app/roarequest_form.html
@@ -0,0 +1,50 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+
+{# This form is used for creating a new ROA request #}
+
+{% block content %}
+<div class='page-title'>
+ <h1>Create ROA</h1>
+</div>
+
+<script src='{{ STATIC_URL }}js/jquery-1.8.3.min.js'></script>
+<script type='text/javascript'>
+ var f = function(){
+ var e = $("#route_table")
+ e.empty()
+ e.append('<tr><th>Prefix</th><th>AS</th></tr>')
+ $.getJSON('/api/v1/route/', {'prefix__in':$(this).val()}, function(data){
+ if (data.length == 1) {
+ $("#id_asn").val(data[0].asn)
+ }
+ for (var x in data) {
+ e.append('<tr><td>' + data[x].prefix + '</td><td>' + data[x].asn + '</td></tr>')
+ }
+ })
+ }
+
+ $(document).ready(function(){ $("#id_prefix").change(f) })
+</script>
+
+<div class='row-fluid'>
+ <div class='span6'>
+ <form method='POST' action='{{ request.get_full_path }}'>
+ {% csrf_token %}
+ {% include "app/bootstrap_form.html" %}
+ <div class="form-actions">
+ <input class="btn" type="submit" value="Preview">
+ <a class="btn" href="{% url "rpki.gui.app.views.dashboard" %}">Cancel</a>
+ </div>
+ </form>
+ </div>
+
+ <div class='span6'>
+ Routes matching your prefix:
+ <table class='table table-condensed table-striped' id='route_table'>
+ <tr><th>Prefix</th><th>AS</th></tr>
+ <!-- script above populates this table based upon prefix matches -->
+ </table>
+ </div>
+</div><!--row-->
+{% endblock content %}
diff --git a/rpki/gui/app/templates/app/roarequest_multi_form.html b/rpki/gui/app/templates/app/roarequest_multi_form.html
new file mode 100644
index 00000000..06d07943
--- /dev/null
+++ b/rpki/gui/app/templates/app/roarequest_multi_form.html
@@ -0,0 +1,28 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+
+{% block content %}
+<div class='page-title'>
+ <h1>Create ROAs</h1>
+</div>
+
+<form method='POST' action='{{ request.get_full_path }}'>
+ {% csrf_token %}
+ {{ formset.management_form }}
+ {% for form in formset %}
+ <div class="controls controls-row">
+ {{ form.prefix }}
+ {{ form.max_prefixlen }}
+ {{ form.asn }}
+ <label class="checkbox inline span1">{{ form.DELETE }} Delete</label>
+ {% if form.errors %}<span class="help-inline">{{ form.errors }}</span>{% endif %}
+ {% if form.non_field_errors %}<span class="help-inline">{{ form.non_field_errors }}</span>{% endif %}
+ </div>
+ {% endfor %}
+
+ <div class="form-actions">
+ <input class="btn" type="submit" value="Preview">
+ <a class="btn" href="{% url "rpki.gui.app.views.dashboard" %}">Cancel</a>
+ </div>
+</form>
+{% endblock %}
diff --git a/rpki/gui/app/templates/app/route_detail.html b/rpki/gui/app/templates/app/route_detail.html
new file mode 100644
index 00000000..84add4a8
--- /dev/null
+++ b/rpki/gui/app/templates/app/route_detail.html
@@ -0,0 +1,58 @@
+{% extends "app/app_base.html" %}
+{% load app_extras %}
+{% load bootstrap_pager %}
+
+{# template for displaying the list of ROAs covering a specific route #}
+
+{% block content %}
+<div class="page-header">
+ <h1>Route Detail</h1>
+</div>
+
+<div class="row-fluid">
+ <div class="span12 well">
+ <table class="table table-striped table-condensed">
+ <thead>
+ <tr><th>Prefix</th><th>AS</th><th>Validity</th></tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>{{ object.as_resource_range }}</td>
+ <td>{{ object.asn }}</td>
+ <td>{% validity_label object.status %}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
+
+<div class="row-fluid">
+ <div class="span12">
+ <p>The table below lists all ROAs which cover the route described above.
+
+ <table class="table table-striped table-condensed">
+ <thead>
+ <tr>
+ <th>Prefix</th>
+ <th>Max Length</th>
+ <th>ASN</th>
+ <th>Expires</th>
+ <th>URI</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for pfx in roa_prefixes %}
+ <tr>
+ <td>{{ pfx.as_resource_range }}</td>
+ <td>{{ pfx.max_length }}</td>
+ <td>{{ pfx.roas.all.0.asid }}</td>
+ <td>{{ pfx.roas.all.0.not_after }}</td>
+ <td>{{ pfx.roas.all.0.repo.uri }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% bootstrap_pager request roa_prefixes %}
+ </div>
+</div>
+{% endblock %}
diff --git a/rpki/gui/app/templates/app/routes_view.html b/rpki/gui/app/templates/app/routes_view.html
new file mode 100644
index 00000000..885f3fa9
--- /dev/null
+++ b/rpki/gui/app/templates/app/routes_view.html
@@ -0,0 +1,55 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+{% load bootstrap_pager %}
+{% load app_extras %}
+
+{% block sidebar_extra %}
+<li class="nav-header">BGP data updated</li>
+<li>IPv4: {{ timestamp.bgp_v4_import.isoformat }}</li>
+<li>IPv6: {{ timestamp.bgp_v6_import.isoformat }}</li>
+<li class="nav-header">rcynic cache updated</li>
+<li>{{ timestamp.rcynic_import.isoformat }}</li>
+{% endblock sidebar_extra %}
+
+{% block content %}
+
+<div class='page-header'>
+ <h1>Route View</h1>
+</div>
+
+<p>
+This view shows currently advertised routes for the prefixes listed in resource certs received from RPKI parents.
+
+<form method="POST" action="{% url "suggest-roas" %}">
+ {% csrf_token %}
+ <table class='table table-striped table-condensed'>
+ <thead>
+ <tr>
+ <th></th>
+ <th>Prefix</th>
+ <th>Origin AS</th>
+ <th>Validation Status</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for r in routes %}
+ <tr>
+ <td><input type="checkbox" name="pk-{{ r.pk }}"></td>
+ <td>{{ r.get_prefix_display }}</td>
+ <td>{{ r.asn }}</td>
+ <td>
+ {% validity_label r.status %}
+ <a href='{% url "rpki.gui.app.views.route_detail" r.pk %}' title='display ROAs covering this prefix'><i class="icon-info-sign"></i></a>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ <div class="form-actions">
+ <button type="submit" title="create ROAs for selected routes"><i class="icon-plus-sign"></i> Create ROAs</button>
+ </div>
+</form>
+
+{% bootstrap_pager request routes %}
+
+{% endblock content %}
diff --git a/rpki/gui/app/templates/app/user_list.html b/rpki/gui/app/templates/app/user_list.html
new file mode 100644
index 00000000..1b419ded
--- /dev/null
+++ b/rpki/gui/app/templates/app/user_list.html
@@ -0,0 +1,37 @@
+{% extends "app/app_base.html" %}
+{% load url from future %}
+
+{% block content %}
+<div class='page-header'>
+ <h1>Users</h1>
+</div>
+
+<p>
+This page lists all user accounts in the web interface. Note that this is distinct from the
+<a href="{% url "rpki.gui.app.views.resource_holder_list" %}">list of resource holders</a>.
+</p>
+
+<table class='table table-striped'>
+ <thead>
+ <tr>
+ <th>Username</th>
+ <th>Email</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for user in object_list %}
+ <tr>
+ <td>{{ user.username }}</td>
+ <td>{{ user.email }}</td>
+ <td>
+ <a class='btn btn-small' href='{% url "rpki.gui.app.views.user_edit" user.pk %}' title="Edit"><i class="icon-edit"></i></a>
+ <a class='btn btn-small' href='{% url "rpki.gui.app.views.user_delete" user.pk %}' title="Delete"><i class="icon-trash"></i></a>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+
+<a class='btn' href="{% url "rpki.gui.app.views.user_create" %}" title="create a new locally hosted resource handle"><i class="icon-plus-sign"></i> Create</a>
+{% endblock content %}
diff --git a/rpki/gui/app/templates/base.html b/rpki/gui/app/templates/base.html
new file mode 100644
index 00000000..08d0c112
--- /dev/null
+++ b/rpki/gui/app/templates/base.html
@@ -0,0 +1,63 @@
+{% load url from future %}
+{% load app_extras %}
+
+<!DOCTYPE HTML>
+<html lang="en">
+ <head>
+ <meta name='Content-Type' content='text/html; charset=UTF-8'>
+ <title>{% block title %}RPKI {% if request.session.handle %}: {{ request.session.handle }}{% endif %}{% endblock %}</title>
+ {% block head %}{% endblock %}
+ <link rel="stylesheet" href="{{ STATIC_URL }}css/bootstrap.min.css" media="screen">
+ <link rel="icon" href="{{ STATIC_URL }}img/sui-riu.ico" type="image/x-icon">
+ <link rel="shortcut icon" href="{{ STATIC_URL }}img/sui-riu.ico" type="image/x-icon">
+ <style type="text/css">
+ body { padding: 40px }
+ </style>
+ </head>
+ <body>
+
+ <!-- TOP BAR -->
+ <div class="container">
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="navbar-inner">
+ <a class="brand" href="#">rpki.net {% rpki_version %}</a>
+ <ul class='nav'>
+ <li class="active">
+ <a href="#">Home</a>
+ </li>
+ <li class="divider-vertical"></li>
+ {% if user.is_authenticated %}
+ <li><p class="navbar-text">Logged in as {{ user }}</li>
+ <li class="divider-vertical"></li>
+ <li><a href="{% url "rpki.gui.views.logout" %}">Log Out</a></li>
+ {% endif %}
+ </ul>
+ <ul class="nav pull-right">
+ <li><a href="https://trac.rpki.net/wiki/doc/RPKI/CA/UI/GUI">Help</a></li>
+ </ul>
+ </div>
+ </div>
+ </div><!-- topbar -->
+
+ <div class="container-fluid">
+ <!-- MAIN CONTENT -->
+ <div class="row-fluid">
+ <div class="span2">
+ {% block sidebar %}{% endblock %}
+ </div>
+
+ <div class="span10">
+ {% if messages %}
+ {% for message in messages %}
+ {# this will break if there is more than one tag, but don't expect to use that feature #}
+ <div class='alert alert-{{ message.tags }}'>
+ {{ message }}
+ </div>
+ {% endfor %}
+ {% endif %}
+ {% block content %}{% endblock %}
+ </div>
+ </div>
+
+ </body>
+</html>
diff --git a/rpki/gui/app/templates/registration/login.html b/rpki/gui/app/templates/registration/login.html
new file mode 100644
index 00000000..0d6fb6fd
--- /dev/null
+++ b/rpki/gui/app/templates/registration/login.html
@@ -0,0 +1,25 @@
+{% extends "base.html" %}
+{% load url from future %}
+
+{% block content %}
+<div class="page-header">
+ <h1>Login</h1>
+</div>
+
+{% if form.errors %}
+<div class='alert'>
+ <p>Your username and password didn't match. Please try again.</p>
+</div>
+{% endif %}
+
+<form class="form-horizontal" method="post" action="{% url "rpki.gui.views.login" %}">
+ {% csrf_token %}
+ {% include "app/bootstrap_form.html" %}
+
+ <input type="hidden" name="next" value="{{ next }}" />
+ <div class="form-actions">
+ <input type="submit" value="Login" class="btn btn-primary" />
+ </div>
+</form>
+
+{% endblock %}