Browse Source

Fixed #19662 -- alter auth modelbackend to accept custom username fields

Thanks to Aymeric and Carl for the review.
Preston Holmes 12 years ago
parent
commit
c44d748272

+ 4 - 4
django/contrib/auth/backends.py

@@ -8,11 +8,11 @@ class ModelBackend(object):
     Authenticates against django.contrib.auth.models.User.
     """
 
-    # TODO: Model, login attribute name and password attribute name should be
-    # configurable.
-    def authenticate(self, username=None, password=None):
+    def authenticate(self, username=None, password=None, **kwargs):
+        UserModel = get_user_model()
+        if username is None:
+            username = kwargs.get(UserModel.USERNAME_FIELD)
         try:
-            UserModel = get_user_model()
             user = UserModel._default_manager.get_by_natural_key(username)
             if user.check_password(password):
                 return user

+ 19 - 1
django/contrib/auth/tests/auth_backends.py

@@ -4,7 +4,7 @@ from datetime import date
 from django.conf import settings
 from django.contrib.auth.models import User, Group, Permission, AnonymousUser
 from django.contrib.auth.tests.utils import skipIfCustomUser
-from django.contrib.auth.tests.custom_user import ExtensionUser, CustomPermissionsUser
+from django.contrib.auth.tests.custom_user import ExtensionUser, CustomPermissionsUser, CustomUser
 from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import ImproperlyConfigured, PermissionDenied
 from django.contrib.auth import authenticate
@@ -190,6 +190,24 @@ class CustomPermissionsUserModelBackendTest(BaseModelBackendTest, TestCase):
         )
 
 
+@override_settings(AUTH_USER_MODEL='auth.CustomUser')
+class CustomUserModelBackendAuthenticateTest(TestCase):
+    """
+    Tests that the model backend can accept a credentials kwarg labeled with
+    custom user model's USERNAME_FIELD.
+    """
+
+    def test_authenticate(self):
+        test_user = CustomUser._default_manager.create_user(
+            email='test@example.com',
+            password='test',
+            date_of_birth=date(2006, 4, 25)
+        )
+        authenticated_user = authenticate(email='test@example.com', password='test')
+        self.assertEqual(test_user, authenticated_user)
+
+
+
 class TestObj(object):
     pass
 

+ 9 - 3
docs/ref/contrib/auth.txt

@@ -412,9 +412,15 @@ The following backends are available in :mod:`django.contrib.auth.backends`:
 .. class:: ModelBackend
 
     This is the default authentication backend used by Django.  It
-    authenticates using usernames and passwords stored in the
-    :class:`~django.contrib.auth.models.User` model.
-
+    authenticates using credentials consisting of a user identifier and
+    password.  For Django's default user model, the user identifier is the
+    username, for custom user models it is the field specified by
+    USERNAME_FIELD (see :doc:`Customizing Users and authentication
+    </topics/auth/customizing>`).
+
+    It also handles the default permissions model as defined for
+    :class:`~django.contrib.auth.models.User` and
+    :class:`~django.contrib.auth.models.PermissionsMixin`.
 
 .. class:: RemoteUserBackend