Fixed #31920 -- Made AuthenticationMiddleware add request.auser().

This commit is contained in:
Jon Janzen 2023-02-13 18:24:35 -05:00 committed by Mariusz Felisiak
parent e83a88566a
commit e846c5e724
5 changed files with 50 additions and 0 deletions

View File

@ -1,3 +1,7 @@
from functools import partial
from asgiref.sync import sync_to_async
from django.contrib import auth
from django.contrib.auth import load_backend
from django.contrib.auth.backends import RemoteUserBackend
@ -12,6 +16,12 @@ def get_user(request):
return request._cached_user
async def auser(request):
if not hasattr(request, "_acached_user"):
request._acached_user = await sync_to_async(auth.get_user)(request)
return request._acached_user
class AuthenticationMiddleware(MiddlewareMixin):
def process_request(self, request):
if not hasattr(request, "session"):
@ -23,6 +33,7 @@ class AuthenticationMiddleware(MiddlewareMixin):
"'django.contrib.auth.middleware.AuthenticationMiddleware'."
)
request.user = SimpleLazyObject(lambda: get_user(request))
request.auser = partial(auser, request)
class RemoteUserMiddleware(MiddlewareMixin):

View File

@ -281,9 +281,23 @@ middleware class is listed in :setting:`MIDDLEWARE`.
else:
... # Do something for anonymous users.
The :meth:`auser` method does the same thing but can be used from async
contexts.
Methods
-------
.. method:: HttpRequest.auser()
.. versionadded:: 5.0
From the :class:`~django.contrib.auth.middleware.AuthenticationMiddleware`:
Coroutine. Returns an instance of :setting:`AUTH_USER_MODEL` representing
the currently logged-in user. If the user isn't currently logged in,
``auser`` will return an instance of
:class:`~django.contrib.auth.models.AnonymousUser`. This is similar to the
:attr:`user` attribute but it works in async contexts.
.. method:: HttpRequest.get_host()
Returns the originating host of the request using information from the

View File

@ -65,6 +65,9 @@ Minor features
* The default iteration count for the PBKDF2 password hasher is increased from
600,000 to 720,000.
* ``AuthenticationMiddleware`` now adds an :meth:`.HttpRequest.auser`
asynchronous method that returns the currently logged-in user.
:mod:`django.contrib.contenttypes`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -368,6 +368,7 @@ Django uses :doc:`sessions </topics/http/sessions>` and middleware to hook the
authentication system into :class:`request objects <django.http.HttpRequest>`.
These provide a :attr:`request.user <django.http.HttpRequest.user>` attribute
and a :meth:`request.auser <django.http.HttpRequest.auser>` async method
on every request which represents the current user. If the current user has not
logged in, this attribute will be set to an instance
of :class:`~django.contrib.auth.models.AnonymousUser`, otherwise it will be an
@ -383,6 +384,20 @@ You can tell them apart with
# Do something for anonymous users.
...
Or in an asynchronous view::
user = await request.auser()
if user.is_authenticated:
# Do something for authenticated users.
...
else:
# Do something for anonymous users.
...
.. versionchanged:: 5.0
The :meth:`.HttpRequest.auser` method was added.
.. _how-to-log-a-user-in:
How to log a user in

View File

@ -43,3 +43,10 @@ class TestAuthenticationMiddleware(TestCase):
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
self.middleware(HttpRequest())
async def test_auser(self):
self.middleware(self.request)
auser = await self.request.auser()
self.assertEqual(auser, self.user)
auser_second = await self.request.auser()
self.assertIs(auser, auser_second)