1
0
mirror of https://github.com/django/django.git synced 2024-12-22 09:05:43 +00:00

Fixed #25847 -- Made User.is_(anonymous|authenticated) properties.

This commit is contained in:
Jeremy Lainé 2016-04-02 13:18:26 +02:00 committed by Tim Graham
parent c16b9dd8e0
commit c1aec0feda
27 changed files with 238 additions and 93 deletions

View File

@ -345,6 +345,7 @@ answer newbie questions, and generally made Django that much better:
Jérémie Blaser <blaserje@gmail.com>
Jeremy Carbaugh <jcarbaugh@gmail.com>
Jeremy Dunck <jdunck@gmail.com>
Jeremy Lainé <jeremy.laine@m4x.org>
Jesse Young <adunar@gmail.com>
jhenry <jhenry@theonion.com>
Jim Dalton <jim.dalton@gmail.com>

View File

@ -138,7 +138,7 @@ def logout(request):
# Dispatch the signal before the user is logged out so the receivers have a
# chance to find out *who* logged out.
user = getattr(request, 'user', None)
if hasattr(user, 'is_authenticated') and not user.is_authenticated():
if hasattr(user, 'is_authenticated') and not user.is_authenticated:
user = None
user_logged_out.send(sender=user.__class__, request=request, user=user)

View File

@ -45,7 +45,7 @@ class ModelBackend(object):
be either "group" or "user" to return permissions from
`_get_group_permissions` or `_get_user_permissions` respectively.
"""
if not user_obj.is_active or user_obj.is_anonymous() or obj is not None:
if not user_obj.is_active or user_obj.is_anonymous or obj is not None:
return set()
perm_cache_name = '_%s_perm_cache' % from_name
@ -73,7 +73,7 @@ class ModelBackend(object):
return self._get_permissions(user_obj, obj, 'group')
def get_all_permissions(self, user_obj, obj=None):
if not user_obj.is_active or user_obj.is_anonymous() or obj is not None:
if not user_obj.is_active or user_obj.is_anonymous or obj is not None:
return set()
if not hasattr(user_obj, '_perm_cache'):
user_obj._perm_cache = self.get_user_permissions(user_obj)

View File

@ -10,6 +10,7 @@ from django.contrib.auth.hashers import (
)
from django.db import models
from django.utils.crypto import get_random_string, salted_hmac
from django.utils.deprecation import CallableFalse, CallableTrue
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
@ -79,19 +80,21 @@ class AbstractBaseUser(models.Model):
def natural_key(self):
return (self.get_username(),)
@property
def is_anonymous(self):
"""
Always return False. This is a way of comparing User objects to
anonymous users.
"""
return False
return CallableFalse
@property
def is_authenticated(self):
"""
Always return True. This is a way to tell if the user has been
authenticated in templates.
"""
return True
return CallableTrue
def set_password(self, raw_password):
self.password = make_password(raw_password)

View File

@ -43,7 +43,7 @@ def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login
to the log-in page if necessary.
"""
actual_decorator = user_passes_test(
lambda u: u.is_authenticated(),
lambda u: u.is_authenticated,
login_url=login_url,
redirect_field_name=redirect_field_name
)

View File

@ -70,13 +70,13 @@ class RemoteUserMiddleware(object):
# If specified header doesn't exist then remove any existing
# authenticated remote-user, or return (leaving request.user set to
# AnonymousUser by the AuthenticationMiddleware).
if self.force_logout_if_no_header and request.user.is_authenticated():
if self.force_logout_if_no_header and request.user.is_authenticated:
self._remove_invalid_user(request)
return
# If the user is already authenticated and that user is the user we are
# getting passed in the headers, then the correct user is already
# persisted in the session and we don't need to continue.
if request.user.is_authenticated():
if request.user.is_authenticated:
if request.user.get_username() == self.clean_username(username, request):
return
else:

View File

