Commit 5f8b97f9 authored by Preston Holmes's avatar Preston Holmes
Browse files

Fixed #19057 -- support custom user models in mod_wsgi auth handler

thanks @freakboy3742 for the catch and review
parent 4c75344c
Loading
Loading
Loading
Loading
+19 −6
Original line number Diff line number Diff line
from django.contrib.auth.models import User
from django.contrib import auth
from django import db
from django.utils.encoding import force_bytes

@@ -11,14 +11,21 @@ def check_password(environ, username, password):
    on whether the user exists and authenticates.
    """

    UserModel = auth.get_user_model()
    # db connection state is managed similarly to the wsgi handler
    # as mod_wsgi may call these functions outside of a request/response cycle
    db.reset_queries()

    try:
        try:
            user = User.objects.get(username=username, is_active=True)
        except User.DoesNotExist:
            user = UserModel.objects.get_by_natural_key(username)
        except UserModel.DoesNotExist:
            return None
        try:
            if not user.is_active:
                return None
        except AttributeError as e:
            # a custom user may not support is_active
            return None
        return user.check_password(password)
    finally:
@@ -30,14 +37,20 @@ def groups_for_user(environ, username):
    Authorizes a user based on groups
    """

    UserModel = auth.get_user_model()
    db.reset_queries()

    try:
        try:
            user = User.objects.get(username=username, is_active=True)
        except User.DoesNotExist:
            user = UserModel.objects.get_by_natural_key(username)
        except UserModel.DoesNotExist:
            return []
        try:
            if not user.is_active:
                return []
        except AttributeError as e:
            # a custom user may not support is_active
            return []

        return [force_bytes(group.name) for group in user.groups.all()]
    finally:
        db.close_connection()
+6 −1
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ from __future__ import unicode_literals

from django.contrib.auth.handlers.modwsgi import check_password, groups_for_user
from django.contrib.auth.models import User, Group
from django.contrib.auth.tests.utils import skipIfCustomUser
from django.test import TransactionTestCase


@@ -13,7 +14,6 @@ class ModWsgiHandlerTestCase(TransactionTestCase):
    def setUp(self):
        user1 = User.objects.create_user('test', 'test@example.com', 'test')
        User.objects.create_user('test1', 'test1@example.com', 'test1')

        group = Group.objects.create(name='test_group')
        user1.groups.add(group)

@@ -21,6 +21,10 @@ class ModWsgiHandlerTestCase(TransactionTestCase):
        """
        Verify that check_password returns the correct values as per
        http://code.google.com/p/modwsgi/wiki/AccessControlMechanisms#Apache_Authentication_Provider

        because the custom user available in the test framework does not
        support the is_active attribute, we can't test this with a custom
        user.
        """

        # User not in database
@@ -32,6 +36,7 @@ class ModWsgiHandlerTestCase(TransactionTestCase):
        # Valid user with incorrect password
        self.assertFalse(check_password({}, 'test', 'incorrect'))

    @skipIfCustomUser
    def test_groups_for_user(self):
        """
        Check that groups_for_user returns correct values as per
+8 −0
Original line number Diff line number Diff line
@@ -14,6 +14,14 @@ version >= 2.2 and mod_wsgi >= 2.0. For example, you could:

* Allow certain users to connect to a WebDAV share created with mod_dav_.

.. note::
    If you have installed a :ref:`custom User model <auth-custom-user>` and
    want to use this default auth handler, it must support an `is_active`
    attribute. If you want to use group based authorization, your custom user
    must have a relation named 'groups', referring to a related object that has
    a 'name' field. You can also specify your own custom mod_wsgi
    auth handler if your custom cannot conform to these requirements.

.. _Subversion: http://subversion.tigris.org/
.. _mod_dav: http://httpd.apache.org/docs/2.2/mod/mod_dav.html