Mikhail Korobov avatar Mikhail Korobov committed 84714ae

Auth implementation is changed. Fix #6.

Comments (0)

Files changed (10)

 *.egg-info
 *~
 
+db.sqlite
+
 #misc files
 pip-log.txt
 

django_webtest/__init__.py

 from django.core.handlers.wsgi import WSGIHandler
 from django.core.servers.basehttp import AdminMediaHandler
 from django.db import close_connection
-from django.http import HttpResponseServerError
 from django.test import TestCase
 from django.test.client import store_rendered_templates
 from django.utils.functional import curry
         if user:
             environ = environ or {}
             if isinstance(user, User):
-                environ['REMOTE_USER'] = str(user.username)
+                environ['WEBTEST_USER'] = str(user.username)
             else:
-                environ['REMOTE_USER'] = user
+                environ['WEBTEST_USER'] = user
         return environ
 
     def do_request(self, req, status, expect_errors):
     setup_auth = True
 
     def _patch_settings(self):
-        ''' Patch settings to add support for REMOTE_USER authorization
+        ''' Patch settings to add support for django-webtest authorization
             and (optional) to disable CSRF checks
         '''
 
 
     def _setup_auth(self):
         ''' Setup REMOTE_USER authorization '''
-        self._setup_remote_user_middleware()
-        self._setup_remote_user_backend()
+        self._setup_auth_middleware()
+        self._setup_auth_backend()
 
     def _disable_csrf_checks(self):
         disable_csrf_middleware = 'django_webtest.middleware.DisableCSRFCheckMiddleware'
         if not disable_csrf_middleware in settings.MIDDLEWARE_CLASSES:
-            settings.MIDDLEWARE_CLASSES = [disable_csrf_middleware] + settings.MIDDLEWARE_CLASSES
+            settings.MIDDLEWARE_CLASSES.insert(0, disable_csrf_middleware)
 
-    def _setup_remote_user_middleware(self):
-        remote_user_middleware = 'django.contrib.auth.middleware.RemoteUserMiddleware'
-        if not remote_user_middleware in settings.MIDDLEWARE_CLASSES:
-            settings.MIDDLEWARE_CLASSES += [remote_user_middleware]
+    def _setup_auth_middleware(self):
+        auth_middleware = 'django_webtest.middleware.WebtestUserMiddleware'
+        settings.MIDDLEWARE_CLASSES += [auth_middleware]
 
-    def _setup_remote_user_backend(self):
-        auth_backends = settings.AUTHENTICATION_BACKENDS
-        try:
-            index = auth_backends.index('django.contrib.auth.backends.ModelBackend')
-            auth_backends[index] = 'django.contrib.auth.backends.RemoteUserBackend'
-        except ValueError:
-            auth_backends.append('django.contrib.auth.backends.RemoteUserBackend')
-        settings.AUTHENTICATION_BACKENDS = auth_backends
+    def _setup_auth_backend(self):
+        backend_name = 'django_webtest.backends.WebtestUserBackend'
+        settings.AUTHENTICATION_BACKENDS.insert(0, backend_name)
 
     def __call__(self, result=None):
         self._patch_settings()

django_webtest/backends.py

+from django.contrib.auth.backends import RemoteUserBackend
+
+class WebtestUserBackend(RemoteUserBackend):
+    """ Auth backend for django-webtest auth system """
+
+    def authenticate(self, django_webtest_user):
+        return super(WebtestUserBackend, self).authenticate(django_webtest_user)
+

django_webtest/middleware.py

 # -*- coding: utf-8 -*-
+from django.contrib.auth.middleware import RemoteUserMiddleware
+from django.core.exceptions import ImproperlyConfigured
+from django.contrib import auth
+
+class WebtestUserMiddleware(RemoteUserMiddleware):
+    """
+    Middleware for utilizing django-webtest simplified auth
+    ('user' arg for self.app.post and self.app.get).
+
+    Mostly copied from RemoteUserMiddleware, but the auth backend is changed
+    (by changing ``auth.authenticate`` arguments) in order to keep
+    RemoteUser backend untouched during django-webtest auth.
+    """
+
+    header = "WEBTEST_USER"
+
+    def process_request(self, request):
+        # AuthenticationMiddleware is required so that request.user exists.
+        if not hasattr(request, 'user'):
+            raise ImproperlyConfigured(
+                "The django-webtest auth middleware requires the"
+                " authentication middleware to be installed.  Edit your"
+                " MIDDLEWARE_CLASSES setting to insert"
+                " 'django.contrib.auth.middleware.AuthenticationMiddleware'"
+                " class.")
+        try:
+            username = request.META[self.header]
+        except KeyError:
+            # If specified header doesn't exist then return (leaving
+            # request.user set to AnonymousUser by the
+            # AuthenticationMiddleware).
+            return
+        # If the user is already authenticated and that user is the user we are
+        # getting passed in the headers, then the correct user is already
+        # persisted in the session and we don't need to continue.
+        if request.user.is_authenticated():
+            if request.user.username == self.clean_username(username, request):
+                return
+        # We are seeing this user for the first time in this session, attempt
+        # to authenticate the user.
+        user = auth.authenticate(django_webtest_user=username)
+        if user:
+            # User is valid.  Set request.user and persist user in the session
+            # by logging the user in.
+            request.user = user
+            auth.login(request, user)
 
 
 class DisableCSRFCheckMiddleware(object):
Add a comment to this file

django_webtest_tests/manage.py

File contents unchanged.

django_webtest_tests/runtests.py

 
 if __name__ == "__main__":
     execute_manager(settings)
-

django_webtest_tests/settings.py

     'django_webtest_tests',
     'django_webtest_tests.testapp_tests',
 )
+
+LOGIN_REDIRECT_URL = '/template/index.html'

django_webtest_tests/templates/registration/login.html

+{% extends "form.html" %}

django_webtest_tests/testapp_tests/tests.py

     def test_auth_is_enabled(self):
         from django.conf import settings
 
-        remote_user_middleware = 'django.contrib.auth.middleware.RemoteUserMiddleware'
-        assert remote_user_middleware in settings.MIDDLEWARE_CLASSES
-        assert 'django.contrib.auth.backends.RemoteUserBackend' in settings.AUTHENTICATION_BACKENDS
+        auth_middleware = 'django_webtest.middleware.WebtestUserMiddleware'
+        assert auth_middleware in settings.MIDDLEWARE_CLASSES
+        assert 'django_webtest.backends.WebtestUserBackend' in settings.AUTHENTICATION_BACKENDS
         self.assertEqual(
-            settings.MIDDLEWARE_CLASSES.index(remote_user_middleware),
+            settings.MIDDLEWARE_CLASSES.index(auth_middleware),
             len(settings.MIDDLEWARE_CLASSES)-1
         )
 
+    def test_standard_auth(self):
+        form = self.app.get(reverse('auth_login')).form
+        form['username'] = self.user.username
+        form['password'] = '123'
+        resp = form.submit().follow()
+        user = resp.context['user']
+        self.assertEqual(user, self.user)
+
+
 
 class DisableAuthSetupTest(WebTest):
     setup_auth = False
 
     def test_no_auth(self):
         from django.conf import settings
-        assert 'django.contrib.auth.middleware.RemoteUserMiddleware' not in settings.MIDDLEWARE_CLASSES
-        assert 'django.contrib.auth.backends.RemoteUserBackend' not in settings.AUTHENTICATION_BACKENDS
+        assert 'django_webtest.middleware.WebtestUserMiddleware' not in settings.MIDDLEWARE_CLASSES
+        assert 'django_webtest.backends.WebtestUserBackend' not in settings.AUTHENTICATION_BACKENDS

django_webtest_tests/urls.py

 urlpatterns = patterns('',
     url(r'^$', simple_method_test, name='simple-method-test'),
     url(r'^template/(.*)$', simple_template_render, name='simple-template-test'),
-    url(r'^check-password/$', 'testapp_tests.views.check_password', name='check_password')
+    url(r'^check-password/$', 'testapp_tests.views.check_password', name='check_password'),
+    url(r'^login/$', 'django.contrib.auth.views.login', name='auth_login'),
 )
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.