# HG changeset patch # User Branko Majic # Date 2013-03-24 19:42:40 # Node ID 90fac7c6abb985f808530bbd53629bea9cb29b71 # Parent e8434f637f9f5abca261e69e64647095ed113690 Renamed the tags library. Removed the line stripper middleware, and replaced it with some custom code that will remove all blank lines. The iptables rule rendering has been rewritten to accomodate this change (a utility function has been added for generating them). Fixed some code styling. 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 %} {% 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 %}
    {{location.name}}{% html_link '' 'project_location_iptables' project.id location.id class="btn btn-link" %}
    {% 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()
    {% html_link project.name 'project' project.id title=project.description %}{% html_link '' 'project_iptables' project.id class="btn btn-link pull-right" %}