summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Graham <timograham@gmail.com>2015-02-11 14:38:52 -0500
committerTim Graham <timograham@gmail.com>2015-02-12 07:38:16 -0500
commit0f7f5bc9e7a94ab91c2b3db29ef7cf000eff593f (patch)
tree17168b2dcd85eab4a78cba0596ee2120f889baab
parent93b3ef9b2e191101c1a49b332d042864df74a658 (diff)
Fixed #24161 -- Stored the user primary key as a serialized value in the session.
This allows using a UUIDField primary key along with the JSON session serializer. Thanks to Trac alias jamesbeith for the report and Simon Charette for the initial patch.
-rw-r--r--django/contrib/auth/__init__.py12
-rw-r--r--tests/auth_tests/models/__init__.py3
-rw-r--r--tests/auth_tests/models/uuid_pk.py13
-rw-r--r--tests/auth_tests/test_auth_backends.py18
4 files changed, 40 insertions, 6 deletions
diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py
index a9eb41a609..be0ab52761 100644
--- a/django/contrib/auth/__init__.py
+++ b/django/contrib/auth/__init__.py
@@ -53,6 +53,12 @@ def _clean_credentials(credentials):
return credentials
+def _get_user_session_key(request):
+ # This value in the session is always serialized to a string, so we need
+ # to convert it back to Python whenever we access it.
+ return get_user_model()._meta.pk.to_python(request.session[SESSION_KEY])
+
+
def authenticate(**credentials):
"""
If the given credentials are valid, return a User object.
@@ -93,7 +99,7 @@ def login(request, user):
session_auth_hash = user.get_session_auth_hash()
if SESSION_KEY in request.session:
- if request.session[SESSION_KEY] != user.pk or (
+ if _get_user_session_key(request) != user.pk or (
session_auth_hash and
request.session.get(HASH_SESSION_KEY) != session_auth_hash):
# To avoid reusing another user's session, create a new, empty
@@ -102,7 +108,7 @@ def login(request, user):
request.session.flush()
else:
request.session.cycle_key()
- request.session[SESSION_KEY] = user.pk
+ request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
request.session[BACKEND_SESSION_KEY] = user.backend
request.session[HASH_SESSION_KEY] = session_auth_hash
if hasattr(request, 'user'):
@@ -158,7 +164,7 @@ def get_user(request):
from .models import AnonymousUser
user = None
try:
- user_id = request.session[SESSION_KEY]
+ user_id = _get_user_session_key(request)
backend_path = request.session[BACKEND_SESSION_KEY]
except KeyError:
pass
diff --git a/tests/auth_tests/models/__init__.py b/tests/auth_tests/models/__init__.py
index edeaef5347..72afdf2358 100644
--- a/tests/auth_tests/models/__init__.py
+++ b/tests/auth_tests/models/__init__.py
@@ -5,9 +5,10 @@ from .invalid_models import (
CustomUserBadRequiredFields,
)
from .with_foreign_key import CustomUserWithFK, Email
+from .uuid_pk import UUIDUser
__all__ = (
'CustomPermissionsUser', 'CustomUserNonUniqueUsername',
'CustomUserNonListRequiredFields', 'CustomUserBadRequiredFields',
- 'CustomUserWithFK', 'Email', 'IsActiveTestUser1',
+ 'CustomUserWithFK', 'Email', 'IsActiveTestUser1', 'UUIDUser',
)
diff --git a/tests/auth_tests/models/uuid_pk.py b/tests/auth_tests/models/uuid_pk.py
new file mode 100644
index 0000000000..44ec4410aa
--- /dev/null
+++ b/tests/auth_tests/models/uuid_pk.py
@@ -0,0 +1,13 @@
+import uuid
+
+from django.contrib.auth.models import AbstractUser
+from django.contrib.auth.tests.custom_user import RemoveGroupsAndPermissions
+from django.db import models
+
+with RemoveGroupsAndPermissions():
+ class UUIDUser(AbstractUser):
+ """A user with a UUID as primary key"""
+ id = models.UUIDField(default=uuid.uuid4, primary_key=True)
+
+ class Meta:
+ app_label = 'auth'
diff --git a/tests/auth_tests/test_auth_backends.py b/tests/auth_tests/test_auth_backends.py
index b5d6b82fcc..1977494a24 100644
--- a/tests/auth_tests/test_auth_backends.py
+++ b/tests/auth_tests/test_auth_backends.py
@@ -2,7 +2,9 @@ from __future__ import unicode_literals
from datetime import date
-from django.contrib.auth import BACKEND_SESSION_KEY, authenticate, get_user
+from django.contrib.auth import (
+ BACKEND_SESSION_KEY, SESSION_KEY, authenticate, get_user,
+)
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.hashers import MD5PasswordHasher
from django.contrib.auth.models import AnonymousUser, Group, Permission, User
@@ -12,7 +14,7 @@ from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.http import HttpRequest
from django.test import TestCase, modify_settings, override_settings
-from .models import CustomPermissionsUser
+from .models import CustomPermissionsUser, UUIDUser
class CountingMD5PasswordHasher(MD5PasswordHasher):
@@ -288,6 +290,18 @@ class CustomUserModelBackendAuthenticateTest(TestCase):
self.assertEqual(test_user, authenticated_user)
+@override_settings(AUTH_USER_MODEL='auth.UUIDUser')
+class UUIDUserTests(TestCase):
+
+ def test_login(self):
+ """
+ A custom user with a UUID primary key should be able to login.
+ """
+ user = UUIDUser.objects.create_user(username='uuid', password='test')
+ self.assertTrue(self.client.login(username='uuid', password='test'))
+ self.assertEqual(UUIDUser.objects.get(pk=self.client.session[SESSION_KEY]), user)
+
+
class TestObj(object):
pass