Commit 0f7f5bc9 authored by Tim Graham's avatar Tim Graham
Browse files

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.
parent 93b3ef9b
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -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
+2 −1
Original line number Diff line number Diff line
@@ -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',
)
+13 −0
Original line number Diff line number Diff line
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'
+16 −2
Original line number Diff line number Diff line
@@ -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