From 7882ee9121592aa98c73140255c65e32663cb944 Mon Sep 17 00:00:00 2001 From: Daniel Roschka Date: Sun, 5 Apr 2015 21:06:01 +0200 Subject: [PATCH] Add global authentication This commit adds global authentication to binder to ensure that only valid users are able to use it. This should enable binder to be used in environemts where it's webfrontend is reachable for unauthenticated users as well. For setups where such a global authentication isn't desired it can be disabled by simply removing the LoginRequiredMiddleware from the list of active middlewares. --- binder/middlewares.py | 23 +++++++++++++ binder/settings.py | 3 ++ binder/templates/base.html | 3 ++ binder/templates/registration/login.html | 44 ++++++++++++++++++++++++ binder/tests/testViews.py | 12 +++++++ binder/urls.py | 4 +++ 6 files changed, 89 insertions(+) create mode 100644 binder/middlewares.py create mode 100644 binder/templates/registration/login.html diff --git a/binder/middlewares.py b/binder/middlewares.py new file mode 100644 index 0000000..f7a0a6f --- /dev/null +++ b/binder/middlewares.py @@ -0,0 +1,23 @@ +from django.conf import settings +from django.contrib.auth import REDIRECT_FIELD_NAME +from django.http import HttpResponseRedirect + +class LoginRequiredMiddleware(object): + """Middleware to redirect to the login page if the user isn't authenticated + + After successful authentication the user is redirected back to the page he + initially wanted to access. + """ + def process_request(self, request): + # allow access to the login url + if request.path == settings.LOGIN_URL: + return + # redirect to the login url if the user isn't authenticated + if not request.user.is_authenticated(): + if request.path not in (settings.LOGIN_URL, + settings.LOGIN_REDIRECT_URL): + return HttpResponseRedirect('%s?%s=%s' % (settings.LOGIN_URL, + REDIRECT_FIELD_NAME, + request.path)) + else: + return HttpResponseRedirect(settings.LOGIN_URL) diff --git a/binder/settings.py b/binder/settings.py index a787a6a..a2be546 100644 --- a/binder/settings.py +++ b/binder/settings.py @@ -67,6 +67,7 @@ MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', + 'binder.middlewares.LoginRequiredMiddleware', ) ROOT_URLCONF = 'binder.urls' @@ -86,3 +87,5 @@ INSTALLED_APPS = ( ) TEST_RUNNER = 'django.test.runner.DiscoverRunner' + +LOGIN_REDIRECT_URL = '/' diff --git a/binder/templates/base.html b/binder/templates/base.html index 1522e9b..8d1657f 100644 --- a/binder/templates/base.html +++ b/binder/templates/base.html @@ -20,6 +20,9 @@
  • Home
  • Server List
  • + {% if user.is_authenticated %} +
  • Logout
  • + {% endif %} {% endblock navigation %} diff --git a/binder/templates/registration/login.html b/binder/templates/registration/login.html new file mode 100644 index 0000000..525db3a --- /dev/null +++ b/binder/templates/registration/login.html @@ -0,0 +1,44 @@ + + + +Binder DNS Admin – Login + + + +
    + + + {% if form.errors %} +
    +
    + +
    + {% endif %} + +
    + {% csrf_token %} +
    + +
    + +
    +
    +
    + +
    + +
    +
    + +
    +
    +
    + +
    +
    +
    +
    + + \ No newline at end of file diff --git a/binder/tests/testViews.py b/binder/tests/testViews.py index c2a34c3..9da9be6 100644 --- a/binder/tests/testViews.py +++ b/binder/tests/testViews.py @@ -1,5 +1,6 @@ from django.test import TestCase from django.test.client import Client +from django.contrib.auth.models import User from django.core.urlresolvers import reverse from binder import models, helpers @@ -9,6 +10,12 @@ class GetTests(TestCase): """ Unit Tests that exercise HTTP GET. """ def setUp(self): self.client = Client() + user = User.objects.create_user('testuser', + 'testuser@example.com', + 'testpassword') + response = self.client.login(username='testuser', + password='testpassword') + def test_GetIndex(self): response = self.client.get(reverse("index")) @@ -44,6 +51,11 @@ class PostTests(TestCase): models.BindServer(hostname="testserver.test.net", statistics_port=1234).save() + user = User.objects.create_user('testuser', + 'testuser@example.com', + 'testpassword') + response = self.client.login(username='testuser', + password='testpassword') def test_DeleteRecordInitial_Empty(self): """ Ensure the initial deletion form works as expected with no RR list. """ diff --git a/binder/urls.py b/binder/urls.py index 97c5130..9962d13 100644 --- a/binder/urls.py +++ b/binder/urls.py @@ -6,6 +6,10 @@ admin.autodiscover() urlpatterns = patterns('', url(r'^admin/', include(admin.site.urls)), + + url(r'^accounts/login/$', 'django.contrib.auth.views.login', name='login'), + url(r'^accounts/logout/$', 'django.contrib.auth.views.logout_then_login', name='logout'), + url(r'^$', 'binder.views.home_index', name="index"), url(r'^server_list/$', 'binder.views.view_server_list', name="server_list"),