@ -51,7 +51,7 @@ class LoginRequiredMixin(AccessMixin):
CBV mixin which verifies that the current user is authenticated.
"""
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated():
if not request.user.is_authenticated:
return self.handle_no_permission()
return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)

View File

@ -10,6 +10,7 @@ from django.core.mail import send_mail
from django.db import models
from django.db.models.manager import EmptyManager
from django.utils import six, timezone
from django.utils.deprecation import CallableFalse, CallableTrue
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
@ -438,11 +439,13 @@ class AnonymousUser(object):
def has_module_perms(self, module):
return _user_has_module_perms(self, module)
@property
def is_anonymous(self):
return True
return CallableTrue
@property
def is_authenticated(self):
return False
return CallableFalse
def get_username(self):
return self.username

View File

@ -68,7 +68,7 @@ def login(request, template_name='registration/login.html',
"""
redirect_to = request.POST.get(redirect_field_name, request.GET.get(redirect_field_name, ''))
if redirect_authenticated_user and request.user.is_authenticated():
if redirect_authenticated_user and request.user.is_authenticated:
redirect_to = _get_login_redirect_url(request, redirect_to)
if redirect_to == request.path:
raise ValueError(

View File

@ -33,7 +33,7 @@ class FlatpageNode(template.Node):
# was provided, filter the list to only public flatpages.
if self.user:
user = self.user.resolve(context)
if not user.is_authenticated():
if not user.is_authenticated:
flatpages = flatpages.filter(registration_required=False)
else:
flatpages = flatpages.filter(registration_required=False)

View File

@ -52,7 +52,7 @@ def render_flatpage(request, f):
"""
# If registration is required for accessing this page, and the user isn't
# logged in, redirect to the login page.
if f.registration_required and not request.user.is_authenticated():
if f.registration_required and not request.user.is_authenticated:
from django.contrib.auth.views import redirect_to_login
return redirect_to_login(request.path)
if f.template_name:

View File

@ -79,3 +79,33 @@ class DeprecationInstanceCheck(type):
self.deprecation_warning, 2
)
return super(DeprecationInstanceCheck, self).__instancecheck__(instance)
class CallableBool:
"""
An boolean-like object that is also callable for backwards compatibility.
"""
do_not_call_in_templates = True
def __init__(self, value):
self.value = value
def __bool__(self):
return self.value
def __call__(self):
warnings.warn(
"Using user.is_authenticated() and user.is_anonymous() as a method "
"is deprecated. Remove the parentheses to use it as an attribute.",
RemovedInDjango20Warning, stacklevel=2
)
return self.value
def __nonzero__(self): # Python 2 compatibility
return self.value
def __repr__(self):
return 'CallableBool(%r)' % self.value
CallableFalse = CallableBool(False)
CallableTrue = CallableBool(True)

View File

@ -256,7 +256,7 @@ given view by setting the ``HttpRequest``s ``exception_reporter_filter``
attribute::
def my_view(request):
if request.user.is_authenticated():
if request.user.is_authenticated:
request.exception_reporter_filter = CustomExceptionReporterFilter()
...

View File

@ -147,6 +147,9 @@ details on these changes.
* The shim for supporting custom related manager classes without a
``_apply_rel_filters()`` method will be removed.
* Using ``User.is_authenticated()`` and ``User.is_anonymous()`` as methods
will no longer be supported.
.. _deprecation-removed-in-1.10:
1.10

View File

@ -111,6 +111,41 @@ Fields
A datetime designating when the account was created. Is set to the
current date/time by default when the account is created.
Attributes
----------
.. class:: models.User
.. attribute:: is_authenticated
Read-only attribute which is always ``True`` (as opposed to
``AnonymousUser.is_authenticated`` which is always ``False``). This is
a way to tell if the user has been authenticated. This does not imply
any permissions and doesn't check if the user is active or has a valid
session. Even though normally you will check this attribute on
``request.user`` to find out whether it has been populated by the
:class:`~django.contrib.auth.middleware.AuthenticationMiddleware`
(representing the currently logged-in user), you should know this
attribute is ``True`` for any :class:`~models.User` instance.
.. versionchanged:: 1.10
In older versions, this was a method. Backwards-compatibility
support for using it as a method will be removed in Django 2.0.
.. attribute:: is_anonymous
Read-only attribute which is always ``False``. This is a way of
differentiating :class:`~models.User` and :class:`~models.AnonymousUser`
objects. Generally, you should prefer using
:attr:`~django.contrib.auth.models.User.is_authenticated` to this
attribute.
.. versionchanged:: 1.10
In older versions, this was a method. Backwards-compatibility
support for using it as a method will be removed in Django 2.0.
Methods
-------
@ -119,31 +154,9 @@ Methods
.. method:: get_username()
Returns the username for the user. Since the User model can be swapped
out, you should use this method instead of referencing the username
out, you should use this method instead of referencing the username
attribute directly.
.. method:: is_anonymous()
Always returns ``False``. This is a way of differentiating
:class:`~django.contrib.auth.models.User` and
:class:`~django.contrib.auth.models.AnonymousUser` objects.
Generally, you should prefer using
:meth:`~django.contrib.auth.models.User.is_authenticated()` to this
method.
.. method:: is_authenticated()
Always returns ``True`` (as opposed to
``AnonymousUser.is_authenticated()`` which always returns ``False``).
This is a way to tell if the user has been authenticated. This does not
imply any permissions, and doesn't check if the user is active or has
a valid session. Even though normally you will call this method on
``request.user`` to find out whether it has been populated by the
:class:`~django.contrib.auth.middleware.AuthenticationMiddleware`
(representing the currently logged-in user), you should know this method
returns ``True`` for any :class:`~django.contrib.auth.models.User`
instance.
.. method:: get_full_name()
Returns the :attr:`~django.contrib.auth.models.User.first_name` plus
@ -287,6 +300,10 @@ Manager methods
string.
* :meth:`~django.contrib.auth.models.User.get_username()` always returns
the empty string.
* :attr:`~django.contrib.auth.models.User.is_anonymous` is ``True``
instead of ``False``.
* :attr:`~django.contrib.auth.models.User.is_authenticated` is
``False`` instead of ``True``.
* :attr:`~django.contrib.auth.models.User.is_staff` and
:attr:`~django.contrib.auth.models.User.is_superuser` are always
``False``.
@ -294,10 +311,6 @@ Manager methods
* :attr:`~django.contrib.auth.models.User.groups` and
:attr:`~django.contrib.auth.models.User.user_permissions` are always
empty.
* :meth:`~django.contrib.auth.models.User.is_anonymous()` returns ``True``
instead of ``False``.
* :meth:`~django.contrib.auth.models.User.is_authenticated()` returns
``False`` instead of ``True``.
* :meth:`~django.contrib.auth.models.User.set_password()`,
:meth:`~django.contrib.auth.models.User.check_password()`,
:meth:`~django.db.models.Model.save` and
@ -471,21 +484,21 @@ The following backends are available in :mod:`django.contrib.auth.backends`:
Returns the set of permission strings the ``user_obj`` has from their
own user permissions. Returns an empty set if
:meth:`~django.contrib.auth.models.AbstractBaseUser.is_anonymous` or
:attr:`~django.contrib.auth.models.AbstractBaseUser.is_anonymous` or
:attr:`~django.contrib.auth.models.CustomUser.is_active` is ``False``.
.. method:: get_group_permissions(user_obj, obj=None)
Returns the set of permission strings the ``user_obj`` has from the
permissions of the groups they belong. Returns an empty set if
:meth:`~django.contrib.auth.models.AbstractBaseUser.is_anonymous` or
:attr:`~django.contrib.auth.models.AbstractBaseUser.is_anonymous` or
:attr:`~django.contrib.auth.models.CustomUser.is_active` is ``False``.
.. method:: get_all_permissions(user_obj, obj=None)
Returns the set of permission strings the ``user_obj`` has, including both
user permissions and group permissions. Returns an empty set if
:meth:`~django.contrib.auth.models.AbstractBaseUser.is_anonymous` or
:attr:`~django.contrib.auth.models.AbstractBaseUser.is_anonymous` or
:attr:`~django.contrib.auth.models.CustomUser.is_active` is ``False``.
.. method:: has_perm(user_obj, perm, obj=None)

View File

@ -233,9 +233,9 @@ middleware class is listed in :setting:`MIDDLEWARE_CLASSES`.
logged-in user. If the user isn't currently logged in, ``user`` will be set
to an instance of :class:`~django.contrib.auth.models.AnonymousUser`. You
can tell them apart with
:meth:`~django.contrib.auth.models.User.is_authenticated`, like so::
:attr:`~django.contrib.auth.models.User.is_authenticated`, like so::
if request.user.is_authenticated():
if request.user.is_authenticated:
... # Do something for logged-in users.
else:
... # Do something for anonymous users.

View File

@ -730,6 +730,10 @@ Miscellaneous
* Middleware classes are now initialized when the server starts rather than
during the first request.
* If you override ``is_authenticated()`` or ``is_anonymous()`` in a custom user
model, you must convert them to attributes or properties as described in
:ref:`the deprecation note <user-is-auth-anon-deprecation>`.
.. _deprecated-features-1.10:
Features deprecated in 1.10
@ -857,6 +861,37 @@ features, is deprecated. Replace it with a custom lookup::
models.CharField.register_lookup(Search)
models.TextField.register_lookup(Search)
.. _user-is-auth-anon-deprecation:
Using ``User.is_authenticated()`` and ``User.is_anonymous()`` as methods
------------------------------------------------------------------------
The ``is_authenticated()`` and ``is_anonymous()`` methods of
:class:`~django.contrib.auth.models.AbstractBaseUser` and
:class:`~django.contrib.auth.models.AnonymousUser` classes are now
properties. They will still work as methods until Django 2.0, but all usage
in Django now uses attribute access.
For example, if you use
:class:`~django.contrib.auth.middleware.AuthenticationMiddleware` and want
to know whether the user is currently logged-in you would use::
if request.user.is_authenticated:
... # Do something for logged-in users.
else:
... # Do something for anonymous users.
instead of ``request.user.is_authenticated()``.
This change avoids accidental information leakage if you forget to call the
method, e.g.::
if request.user.is_authenticated:
return sensitive_information
If you override these methods in a custom user model, you must change them to
properties or attributes.
Custom manager classes available through ``prefetch_related`` must define a ``_apply_rel_filters()`` method
-----------------------------------------------------------------------------------------------------------

View File

@ -603,7 +603,7 @@ password resets. You must then provide some key implementation details:
raised a deprecation warning in older versions and is no longer
supported in Django 1.9).
The following methods are available on any subclass of
The following attributes and methods are available on any subclass of
:class:`~django.contrib.auth.models.AbstractBaseUser`:
.. class:: models.AbstractBaseUser
@ -612,20 +612,34 @@ The following methods are available on any subclass of
Returns the value of the field nominated by ``USERNAME_FIELD``.
.. method:: models.AbstractBaseUser.is_anonymous()
.. attribute:: models.AbstractBaseUser.is_authenticated
Always returns ``False``. This is a way of differentiating
from :class:`~django.contrib.auth.models.AnonymousUser` objects.
Generally, you should prefer using
:meth:`~django.contrib.auth.models.AbstractBaseUser.is_authenticated()` to this
method.
Read-only attribute which is always ``True`` (as opposed to
``AnonymousUser.is_authenticated`` which is always ``False``).
This is a way to tell if the user has been authenticated. This does not
imply any permissions and doesn't check if the user is active or has
a valid session. Even though normally you will check this attribute on
``request.user`` to find out whether it has been populated by the
:class:`~django.contrib.auth.middleware.AuthenticationMiddleware`
(representing the currently logged-in user), you should know this
attribute is ``True`` for any :class:`~models.User` instance.
.. method:: models.AbstractBaseUser.is_authenticated()
.. versionchanged:: 1.10
Always returns ``True``. This is a way to tell if the user has been
authenticated. This does not imply any permissions, and doesn't check
if the user is active - it only indicates that the user has provided a
valid username and password.
In older versions, this was a method. Backwards-compatibility
support for using it as a method will be removed in Django 2.0.
.. attribute:: models.AbstractBaseUser.is_anonymous
Read-only attribute which is always ``False``. This is a way of
differentiating :class:`~models.User` and :class:`~models.AnonymousUser`
objects. Generally, you should prefer using
:attr:`~models.User.is_authenticated` to this attribute.
.. versionchanged:: 1.10
In older versions, this was a method. Backwards-compatibility
support for using it as a method will be removed in Django 2.0.
.. method:: models.AbstractBaseUser.set_password(raw_password)

View File

@ -306,9 +306,9 @@ of :class:`~django.contrib.auth.models.AnonymousUser`, otherwise it will be an
instance of :class:`~django.contrib.auth.models.User`.
You can tell them apart with
:meth:`~django.contrib.auth.models.User.is_authenticated()`, like so::
:attr:`~django.contrib.auth.models.User.is_authenticated`, like so::
if request.user.is_authenticated():
if request.user.is_authenticated:
# Do something for authenticated users.
...
else:
@ -421,15 +421,15 @@ The raw way
~~~~~~~~~~~
The simple, raw way to limit access to pages is to check
:meth:`request.user.is_authenticated()
<django.contrib.auth.models.User.is_authenticated()>` and either redirect to a
:attr:`request.user.is_authenticated
<django.contrib.auth.models.User.is_authenticated>` and either redirect to a
login page::
from django.conf import settings
from django.shortcuts import redirect
def my_view(request):
if not request.user.is_authenticated():
if not request.user.is_authenticated:
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
# ...
@ -438,7 +438,7 @@ login page::
from django.shortcuts import render
def my_view(request):
if not request.user.is_authenticated():
if not request.user.is_authenticated:
return render(request, 'myapp/login_error.html')
# ...

View File

@ -1170,7 +1170,7 @@ decorator)::
@vary_on_cookie
def list_blog_entries_view(request):
if request.user.is_anonymous():
if request.user.is_anonymous:
response = render_only_public_entries()
patch_cache_control(response, public=True)
else:

View File

@ -235,7 +235,7 @@ We'll demonstrate this with the ``Author`` model we used in the
model = Author
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated():
if not request.user.is_authenticated:
return HttpResponseForbidden()
# Look up the author we're interested in.
@ -466,7 +466,7 @@ Our new ``AuthorDetail`` looks like this::
return context
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated():
if not request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
form = self.get_form()
@ -552,7 +552,7 @@ template as ``AuthorDisplay`` is using on ``GET``::
model = Author
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated():
if not request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
return super(AuthorInterest, self).post(request, *args, **kwargs)

View File

@ -12,7 +12,7 @@ from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.http import HttpRequest
from django.test import (
SimpleTestCase, TestCase, modify_settings, override_settings,
SimpleTestCase, TestCase, mock, modify_settings, override_settings,
)
from .models import (
@ -142,11 +142,10 @@ class BaseModelBackendTest(object):
self.assertEqual(backend.get_user_permissions(user), {'auth.test_user', 'auth.test_group'})
self.assertEqual(backend.get_group_permissions(user), {'auth.test_group'})
user.is_anonymous = lambda: True
self.assertEqual(backend.get_all_permissions(user), set())
self.assertEqual(backend.get_user_permissions(user), set())
self.assertEqual(backend.get_group_permissions(user), set())
with mock.patch.object(self.UserModel, 'is_anonymous', True):
self.assertEqual(backend.get_all_permissions(user), set())
self.assertEqual(backend.get_user_permissions(user), set())
self.assertEqual(backend.get_group_permissions(user), set())
def test_inactive_has_no_permissions(self):
"""
@ -334,14 +333,14 @@ class SimpleRowlevelBackend(object):
if isinstance(obj, TestObj):
if user.username == 'test2':
return True
elif user.is_anonymous() and perm == 'anon':
elif user.is_anonymous and perm == 'anon':
return True
elif not user.is_active and perm == 'inactive':
return True
return False
def has_module_perms(self, user, app_label):
if not user.is_anonymous() and not user.is_active:
if not user.is_anonymous and not user.is_active:
return False
return app_label == "app1"
@ -352,7 +351,7 @@ class SimpleRowlevelBackend(object):
if not isinstance(obj, TestObj):
return ['none']
if user.is_anonymous():
if user.is_anonymous:
return ['anon']
if user.username == 'test2':
return ['simple', 'advanced']
@ -578,7 +577,7 @@ class ChangedBackendSettingsTest(TestCase):
# Assert that the user retrieval is successful and the user is
# anonymous as the backend is not longer available.
self.assertIsNotNone(user)
self.assertTrue(user.is_anonymous())
self.assertTrue(user.is_anonymous)
class TypeErrorBackend(object):

View File

@ -1,5 +1,7 @@
from __future__ import unicode_literals
import warnings
from django.apps import apps
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser, User
@ -44,7 +46,8 @@ class BasicTestCase(TestCase):
self.assertEqual(u.get_username(), 'testuser')
# Check authentication/permissions
self.assertTrue(u.is_authenticated())
self.assertFalse(u.is_anonymous)
self.assertTrue(u.is_authenticated)
self.assertFalse(u.is_staff)
self.assertTrue(u.is_active)
self.assertFalse(u.is_superuser)
@ -53,6 +56,26 @@ class BasicTestCase(TestCase):
u2 = User.objects.create_user('testuser2', 'test2@example.com')
self.assertFalse(u2.has_usable_password())
def test_is_anonymous_authenticated_method_deprecation(self):
deprecation_message = (
'Using user.is_authenticated() and user.is_anonymous() as a '
'method is deprecated. Remove the parentheses to use it as an '
'attribute.'
)
u = User.objects.create_user('testuser', 'test@example.com', 'testpw')
# Backwards-compatibility callables
with warnings.catch_warnings(record=True) as warns:
warnings.simplefilter('always')
self.assertFalse(u.is_anonymous())
self.assertEqual(len(warns), 1)
self.assertEqual(str(warns[0].message), deprecation_message)
with warnings.catch_warnings(record=True) as warns:
warnings.simplefilter('always')
self.assertTrue(u.is_authenticated())
self.assertEqual(len(warns), 1)
self.assertEqual(str(warns[0].message), deprecation_message)
def test_user_no_email(self):
"Check that users can be created without an email"
u = User.objects.create_user('testuser1')
@ -70,13 +93,34 @@ class BasicTestCase(TestCase):
self.assertEqual(a.pk, None)
self.assertEqual(a.username, '')
self.assertEqual(a.get_username(), '')
self.assertFalse(a.is_authenticated())
self.assertTrue(a.is_anonymous)
self.assertFalse(a.is_authenticated)
self.assertFalse(a.is_staff)
self.assertFalse(a.is_active)
self.assertFalse(a.is_superuser)
self.assertEqual(a.groups.all().count(), 0)
self.assertEqual(a.user_permissions.all().count(), 0)
def test_anonymous_user_is_anonymous_authenticated_method_deprecation(self):
a = AnonymousUser()
deprecation_message = (
'Using user.is_authenticated() and user.is_anonymous() as a '
'method is deprecated. Remove the parentheses to use it as an '
'attribute.'
)
# Backwards-compatibility callables
with warnings.catch_warnings(record=True) as warns:
warnings.simplefilter('always') # prevent warnings from appearing as errors
self.assertTrue(a.is_anonymous())
self.assertEqual(len(warns), 1)
self.assertEqual(str(warns[0].message), deprecation_message)
with warnings.catch_warnings(record=True) as warns:
warnings.simplefilter('always') # prevent warnings from appearing as errors
self.assertFalse(a.is_authenticated())
self.assertEqual(len(warns), 1)
self.assertEqual(str(warns[0].message), deprecation_message)
def test_superuser(self):
"Check the creation and properties of a superuser"
super = User.objects.create_superuser('super', 'super@example.com', 'super')

View File

@ -16,7 +16,7 @@ class TestAuthenticationMiddleware(TestCase):
self.request.session = self.client.session
self.middleware.process_request(self.request)
self.assertIsNotNone(self.request.user)
self.assertFalse(self.request.user.is_anonymous())
self.assertFalse(self.request.user.is_anonymous)
def test_changed_password_invalidates_session(self):
# After password change, user should be anonymous
@ -24,6 +24,6 @@ class TestAuthenticationMiddleware(TestCase):
self.user.save()
self.middleware.process_request(self.request)
self.assertIsNotNone(self.request.user)
self.assertTrue(self.request.user.is_anonymous())
self.assertTrue(self.request.user.is_anonymous)
# session should be flushed
self.assertIsNone(self.request.session.session_key)

View File

@ -5,7 +5,7 @@ from django.contrib.auth.mixins import (
from django.contrib.auth.models import AnonymousUser
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.test import RequestFactory, TestCase
from django.test import RequestFactory, TestCase, mock
from django.views.generic import View
@ -78,9 +78,9 @@ class AccessMixinTests(TestCase):
with self.assertRaises(PermissionDenied):
view(request)
@mock.patch.object(models.User, 'is_authenticated', False)
def test_stacked_mixins_not_logged_in(self):
user = models.User.objects.create(username='joe', password='qwerty')
user.is_authenticated = lambda: False
perms = models.Permission.objects.filter(codename__in=('add_customuser', 'change_customuser'))
user.user_permissions.add(*perms)
request = self.factory.get('/rand')

View File

@ -38,15 +38,15 @@ class RemoteUserTest(TestCase):
num_users = User.objects.count()
response = self.client.get('/remote_user/')
self.assertTrue(response.context['user'].is_anonymous())
self.assertTrue(response.context['user'].is_anonymous)
self.assertEqual(User.objects.count(), num_users)
response = self.client.get('/remote_user/', **{self.header: None})
self.assertTrue(response.context['user'].is_anonymous())
self.assertTrue(response.context['user'].is_anonymous)
self.assertEqual(User.objects.count(), num_users)
response = self.client.get('/remote_user/', **{self.header: ''})
self.assertTrue(response.context['user'].is_anonymous())
self.assertTrue(response.context['user'].is_anonymous)
self.assertEqual(User.objects.count(), num_users)
def test_unknown_user(self):
@ -118,7 +118,7 @@ class RemoteUserTest(TestCase):
self.assertEqual(response.context['user'].username, 'knownuser')
# During the session, the REMOTE_USER header disappears. Should trigger logout.
response = self.client.get('/remote_user/')
self.assertEqual(response.context['user'].is_anonymous(), True)
self.assertTrue(response.context['user'].is_anonymous)
# verify the remoteuser middleware will not remove a user
# authenticated via another backend
User.objects.create_user(username='modeluser', password='foo')
@ -148,7 +148,7 @@ class RemoteUserTest(TestCase):
def test_inactive_user(self):
User.objects.create(username='knownuser', is_active=False)
response = self.client.get('/remote_user/', **{self.header: 'knownuser'})
self.assertTrue(response.context['user'].is_anonymous())
self.assertTrue(response.context['user'].is_anonymous)
class RemoteUserNoCreateBackend(RemoteUserBackend):
@ -167,7 +167,7 @@ class RemoteUserNoCreateTest(RemoteUserTest):
def test_unknown_user(self):
num_users = User.objects.count()
response = self.client.get('/remote_user/', **{self.header: 'newuser'})
self.assertTrue(response.context['user'].is_anonymous())
self.assertTrue(response.context['user'].is_anonymous)
self.assertEqual(User.objects.count(), num_users)
@ -268,5 +268,5 @@ class PersistentRemoteUserTest(RemoteUserTest):
self.assertEqual(response.context['user'].username, 'knownuser')
# Should stay logged in if the REMOTE_USER header disappears.
response = self.client.get('/remote_user/')
self.assertEqual(response.context['user'].is_anonymous(), False)
self.assertFalse(response.context['user'].is_anonymous)
self.assertEqual(response.context['user'].username, 'knownuser')

View File

@ -45,7 +45,7 @@ class LazyRedirectView(RedirectView):
url = reverse_lazy('named-lazy-url-redirected-to')
@user_passes_test(lambda u: u.is_authenticated(), login_url=reverse_lazy('some-login-page'))
@user_passes_test(lambda u: u.is_authenticated, login_url=reverse_lazy('some-login-page'))
def login_required_view(request):
return HttpResponse('Hello you')