diff --git a/conntrackt/templates/conntrackt/entity_detail.html b/conntrackt/templates/conntrackt/entity_detail.html
--- a/conntrackt/templates/conntrackt/entity_detail.html
+++ b/conntrackt/templates/conntrackt/entity_detail.html
@@ -1,7 +1,7 @@
{% extends "conntrackt/template.html" %}
{# For html_link. #}
-{% load conntrackt %}
+{% load conntrackt_tags %}
{% block content %}
{# Use a bit shorter variable names. #}
@@ -20,7 +20,7 @@
{% for communication in interface.source_set.all %}
{{communication.destination}} - {{communication.protocol}}: {{communication.port}}
{% endfor %}{% endfor %}
- iptables rules{% include "conntrackt/entity_iptables.html" with entity=entity %}
{% html_link 'Download' 'entity_iptables' entity.id class="btn btn-primary" %}
+ iptables rules{{ entity_iptables }}
{% html_link 'Download' 'entity_iptables' entity.id class="btn btn-primary" %}
{% endif %}
{% endwith %}
diff --git a/conntrackt/templates/conntrackt/entity_iptables.html b/conntrackt/templates/conntrackt/entity_iptables.html
--- a/conntrackt/templates/conntrackt/entity_iptables.html
+++ b/conntrackt/templates/conntrackt/entity_iptables.html
@@ -1,4 +1,4 @@
-{% load conntrackt %}
+{% load conntrackt_tags %}
# iptables rules generated by conntrackt for {{entity}}
*filter
:INPUT ACCEPT [0:0]
diff --git a/conntrackt/templates/conntrackt/index.html b/conntrackt/templates/conntrackt/index.html
--- a/conntrackt/templates/conntrackt/index.html
+++ b/conntrackt/templates/conntrackt/index.html
@@ -1,7 +1,7 @@
{% extends "conntrackt/template.html" %}
{# For html_link #}
-{% load conntrackt %}
+{% load conntrackt_tags %}
{% block content %}
Welcome to Conntrackt
diff --git a/conntrackt/templates/conntrackt/location_widget.html b/conntrackt/templates/conntrackt/location_widget.html
--- a/conntrackt/templates/conntrackt/location_widget.html
+++ b/conntrackt/templates/conntrackt/location_widget.html
@@ -1,4 +1,4 @@
-{% load conntrackt %}
+{% load conntrackt_tags %}
{{location.name}} | {% html_link '' 'project_location_iptables' project.id location.id class="btn btn-link" %} |
{% for entity in entities %}
diff --git a/conntrackt/templates/conntrackt/login.html b/conntrackt/templates/conntrackt/login.html
--- a/conntrackt/templates/conntrackt/login.html
+++ b/conntrackt/templates/conntrackt/login.html
@@ -1,7 +1,7 @@
{% extends "conntrackt/template.html" %}
{# For html_link #}
-{% load conntrackt %}
+{% load conntrackt_tags %}
{% block content %}
diff --git a/conntrackt/templates/conntrackt/project_detail.html b/conntrackt/templates/conntrackt/project_detail.html
--- a/conntrackt/templates/conntrackt/project_detail.html
+++ b/conntrackt/templates/conntrackt/project_detail.html
@@ -1,6 +1,6 @@
{% extends "conntrackt/template.html" %}
-{% load conntrackt %}
+{% load conntrackt_tags %}
{% block content %}
{{project.name}}
diff --git a/conntrackt/templates/conntrackt/project_widget.html b/conntrackt/templates/conntrackt/project_widget.html
--- a/conntrackt/templates/conntrackt/project_widget.html
+++ b/conntrackt/templates/conntrackt/project_widget.html
@@ -1,4 +1,4 @@
-{% load conntrackt %}
+{% load conntrackt_tags %}
{% html_link project.name 'project' project.id title=project.description %} | {% html_link '' 'project_iptables' project.id class="btn btn-link pull-right" %} |
{% for entity in project.entity_set.all %}
diff --git a/conntrackt/templates/conntrackt/template.html b/conntrackt/templates/conntrackt/template.html
--- a/conntrackt/templates/conntrackt/template.html
+++ b/conntrackt/templates/conntrackt/template.html
@@ -1,4 +1,4 @@
-{% load conntrackt %}
+{% load conntrackt_tags %}
diff --git a/conntrackt/templatetags/conntrackt.py b/conntrackt/templatetags/conntrackt_tags.py
rename from conntrackt/templatetags/conntrackt.py
rename to conntrackt/templatetags/conntrackt_tags.py
--- a/conntrackt/templatetags/conntrackt.py
+++ b/conntrackt/templatetags/conntrackt_tags.py
@@ -1,12 +1,12 @@
# Import Django's template library.
from django import template
-
# Import for determining the active URL.
from django.core import urlresolvers
# Get an instance of Django's template library.
register = template.Library()
+
@register.inclusion_tag('conntrackt/html_link.html')
def html_link(text, view, *args, **kwargs):
"""
@@ -51,6 +51,7 @@ def html_link(text, view, *args, **kwarg
return context
+
@register.simple_tag
def iptables(communication):
"""
@@ -70,6 +71,7 @@ def iptables(communication):
return rule_template % values
+
@register.simple_tag(takes_context = True)
def active_link(context, url_name, return_value='active', **kwargs):
"""
diff --git a/conntrackt/urls.py b/conntrackt/urls.py
--- a/conntrackt/urls.py
+++ b/conntrackt/urls.py
@@ -9,7 +9,7 @@ from conntrackt.models import Entity
from django.views.generic import DetailView
# Import some app-specific views.
-from conntrackt.views import IndexView, IptablesView, ProjectView, get_project_iptables
+from conntrackt.views import IndexView, ProjectView, EntityView, entity_iptables, project_iptables
urlpatterns = patterns(
'conntrackt.views',
@@ -19,14 +19,14 @@ urlpatterns = patterns(
url(r'^project/(?P\d+)/$', ProjectView.as_view(),
name = 'project'),
# View for showing information about an entity.
- url(r'^entity/(?P\d+)/$', DetailView.as_view(model = Entity),
+ url(r'^entity/(?P\d+)/$', EntityView.as_view(),
name = 'entity'),
# View for rendering iptables rules for a specific entity.
- url(r'^entity/(?P\d+)/iptables/$', IptablesView.as_view(), name="entity_iptables"),
+ url(r'^entity/(?P\d+)/iptables/$', entity_iptables, name="entity_iptables"),
# View for rendering zip file with iptables rules for all entities in a project.
- url(r'^project/(?P\d+)/iptables/$', get_project_iptables, name="project_iptables"),
+ url(r'^project/(?P\d+)/iptables/$', project_iptables, name="project_iptables"),
# View for rendering zip file with iptables rules for all entities in a project for a specific location.
- url(r'^project/(?P\d+)/location/(?P\d+)/iptables/$', get_project_iptables, name="project_location_iptables"),
+ url(r'^project/(?P\d+)/location/(?P\d+)/iptables/$', project_iptables, name="project_location_iptables"),
# Views for logging-in/out the users.
url(r'^login/$', login, {'template_name': 'conntrackt/login.html'}, name = "login"),
url(r'^logout/$', logout, name = "logout"),
diff --git a/conntrackt/utils.py b/conntrackt/utils.py
new file mode 100644
--- /dev/null
+++ b/conntrackt/utils.py
@@ -0,0 +1,33 @@
+# Standard library imports.
+import re
+
+# Django-specific imports.
+from django.template import Context, loader
+
+
+def generate_entity_iptables(entity):
+ """
+ Generates full iptables rules for the supplied entity. The generated rules
+ can be fed directly to the iptables-restore utility.
+
+ Arguments:
+
+ entity - An Entity instance for which the iptables rules should be
+ generated.
+
+ Returns:
+
+ String containing the iptables rules for entity.
+ """
+
+ # Render the iptables template.
+ template = loader.get_template('conntrackt/entity_iptables.html')
+ context = Context({'entity': entity})
+ content = template.render(context)
+
+ # Remove the blank lines.
+ content = re.sub('^\s*\n', '', content)
+ content = re.sub('\n\s*\n', '\n', content)
+
+ return content
+
diff --git a/conntrackt/views.py b/conntrackt/views.py
--- a/conntrackt/views.py
+++ b/conntrackt/views.py
@@ -1,7 +1,6 @@
# For generating ZIP files.
from StringIO import StringIO
from zipfile import ZipFile, ZIP_DEFLATED
-import re
# Django-specific imports.
from django.http import HttpResponse
@@ -9,8 +8,10 @@ from django.shortcuts import render_to_r
from django.views.generic import TemplateView, DetailView
# Application-specific imports.
-from conntrackt.models import Project, Entity, Location
-from conntrackt.stripper import StripperMiddleware
+from .models import Project, Entity, Location
+from .stripper import StripperMiddleware
+from .utils import generate_entity_iptables
+
class IndexView(TemplateView):
"""
@@ -35,6 +36,7 @@ class IndexView(TemplateView):
return context
+
class ProjectView(DetailView):
"""
Custom view for presenting the project information.
@@ -71,44 +73,64 @@ class ProjectView(DetailView):
# Finally return the context.
return context
-class IptablesView(DetailView):
+
+class EntityView(DetailView):
+ """
+ Custom view for presenting entity information.
"""
- Custom view for rendering iptables rules for a specific entity, and starting
- automatic download by browser.
+ model = Entity
+
+ def get_context_data(self, **kwargs):
+ """
+ Returns the context data that should be used for rendering of the
+ template.
+
+ Adds the 'entity_iptables' context object that contains full iptables
+ rules generated for the entity.
+ """
+
+ # Call the parent class method.
+ context = super(DetailView, self).get_context_data(**kwargs)
+
+ # Add the rendered iptables rules to the context.
+ context['entity_iptables'] = generate_entity_iptables(self.object)
+
+ return context
+
+
+def entity_iptables(request, pk):
+ """
+ Custom view that returns response containing iptables rules generated for an
+ entity.
+
+ Makes sure to set the Content-Disposition of a response in order to
+ signal the browser it should start download of this view's response
+ immediately. Also sets the suggested filename for it.
+
+ Arguments:
+
+ pk - Primary key of the Entity object for which the rules should be
+ generated.
+
+ Returns:
+
+ Response object that contains the iptables rules for specified entity.
"""
- model = Entity
- template_name = 'conntrackt/entity_iptables.html'
-
- def render_to_response(self, context, **kwargs):
- """
- Renders the template with the given context to response. The response
- will be an iptables configuration file that can be used with
- iptables-restore.
-
- Makes sure to set the Content-Disposition of a response in order to
- signal the browser it should start download of this view's response
- immediately. Also sets the suggested filename for it.
- """
+ # Fetch the entity, and construct the response with iptables rules as
+ # content.
+ entity = get_object_or_404(Entity, pk = pk)
+ content = generate_entity_iptables(entity)
+ response = HttpResponse(content, mimetype='text/plain')
+
+ # Add the Content-Disposition information for the browser, telling the
+ # browser to download the file with suggested filename.
+ response['Content-Disposition']="attachment; filename=%s-iptables.conf" % entity.name.lower().replace(" ", "_")
- # Call the parent class method first. This will render the template. Set
- # the content type to text/plain.
- response = super(IptablesView, self).render_to_response(context,
- content_type='text/plain', **kwargs)
-
- # Add the Content-Disposition information for the browser, telling the
- # browser to download the file with suggested filename.
- response['Content-Disposition']="attachment; filename=%s-iptables.conf" % self.object.name.lower().replace(" ", "_")
+ return response
- # Render the response, and remove the blank lines from the template.
- response.render()
- response.content = re.sub('^\s*\n', '', response.content)
- response.content = re.sub('\n\s*\n', '\n', response.content)
- # Return the modified response.
- return response
-
-def get_project_iptables(request, project_id, location_id = None):
+def project_iptables(request, project_id, location_id = None):
"""
Custom view for obtaining iptables for all entities of a project or project
location in a single ZIP file.
@@ -143,10 +165,6 @@ def get_project_iptables(request, projec
# to open the file with program as well.
response = HttpResponse(mimetype='application/zip')
- # Stripper middleware has to be used in order to remove the excess blank
- # lines from rendering (this has to be done manually).
- stripper_middleware = StripperMiddleware()
-
# If specific location was specified, get the entities that are part of that
# project location only, otherwise fetch all of the project's entities. Also
# set-up the filename that will be suggested to the browser.
@@ -163,8 +181,8 @@ def get_project_iptables(request, projec
# Render iptables rules for each entity, placing them in the ZIP archive.
for entity in entities:
- entity_iptables = stripper_middleware.process_response(request,render_to_response('conntrackt/entity_iptables.html', {'entity': entity}, mimetype="text/plain"))
- zipped_iptables.writestr("%s-iptables.conf" % entity.name.lower().replace(" ", "_"), entity_iptables.content)
+ entity_iptables = generate_entity_iptables(entity)
+ zipped_iptables.writestr("%s-iptables.conf" % entity.name.lower().replace(" ", "_"), entity_iptables)
# Close the archive, and flush the buffer.
zipped_iptables.close()