1
0
mirror of https://github.com/django/django.git synced 2025-10-31 09:41:08 +00:00

Refs #33476 -- Reformatted code with Black.

This commit is contained in:
django-bot
2022-02-03 20:24:19 +01:00
committed by Mariusz Felisiak
parent f68fa8b45d
commit 9c19aff7c7
1992 changed files with 139577 additions and 96284 deletions

View File

@@ -1,4 +1,4 @@
# For testing that auth backends can be referenced using a convenience import
from .test_auth_backends import ImportedModelBackend
__all__ = ['ImportedModelBackend']
__all__ = ["ImportedModelBackend"]

View File

@@ -1,13 +1,14 @@
import re
from django.contrib.auth.views import (
INTERNAL_RESET_SESSION_TOKEN, PasswordResetConfirmView,
INTERNAL_RESET_SESSION_TOKEN,
PasswordResetConfirmView,
)
from django.test import Client
def extract_token_from_url(url):
token_search = re.search(r'/reset/.*/(.+?)/', url)
token_search = re.search(r"/reset/.*/(.+?)/", url)
if token_search:
return token_search[1]
@@ -22,6 +23,7 @@ class PasswordResetConfirmClient(Client):
>>> client = PasswordResetConfirmClient()
>>> client.get('/reset/bla/my-token/')
"""
reset_url_token = PasswordResetConfirmView.reset_url_token
def _get_password_reset_confirm_redirect_url(self, url):

View File

@@ -1,7 +1,5 @@
from .custom_permissions import CustomPermissionsUser
from .custom_user import (
CustomUser, CustomUserWithoutIsActiveField, ExtensionUser,
)
from .custom_user import CustomUser, CustomUserWithoutIsActiveField, ExtensionUser
from .invalid_models import CustomUserNonUniqueUsername
from .is_active import IsActiveTestUser1
from .minimal import MinimalUser
@@ -12,15 +10,26 @@ from .with_custom_email_field import CustomEmailField
from .with_foreign_key import CustomUserWithFK, Email
from .with_integer_username import IntegerUsernameUser
from .with_last_login_attr import UserWithDisabledLastLoginField
from .with_many_to_many import (
CustomUserWithM2M, CustomUserWithM2MThrough, Organization,
)
from .with_many_to_many import CustomUserWithM2M, CustomUserWithM2MThrough, Organization
__all__ = (
'CustomEmailField', 'CustomPermissionsUser', 'CustomUser',
'CustomUserNonUniqueUsername', 'CustomUserWithFK', 'CustomUserWithM2M',
'CustomUserWithM2MThrough', 'CustomUserWithoutIsActiveField', 'Email',
'ExtensionUser', 'IntegerUsernameUser', 'IsActiveTestUser1', 'MinimalUser',
'NoPasswordUser', 'Organization', 'Proxy', 'UUIDUser', 'UserProxy',
'UserWithDisabledLastLoginField',
"CustomEmailField",
"CustomPermissionsUser",
"CustomUser",
"CustomUserNonUniqueUsername",
"CustomUserWithFK",
"CustomUserWithM2M",
"CustomUserWithM2MThrough",
"CustomUserWithoutIsActiveField",
"Email",
"ExtensionUser",
"IntegerUsernameUser",
"IsActiveTestUser1",
"MinimalUser",
"NoPasswordUser",
"Organization",
"Proxy",
"UUIDUser",
"UserProxy",
"UserWithDisabledLastLoginField",
)

View File

@@ -18,14 +18,17 @@ class CustomPermissionsUserManager(CustomUserManager):
with RemoveGroupsAndPermissions():
class CustomPermissionsUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(verbose_name='email address', max_length=255, unique=True)
email = models.EmailField(
verbose_name="email address", max_length=255, unique=True
)
date_of_birth = models.DateField()
custom_objects = CustomPermissionsUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['date_of_birth']
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["date_of_birth"]
def __str__(self):
return self.email

View File

@@ -1,6 +1,11 @@
from django.contrib.auth.models import (
AbstractBaseUser, AbstractUser, BaseUserManager, Group, Permission,
PermissionsMixin, UserManager,
AbstractBaseUser,
AbstractUser,
BaseUserManager,
Group,
Permission,
PermissionsMixin,
UserManager,
)
from django.db import models
@@ -14,12 +19,10 @@ class CustomUserManager(BaseUserManager):
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('Users must have an email address')
raise ValueError("Users must have an email address")
user = self.model(
email=self.normalize_email(email),
date_of_birth=date_of_birth,
**fields
email=self.normalize_email(email), date_of_birth=date_of_birth, **fields
)
user.set_password(password)
@@ -27,14 +30,16 @@ class CustomUserManager(BaseUserManager):
return user
def create_superuser(self, email, password, date_of_birth, **fields):
u = self.create_user(email, password=password, date_of_birth=date_of_birth, **fields)
u = self.create_user(
email, password=password, date_of_birth=date_of_birth, **fields
)
u.is_admin = True
u.save(using=self._db)
return u
class CustomUser(AbstractBaseUser):
email = models.EmailField(verbose_name='email address', max_length=255, unique=True)
email = models.EmailField(verbose_name="email address", max_length=255, unique=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
date_of_birth = models.DateField()
@@ -42,8 +47,8 @@ class CustomUser(AbstractBaseUser):
custom_objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['date_of_birth', 'first_name']
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["date_of_birth", "first_name"]
def __str__(self):
return self.email
@@ -76,6 +81,7 @@ class RemoveGroupsAndPermissions:
fields from the AbstractUser class, so they don't clash with the
related_name sets.
"""
def __enter__(self):
self._old_au_local_m2m = AbstractUser._meta.local_many_to_many
self._old_pm_local_m2m = PermissionsMixin._meta.local_many_to_many
@@ -97,16 +103,17 @@ class CustomUserWithoutIsActiveField(AbstractBaseUser):
objects = UserManager()
USERNAME_FIELD = 'username'
USERNAME_FIELD = "username"
# The extension user is a simple extension of the built-in user class,
# adding a required date_of_birth field. This allows us to check for
# any hard references to the name "User" in forms/handlers etc.
with RemoveGroupsAndPermissions():
class ExtensionUser(AbstractUser):
date_of_birth = models.DateField()
custom_objects = UserManager()
REQUIRED_FIELDS = AbstractUser.REQUIRED_FIELDS + ['date_of_birth']
REQUIRED_FIELDS = AbstractUser.REQUIRED_FIELDS + ["date_of_birth"]

View File

@@ -9,12 +9,13 @@ class CustomUserNonUniqueUsername(AbstractBaseUser):
This model is not invalid if it is used with a custom authentication
backend which supports non-unique usernames.
"""
username = models.CharField(max_length=30)
email = models.EmailField(blank=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ["email"]
objects = UserManager()

View File

@@ -6,10 +6,11 @@ class IsActiveTestUser1(AbstractBaseUser):
"""
This test user class and derivatives test the default is_active behavior
"""
username = models.CharField(max_length=30, unique=True)
custom_objects = BaseUserManager()
USERNAME_FIELD = 'username'
USERNAME_FIELD = "username"
# the is_active attr is provided by AbstractBaseUser

View File

@@ -3,4 +3,4 @@ from django.db import models
class MinimalUser(models.Model):
REQUIRED_FIELDS = ()
USERNAME_FIELD = 'id'
USERNAME_FIELD = "id"

View File

@@ -17,5 +17,5 @@ class NoPasswordUser(AbstractBaseUser):
last_login = None
username = models.CharField(max_length=50, unique=True)
USERNAME_FIELD = 'username'
USERNAME_FIELD = "username"
objects = UserManager()

View File

@@ -9,14 +9,10 @@ class Concrete(models.Model):
class Proxy(Concrete):
class Meta:
proxy = True
permissions = (
('display_proxys', 'May display proxys information'),
)
permissions = (("display_proxys", "May display proxys information"),)
class UserProxy(User):
class Meta:
proxy = True
permissions = (
('use_different_app_label', 'May use a different app label'),
)
permissions = (("use_different_app_label", "May use a different app label"),)

View File

@@ -6,6 +6,8 @@ from django.db import models
from .custom_user import RemoveGroupsAndPermissions
with RemoveGroupsAndPermissions():
class UUIDUser(AbstractUser):
"""A user with a UUID as primary key"""
id = models.UUIDField(default=uuid.uuid4, primary_key=True)

View File

@@ -18,7 +18,7 @@ class CustomEmailField(AbstractBaseUser):
email_address = models.EmailField(null=True)
is_active = models.BooleanField(default=True)
EMAIL_FIELD = 'email_address'
USERNAME_FIELD = 'username'
EMAIL_FIELD = "email_address"
USERNAME_FIELD = "username"
objects = CustomEmailFieldUserManager()

View File

@@ -3,7 +3,7 @@ from django.db import models
class Email(models.Model):
email = models.EmailField(verbose_name='email address', max_length=255, unique=True)
email = models.EmailField(verbose_name="email address", max_length=255, unique=True)
class CustomUserWithFKManager(BaseUserManager):
@@ -15,11 +15,13 @@ class CustomUserWithFKManager(BaseUserManager):
class CustomUserWithFK(AbstractBaseUser):
username = models.ForeignKey(Email, models.CASCADE, related_name='primary')
email = models.ForeignKey(Email, models.CASCADE, to_field='email', related_name='secondary')
username = models.ForeignKey(Email, models.CASCADE, related_name="primary")
email = models.ForeignKey(
Email, models.CASCADE, to_field="email", related_name="secondary"
)
group = models.ForeignKey(Group, models.CASCADE)
custom_objects = CustomUserWithFKManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email', 'group']
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ["email", "group"]

View File

@@ -17,7 +17,7 @@ class IntegerUsernameUser(AbstractBaseUser):
username = models.IntegerField()
password = models.CharField(max_length=255)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['username', 'password']
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ["username", "password"]
objects = IntegerUsernameUserManager()

View File

@@ -21,18 +21,18 @@ class CustomUserWithM2M(AbstractBaseUser):
custom_objects = CustomUserWithM2MManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['orgs']
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ["orgs"]
class CustomUserWithM2MThrough(AbstractBaseUser):
username = models.CharField(max_length=30, unique=True)
orgs = models.ManyToManyField(Organization, through='Membership')
orgs = models.ManyToManyField(Organization, through="Membership")
custom_objects = CustomUserWithM2MManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['orgs']
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ["orgs"]
class Membership(models.Model):

View File

@@ -1,19 +1,21 @@
import os
AUTH_MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
"django.contrib.sessions.middleware.SessionMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
]
AUTH_TEMPLATES = [{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(os.path.dirname(__file__), 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
}]
AUTH_TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [os.path.join(os.path.dirname(__file__), "templates")],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
}
]

View File

@@ -16,17 +16,17 @@ class Router:
db_for_write = db_for_read
site = admin.AdminSite(name='test_adminsite')
site = admin.AdminSite(name="test_adminsite")
site.register(User, admin_class=UserAdmin)
urlpatterns = [
path('admin/', site.urls),
path("admin/", site.urls),
]
@override_settings(ROOT_URLCONF=__name__, DATABASE_ROUTERS=['%s.Router' % __name__])
@override_settings(ROOT_URLCONF=__name__, DATABASE_ROUTERS=["%s.Router" % __name__])
class MultiDatabaseTests(TestCase):
databases = {'default', 'other'}
databases = {"default", "other"}
@classmethod
def setUpTestData(cls):
@@ -34,18 +34,23 @@ class MultiDatabaseTests(TestCase):
for db in cls.databases:
Router.target_db = db
cls.superusers[db] = User.objects.create_superuser(
username='admin', password='something', email='test@test.org',
username="admin",
password="something",
email="test@test.org",
)
@mock.patch('django.contrib.auth.admin.transaction')
@mock.patch("django.contrib.auth.admin.transaction")
def test_add_view(self, mock):
for db in self.databases:
with self.subTest(db_connection=db):
Router.target_db = db
self.client.force_login(self.superusers[db])
self.client.post(reverse('test_adminsite:auth_user_add'), {
'username': 'some_user',
'password1': 'helloworld',
'password2': 'helloworld',
})
self.client.post(
reverse("test_adminsite:auth_user_add"),
{
"username": "some_user",
"password1": "helloworld",
"password2": "helloworld",
},
)
mock.atomic.assert_called_with(using=db)

View File

@@ -3,8 +3,12 @@ from datetime import date
from unittest import mock
from django.contrib.auth import (
BACKEND_SESSION_KEY, SESSION_KEY, _clean_credentials, authenticate,
get_user, signals,
BACKEND_SESSION_KEY,
SESSION_KEY,
_clean_credentials,
authenticate,
get_user,
signals,
)
from django.contrib.auth.backends import BaseBackend, ModelBackend
from django.contrib.auth.hashers import MD5PasswordHasher
@@ -13,50 +17,58 @@ from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.http import HttpRequest
from django.test import (
RequestFactory, SimpleTestCase, TestCase, modify_settings,
RequestFactory,
SimpleTestCase,
TestCase,
modify_settings,
override_settings,
)
from django.views.debug import technical_500_response
from django.views.decorators.debug import sensitive_variables
from .models import (
CustomPermissionsUser, CustomUser, CustomUserWithoutIsActiveField,
ExtensionUser, UUIDUser,
CustomPermissionsUser,
CustomUser,
CustomUserWithoutIsActiveField,
ExtensionUser,
UUIDUser,
)
class SimpleBackend(BaseBackend):
def get_user_permissions(self, user_obj, obj=None):
return ['user_perm']
return ["user_perm"]
def get_group_permissions(self, user_obj, obj=None):
return ['group_perm']
return ["group_perm"]
@override_settings(AUTHENTICATION_BACKENDS=['auth_tests.test_auth_backends.SimpleBackend'])
@override_settings(
AUTHENTICATION_BACKENDS=["auth_tests.test_auth_backends.SimpleBackend"]
)
class BaseBackendTest(TestCase):
@classmethod
def setUpTestData(cls):
cls.user = User.objects.create_user('test', 'test@example.com', 'test')
cls.user = User.objects.create_user("test", "test@example.com", "test")
def test_get_user_permissions(self):
self.assertEqual(self.user.get_user_permissions(), {'user_perm'})
self.assertEqual(self.user.get_user_permissions(), {"user_perm"})
def test_get_group_permissions(self):
self.assertEqual(self.user.get_group_permissions(), {'group_perm'})
self.assertEqual(self.user.get_group_permissions(), {"group_perm"})
def test_get_all_permissions(self):
self.assertEqual(self.user.get_all_permissions(), {'user_perm', 'group_perm'})
self.assertEqual(self.user.get_all_permissions(), {"user_perm", "group_perm"})
def test_has_perm(self):
self.assertIs(self.user.has_perm('user_perm'), True)
self.assertIs(self.user.has_perm('group_perm'), True)
self.assertIs(self.user.has_perm('other_perm', TestObj()), False)
self.assertIs(self.user.has_perm("user_perm"), True)
self.assertIs(self.user.has_perm("group_perm"), True)
self.assertIs(self.user.has_perm("other_perm", TestObj()), False)
def test_has_perms_perm_list_invalid(self):
msg = 'perm_list must be an iterable of permissions.'
msg = "perm_list must be an iterable of permissions."
with self.assertRaisesMessage(ValueError, msg):
self.user.has_perms('user_perm')
self.user.has_perms("user_perm")
with self.assertRaisesMessage(ValueError, msg):
self.user.has_perms(object())
@@ -78,11 +90,12 @@ class BaseModelBackendTest:
level UserModel attribute, and a create_users() method to
construct two users for test purposes.
"""
backend = 'django.contrib.auth.backends.ModelBackend'
backend = "django.contrib.auth.backends.ModelBackend"
def setUp(self):
self.patched_settings = modify_settings(
AUTHENTICATION_BACKENDS={'append': self.backend},
AUTHENTICATION_BACKENDS={"append": self.backend},
)
self.patched_settings.enable()
self.create_users()
@@ -96,72 +109,84 @@ class BaseModelBackendTest:
def test_has_perm(self):
user = self.UserModel._default_manager.get(pk=self.user.pk)
self.assertIs(user.has_perm('auth.test'), False)
self.assertIs(user.has_perm("auth.test"), False)
user.is_staff = True
user.save()
self.assertIs(user.has_perm('auth.test'), False)
self.assertIs(user.has_perm("auth.test"), False)
user.is_superuser = True
user.save()
self.assertIs(user.has_perm('auth.test'), True)
self.assertIs(user.has_perm("auth.test"), True)
user.is_staff = True
user.is_superuser = True
user.is_active = False
user.save()
self.assertIs(user.has_perm('auth.test'), False)
self.assertIs(user.has_perm("auth.test"), False)
def test_custom_perms(self):
user = self.UserModel._default_manager.get(pk=self.user.pk)
content_type = ContentType.objects.get_for_model(Group)
perm = Permission.objects.create(name='test', content_type=content_type, codename='test')
perm = Permission.objects.create(
name="test", content_type=content_type, codename="test"
)
user.user_permissions.add(perm)
# reloading user to purge the _perm_cache
user = self.UserModel._default_manager.get(pk=self.user.pk)
self.assertEqual(user.get_all_permissions(), {'auth.test'})
self.assertEqual(user.get_user_permissions(), {'auth.test'})
self.assertEqual(user.get_all_permissions(), {"auth.test"})
self.assertEqual(user.get_user_permissions(), {"auth.test"})
self.assertEqual(user.get_group_permissions(), set())
self.assertIs(user.has_module_perms('Group'), False)
self.assertIs(user.has_module_perms('auth'), True)
self.assertIs(user.has_module_perms("Group"), False)
self.assertIs(user.has_module_perms("auth"), True)
perm = Permission.objects.create(name='test2', content_type=content_type, codename='test2')
perm = Permission.objects.create(
name="test2", content_type=content_type, codename="test2"
)
user.user_permissions.add(perm)
perm = Permission.objects.create(name='test3', content_type=content_type, codename='test3')
perm = Permission.objects.create(
name="test3", content_type=content_type, codename="test3"
)
user.user_permissions.add(perm)
user = self.UserModel._default_manager.get(pk=self.user.pk)
expected_user_perms = {'auth.test2', 'auth.test', 'auth.test3'}
expected_user_perms = {"auth.test2", "auth.test", "auth.test3"}
self.assertEqual(user.get_all_permissions(), expected_user_perms)
self.assertIs(user.has_perm('test'), False)
self.assertIs(user.has_perm('auth.test'), True)
self.assertIs(user.has_perms(['auth.test2', 'auth.test3']), True)
self.assertIs(user.has_perm("test"), False)
self.assertIs(user.has_perm("auth.test"), True)
self.assertIs(user.has_perms(["auth.test2", "auth.test3"]), True)
perm = Permission.objects.create(name='test_group', content_type=content_type, codename='test_group')
group = Group.objects.create(name='test_group')
perm = Permission.objects.create(
name="test_group", content_type=content_type, codename="test_group"
)
group = Group.objects.create(name="test_group")
group.permissions.add(perm)
user.groups.add(group)
user = self.UserModel._default_manager.get(pk=self.user.pk)
self.assertEqual(user.get_all_permissions(), {*expected_user_perms, 'auth.test_group'})
self.assertEqual(
user.get_all_permissions(), {*expected_user_perms, "auth.test_group"}
)
self.assertEqual(user.get_user_permissions(), expected_user_perms)
self.assertEqual(user.get_group_permissions(), {'auth.test_group'})
self.assertIs(user.has_perms(['auth.test3', 'auth.test_group']), True)
self.assertEqual(user.get_group_permissions(), {"auth.test_group"})
self.assertIs(user.has_perms(["auth.test3", "auth.test_group"]), True)
user = AnonymousUser()
self.assertIs(user.has_perm('test'), False)
self.assertIs(user.has_perms(['auth.test2', 'auth.test3']), False)
self.assertIs(user.has_perm("test"), False)
self.assertIs(user.has_perms(["auth.test2", "auth.test3"]), False)
def test_has_no_object_perm(self):
"""Regressiontest for #12462"""
user = self.UserModel._default_manager.get(pk=self.user.pk)
content_type = ContentType.objects.get_for_model(Group)
perm = Permission.objects.create(name='test', content_type=content_type, codename='test')
perm = Permission.objects.create(
name="test", content_type=content_type, codename="test"
)
user.user_permissions.add(perm)
self.assertIs(user.has_perm('auth.test', 'object'), False)
self.assertEqual(user.get_all_permissions('object'), set())
self.assertIs(user.has_perm('auth.test'), True)
self.assertEqual(user.get_all_permissions(), {'auth.test'})
self.assertIs(user.has_perm("auth.test", "object"), False)
self.assertEqual(user.get_all_permissions("object"), set())
self.assertIs(user.has_perm("auth.test"), True)
self.assertEqual(user.get_all_permissions(), {"auth.test"})
def test_anonymous_has_no_permissions(self):
"""
@@ -172,19 +197,25 @@ class BaseModelBackendTest:
user = self.UserModel._default_manager.get(pk=self.user.pk)
content_type = ContentType.objects.get_for_model(Group)
user_perm = Permission.objects.create(name='test', content_type=content_type, codename='test_user')
group_perm = Permission.objects.create(name='test2', content_type=content_type, codename='test_group')
user_perm = Permission.objects.create(
name="test", content_type=content_type, codename="test_user"
)
group_perm = Permission.objects.create(
name="test2", content_type=content_type, codename="test_group"
)
user.user_permissions.add(user_perm)
group = Group.objects.create(name='test_group')
group = Group.objects.create(name="test_group")
user.groups.add(group)
group.permissions.add(group_perm)
self.assertEqual(backend.get_all_permissions(user), {'auth.test_user', 'auth.test_group'})
self.assertEqual(backend.get_user_permissions(user), {'auth.test_user'})
self.assertEqual(backend.get_group_permissions(user), {'auth.test_group'})
self.assertEqual(
backend.get_all_permissions(user), {"auth.test_user", "auth.test_group"}
)
self.assertEqual(backend.get_user_permissions(user), {"auth.test_user"})
self.assertEqual(backend.get_group_permissions(user), {"auth.test_group"})
with mock.patch.object(self.UserModel, 'is_anonymous', True):
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())
@@ -198,17 +229,23 @@ class BaseModelBackendTest:
user = self.UserModel._default_manager.get(pk=self.user.pk)
content_type = ContentType.objects.get_for_model(Group)
user_perm = Permission.objects.create(name='test', content_type=content_type, codename='test_user')
group_perm = Permission.objects.create(name='test2', content_type=content_type, codename='test_group')
user_perm = Permission.objects.create(
name="test", content_type=content_type, codename="test_user"
)
group_perm = Permission.objects.create(
name="test2", content_type=content_type, codename="test_group"
)
user.user_permissions.add(user_perm)
group = Group.objects.create(name='test_group')
group = Group.objects.create(name="test_group")
user.groups.add(group)
group.permissions.add(group_perm)
self.assertEqual(backend.get_all_permissions(user), {'auth.test_user', 'auth.test_group'})
self.assertEqual(backend.get_user_permissions(user), {'auth.test_user'})
self.assertEqual(backend.get_group_permissions(user), {'auth.test_group'})
self.assertEqual(
backend.get_all_permissions(user), {"auth.test_user", "auth.test_group"}
)
self.assertEqual(backend.get_user_permissions(user), {"auth.test_user"})
self.assertEqual(backend.get_group_permissions(user), {"auth.test_group"})
user.is_active = False
user.save()
@@ -222,29 +259,33 @@ class BaseModelBackendTest:
user = self.UserModel._default_manager.get(pk=self.superuser.pk)
self.assertEqual(len(user.get_all_permissions()), len(Permission.objects.all()))
@override_settings(PASSWORD_HASHERS=['auth_tests.test_auth_backends.CountingMD5PasswordHasher'])
@override_settings(
PASSWORD_HASHERS=["auth_tests.test_auth_backends.CountingMD5PasswordHasher"]
)
def test_authentication_timing(self):
"""Hasher is run once regardless of whether the user exists. Refs #20760."""
# Re-set the password, because this tests overrides PASSWORD_HASHERS
self.user.set_password('test')
self.user.set_password("test")
self.user.save()
CountingMD5PasswordHasher.calls = 0
username = getattr(self.user, self.UserModel.USERNAME_FIELD)
authenticate(username=username, password='test')
authenticate(username=username, password="test")
self.assertEqual(CountingMD5PasswordHasher.calls, 1)
CountingMD5PasswordHasher.calls = 0
authenticate(username='no_such_user', password='test')
authenticate(username="no_such_user", password="test")
self.assertEqual(CountingMD5PasswordHasher.calls, 1)
@override_settings(PASSWORD_HASHERS=['auth_tests.test_auth_backends.CountingMD5PasswordHasher'])
@override_settings(
PASSWORD_HASHERS=["auth_tests.test_auth_backends.CountingMD5PasswordHasher"]
)
def test_authentication_without_credentials(self):
CountingMD5PasswordHasher.calls = 0
for credentials in (
{},
{'username': getattr(self.user, self.UserModel.USERNAME_FIELD)},
{'password': 'test'},
{"username": getattr(self.user, self.UserModel.USERNAME_FIELD)},
{"password": "test"},
):
with self.subTest(credentials=credentials):
with self.assertNumQueries(0):
@@ -256,15 +297,18 @@ class ModelBackendTest(BaseModelBackendTest, TestCase):
"""
Tests for the ModelBackend using the default User model.
"""
UserModel = User
user_credentials = {'username': 'test', 'password': 'test'}
user_credentials = {"username": "test", "password": "test"}
def create_users(self):
self.user = User.objects.create_user(email='test@example.com', **self.user_credentials)
self.user = User.objects.create_user(
email="test@example.com", **self.user_credentials
)
self.superuser = User.objects.create_superuser(
username='test2',
email='test2@example.com',
password='test',
username="test2",
email="test2@example.com",
password="test",
)
def test_authenticate_inactive(self):
@@ -276,18 +320,20 @@ class ModelBackendTest(BaseModelBackendTest, TestCase):
self.user.save()
self.assertIsNone(authenticate(**self.user_credentials))
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUserWithoutIsActiveField')
@override_settings(AUTH_USER_MODEL="auth_tests.CustomUserWithoutIsActiveField")
def test_authenticate_user_without_is_active_field(self):
"""
A custom user without an `is_active` field is allowed to authenticate.
"""
user = CustomUserWithoutIsActiveField.objects._create_user(
username='test', email='test@example.com', password='test',
username="test",
email="test@example.com",
password="test",
)
self.assertEqual(authenticate(username='test', password='test'), user)
self.assertEqual(authenticate(username="test", password="test"), user)
@override_settings(AUTH_USER_MODEL='auth_tests.ExtensionUser')
@override_settings(AUTH_USER_MODEL="auth_tests.ExtensionUser")
class ExtensionUserModelBackendTest(BaseModelBackendTest, TestCase):
"""
Tests for the ModelBackend using the custom ExtensionUser model.
@@ -309,20 +355,20 @@ class ExtensionUserModelBackendTest(BaseModelBackendTest, TestCase):
def create_users(self):
self.user = ExtensionUser._default_manager.create_user(
username='test',
email='test@example.com',
password='test',
date_of_birth=date(2006, 4, 25)
username="test",
email="test@example.com",
password="test",
date_of_birth=date(2006, 4, 25),
)
self.superuser = ExtensionUser._default_manager.create_superuser(
username='test2',
email='test2@example.com',
password='test',
date_of_birth=date(1976, 11, 8)
username="test2",
email="test2@example.com",
password="test",
date_of_birth=date(1976, 11, 8),
)
@override_settings(AUTH_USER_MODEL='auth_tests.CustomPermissionsUser')
@override_settings(AUTH_USER_MODEL="auth_tests.CustomPermissionsUser")
class CustomPermissionsUserModelBackendTest(BaseModelBackendTest, TestCase):
"""
Tests for the ModelBackend using the CustomPermissionsUser model.
@@ -336,18 +382,14 @@ class CustomPermissionsUserModelBackendTest(BaseModelBackendTest, TestCase):
def create_users(self):
self.user = CustomPermissionsUser._default_manager.create_user(
email='test@example.com',
password='test',
date_of_birth=date(2006, 4, 25)
email="test@example.com", password="test", date_of_birth=date(2006, 4, 25)
)
self.superuser = CustomPermissionsUser._default_manager.create_superuser(
email='test2@example.com',
password='test',
date_of_birth=date(1976, 11, 8)
email="test2@example.com", password="test", date_of_birth=date(1976, 11, 8)
)
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUser')
@override_settings(AUTH_USER_MODEL="auth_tests.CustomUser")
class CustomUserModelBackendAuthenticateTest(TestCase):
"""
The model backend can accept a credentials kwarg labeled with
@@ -356,24 +398,23 @@ class CustomUserModelBackendAuthenticateTest(TestCase):
def test_authenticate(self):
test_user = CustomUser._default_manager.create_user(
email='test@example.com',
password='test',
date_of_birth=date(2006, 4, 25)
email="test@example.com", password="test", date_of_birth=date(2006, 4, 25)
)
authenticated_user = authenticate(email='test@example.com', password='test')
authenticated_user = authenticate(email="test@example.com", password="test")
self.assertEqual(test_user, authenticated_user)
@override_settings(AUTH_USER_MODEL='auth_tests.UUIDUser')
@override_settings(AUTH_USER_MODEL="auth_tests.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)
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:
@@ -386,47 +427,49 @@ class SimpleRowlevelBackend:
return # We only support row level perms
if isinstance(obj, TestObj):
if user.username == 'test2':
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':
elif not user.is_active and perm == "inactive":
return True
return False
def has_module_perms(self, user, app_label):
return (user.is_anonymous or user.is_active) and app_label == 'app1'
return (user.is_anonymous or user.is_active) and app_label == "app1"
def get_all_permissions(self, user, obj=None):
if not obj:
return [] # We only support row level perms
if not isinstance(obj, TestObj):
return ['none']
return ["none"]
if user.is_anonymous:
return ['anon']
if user.username == 'test2':
return ['simple', 'advanced']
return ["anon"]
if user.username == "test2":
return ["simple", "advanced"]
else:
return ['simple']
return ["simple"]
def get_group_permissions(self, user, obj=None):
if not obj:
return # We only support row level perms
if not isinstance(obj, TestObj):
return ['none']
return ["none"]
if 'test_group' in [group.name for group in user.groups.all()]:
return ['group_perm']
if "test_group" in [group.name for group in user.groups.all()]:
return ["group_perm"]
else:
return ['none']
return ["none"]
@modify_settings(AUTHENTICATION_BACKENDS={
'append': 'auth_tests.test_auth_backends.SimpleRowlevelBackend',
})
@modify_settings(
AUTHENTICATION_BACKENDS={
"append": "auth_tests.test_auth_backends.SimpleRowlevelBackend",
}
)
class RowlevelBackendTest(TestCase):
"""
Tests for auth backend that supports object level permissions
@@ -434,9 +477,9 @@ class RowlevelBackendTest(TestCase):
@classmethod
def setUpTestData(cls):
cls.user1 = User.objects.create_user('test', 'test@example.com', 'test')
cls.user2 = User.objects.create_user('test2', 'test2@example.com', 'test')
cls.user3 = User.objects.create_user('test3', 'test3@example.com', 'test')
cls.user1 = User.objects.create_user("test", "test@example.com", "test")
cls.user2 = User.objects.create_user("test2", "test2@example.com", "test")
cls.user3 = User.objects.create_user("test3", "test3@example.com", "test")
def tearDown(self):
# The get_group_permissions test messes with ContentTypes, which will
@@ -445,27 +488,29 @@ class RowlevelBackendTest(TestCase):
ContentType.objects.clear_cache()
def test_has_perm(self):
self.assertIs(self.user1.has_perm('perm', TestObj()), False)
self.assertIs(self.user2.has_perm('perm', TestObj()), True)
self.assertIs(self.user2.has_perm('perm'), False)
self.assertIs(self.user2.has_perms(['simple', 'advanced'], TestObj()), True)
self.assertIs(self.user3.has_perm('perm', TestObj()), False)
self.assertIs(self.user3.has_perm('anon', TestObj()), False)
self.assertIs(self.user3.has_perms(['simple', 'advanced'], TestObj()), False)
self.assertIs(self.user1.has_perm("perm", TestObj()), False)
self.assertIs(self.user2.has_perm("perm", TestObj()), True)
self.assertIs(self.user2.has_perm("perm"), False)
self.assertIs(self.user2.has_perms(["simple", "advanced"], TestObj()), True)
self.assertIs(self.user3.has_perm("perm", TestObj()), False)
self.assertIs(self.user3.has_perm("anon", TestObj()), False)
self.assertIs(self.user3.has_perms(["simple", "advanced"], TestObj()), False)
def test_get_all_permissions(self):
self.assertEqual(self.user1.get_all_permissions(TestObj()), {'simple'})
self.assertEqual(self.user2.get_all_permissions(TestObj()), {'simple', 'advanced'})
self.assertEqual(self.user1.get_all_permissions(TestObj()), {"simple"})
self.assertEqual(
self.user2.get_all_permissions(TestObj()), {"simple", "advanced"}
)
self.assertEqual(self.user2.get_all_permissions(), set())
def test_get_group_permissions(self):
group = Group.objects.create(name='test_group')
group = Group.objects.create(name="test_group")
self.user3.groups.add(group)
self.assertEqual(self.user3.get_group_permissions(TestObj()), {'group_perm'})
self.assertEqual(self.user3.get_group_permissions(TestObj()), {"group_perm"})
@override_settings(
AUTHENTICATION_BACKENDS=['auth_tests.test_auth_backends.SimpleRowlevelBackend'],
AUTHENTICATION_BACKENDS=["auth_tests.test_auth_backends.SimpleRowlevelBackend"],
)
class AnonymousUserBackendTest(SimpleTestCase):
"""
@@ -476,17 +521,17 @@ class AnonymousUserBackendTest(SimpleTestCase):
self.user1 = AnonymousUser()
def test_has_perm(self):
self.assertIs(self.user1.has_perm('perm', TestObj()), False)
self.assertIs(self.user1.has_perm('anon', TestObj()), True)
self.assertIs(self.user1.has_perm("perm", TestObj()), False)
self.assertIs(self.user1.has_perm("anon", TestObj()), True)
def test_has_perms(self):
self.assertIs(self.user1.has_perms(['anon'], TestObj()), True)
self.assertIs(self.user1.has_perms(['anon', 'perm'], TestObj()), False)
self.assertIs(self.user1.has_perms(["anon"], TestObj()), True)
self.assertIs(self.user1.has_perms(["anon", "perm"], TestObj()), False)
def test_has_perms_perm_list_invalid(self):
msg = 'perm_list must be an iterable of permissions.'
msg = "perm_list must be an iterable of permissions."
with self.assertRaisesMessage(ValueError, msg):
self.user1.has_perms('perm')
self.user1.has_perms("perm")
with self.assertRaisesMessage(ValueError, msg):
self.user1.has_perms(object())
@@ -495,7 +540,7 @@ class AnonymousUserBackendTest(SimpleTestCase):
self.assertIs(self.user1.has_module_perms("app2"), False)
def test_get_all_permissions(self):
self.assertEqual(self.user1.get_all_permissions(TestObj()), {'anon'})
self.assertEqual(self.user1.get_all_permissions(TestObj()), {"anon"})
@override_settings(AUTHENTICATION_BACKENDS=[])
@@ -503,20 +548,23 @@ class NoBackendsTest(TestCase):
"""
An appropriate error is raised if no auth backends are provided.
"""
@classmethod
def setUpTestData(cls):
cls.user = User.objects.create_user('test', 'test@example.com', 'test')
cls.user = User.objects.create_user("test", "test@example.com", "test")
def test_raises_exception(self):
msg = (
'No authentication backends have been defined. '
'Does AUTHENTICATION_BACKENDS contain anything?'
"No authentication backends have been defined. "
"Does AUTHENTICATION_BACKENDS contain anything?"
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
self.user.has_perm(('perm', TestObj()))
self.user.has_perm(("perm", TestObj()))
@override_settings(AUTHENTICATION_BACKENDS=['auth_tests.test_auth_backends.SimpleRowlevelBackend'])
@override_settings(
AUTHENTICATION_BACKENDS=["auth_tests.test_auth_backends.SimpleRowlevelBackend"]
)
class InActiveUserBackendTest(TestCase):
"""
Tests for an inactive user
@@ -524,13 +572,13 @@ class InActiveUserBackendTest(TestCase):
@classmethod
def setUpTestData(cls):
cls.user1 = User.objects.create_user('test', 'test@example.com', 'test')
cls.user1 = User.objects.create_user("test", "test@example.com", "test")
cls.user1.is_active = False
cls.user1.save()
def test_has_perm(self):
self.assertIs(self.user1.has_perm('perm', TestObj()), False)
self.assertIs(self.user1.has_perm('inactive', TestObj()), True)
self.assertIs(self.user1.has_perm("perm", TestObj()), False)
self.assertIs(self.user1.has_perm("inactive", TestObj()), True)
def test_has_module_perms(self):
self.assertIs(self.user1.has_module_perms("app1"), False)
@@ -556,11 +604,12 @@ class PermissionDeniedBackendTest(TestCase):
"""
Other backends are not checked once a backend raises PermissionDenied
"""
backend = 'auth_tests.test_auth_backends.PermissionDeniedBackend'
backend = "auth_tests.test_auth_backends.PermissionDeniedBackend"
@classmethod
def setUpTestData(cls):
cls.user1 = User.objects.create_user('test', 'test@example.com', 'test')
cls.user1 = User.objects.create_user("test", "test@example.com", "test")
def setUp(self):
self.user_login_failed = []
@@ -572,34 +621,41 @@ class PermissionDeniedBackendTest(TestCase):
def user_login_failed_listener(self, sender, credentials, **kwargs):
self.user_login_failed.append(credentials)
@modify_settings(AUTHENTICATION_BACKENDS={'prepend': backend})
@modify_settings(AUTHENTICATION_BACKENDS={"prepend": backend})
def test_permission_denied(self):
"user is not authenticated after a backend raises permission denied #2550"
self.assertIsNone(authenticate(username='test', password='test'))
self.assertIsNone(authenticate(username="test", password="test"))
# user_login_failed signal is sent.
self.assertEqual(self.user_login_failed, [{'password': '********************', 'username': 'test'}])
self.assertEqual(
self.user_login_failed,
[{"password": "********************", "username": "test"}],
)
@modify_settings(AUTHENTICATION_BACKENDS={'append': backend})
@modify_settings(AUTHENTICATION_BACKENDS={"append": backend})
def test_authenticates(self):
self.assertEqual(authenticate(username='test', password='test'), self.user1)
self.assertEqual(authenticate(username="test", password="test"), self.user1)
@modify_settings(AUTHENTICATION_BACKENDS={'prepend': backend})
@modify_settings(AUTHENTICATION_BACKENDS={"prepend": backend})
def test_has_perm_denied(self):
content_type = ContentType.objects.get_for_model(Group)
perm = Permission.objects.create(name='test', content_type=content_type, codename='test')
perm = Permission.objects.create(
name="test", content_type=content_type, codename="test"
)
self.user1.user_permissions.add(perm)
self.assertIs(self.user1.has_perm('auth.test'), False)
self.assertIs(self.user1.has_module_perms('auth'), False)
self.assertIs(self.user1.has_perm("auth.test"), False)
self.assertIs(self.user1.has_module_perms("auth"), False)
@modify_settings(AUTHENTICATION_BACKENDS={'append': backend})
@modify_settings(AUTHENTICATION_BACKENDS={"append": backend})
def test_has_perm(self):
content_type = ContentType.objects.get_for_model(Group)
perm = Permission.objects.create(name='test', content_type=content_type, codename='test')
perm = Permission.objects.create(
name="test", content_type=content_type, codename="test"
)
self.user1.user_permissions.add(perm)
self.assertIs(self.user1.has_perm('auth.test'), True)
self.assertIs(self.user1.has_module_perms('auth'), True)
self.assertIs(self.user1.has_perm("auth.test"), True)
self.assertIs(self.user1.has_module_perms("auth"), True)
class NewModelBackend(ModelBackend):
@@ -610,11 +666,12 @@ class ChangedBackendSettingsTest(TestCase):
"""
Tests for changes in the settings.AUTHENTICATION_BACKENDS
"""
backend = 'auth_tests.test_auth_backends.NewModelBackend'
TEST_USERNAME = 'test_user'
TEST_PASSWORD = 'test_password'
TEST_EMAIL = 'test@example.com'
backend = "auth_tests.test_auth_backends.NewModelBackend"
TEST_USERNAME = "test_user"
TEST_PASSWORD = "test_password"
TEST_EMAIL = "test@example.com"
@classmethod
def setUpTestData(cls):
@@ -627,16 +684,19 @@ class ChangedBackendSettingsTest(TestCase):
logged-in users disconnect.
"""
# Get a session for the test user
self.assertTrue(self.client.login(
username=self.TEST_USERNAME,
password=self.TEST_PASSWORD,
))
self.assertTrue(
self.client.login(
username=self.TEST_USERNAME,
password=self.TEST_PASSWORD,
)
)
# Prepare a request object
request = HttpRequest()
request.session = self.client.session
# Remove NewModelBackend
with self.settings(AUTHENTICATION_BACKENDS=[
'django.contrib.auth.backends.ModelBackend']):
with self.settings(
AUTHENTICATION_BACKENDS=["django.contrib.auth.backends.ModelBackend"]
):
# Get the user from the request
user = get_user(request)
@@ -651,7 +711,7 @@ class TypeErrorBackend:
Always raises TypeError.
"""
@sensitive_variables('password')
@sensitive_variables("password")
def authenticate(self, request, username=None, password=None):
raise TypeError
@@ -671,31 +731,35 @@ class SkippedBackendWithDecoratedMethod:
class AuthenticateTests(TestCase):
@classmethod
def setUpTestData(cls):
cls.user1 = User.objects.create_user('test', 'test@example.com', 'test')
cls.user1 = User.objects.create_user("test", "test@example.com", "test")
def setUp(self):
self.sensitive_password = 'mypassword'
self.sensitive_password = "mypassword"
@override_settings(AUTHENTICATION_BACKENDS=['auth_tests.test_auth_backends.TypeErrorBackend'])
@override_settings(
AUTHENTICATION_BACKENDS=["auth_tests.test_auth_backends.TypeErrorBackend"]
)
def test_type_error_raised(self):
"""A TypeError within a backend is propagated properly (#18171)."""
with self.assertRaises(TypeError):
authenticate(username='test', password='test')
authenticate(username="test", password="test")
@override_settings(AUTHENTICATION_BACKENDS=['auth_tests.test_auth_backends.TypeErrorBackend'])
@override_settings(
AUTHENTICATION_BACKENDS=["auth_tests.test_auth_backends.TypeErrorBackend"]
)
def test_authenticate_sensitive_variables(self):
try:
authenticate(username='testusername', password=self.sensitive_password)
authenticate(username="testusername", password=self.sensitive_password)
except TypeError:
exc_info = sys.exc_info()
rf = RequestFactory()
response = technical_500_response(rf.get('/'), *exc_info)
response = technical_500_response(rf.get("/"), *exc_info)
self.assertNotContains(response, self.sensitive_password, status_code=500)
self.assertContains(response, 'TypeErrorBackend', status_code=500)
self.assertContains(response, "TypeErrorBackend", status_code=500)
self.assertContains(
response,
'<tr><td>credentials</td><td class="code">'
'<pre>&#39;********************&#39;</pre></td></tr>',
"<pre>&#39;********************&#39;</pre></td></tr>",
html=True,
status_code=500,
)
@@ -707,33 +771,37 @@ class AuthenticateTests(TestCase):
except TypeError:
exc_info = sys.exc_info()
rf = RequestFactory()
response = technical_500_response(rf.get('/'), *exc_info)
response = technical_500_response(rf.get("/"), *exc_info)
self.assertNotContains(response, self.sensitive_password, status_code=500)
self.assertContains(
response,
'<tr><td>credentials</td><td class="code">'
'<pre>&#39;********************&#39;</pre></td></tr>',
"<pre>&#39;********************&#39;</pre></td></tr>",
html=True,
status_code=500,
)
@override_settings(AUTHENTICATION_BACKENDS=(
'auth_tests.test_auth_backends.SkippedBackend',
'django.contrib.auth.backends.ModelBackend',
))
@override_settings(
AUTHENTICATION_BACKENDS=(
"auth_tests.test_auth_backends.SkippedBackend",
"django.contrib.auth.backends.ModelBackend",
)
)
def test_skips_backends_without_arguments(self):
"""
A backend (SkippedBackend) is ignored if it doesn't accept the
credentials as arguments.
"""
self.assertEqual(authenticate(username='test', password='test'), self.user1)
self.assertEqual(authenticate(username="test", password="test"), self.user1)
@override_settings(AUTHENTICATION_BACKENDS=(
'auth_tests.test_auth_backends.SkippedBackendWithDecoratedMethod',
'django.contrib.auth.backends.ModelBackend',
))
@override_settings(
AUTHENTICATION_BACKENDS=(
"auth_tests.test_auth_backends.SkippedBackendWithDecoratedMethod",
"django.contrib.auth.backends.ModelBackend",
)
)
def test_skips_backends_with_decorated_method(self):
self.assertEqual(authenticate(username='test', password='test'), self.user1)
self.assertEqual(authenticate(username="test", password="test"), self.user1)
class ImproperlyConfiguredUserModelTest(TestCase):
@@ -741,14 +809,15 @@ class ImproperlyConfiguredUserModelTest(TestCase):
An exception from within get_user_model() is propagated and doesn't
raise an UnboundLocalError (#21439).
"""
@classmethod
def setUpTestData(cls):
cls.user1 = User.objects.create_user('test', 'test@example.com', 'test')
cls.user1 = User.objects.create_user("test", "test@example.com", "test")
def setUp(self):
self.client.login(username='test', password='test')
self.client.login(username="test", password="test")
@override_settings(AUTH_USER_MODEL='thismodel.doesntexist')
@override_settings(AUTH_USER_MODEL="thismodel.doesntexist")
def test_does_not_shadow_exception(self):
# Prepare a request object
request = HttpRequest()
@@ -780,13 +849,13 @@ class ImportedBackendTests(TestCase):
as the one defined in AUTHENTICATION_BACKENDS setting.
"""
backend = 'auth_tests.backend_alias.ImportedModelBackend'
backend = "auth_tests.backend_alias.ImportedModelBackend"
@override_settings(AUTHENTICATION_BACKENDS=[backend])
def test_backend_path(self):
username = 'username'
password = 'password'
User.objects.create_user(username, 'email', password)
username = "username"
password = "password"
User.objects.create_user(username, "email", password)
self.assertTrue(self.client.login(username=username, password=password))
request = HttpRequest()
request.session = self.client.session
@@ -794,10 +863,10 @@ class ImportedBackendTests(TestCase):
class SelectingBackendTests(TestCase):
backend = 'auth_tests.test_auth_backends.CustomModelBackend'
other_backend = 'auth_tests.test_auth_backends.OtherModelBackend'
username = 'username'
password = 'password'
backend = "auth_tests.test_auth_backends.CustomModelBackend"
other_backend = "auth_tests.test_auth_backends.OtherModelBackend"
username = "username"
password = "password"
def assertBackendInSession(self, backend):
request = HttpRequest()
@@ -806,49 +875,51 @@ class SelectingBackendTests(TestCase):
@override_settings(AUTHENTICATION_BACKENDS=[backend])
def test_backend_path_login_without_authenticate_single_backend(self):
user = User.objects.create_user(self.username, 'email', self.password)
user = User.objects.create_user(self.username, "email", self.password)
self.client._login(user)
self.assertBackendInSession(self.backend)
@override_settings(AUTHENTICATION_BACKENDS=[backend, other_backend])
def test_backend_path_login_without_authenticate_multiple_backends(self):
user = User.objects.create_user(self.username, 'email', self.password)
user = User.objects.create_user(self.username, "email", self.password)
expected_message = (
'You have multiple authentication backends configured and '
'therefore must provide the `backend` argument or set the '
'`backend` attribute on the user.'
"You have multiple authentication backends configured and "
"therefore must provide the `backend` argument or set the "
"`backend` attribute on the user."
)
with self.assertRaisesMessage(ValueError, expected_message):
self.client._login(user)
def test_non_string_backend(self):
user = User.objects.create_user(self.username, 'email', self.password)
user = User.objects.create_user(self.username, "email", self.password)
expected_message = (
'backend must be a dotted import path string (got '
'<class \'django.contrib.auth.backends.ModelBackend\'>).'
"backend must be a dotted import path string (got "
"<class 'django.contrib.auth.backends.ModelBackend'>)."
)
with self.assertRaisesMessage(TypeError, expected_message):
self.client._login(user, backend=ModelBackend)
@override_settings(AUTHENTICATION_BACKENDS=[backend, other_backend])
def test_backend_path_login_with_explicit_backends(self):
user = User.objects.create_user(self.username, 'email', self.password)
user = User.objects.create_user(self.username, "email", self.password)
self.client._login(user, self.other_backend)
self.assertBackendInSession(self.other_backend)
@override_settings(AUTHENTICATION_BACKENDS=['django.contrib.auth.backends.AllowAllUsersModelBackend'])
@override_settings(
AUTHENTICATION_BACKENDS=["django.contrib.auth.backends.AllowAllUsersModelBackend"]
)
class AllowAllUsersModelBackendTest(TestCase):
"""
Inactive users may authenticate with the AllowAllUsersModelBackend.
"""
user_credentials = {'username': 'test', 'password': 'test'}
user_credentials = {"username": "test", "password": "test"}
@classmethod
def setUpTestData(cls):
cls.user = User.objects.create_user(
email='test@example.com', is_active=False,
**cls.user_credentials
email="test@example.com", is_active=False, **cls.user_credentials
)
def test_authenticate(self):

View File

@@ -12,23 +12,23 @@ from .models import CustomUser
class BasicTestCase(TestCase):
def test_user(self):
"Users can be created and can set their password"
u = User.objects.create_user('testuser', 'test@example.com', 'testpw')
u = User.objects.create_user("testuser", "test@example.com", "testpw")
self.assertTrue(u.has_usable_password())
self.assertFalse(u.check_password('bad'))
self.assertTrue(u.check_password('testpw'))
self.assertFalse(u.check_password("bad"))
self.assertTrue(u.check_password("testpw"))
# Check we can manually set an unusable password
u.set_unusable_password()
u.save()
self.assertFalse(u.check_password('testpw'))
self.assertFalse(u.check_password("testpw"))
self.assertFalse(u.has_usable_password())
u.set_password('testpw')
self.assertTrue(u.check_password('testpw'))
u.set_password("testpw")
self.assertTrue(u.check_password("testpw"))
u.set_password(None)
self.assertFalse(u.has_usable_password())
# Check username getter
self.assertEqual(u.get_username(), 'testuser')
self.assertEqual(u.get_username(), "testuser")
# Check authentication/permissions
self.assertFalse(u.is_anonymous)
@@ -38,15 +38,15 @@ class BasicTestCase(TestCase):
self.assertFalse(u.is_superuser)
# Check API-based user creation with no password
u2 = User.objects.create_user('testuser2', 'test2@example.com')
u2 = User.objects.create_user("testuser2", "test2@example.com")
self.assertFalse(u2.has_usable_password())
def test_unicode_username(self):
User.objects.create_user('jörg')
User.objects.create_user('Григорий')
User.objects.create_user("jörg")
User.objects.create_user("Григорий")
# Two equivalent Unicode normalized usernames are duplicates.
omega_username = 'iamtheΩ' # U+03A9 GREEK CAPITAL LETTER OMEGA
ohm_username = 'iamtheΩ' # U+2126 OHM SIGN
omega_username = "iamtheΩ" # U+03A9 GREEK CAPITAL LETTER OMEGA
ohm_username = "iamtheΩ" # U+2126 OHM SIGN
User.objects.create_user(ohm_username)
with self.assertRaises(IntegrityError):
User.objects.create_user(omega_username)
@@ -55,20 +55,17 @@ class BasicTestCase(TestCase):
"Users can be created without an email"
cases = [
{},
{'email': ''},
{'email': None},
{"email": ""},
{"email": None},
]
for i, kwargs in enumerate(cases):
with self.subTest(**kwargs):
u = User.objects.create_user(
'testuser{}'.format(i),
**kwargs
)
self.assertEqual(u.email, '')
u = User.objects.create_user("testuser{}".format(i), **kwargs)
self.assertEqual(u.email, "")
def test_superuser(self):
"Check the creation and properties of a superuser"
super = User.objects.create_superuser('super', 'super@example.com', 'super')
super = User.objects.create_superuser("super", "super@example.com", "super")
self.assertTrue(super.is_superuser)
self.assertTrue(super.is_active)
self.assertTrue(super.is_staff)
@@ -76,38 +73,35 @@ class BasicTestCase(TestCase):
def test_superuser_no_email_or_password(self):
cases = [
{},
{'email': ''},
{'email': None},
{'password': None},
{"email": ""},
{"email": None},
{"password": None},
]
for i, kwargs in enumerate(cases):
with self.subTest(**kwargs):
superuser = User.objects.create_superuser(
'super{}'.format(i),
**kwargs
)
self.assertEqual(superuser.email, '')
superuser = User.objects.create_superuser("super{}".format(i), **kwargs)
self.assertEqual(superuser.email, "")
self.assertFalse(superuser.has_usable_password())
def test_get_user_model(self):
"The current user model can be retrieved"
self.assertEqual(get_user_model(), User)
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUser')
@override_settings(AUTH_USER_MODEL="auth_tests.CustomUser")
def test_swappable_user(self):
"The current user model can be swapped out for another"
self.assertEqual(get_user_model(), CustomUser)
with self.assertRaises(AttributeError):
User.objects.all()
@override_settings(AUTH_USER_MODEL='badsetting')
@override_settings(AUTH_USER_MODEL="badsetting")
def test_swappable_user_bad_setting(self):
"The alternate user setting must point to something in the format app.model"
msg = "AUTH_USER_MODEL must be of the form 'app_label.model_name'"
with self.assertRaisesMessage(ImproperlyConfigured, msg):
get_user_model()
@override_settings(AUTH_USER_MODEL='thismodel.doesntexist')
@override_settings(AUTH_USER_MODEL="thismodel.doesntexist")
def test_swappable_user_nonexistent_model(self):
"The current user model must point to an installed model"
msg = (
@@ -119,16 +113,15 @@ class BasicTestCase(TestCase):
def test_user_verbose_names_translatable(self):
"Default User model verbose names are translatable (#19945)"
with translation.override('en'):
self.assertEqual(User._meta.verbose_name, 'user')
self.assertEqual(User._meta.verbose_name_plural, 'users')
with translation.override('es'):
self.assertEqual(User._meta.verbose_name, 'usuario')
self.assertEqual(User._meta.verbose_name_plural, 'usuarios')
with translation.override("en"):
self.assertEqual(User._meta.verbose_name, "user")
self.assertEqual(User._meta.verbose_name_plural, "users")
with translation.override("es"):
self.assertEqual(User._meta.verbose_name, "usuario")
self.assertEqual(User._meta.verbose_name_plural, "usuarios")
class TestGetUser(TestCase):
def test_get_user_anonymous(self):
request = HttpRequest()
request.session = self.client.session
@@ -136,8 +129,10 @@ class TestGetUser(TestCase):
self.assertIsInstance(user, AnonymousUser)
def test_get_user(self):
created_user = User.objects.create_user('testuser', 'test@example.com', 'testpw')
self.client.login(username='testuser', password='testpw')
created_user = User.objects.create_user(
"testuser", "test@example.com", "testpw"
)
self.client.login(username="testuser", password="testpw")
request = HttpRequest()
request.session = self.client.session
user = get_user(request)

View File

@@ -1,154 +1,171 @@
from django.contrib.auth.checks import (
check_models_permissions, check_user_model,
)
from django.contrib.auth.checks import check_models_permissions, check_user_model
from django.contrib.auth.models import AbstractBaseUser
from django.core import checks
from django.db import models
from django.db.models import Q, UniqueConstraint
from django.test import (
SimpleTestCase, override_settings, override_system_checks,
)
from django.test import SimpleTestCase, override_settings, override_system_checks
from django.test.utils import isolate_apps
from .models import CustomUserNonUniqueUsername
@isolate_apps('auth_tests', attr_name='apps')
@isolate_apps("auth_tests", attr_name="apps")
@override_system_checks([check_user_model])
class UserModelChecksTests(SimpleTestCase):
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUserNonListRequiredFields')
@override_settings(AUTH_USER_MODEL="auth_tests.CustomUserNonListRequiredFields")
def test_required_fields_is_list(self):
"""REQUIRED_FIELDS should be a list."""
class CustomUserNonListRequiredFields(AbstractBaseUser):
username = models.CharField(max_length=30, unique=True)
date_of_birth = models.DateField()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = 'date_of_birth'
USERNAME_FIELD = "username"
REQUIRED_FIELDS = "date_of_birth"
errors = checks.run_checks(app_configs=self.apps.get_app_configs())
self.assertEqual(errors, [
checks.Error(
"'REQUIRED_FIELDS' must be a list or tuple.",
obj=CustomUserNonListRequiredFields,
id='auth.E001',
),
])
self.assertEqual(
errors,
[
checks.Error(
"'REQUIRED_FIELDS' must be a list or tuple.",
obj=CustomUserNonListRequiredFields,
id="auth.E001",
),
],
)
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUserBadRequiredFields')
@override_settings(AUTH_USER_MODEL="auth_tests.CustomUserBadRequiredFields")
def test_username_not_in_required_fields(self):
"""USERNAME_FIELD should not appear in REQUIRED_FIELDS."""
class CustomUserBadRequiredFields(AbstractBaseUser):
username = models.CharField(max_length=30, unique=True)
date_of_birth = models.DateField()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['username', 'date_of_birth']
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ["username", "date_of_birth"]
errors = checks.run_checks(self.apps.get_app_configs())
self.assertEqual(errors, [
checks.Error(
"The field named as the 'USERNAME_FIELD' for a custom user model "
"must not be included in 'REQUIRED_FIELDS'.",
hint=(
"The 'USERNAME_FIELD' is currently set to 'username', you "
"should remove 'username' from the 'REQUIRED_FIELDS'."
self.assertEqual(
errors,
[
checks.Error(
"The field named as the 'USERNAME_FIELD' for a custom user model "
"must not be included in 'REQUIRED_FIELDS'.",
hint=(
"The 'USERNAME_FIELD' is currently set to 'username', you "
"should remove 'username' from the 'REQUIRED_FIELDS'."
),
obj=CustomUserBadRequiredFields,
id="auth.E002",
),
obj=CustomUserBadRequiredFields,
id='auth.E002',
),
])
],
)
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUserNonUniqueUsername')
@override_settings(AUTH_USER_MODEL="auth_tests.CustomUserNonUniqueUsername")
def test_username_non_unique(self):
"""
A non-unique USERNAME_FIELD raises an error only if the default
authentication backend is used. Otherwise, a warning is raised.
"""
errors = checks.run_checks()
self.assertEqual(errors, [
checks.Error(
"'CustomUserNonUniqueUsername.username' must be "
"unique because it is named as the 'USERNAME_FIELD'.",
obj=CustomUserNonUniqueUsername,
id='auth.E003',
),
])
with self.settings(AUTHENTICATION_BACKENDS=['my.custom.backend']):
errors = checks.run_checks()
self.assertEqual(errors, [
checks.Warning(
"'CustomUserNonUniqueUsername.username' is named as "
"the 'USERNAME_FIELD', but it is not unique.",
hint='Ensure that your authentication backend(s) can handle non-unique usernames.',
self.assertEqual(
errors,
[
checks.Error(
"'CustomUserNonUniqueUsername.username' must be "
"unique because it is named as the 'USERNAME_FIELD'.",
obj=CustomUserNonUniqueUsername,
id='auth.W004',
id="auth.E003",
),
])
],
)
with self.settings(AUTHENTICATION_BACKENDS=["my.custom.backend"]):
errors = checks.run_checks()
self.assertEqual(
errors,
[
checks.Warning(
"'CustomUserNonUniqueUsername.username' is named as "
"the 'USERNAME_FIELD', but it is not unique.",
hint="Ensure that your authentication backend(s) can handle non-unique usernames.",
obj=CustomUserNonUniqueUsername,
id="auth.W004",
),
],
)
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUserPartiallyUnique')
@override_settings(AUTH_USER_MODEL="auth_tests.CustomUserPartiallyUnique")
def test_username_partially_unique(self):
class CustomUserPartiallyUnique(AbstractBaseUser):
username = models.CharField(max_length=30)
USERNAME_FIELD = 'username'
USERNAME_FIELD = "username"
class Meta:
constraints = [
UniqueConstraint(
fields=['username'],
name='partial_username_unique',
fields=["username"],
name="partial_username_unique",
condition=Q(password__isnull=False),
),
]
errors = checks.run_checks(app_configs=self.apps.get_app_configs())
self.assertEqual(errors, [
checks.Error(
"'CustomUserPartiallyUnique.username' must be unique because "
"it is named as the 'USERNAME_FIELD'.",
obj=CustomUserPartiallyUnique,
id='auth.E003',
),
])
with self.settings(AUTHENTICATION_BACKENDS=['my.custom.backend']):
errors = checks.run_checks(app_configs=self.apps.get_app_configs())
self.assertEqual(errors, [
checks.Warning(
"'CustomUserPartiallyUnique.username' is named as the "
"'USERNAME_FIELD', but it is not unique.",
hint=(
'Ensure that your authentication backend(s) can '
'handle non-unique usernames.'
),
self.assertEqual(
errors,
[
checks.Error(
"'CustomUserPartiallyUnique.username' must be unique because "
"it is named as the 'USERNAME_FIELD'.",
obj=CustomUserPartiallyUnique,
id='auth.W004',
id="auth.E003",
),
])
],
)
with self.settings(AUTHENTICATION_BACKENDS=["my.custom.backend"]):
errors = checks.run_checks(app_configs=self.apps.get_app_configs())
self.assertEqual(
errors,
[
checks.Warning(
"'CustomUserPartiallyUnique.username' is named as the "
"'USERNAME_FIELD', but it is not unique.",
hint=(
"Ensure that your authentication backend(s) can "
"handle non-unique usernames."
),
obj=CustomUserPartiallyUnique,
id="auth.W004",
),
],
)
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUserUniqueConstraint')
@override_settings(AUTH_USER_MODEL="auth_tests.CustomUserUniqueConstraint")
def test_username_unique_with_model_constraint(self):
class CustomUserUniqueConstraint(AbstractBaseUser):
username = models.CharField(max_length=30)
USERNAME_FIELD = 'username'
USERNAME_FIELD = "username"
class Meta:
constraints = [
UniqueConstraint(fields=['username'], name='username_unique'),
UniqueConstraint(fields=["username"], name="username_unique"),
]
self.assertEqual(checks.run_checks(app_configs=self.apps.get_app_configs()), [])
with self.settings(AUTHENTICATION_BACKENDS=['my.custom.backend']):
with self.settings(AUTHENTICATION_BACKENDS=["my.custom.backend"]):
errors = checks.run_checks(app_configs=self.apps.get_app_configs())
self.assertEqual(errors, [])
@override_settings(AUTH_USER_MODEL='auth_tests.BadUser')
@override_settings(AUTH_USER_MODEL="auth_tests.BadUser")
def test_is_anonymous_authenticated_methods(self):
"""
<User Model>.is_anonymous/is_authenticated must not be methods.
"""
class BadUser(AbstractBaseUser):
username = models.CharField(max_length=30, unique=True)
USERNAME_FIELD = 'username'
USERNAME_FIELD = "username"
def is_anonymous(self):
return True
@@ -157,50 +174,56 @@ class UserModelChecksTests(SimpleTestCase):
return True
errors = checks.run_checks(app_configs=self.apps.get_app_configs())
self.assertEqual(errors, [
checks.Critical(
'%s.is_anonymous must be an attribute or property rather than '
'a method. Ignoring this is a security issue as anonymous '
'users will be treated as authenticated!' % BadUser,
obj=BadUser,
id='auth.C009',
),
checks.Critical(
'%s.is_authenticated must be an attribute or property rather '
'than a method. Ignoring this is a security issue as anonymous '
'users will be treated as authenticated!' % BadUser,
obj=BadUser,
id='auth.C010',
),
])
self.assertEqual(
errors,
[
checks.Critical(
"%s.is_anonymous must be an attribute or property rather than "
"a method. Ignoring this is a security issue as anonymous "
"users will be treated as authenticated!" % BadUser,
obj=BadUser,
id="auth.C009",
),
checks.Critical(
"%s.is_authenticated must be an attribute or property rather "
"than a method. Ignoring this is a security issue as anonymous "
"users will be treated as authenticated!" % BadUser,
obj=BadUser,
id="auth.C010",
),
],
)
@isolate_apps('auth_tests', attr_name='apps')
@isolate_apps("auth_tests", attr_name="apps")
@override_system_checks([check_models_permissions])
class ModelsPermissionsChecksTests(SimpleTestCase):
def test_clashing_default_permissions(self):
class Checked(models.Model):
class Meta:
permissions = [
('change_checked', 'Can edit permission (duplicate)')
]
permissions = [("change_checked", "Can edit permission (duplicate)")]
errors = checks.run_checks(self.apps.get_app_configs())
self.assertEqual(errors, [
checks.Error(
"The permission codenamed 'change_checked' clashes with a builtin "
"permission for model 'auth_tests.Checked'.",
obj=Checked,
id='auth.E005',
),
])
self.assertEqual(
errors,
[
checks.Error(
"The permission codenamed 'change_checked' clashes with a builtin "
"permission for model 'auth_tests.Checked'.",
obj=Checked,
id="auth.E005",
),
],
)
def test_non_clashing_custom_permissions(self):
class Checked(models.Model):
class Meta:
permissions = [
('my_custom_permission', 'Some permission'),
('other_one', 'Some other permission'),
("my_custom_permission", "Some permission"),
("other_one", "Some other permission"),
]
errors = checks.run_checks(self.apps.get_app_configs())
self.assertEqual(errors, [])
@@ -208,84 +231,109 @@ class ModelsPermissionsChecksTests(SimpleTestCase):
class Checked(models.Model):
class Meta:
permissions = [
('my_custom_permission', 'Some permission'),
('other_one', 'Some other permission'),
('my_custom_permission', 'Some permission with duplicate permission code'),
("my_custom_permission", "Some permission"),
("other_one", "Some other permission"),
(
"my_custom_permission",
"Some permission with duplicate permission code",
),
]
errors = checks.run_checks(self.apps.get_app_configs())
self.assertEqual(errors, [
checks.Error(
"The permission codenamed 'my_custom_permission' is duplicated for "
"model 'auth_tests.Checked'.",
obj=Checked,
id='auth.E006',
),
])
self.assertEqual(
errors,
[
checks.Error(
"The permission codenamed 'my_custom_permission' is duplicated for "
"model 'auth_tests.Checked'.",
obj=Checked,
id="auth.E006",
),
],
)
def test_verbose_name_max_length(self):
class Checked(models.Model):
class Meta:
verbose_name = 'some ridiculously long verbose name that is out of control' * 5
verbose_name = (
"some ridiculously long verbose name that is out of control" * 5
)
errors = checks.run_checks(self.apps.get_app_configs())
self.assertEqual(errors, [
checks.Error(
"The verbose_name of model 'auth_tests.Checked' must be at most 244 "
"characters for its builtin permission names to be at most 255 characters.",
obj=Checked,
id='auth.E007',
),
])
self.assertEqual(
errors,
[
checks.Error(
"The verbose_name of model 'auth_tests.Checked' must be at most 244 "
"characters for its builtin permission names to be at most 255 characters.",
obj=Checked,
id="auth.E007",
),
],
)
def test_model_name_max_length(self):
model_name = 'X' * 94
model = type(model_name, (models.Model,), {'__module__': self.__module__})
model_name = "X" * 94
model = type(model_name, (models.Model,), {"__module__": self.__module__})
errors = checks.run_checks(self.apps.get_app_configs())
self.assertEqual(errors, [
checks.Error(
"The name of model 'auth_tests.%s' must be at most 93 "
"characters for its builtin permission codenames to be at "
"most 100 characters." % model_name,
obj=model,
id='auth.E011',
),
])
self.assertEqual(
errors,
[
checks.Error(
"The name of model 'auth_tests.%s' must be at most 93 "
"characters for its builtin permission codenames to be at "
"most 100 characters." % model_name,
obj=model,
id="auth.E011",
),
],
)
def test_custom_permission_name_max_length(self):
custom_permission_name = 'some ridiculously long verbose name that is out of control' * 5
custom_permission_name = (
"some ridiculously long verbose name that is out of control" * 5
)
class Checked(models.Model):
class Meta:
permissions = [
('my_custom_permission', custom_permission_name),
("my_custom_permission", custom_permission_name),
]
errors = checks.run_checks(self.apps.get_app_configs())
self.assertEqual(errors, [
checks.Error(
"The permission named '%s' of model 'auth_tests.Checked' is longer "
"than 255 characters." % custom_permission_name,
obj=Checked,
id='auth.E008',
),
])
self.assertEqual(
errors,
[
checks.Error(
"The permission named '%s' of model 'auth_tests.Checked' is longer "
"than 255 characters." % custom_permission_name,
obj=Checked,
id="auth.E008",
),
],
)
def test_custom_permission_codename_max_length(self):
custom_permission_codename = 'x' * 101
custom_permission_codename = "x" * 101
class Checked(models.Model):
class Meta:
permissions = [
(custom_permission_codename, 'Custom permission'),
(custom_permission_codename, "Custom permission"),
]
errors = checks.run_checks(self.apps.get_app_configs())
self.assertEqual(errors, [
checks.Error(
"The permission codenamed '%s' of model 'auth_tests.Checked' "
"is longer than 100 characters." % custom_permission_codename,
obj=Checked,
id='auth.E012',
),
])
self.assertEqual(
errors,
[
checks.Error(
"The permission codenamed '%s' of model 'auth_tests.Checked' "
"is longer than 100 characters." % custom_permission_codename,
obj=Checked,
id="auth.E012",
),
],
)
def test_empty_default_permissions(self):
class Checked(models.Model):

View File

@@ -10,23 +10,25 @@ from .settings import AUTH_MIDDLEWARE, AUTH_TEMPLATES
class MockUser:
def __repr__(self):
return 'MockUser()'
return "MockUser()"
def has_module_perms(self, perm):
return perm == 'mockapp'
return perm == "mockapp"
def has_perm(self, perm, obj=None):
return perm == 'mockapp.someperm'
return perm == "mockapp.someperm"
class PermWrapperTests(SimpleTestCase):
"""
Test some details of the PermWrapper implementation.
"""
class EQLimiterObject:
"""
This object makes sure __eq__ will not be called endlessly.
"""
def __init__(self):
self.eq_calls = 0
@@ -38,7 +40,7 @@ class PermWrapperTests(SimpleTestCase):
def test_repr(self):
perms = PermWrapper(MockUser())
self.assertEqual(repr(perms), 'PermWrapper(MockUser())')
self.assertEqual(repr(perms), "PermWrapper(MockUser())")
def test_permwrapper_in(self):
"""
@@ -46,25 +48,25 @@ class PermWrapperTests(SimpleTestCase):
"""
perms = PermWrapper(MockUser())
# Works for modules and full permissions.
self.assertIn('mockapp', perms)
self.assertNotIn('nonexistent', perms)
self.assertIn('mockapp.someperm', perms)
self.assertNotIn('mockapp.nonexistent', perms)
self.assertIn("mockapp", perms)
self.assertNotIn("nonexistent", perms)
self.assertIn("mockapp.someperm", perms)
self.assertNotIn("mockapp.nonexistent", perms)
def test_permlookupdict_in(self):
"""
No endless loops if accessed with 'in' - refs #18979.
"""
pldict = PermLookupDict(MockUser(), 'mockapp')
pldict = PermLookupDict(MockUser(), "mockapp")
with self.assertRaises(TypeError):
self.EQLimiterObject() in pldict
def test_iter(self):
with self.assertRaisesMessage(TypeError, 'PermWrapper is not iterable.'):
with self.assertRaisesMessage(TypeError, "PermWrapper is not iterable."):
iter(PermWrapper(MockUser()))
@override_settings(ROOT_URLCONF='auth_tests.urls', TEMPLATES=AUTH_TEMPLATES)
@override_settings(ROOT_URLCONF="auth_tests.urls", TEMPLATES=AUTH_TEMPLATES)
class AuthContextProcessorTests(TestCase):
"""
Tests for the ``django.contrib.auth.context_processors.auth`` processor
@@ -72,7 +74,9 @@ class AuthContextProcessorTests(TestCase):
@classmethod
def setUpTestData(cls):
cls.superuser = User.objects.create_superuser(username='super', password='secret', email='super@example.com')
cls.superuser = User.objects.create_superuser(
username="super", password="secret", email="super@example.com"
)
@override_settings(MIDDLEWARE=AUTH_MIDDLEWARE)
def test_session_not_accessed(self):
@@ -80,7 +84,7 @@ class AuthContextProcessorTests(TestCase):
The session is not accessed simply by including
the auth context processor
"""
response = self.client.get('/auth_processor_no_attr_access/')
response = self.client.get("/auth_processor_no_attr_access/")
self.assertContains(response, "Session not accessed")
@override_settings(MIDDLEWARE=AUTH_MIDDLEWARE)
@@ -89,36 +93,40 @@ class AuthContextProcessorTests(TestCase):
The session is accessed if the auth context processor
is used and relevant attributes accessed.
"""
response = self.client.get('/auth_processor_attr_access/')
response = self.client.get("/auth_processor_attr_access/")
self.assertContains(response, "Session accessed")
def test_perms_attrs(self):
u = User.objects.create_user(username='normal', password='secret')
u = User.objects.create_user(username="normal", password="secret")
u.user_permissions.add(
Permission.objects.get(
content_type=ContentType.objects.get_for_model(Permission),
codename='add_permission'))
codename="add_permission",
)
)
self.client.force_login(u)
response = self.client.get('/auth_processor_perms/')
response = self.client.get("/auth_processor_perms/")
self.assertContains(response, "Has auth permissions")
self.assertContains(response, "Has auth.add_permission permissions")
self.assertNotContains(response, "nonexistent")
def test_perm_in_perms_attrs(self):
u = User.objects.create_user(username='normal', password='secret')
u = User.objects.create_user(username="normal", password="secret")
u.user_permissions.add(
Permission.objects.get(
content_type=ContentType.objects.get_for_model(Permission),
codename='add_permission'))
self.client.login(username='normal', password='secret')
response = self.client.get('/auth_processor_perm_in_perms/')
codename="add_permission",
)
)
self.client.login(username="normal", password="secret")
response = self.client.get("/auth_processor_perm_in_perms/")
self.assertContains(response, "Has auth permissions")
self.assertContains(response, "Has auth.add_permission permissions")
self.assertNotContains(response, "nonexistent")
def test_message_attrs(self):
self.client.force_login(self.superuser)
response = self.client.get('/auth_processor_messages/')
response = self.client.get("/auth_processor_messages/")
self.assertContains(response, "Message 1")
def test_user_attrs(self):
@@ -128,9 +136,9 @@ class AuthContextProcessorTests(TestCase):
# These are 'functional' level tests for common use cases. Direct
# testing of the implementation (SimpleLazyObject) is in the 'utils'
# tests.
self.client.login(username='super', password='secret')
user = authenticate(username='super', password='secret')
response = self.client.get('/auth_processor_user/')
self.client.login(username="super", password="secret")
user = authenticate(username="super", password="secret")
response = self.client.get("/auth_processor_user/")
self.assertContains(response, "unicode: super")
self.assertContains(response, "id: %d" % self.superuser.pk)
self.assertContains(response, "username: super")
@@ -138,10 +146,10 @@ class AuthContextProcessorTests(TestCase):
self.assertContains(response, "url: /userpage/super/")
# A Q() comparing a user and with another Q() (in an AND or OR fashion).
Q(user=response.context['user']) & Q(someflag=True)
Q(user=response.context["user"]) & Q(someflag=True)
# Tests for user equality. This is hard because User defines
# equality in a non-duck-typing way
# See bug #12060
self.assertEqual(response.context['user'], user)
self.assertEqual(user, response.context['user'])
self.assertEqual(response.context["user"], user)
self.assertEqual(user, response.context["user"])

View File

@@ -9,7 +9,7 @@ from django.test.client import RequestFactory
from .test_views import AuthViewsTestCase
@override_settings(ROOT_URLCONF='auth_tests.urls')
@override_settings(ROOT_URLCONF="auth_tests.urls")
class LoginRequiredTestCase(AuthViewsTestCase):
"""
Tests the login_required decorators
@@ -19,20 +19,24 @@ class LoginRequiredTestCase(AuthViewsTestCase):
"""
login_required is assignable to callable objects.
"""
class CallableView:
def __call__(self, *args, **kwargs):
pass
login_required(CallableView())
def test_view(self):
"""
login_required is assignable to normal views.
"""
def normal_view(request):
pass
login_required(normal_view)
def test_login_required(self, view_url='/login_required/', login_url=None):
def test_login_required(self, view_url="/login_required/", login_url=None):
"""
login_required works on a simple view wrapped in a login_required
decorator.
@@ -51,70 +55,90 @@ class LoginRequiredTestCase(AuthViewsTestCase):
login_required works on a simple view wrapped in a login_required
decorator with a login_url set.
"""
self.test_login_required(view_url='/login_required_login_url/', login_url='/somewhere/')
self.test_login_required(
view_url="/login_required_login_url/", login_url="/somewhere/"
)
class PermissionsRequiredDecoratorTest(TestCase):
"""
Tests for the permission_required decorator
"""
factory = RequestFactory()
@classmethod
def setUpTestData(cls):
cls.user = models.User.objects.create(username='joe', password='qwerty')
cls.user = models.User.objects.create(username="joe", password="qwerty")
# Add permissions auth.add_customuser and auth.change_customuser
perms = models.Permission.objects.filter(codename__in=('add_customuser', 'change_customuser'))
perms = models.Permission.objects.filter(
codename__in=("add_customuser", "change_customuser")
)
cls.user.user_permissions.add(*perms)
def test_many_permissions_pass(self):
@permission_required(['auth_tests.add_customuser', 'auth_tests.change_customuser'])
@permission_required(
["auth_tests.add_customuser", "auth_tests.change_customuser"]
)
def a_view(request):
return HttpResponse()
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = self.user
resp = a_view(request)
self.assertEqual(resp.status_code, 200)
def test_many_permissions_in_set_pass(self):
@permission_required({'auth_tests.add_customuser', 'auth_tests.change_customuser'})
@permission_required(
{"auth_tests.add_customuser", "auth_tests.change_customuser"}
)
def a_view(request):
return HttpResponse()
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = self.user
resp = a_view(request)
self.assertEqual(resp.status_code, 200)
def test_single_permission_pass(self):
@permission_required('auth_tests.add_customuser')
@permission_required("auth_tests.add_customuser")
def a_view(request):
return HttpResponse()
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = self.user
resp = a_view(request)
self.assertEqual(resp.status_code, 200)
def test_permissioned_denied_redirect(self):
@permission_required(['auth_tests.add_customuser', 'auth_tests.change_customuser', 'nonexistent-permission'])
@permission_required(
[
"auth_tests.add_customuser",
"auth_tests.change_customuser",
"nonexistent-permission",
]
)
def a_view(request):
return HttpResponse()
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = self.user
resp = a_view(request)
self.assertEqual(resp.status_code, 302)
def test_permissioned_denied_exception_raised(self):
@permission_required([
'auth_tests.add_customuser', 'auth_tests.change_customuser', 'nonexistent-permission'
], raise_exception=True)
@permission_required(
[
"auth_tests.add_customuser",
"auth_tests.change_customuser",
"nonexistent-permission",
],
raise_exception=True,
)
def a_view(request):
return HttpResponse()
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = self.user
with self.assertRaises(PermissionDenied):
a_view(request)

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,4 @@
from django.contrib.auth.handlers.modwsgi import (
check_password, groups_for_user,
)
from django.contrib.auth.handlers.modwsgi import check_password, groups_for_user
from django.contrib.auth.models import Group, User
from django.test import TransactionTestCase, override_settings
@@ -15,9 +13,9 @@ class ModWsgiHandlerTestCase(TransactionTestCase):
"""
available_apps = [
'django.contrib.auth',
'django.contrib.contenttypes',
'auth_tests',
"django.contrib.auth",
"django.contrib.contenttypes",
"auth_tests",
]
def test_check_password(self):
@@ -25,51 +23,53 @@ class ModWsgiHandlerTestCase(TransactionTestCase):
check_password() returns the correct values as per
https://modwsgi.readthedocs.io/en/develop/user-guides/access-control-mechanisms.html#apache-authentication-provider
"""
User.objects.create_user('test', 'test@example.com', 'test')
User.objects.create_user("test", "test@example.com", "test")
# User not in database
self.assertIsNone(check_password({}, 'unknown', ''))
self.assertIsNone(check_password({}, "unknown", ""))
# Valid user with correct password
self.assertTrue(check_password({}, 'test', 'test'))
self.assertTrue(check_password({}, "test", "test"))
# correct password, but user is inactive
User.objects.filter(username='test').update(is_active=False)
self.assertFalse(check_password({}, 'test', 'test'))
User.objects.filter(username="test").update(is_active=False)
self.assertFalse(check_password({}, "test", "test"))
# Valid user with incorrect password
self.assertFalse(check_password({}, 'test', 'incorrect'))
self.assertFalse(check_password({}, "test", "incorrect"))
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUser')
@override_settings(AUTH_USER_MODEL="auth_tests.CustomUser")
def test_check_password_custom_user(self):
"""
check_password() returns the correct values as per
https://modwsgi.readthedocs.io/en/develop/user-guides/access-control-mechanisms.html#apache-authentication-provider
with a custom user installed.
"""
CustomUser._default_manager.create_user('test@example.com', '1990-01-01', 'test')
CustomUser._default_manager.create_user(
"test@example.com", "1990-01-01", "test"
)
# User not in database
self.assertIsNone(check_password({}, 'unknown', ''))
self.assertIsNone(check_password({}, "unknown", ""))
# Valid user with correct password'
self.assertTrue(check_password({}, 'test@example.com', 'test'))
self.assertTrue(check_password({}, "test@example.com", "test"))
# Valid user with incorrect password
self.assertFalse(check_password({}, 'test@example.com', 'incorrect'))
self.assertFalse(check_password({}, "test@example.com", "incorrect"))
def test_groups_for_user(self):
"""
groups_for_user() returns correct values as per
https://modwsgi.readthedocs.io/en/develop/user-guides/access-control-mechanisms.html#apache-group-authorisation
"""
user1 = User.objects.create_user('test', 'test@example.com', 'test')
User.objects.create_user('test1', 'test1@example.com', 'test1')
group = Group.objects.create(name='test_group')
user1 = User.objects.create_user("test", "test@example.com", "test")
User.objects.create_user("test1", "test1@example.com", "test1")
group = Group.objects.create(name="test_group")
user1.groups.add(group)
# User not in database
self.assertEqual(groups_for_user({}, 'unknown'), [])
self.assertEqual(groups_for_user({}, "unknown"), [])
self.assertEqual(groups_for_user({}, 'test'), [b'test_group'])
self.assertEqual(groups_for_user({}, 'test1'), [])
self.assertEqual(groups_for_user({}, "test"), [b"test_group"])
self.assertEqual(groups_for_user({}, "test1"), [])

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,9 @@ from django.test import TestCase
class TestAuthenticationMiddleware(TestCase):
@classmethod
def setUpTestData(cls):
cls.user = User.objects.create_user('test_user', 'test@example.com', 'test_password')
cls.user = User.objects.create_user(
"test_user", "test@example.com", "test_password"
)
def setUp(self):
self.middleware = AuthenticationMiddleware(lambda req: HttpResponse())
@@ -24,7 +26,7 @@ class TestAuthenticationMiddleware(TestCase):
def test_changed_password_invalidates_session(self):
# After password change, user should be anonymous
self.user.set_password('new_password')
self.user.set_password("new_password")
self.user.save()
self.middleware(self.request)
self.assertIsNotNone(self.request.user)

View File

@@ -9,14 +9,16 @@ from django.test.utils import captured_stdout
from .models import Proxy, UserProxy
update_proxy_permissions = import_module('django.contrib.auth.migrations.0011_update_proxy_permissions')
update_proxy_permissions = import_module(
"django.contrib.auth.migrations.0011_update_proxy_permissions"
)
class ProxyModelWithDifferentAppLabelTests(TransactionTestCase):
available_apps = [
'auth_tests',
'django.contrib.auth',
'django.contrib.contenttypes',
"auth_tests",
"django.contrib.auth",
"django.contrib.contenttypes",
]
def setUp(self):
@@ -29,19 +31,25 @@ class ProxyModelWithDifferentAppLabelTests(TransactionTestCase):
self.concrete_content_type = ContentType.objects.get_for_model(UserProxy)
self.default_permission = Permission.objects.create(
content_type=self.concrete_content_type,
codename='add_userproxy',
name='Can add userproxy',
codename="add_userproxy",
name="Can add userproxy",
)
self.custom_permission = Permission.objects.create(
content_type=self.concrete_content_type,
codename='use_different_app_label',
name='May use a different app label',
codename="use_different_app_label",
name="May use a different app label",
)
def test_proxy_model_permissions_contenttype(self):
proxy_model_content_type = ContentType.objects.get_for_model(UserProxy, for_concrete_model=False)
self.assertEqual(self.default_permission.content_type, self.concrete_content_type)
self.assertEqual(self.custom_permission.content_type, self.concrete_content_type)
proxy_model_content_type = ContentType.objects.get_for_model(
UserProxy, for_concrete_model=False
)
self.assertEqual(
self.default_permission.content_type, self.concrete_content_type
)
self.assertEqual(
self.custom_permission.content_type, self.concrete_content_type
)
with connection.schema_editor() as editor:
update_proxy_permissions.update_proxy_model_permissions(apps, editor)
self.default_permission.refresh_from_db()
@@ -54,47 +62,51 @@ class ProxyModelWithDifferentAppLabelTests(TransactionTestCase):
user.user_permissions.add(self.default_permission)
user.user_permissions.add(self.custom_permission)
for permission in [self.default_permission, self.custom_permission]:
self.assertTrue(user.has_perm('auth.' + permission.codename))
self.assertFalse(user.has_perm('auth_tests.' + permission.codename))
self.assertTrue(user.has_perm("auth." + permission.codename))
self.assertFalse(user.has_perm("auth_tests." + permission.codename))
with connection.schema_editor() as editor:
update_proxy_permissions.update_proxy_model_permissions(apps, editor)
# Reload user to purge the _perm_cache.
user = User._default_manager.get(pk=user.pk)
for permission in [self.default_permission, self.custom_permission]:
self.assertFalse(user.has_perm('auth.' + permission.codename))
self.assertTrue(user.has_perm('auth_tests.' + permission.codename))
self.assertFalse(user.has_perm("auth." + permission.codename))
self.assertTrue(user.has_perm("auth_tests." + permission.codename))
def test_migrate_backwards(self):
with connection.schema_editor() as editor:
update_proxy_permissions.update_proxy_model_permissions(apps, editor)
update_proxy_permissions.revert_proxy_model_permissions(apps, editor)
self.default_permission.refresh_from_db()
self.assertEqual(self.default_permission.content_type, self.concrete_content_type)
self.assertEqual(
self.default_permission.content_type, self.concrete_content_type
)
self.custom_permission.refresh_from_db()
self.assertEqual(self.custom_permission.content_type, self.concrete_content_type)
self.assertEqual(
self.custom_permission.content_type, self.concrete_content_type
)
def test_user_keeps_same_permissions_after_migrating_backward(self):
user = User.objects.create()
user.user_permissions.add(self.default_permission)
user.user_permissions.add(self.custom_permission)
for permission in [self.default_permission, self.custom_permission]:
self.assertTrue(user.has_perm('auth.' + permission.codename))
self.assertFalse(user.has_perm('auth_tests.' + permission.codename))
self.assertTrue(user.has_perm("auth." + permission.codename))
self.assertFalse(user.has_perm("auth_tests." + permission.codename))
with connection.schema_editor() as editor:
update_proxy_permissions.update_proxy_model_permissions(apps, editor)
update_proxy_permissions.revert_proxy_model_permissions(apps, editor)
# Reload user to purge the _perm_cache.
user = User._default_manager.get(pk=user.pk)
for permission in [self.default_permission, self.custom_permission]:
self.assertTrue(user.has_perm('auth.' + permission.codename))
self.assertFalse(user.has_perm('auth_tests.' + permission.codename))
self.assertTrue(user.has_perm("auth." + permission.codename))
self.assertFalse(user.has_perm("auth_tests." + permission.codename))
class ProxyModelWithSameAppLabelTests(TransactionTestCase):
available_apps = [
'auth_tests',
'django.contrib.auth',
'django.contrib.contenttypes',
"auth_tests",
"django.contrib.auth",
"django.contrib.contenttypes",
]
def setUp(self):
@@ -107,19 +119,25 @@ class ProxyModelWithSameAppLabelTests(TransactionTestCase):
self.concrete_content_type = ContentType.objects.get_for_model(Proxy)
self.default_permission = Permission.objects.create(
content_type=self.concrete_content_type,
codename='add_proxy',
name='Can add proxy',
codename="add_proxy",
name="Can add proxy",
)
self.custom_permission = Permission.objects.create(
content_type=self.concrete_content_type,
codename='display_proxys',
name='May display proxys information',
codename="display_proxys",
name="May display proxys information",
)
def test_proxy_model_permissions_contenttype(self):
proxy_model_content_type = ContentType.objects.get_for_model(Proxy, for_concrete_model=False)
self.assertEqual(self.default_permission.content_type, self.concrete_content_type)
self.assertEqual(self.custom_permission.content_type, self.concrete_content_type)
proxy_model_content_type = ContentType.objects.get_for_model(
Proxy, for_concrete_model=False
)
self.assertEqual(
self.default_permission.content_type, self.concrete_content_type
)
self.assertEqual(
self.custom_permission.content_type, self.concrete_content_type
)
with connection.schema_editor() as editor:
update_proxy_permissions.update_proxy_model_permissions(apps, editor)
self.default_permission.refresh_from_db()
@@ -132,36 +150,40 @@ class ProxyModelWithSameAppLabelTests(TransactionTestCase):
user.user_permissions.add(self.default_permission)
user.user_permissions.add(self.custom_permission)
for permission in [self.default_permission, self.custom_permission]:
self.assertTrue(user.has_perm('auth_tests.' + permission.codename))
self.assertTrue(user.has_perm("auth_tests." + permission.codename))
with connection.schema_editor() as editor:
update_proxy_permissions.update_proxy_model_permissions(apps, editor)
# Reload user to purge the _perm_cache.
user = User._default_manager.get(pk=user.pk)
for permission in [self.default_permission, self.custom_permission]:
self.assertTrue(user.has_perm('auth_tests.' + permission.codename))
self.assertTrue(user.has_perm("auth_tests." + permission.codename))
def test_migrate_backwards(self):
with connection.schema_editor() as editor:
update_proxy_permissions.update_proxy_model_permissions(apps, editor)
update_proxy_permissions.revert_proxy_model_permissions(apps, editor)
self.default_permission.refresh_from_db()
self.assertEqual(self.default_permission.content_type, self.concrete_content_type)
self.assertEqual(
self.default_permission.content_type, self.concrete_content_type
)
self.custom_permission.refresh_from_db()
self.assertEqual(self.custom_permission.content_type, self.concrete_content_type)
self.assertEqual(
self.custom_permission.content_type, self.concrete_content_type
)
def test_user_keeps_same_permissions_after_migrating_backward(self):
user = User.objects.create()
user.user_permissions.add(self.default_permission)
user.user_permissions.add(self.custom_permission)
for permission in [self.default_permission, self.custom_permission]:
self.assertTrue(user.has_perm('auth_tests.' + permission.codename))
self.assertTrue(user.has_perm("auth_tests." + permission.codename))
with connection.schema_editor() as editor:
update_proxy_permissions.update_proxy_model_permissions(apps, editor)
update_proxy_permissions.revert_proxy_model_permissions(apps, editor)
# Reload user to purge the _perm_cache.
user = User._default_manager.get(pk=user.pk)
for permission in [self.default_permission, self.custom_permission]:
self.assertTrue(user.has_perm('auth_tests.' + permission.codename))
self.assertTrue(user.has_perm("auth_tests." + permission.codename))
def test_migrate_with_existing_target_permission(self):
"""
@@ -172,48 +194,52 @@ class ProxyModelWithSameAppLabelTests(TransactionTestCase):
Output a reminder to audit relevant permissions.
"""
proxy_model_content_type = ContentType.objects.get_for_model(Proxy, for_concrete_model=False)
Permission.objects.create(
content_type=proxy_model_content_type,
codename='add_proxy',
name='Can add proxy',
proxy_model_content_type = ContentType.objects.get_for_model(
Proxy, for_concrete_model=False
)
Permission.objects.create(
content_type=proxy_model_content_type,
codename='display_proxys',
name='May display proxys information',
codename="add_proxy",
name="Can add proxy",
)
Permission.objects.create(
content_type=proxy_model_content_type,
codename="display_proxys",
name="May display proxys information",
)
with captured_stdout() as stdout:
with connection.schema_editor() as editor:
update_proxy_permissions.update_proxy_model_permissions(apps, editor)
self.assertIn('A problem arose migrating proxy model permissions', stdout.getvalue())
self.assertIn(
"A problem arose migrating proxy model permissions", stdout.getvalue()
)
class MultiDBProxyModelAppLabelTests(TransactionTestCase):
databases = {'default', 'other'}
databases = {"default", "other"}
available_apps = [
'auth_tests',
'django.contrib.auth',
'django.contrib.contenttypes',
"auth_tests",
"django.contrib.auth",
"django.contrib.contenttypes",
]
def setUp(self):
ContentType.objects.all().delete()
Permission.objects.using('other').delete()
concrete_content_type = ContentType.objects.db_manager(
'other'
).get_for_model(Proxy)
self.permission = Permission.objects.using('other').create(
Permission.objects.using("other").delete()
concrete_content_type = ContentType.objects.db_manager("other").get_for_model(
Proxy
)
self.permission = Permission.objects.using("other").create(
content_type=concrete_content_type,
codename='add_proxy',
name='Can add proxy',
codename="add_proxy",
name="Can add proxy",
)
def test_migrate_other_database(self):
proxy_model_content_type = ContentType.objects.db_manager(
'other'
"other"
).get_for_model(Proxy, for_concrete_model=False)
with connections['other'].schema_editor() as editor:
with connections["other"].schema_editor() as editor:
update_proxy_permissions.update_proxy_model_permissions(apps, editor)
self.permission.refresh_from_db()
self.assertEqual(self.permission.content_type, proxy_model_content_type)

View File

@@ -2,7 +2,9 @@ from unittest import mock
from django.contrib.auth import models
from django.contrib.auth.mixins import (
LoginRequiredMixin, PermissionRequiredMixin, UserPassesTestMixin,
LoginRequiredMixin,
PermissionRequiredMixin,
UserPassesTestMixin,
)
from django.contrib.auth.models import AnonymousUser
from django.core.exceptions import PermissionDenied
@@ -12,13 +14,11 @@ from django.views.generic import View
class AlwaysTrueMixin(UserPassesTestMixin):
def test_func(self):
return True
class AlwaysFalseMixin(UserPassesTestMixin):
def test_func(self):
return False
@@ -36,13 +36,17 @@ class AlwaysFalseView(AlwaysFalseMixin, EmptyResponseView):
pass
class StackedMixinsView1(LoginRequiredMixin, PermissionRequiredMixin, EmptyResponseView):
permission_required = ['auth_tests.add_customuser', 'auth_tests.change_customuser']
class StackedMixinsView1(
LoginRequiredMixin, PermissionRequiredMixin, EmptyResponseView
):
permission_required = ["auth_tests.add_customuser", "auth_tests.change_customuser"]
raise_exception = True
class StackedMixinsView2(PermissionRequiredMixin, LoginRequiredMixin, EmptyResponseView):
permission_required = ['auth_tests.add_customuser', 'auth_tests.change_customuser']
class StackedMixinsView2(
PermissionRequiredMixin, LoginRequiredMixin, EmptyResponseView
):
permission_required = ["auth_tests.add_customuser", "auth_tests.change_customuser"]
raise_exception = True
@@ -51,10 +55,12 @@ class AccessMixinTests(TestCase):
factory = RequestFactory()
def test_stacked_mixins_success(self):
user = models.User.objects.create(username='joe', password='qwerty')
perms = models.Permission.objects.filter(codename__in=('add_customuser', 'change_customuser'))
user = models.User.objects.create(username="joe", password="qwerty")
perms = models.Permission.objects.filter(
codename__in=("add_customuser", "change_customuser")
)
user.user_permissions.add(*perms)
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = user
view = StackedMixinsView1.as_view()
@@ -66,10 +72,10 @@ class AccessMixinTests(TestCase):
self.assertEqual(response.status_code, 200)
def test_stacked_mixins_missing_permission(self):
user = models.User.objects.create(username='joe', password='qwerty')
perms = models.Permission.objects.filter(codename__in=('add_customuser',))
user = models.User.objects.create(username="joe", password="qwerty")
perms = models.Permission.objects.filter(codename__in=("add_customuser",))
user.user_permissions.add(*perms)
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = user
view = StackedMixinsView1.as_view()
@@ -81,9 +87,9 @@ class AccessMixinTests(TestCase):
view(request)
def test_access_mixin_permission_denied_response(self):
user = models.User.objects.create(username='joe', password='qwerty')
user = models.User.objects.create(username="joe", password="qwerty")
# Authenticated users receive PermissionDenied.
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = user
view = AlwaysFalseView.as_view()
with self.assertRaises(PermissionDenied):
@@ -92,28 +98,30 @@ class AccessMixinTests(TestCase):
request.user = AnonymousUser()
response = view(request)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, '/accounts/login/?next=/rand')
self.assertEqual(response.url, "/accounts/login/?next=/rand")
def test_access_mixin_permission_denied_remote_login_url(self):
class AView(AlwaysFalseView):
login_url = 'https://www.remote.example.com/login'
login_url = "https://www.remote.example.com/login"
view = AView.as_view()
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = AnonymousUser()
response = view(request)
self.assertEqual(response.status_code, 302)
self.assertEqual(
response.url,
'https://www.remote.example.com/login?next=http%3A//testserver/rand',
"https://www.remote.example.com/login?next=http%3A//testserver/rand",
)
@mock.patch.object(models.User, 'is_authenticated', False)
@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')
perms = models.Permission.objects.filter(codename__in=('add_customuser', 'change_customuser'))
user = models.User.objects.create(username="joe", password="qwerty")
perms = models.Permission.objects.filter(
codename__in=("add_customuser", "change_customuser")
)
user.user_permissions.add(*perms)
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = user
view = StackedMixinsView1.as_view()
@@ -129,10 +137,10 @@ class UserPassesTestTests(SimpleTestCase):
factory = RequestFactory()
def _test_redirect(self, view=None, url='/accounts/login/?next=/rand'):
def _test_redirect(self, view=None, url="/accounts/login/?next=/rand"):
if not view:
view = AlwaysFalseView.as_view()
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = AnonymousUser()
response = view(request)
self.assertEqual(response.status_code, 302)
@@ -143,27 +151,27 @@ class UserPassesTestTests(SimpleTestCase):
def test_custom_redirect_url(self):
class AView(AlwaysFalseView):
login_url = '/login/'
login_url = "/login/"
self._test_redirect(AView.as_view(), '/login/?next=/rand')
self._test_redirect(AView.as_view(), "/login/?next=/rand")
def test_custom_redirect_parameter(self):
class AView(AlwaysFalseView):
redirect_field_name = 'goto'
redirect_field_name = "goto"
self._test_redirect(AView.as_view(), '/accounts/login/?goto=/rand')
self._test_redirect(AView.as_view(), "/accounts/login/?goto=/rand")
def test_no_redirect_parameter(self):
class AView(AlwaysFalseView):
redirect_field_name = None
self._test_redirect(AView.as_view(), '/accounts/login/')
self._test_redirect(AView.as_view(), "/accounts/login/")
def test_raise_exception(self):
class AView(AlwaysFalseView):
raise_exception = True
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = AnonymousUser()
with self.assertRaises(PermissionDenied):
AView.as_view()(request)
@@ -175,7 +183,7 @@ class UserPassesTestTests(SimpleTestCase):
raise_exception = True
permission_denied_message = msg
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = AnonymousUser()
view = AView.as_view()
with self.assertRaisesMessage(PermissionDenied, msg):
@@ -190,7 +198,7 @@ class UserPassesTestTests(SimpleTestCase):
def get_permission_denied_message(self):
return msg
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = AnonymousUser()
view = AView.as_view()
with self.assertRaisesMessage(PermissionDenied, msg):
@@ -198,7 +206,7 @@ class UserPassesTestTests(SimpleTestCase):
def test_user_passes(self):
view = AlwaysTrueView.as_view()
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = AnonymousUser()
response = view(request)
self.assertEqual(response.status_code, 200)
@@ -210,24 +218,25 @@ class LoginRequiredMixinTests(TestCase):
@classmethod
def setUpTestData(cls):
cls.user = models.User.objects.create(username='joe', password='qwerty')
cls.user = models.User.objects.create(username="joe", password="qwerty")
def test_login_required(self):
"""
login_required works on a simple view wrapped in a login_required
decorator.
"""
class AView(LoginRequiredMixin, EmptyResponseView):
pass
view = AView.as_view()
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = AnonymousUser()
response = view(request)
self.assertEqual(response.status_code, 302)
self.assertEqual('/accounts/login/?next=/rand', response.url)
request = self.factory.get('/rand')
self.assertEqual("/accounts/login/?next=/rand", response.url)
request = self.factory.get("/rand")
request.user = self.user
response = view(request)
self.assertEqual(response.status_code, 200)
@@ -239,24 +248,29 @@ class PermissionsRequiredMixinTests(TestCase):
@classmethod
def setUpTestData(cls):
cls.user = models.User.objects.create(username='joe', password='qwerty')
perms = models.Permission.objects.filter(codename__in=('add_customuser', 'change_customuser'))
cls.user = models.User.objects.create(username="joe", password="qwerty")
perms = models.Permission.objects.filter(
codename__in=("add_customuser", "change_customuser")
)
cls.user.user_permissions.add(*perms)
def test_many_permissions_pass(self):
class AView(PermissionRequiredMixin, EmptyResponseView):
permission_required = ['auth_tests.add_customuser', 'auth_tests.change_customuser']
permission_required = [
"auth_tests.add_customuser",
"auth_tests.change_customuser",
]
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = self.user
resp = AView.as_view()(request)
self.assertEqual(resp.status_code, 200)
def test_single_permission_pass(self):
class AView(PermissionRequiredMixin, EmptyResponseView):
permission_required = 'auth_tests.add_customuser'
permission_required = "auth_tests.add_customuser"
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = self.user
resp = AView.as_view()(request)
self.assertEqual(resp.status_code, 200)
@@ -264,11 +278,13 @@ class PermissionsRequiredMixinTests(TestCase):
def test_permissioned_denied_redirect(self):
class AView(PermissionRequiredMixin, EmptyResponseView):
permission_required = [
'auth_tests.add_customuser', 'auth_tests.change_customuser', 'nonexistent-permission',
"auth_tests.add_customuser",
"auth_tests.change_customuser",
"nonexistent-permission",
]
# Authenticated users receive PermissionDenied.
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = self.user
with self.assertRaises(PermissionDenied):
AView.as_view()(request)
@@ -280,11 +296,13 @@ class PermissionsRequiredMixinTests(TestCase):
def test_permissioned_denied_exception_raised(self):
class AView(PermissionRequiredMixin, EmptyResponseView):
permission_required = [
'auth_tests.add_customuser', 'auth_tests.change_customuser', 'nonexistent-permission',
"auth_tests.add_customuser",
"auth_tests.change_customuser",
"nonexistent-permission",
]
raise_exception = True
request = self.factory.get('/rand')
request = self.factory.get("/rand")
request.user = self.user
with self.assertRaises(PermissionDenied):
AView.as_view()(request)

View File

@@ -6,73 +6,74 @@ from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.hashers import get_hasher
from django.contrib.auth.models import (
AnonymousUser, Group, Permission, User, UserManager,
AnonymousUser,
Group,
Permission,
User,
UserManager,
)
from django.contrib.contenttypes.models import ContentType
from django.core import mail
from django.db import connection, migrations
from django.db.migrations.state import ModelState, ProjectState
from django.db.models.signals import post_save
from django.test import (
SimpleTestCase, TestCase, TransactionTestCase, override_settings,
)
from django.test import SimpleTestCase, TestCase, TransactionTestCase, override_settings
from .models import CustomEmailField, IntegerUsernameUser
class NaturalKeysTestCase(TestCase):
def test_user_natural_key(self):
staff_user = User.objects.create_user(username='staff')
self.assertEqual(User.objects.get_by_natural_key('staff'), staff_user)
self.assertEqual(staff_user.natural_key(), ('staff',))
staff_user = User.objects.create_user(username="staff")
self.assertEqual(User.objects.get_by_natural_key("staff"), staff_user)
self.assertEqual(staff_user.natural_key(), ("staff",))
def test_group_natural_key(self):
users_group = Group.objects.create(name='users')
self.assertEqual(Group.objects.get_by_natural_key('users'), users_group)
users_group = Group.objects.create(name="users")
self.assertEqual(Group.objects.get_by_natural_key("users"), users_group)
class LoadDataWithoutNaturalKeysTestCase(TestCase):
fixtures = ['regular.json']
fixtures = ["regular.json"]
def test_user_is_created_and_added_to_group(self):
user = User.objects.get(username='my_username')
group = Group.objects.get(name='my_group')
user = User.objects.get(username="my_username")
group = Group.objects.get(name="my_group")
self.assertEqual(group, user.groups.get())
class LoadDataWithNaturalKeysTestCase(TestCase):
fixtures = ['natural.json']
fixtures = ["natural.json"]
def test_user_is_created_and_added_to_group(self):
user = User.objects.get(username='my_username')
group = Group.objects.get(name='my_group')
user = User.objects.get(username="my_username")
group = Group.objects.get(name="my_group")
self.assertEqual(group, user.groups.get())
class LoadDataWithNaturalKeysAndMultipleDatabasesTestCase(TestCase):
databases = {'default', 'other'}
databases = {"default", "other"}
def test_load_data_with_user_permissions(self):
# Create test contenttypes for both databases
default_objects = [
ContentType.objects.db_manager('default').create(
model='examplemodela',
app_label='app_a',
ContentType.objects.db_manager("default").create(
model="examplemodela",
app_label="app_a",
),
ContentType.objects.db_manager('default').create(
model='examplemodelb',
app_label='app_b',
ContentType.objects.db_manager("default").create(
model="examplemodelb",
app_label="app_b",
),
]
other_objects = [
ContentType.objects.db_manager('other').create(
model='examplemodelb',
app_label='app_b',
ContentType.objects.db_manager("other").create(
model="examplemodelb",
app_label="app_b",
),
ContentType.objects.db_manager('other').create(
model='examplemodela',
app_label='app_a',
ContentType.objects.db_manager("other").create(
model="examplemodela",
app_label="app_a",
),
]
@@ -89,15 +90,15 @@ class LoadDataWithNaturalKeysAndMultipleDatabasesTestCase(TestCase):
)
perm_default = Permission.objects.get_by_natural_key(
'delete_examplemodelb',
'app_b',
'examplemodelb',
"delete_examplemodelb",
"app_b",
"examplemodelb",
)
perm_other = Permission.objects.db_manager('other').get_by_natural_key(
'delete_examplemodelb',
'app_b',
'examplemodelb',
perm_other = Permission.objects.db_manager("other").get_by_natural_key(
"delete_examplemodelb",
"app_b",
"examplemodelb",
)
self.assertEqual(perm_default.content_type_id, default_objects[1].id)
@@ -106,59 +107,65 @@ class LoadDataWithNaturalKeysAndMultipleDatabasesTestCase(TestCase):
class UserManagerTestCase(TransactionTestCase):
available_apps = [
'auth_tests',
'django.contrib.auth',
'django.contrib.contenttypes',
"auth_tests",
"django.contrib.auth",
"django.contrib.contenttypes",
]
def test_create_user(self):
email_lowercase = 'normal@normal.com'
user = User.objects.create_user('user', email_lowercase)
email_lowercase = "normal@normal.com"
user = User.objects.create_user("user", email_lowercase)
self.assertEqual(user.email, email_lowercase)
self.assertEqual(user.username, 'user')
self.assertEqual(user.username, "user")
self.assertFalse(user.has_usable_password())
def test_create_user_email_domain_normalize_rfc3696(self):
# According to https://tools.ietf.org/html/rfc3696#section-3
# the "@" symbol can be part of the local part of an email address
returned = UserManager.normalize_email(r'Abc\@DEF@EXAMPLE.com')
self.assertEqual(returned, r'Abc\@DEF@example.com')
returned = UserManager.normalize_email(r"Abc\@DEF@EXAMPLE.com")
self.assertEqual(returned, r"Abc\@DEF@example.com")
def test_create_user_email_domain_normalize(self):
returned = UserManager.normalize_email('normal@DOMAIN.COM')
self.assertEqual(returned, 'normal@domain.com')
returned = UserManager.normalize_email("normal@DOMAIN.COM")
self.assertEqual(returned, "normal@domain.com")
def test_create_user_email_domain_normalize_with_whitespace(self):
returned = UserManager.normalize_email(r'email\ with_whitespace@D.COM')
self.assertEqual(returned, r'email\ with_whitespace@d.com')
returned = UserManager.normalize_email(r"email\ with_whitespace@D.COM")
self.assertEqual(returned, r"email\ with_whitespace@d.com")
def test_empty_username(self):
with self.assertRaisesMessage(ValueError, 'The given username must be set'):
User.objects.create_user(username='')
with self.assertRaisesMessage(ValueError, "The given username must be set"):
User.objects.create_user(username="")
def test_create_user_is_staff(self):
email = 'normal@normal.com'
user = User.objects.create_user('user', email, is_staff=True)
email = "normal@normal.com"
user = User.objects.create_user("user", email, is_staff=True)
self.assertEqual(user.email, email)
self.assertEqual(user.username, 'user')
self.assertEqual(user.username, "user")
self.assertTrue(user.is_staff)
def test_create_super_user_raises_error_on_false_is_superuser(self):
with self.assertRaisesMessage(ValueError, 'Superuser must have is_superuser=True.'):
with self.assertRaisesMessage(
ValueError, "Superuser must have is_superuser=True."
):
User.objects.create_superuser(
username='test', email='test@test.com',
password='test', is_superuser=False,
username="test",
email="test@test.com",
password="test",
is_superuser=False,
)
def test_create_superuser_raises_error_on_false_is_staff(self):
with self.assertRaisesMessage(ValueError, 'Superuser must have is_staff=True.'):
with self.assertRaisesMessage(ValueError, "Superuser must have is_staff=True."):
User.objects.create_superuser(
username='test', email='test@test.com',
password='test', is_staff=False,
username="test",
email="test@test.com",
password="test",
is_staff=False,
)
def test_make_random_password(self):
allowed_chars = 'abcdefg'
allowed_chars = "abcdefg"
password = UserManager().make_random_password(5, allowed_chars)
self.assertEqual(len(password), 5)
for char in password:
@@ -166,8 +173,8 @@ class UserManagerTestCase(TransactionTestCase):
def test_runpython_manager_methods(self):
def forwards(apps, schema_editor):
UserModel = apps.get_model('auth', 'User')
user = UserModel.objects.create_user('user1', password='secure')
UserModel = apps.get_model("auth", "User")
user = UserModel.objects.create_user("user1", password="secure")
self.assertIsInstance(user, UserModel)
operation = migrations.RunPython(forwards, migrations.RunPython.noop)
@@ -178,47 +185,48 @@ class UserManagerTestCase(TransactionTestCase):
project_state.add_model(ModelState.from_model(ContentType))
new_state = project_state.clone()
with connection.schema_editor() as editor:
operation.state_forwards('test_manager_methods', new_state)
operation.state_forwards("test_manager_methods", new_state)
operation.database_forwards(
'test_manager_methods',
"test_manager_methods",
editor,
project_state,
new_state,
)
user = User.objects.get(username='user1')
self.assertTrue(user.check_password('secure'))
user = User.objects.get(username="user1")
self.assertTrue(user.check_password("secure"))
class AbstractBaseUserTests(SimpleTestCase):
def test_has_usable_password(self):
"""
Passwords are usable even if they don't correspond to a hasher in
settings.PASSWORD_HASHERS.
"""
self.assertIs(User(password='some-gibbberish').has_usable_password(), True)
self.assertIs(User(password="some-gibbberish").has_usable_password(), True)
def test_normalize_username(self):
self.assertEqual(IntegerUsernameUser().normalize_username(123), 123)
def test_clean_normalize_username(self):
# The normalization happens in AbstractBaseUser.clean()
ohm_username = 'iamtheΩ' # U+2126 OHM SIGN
for model in ('auth.User', 'auth_tests.CustomUser'):
ohm_username = "iamtheΩ" # U+2126 OHM SIGN
for model in ("auth.User", "auth_tests.CustomUser"):
with self.subTest(model=model), self.settings(AUTH_USER_MODEL=model):
User = get_user_model()
user = User(**{User.USERNAME_FIELD: ohm_username, 'password': 'foo'})
user = User(**{User.USERNAME_FIELD: ohm_username, "password": "foo"})
user.clean()
username = user.get_username()
self.assertNotEqual(username, ohm_username)
self.assertEqual(username, 'iamtheΩ') # U+03A9 GREEK CAPITAL LETTER OMEGA
self.assertEqual(
username, "iamtheΩ"
) # U+03A9 GREEK CAPITAL LETTER OMEGA
def test_default_email(self):
self.assertEqual(AbstractBaseUser.get_email_field_name(), 'email')
self.assertEqual(AbstractBaseUser.get_email_field_name(), "email")
def test_custom_email(self):
user = CustomEmailField()
self.assertEqual(user.get_email_field_name(), 'email_address')
self.assertEqual(user.get_email_field_name(), "email_address")
class AbstractUserTestCase(TestCase):
@@ -231,12 +239,12 @@ class AbstractUserTestCase(TestCase):
"connection": None,
"html_message": None,
}
user = User(email='foo@bar.com')
user = User(email="foo@bar.com")
user.email_user(
subject="Subject here",
message="This is a message",
from_email="from@domain.com",
**kwargs
**kwargs,
)
self.assertEqual(len(mail.outbox), 1)
message = mail.outbox[0]
@@ -246,24 +254,26 @@ class AbstractUserTestCase(TestCase):
self.assertEqual(message.to, [user.email])
def test_last_login_default(self):
user1 = User.objects.create(username='user1')
user1 = User.objects.create(username="user1")
self.assertIsNone(user1.last_login)
user2 = User.objects.create_user(username='user2')
user2 = User.objects.create_user(username="user2")
self.assertIsNone(user2.last_login)
def test_user_clean_normalize_email(self):
user = User(username='user', password='foo', email='foo@BAR.com')
user = User(username="user", password="foo", email="foo@BAR.com")
user.clean()
self.assertEqual(user.email, 'foo@bar.com')
self.assertEqual(user.email, "foo@bar.com")
def test_user_double_save(self):
"""
Calling user.save() twice should trigger password_changed() once.
"""
user = User.objects.create_user(username='user', password='foo')
user.set_password('bar')
with mock.patch('django.contrib.auth.password_validation.password_changed') as pw_changed:
user = User.objects.create_user(username="user", password="foo")
user.set_password("bar")
with mock.patch(
"django.contrib.auth.password_validation.password_changed"
) as pw_changed:
user.save()
self.assertEqual(pw_changed.call_count, 1)
user.save()
@@ -275,18 +285,20 @@ class AbstractUserTestCase(TestCase):
password_changed() shouldn't be called if User.check_password()
triggers a hash iteration upgrade.
"""
user = User.objects.create_user(username='user', password='foo')
user = User.objects.create_user(username="user", password="foo")
initial_password = user.password
self.assertTrue(user.check_password('foo'))
hasher = get_hasher('default')
self.assertEqual('pbkdf2_sha256', hasher.algorithm)
self.assertTrue(user.check_password("foo"))
hasher = get_hasher("default")
self.assertEqual("pbkdf2_sha256", hasher.algorithm)
old_iterations = hasher.iterations
try:
# Upgrade the password iterations
hasher.iterations = old_iterations + 1
with mock.patch('django.contrib.auth.password_validation.password_changed') as pw_changed:
user.check_password('foo')
with mock.patch(
"django.contrib.auth.password_validation.password_changed"
) as pw_changed:
user.check_password("foo")
self.assertEqual(pw_changed.call_count, 0)
self.assertNotEqual(initial_password, user.password)
finally:
@@ -294,137 +306,154 @@ class AbstractUserTestCase(TestCase):
class CustomModelBackend(ModelBackend):
def with_perm(self, perm, is_active=True, include_superusers=True, backend=None, obj=None):
if obj is not None and obj.username == 'charliebrown':
def with_perm(
self, perm, is_active=True, include_superusers=True, backend=None, obj=None
):
if obj is not None and obj.username == "charliebrown":
return User.objects.filter(pk=obj.pk)
return User.objects.filter(username__startswith='charlie')
return User.objects.filter(username__startswith="charlie")
class UserWithPermTestCase(TestCase):
@classmethod
def setUpTestData(cls):
content_type = ContentType.objects.get_for_model(Group)
cls.permission = Permission.objects.create(
name='test', content_type=content_type, codename='test',
name="test",
content_type=content_type,
codename="test",
)
# User with permission.
cls.user1 = User.objects.create_user('user 1', 'foo@example.com')
cls.user1 = User.objects.create_user("user 1", "foo@example.com")
cls.user1.user_permissions.add(cls.permission)
# User with group permission.
group1 = Group.objects.create(name='group 1')
group1 = Group.objects.create(name="group 1")
group1.permissions.add(cls.permission)
group2 = Group.objects.create(name='group 2')
group2 = Group.objects.create(name="group 2")
group2.permissions.add(cls.permission)
cls.user2 = User.objects.create_user('user 2', 'bar@example.com')
cls.user2 = User.objects.create_user("user 2", "bar@example.com")
cls.user2.groups.add(group1, group2)
# Users without permissions.
cls.user_charlie = User.objects.create_user('charlie', 'charlie@example.com')
cls.user_charlie_b = User.objects.create_user('charliebrown', 'charlie@brown.com')
cls.user_charlie = User.objects.create_user("charlie", "charlie@example.com")
cls.user_charlie_b = User.objects.create_user(
"charliebrown", "charlie@brown.com"
)
# Superuser.
cls.superuser = User.objects.create_superuser(
'superuser', 'superuser@example.com', 'superpassword',
"superuser",
"superuser@example.com",
"superpassword",
)
# Inactive user with permission.
cls.inactive_user = User.objects.create_user(
'inactive_user', 'baz@example.com', is_active=False,
"inactive_user",
"baz@example.com",
is_active=False,
)
cls.inactive_user.user_permissions.add(cls.permission)
def test_invalid_permission_name(self):
msg = 'Permission name should be in the form app_label.permission_codename.'
for perm in ('nodots', 'too.many.dots', '...', ''):
msg = "Permission name should be in the form app_label.permission_codename."
for perm in ("nodots", "too.many.dots", "...", ""):
with self.subTest(perm), self.assertRaisesMessage(ValueError, msg):
User.objects.with_perm(perm)
def test_invalid_permission_type(self):
msg = 'The `perm` argument must be a string or a permission instance.'
for perm in (b'auth.test', object(), None):
msg = "The `perm` argument must be a string or a permission instance."
for perm in (b"auth.test", object(), None):
with self.subTest(perm), self.assertRaisesMessage(TypeError, msg):
User.objects.with_perm(perm)
def test_invalid_backend_type(self):
msg = 'backend must be a dotted import path string (got %r).'
for backend in (b'auth_tests.CustomModelBackend', object()):
msg = "backend must be a dotted import path string (got %r)."
for backend in (b"auth_tests.CustomModelBackend", object()):
with self.subTest(backend):
with self.assertRaisesMessage(TypeError, msg % backend):
User.objects.with_perm('auth.test', backend=backend)
User.objects.with_perm("auth.test", backend=backend)
def test_basic(self):
active_users = [self.user1, self.user2]
tests = [
({}, [*active_users, self.superuser]),
({'obj': self.user1}, []),
({"obj": self.user1}, []),
# Only inactive users.
({'is_active': False}, [self.inactive_user]),
({"is_active": False}, [self.inactive_user]),
# All users.
({'is_active': None}, [*active_users, self.superuser, self.inactive_user]),
({"is_active": None}, [*active_users, self.superuser, self.inactive_user]),
# Exclude superusers.
({'include_superusers': False}, active_users),
({"include_superusers": False}, active_users),
(
{'include_superusers': False, 'is_active': False},
{"include_superusers": False, "is_active": False},
[self.inactive_user],
),
(
{'include_superusers': False, 'is_active': None},
{"include_superusers": False, "is_active": None},
[*active_users, self.inactive_user],
),
]
for kwargs, expected_users in tests:
for perm in ('auth.test', self.permission):
for perm in ("auth.test", self.permission):
with self.subTest(perm=perm, **kwargs):
self.assertCountEqual(
User.objects.with_perm(perm, **kwargs),
expected_users,
)
@override_settings(AUTHENTICATION_BACKENDS=['django.contrib.auth.backends.BaseBackend'])
@override_settings(
AUTHENTICATION_BACKENDS=["django.contrib.auth.backends.BaseBackend"]
)
def test_backend_without_with_perm(self):
self.assertSequenceEqual(User.objects.with_perm('auth.test'), [])
self.assertSequenceEqual(User.objects.with_perm("auth.test"), [])
def test_nonexistent_permission(self):
self.assertSequenceEqual(User.objects.with_perm('auth.perm'), [self.superuser])
self.assertSequenceEqual(User.objects.with_perm("auth.perm"), [self.superuser])
def test_nonexistent_backend(self):
with self.assertRaises(ImportError):
User.objects.with_perm(
'auth.test',
backend='invalid.backend.CustomModelBackend',
"auth.test",
backend="invalid.backend.CustomModelBackend",
)
@override_settings(AUTHENTICATION_BACKENDS=['auth_tests.test_models.CustomModelBackend'])
@override_settings(
AUTHENTICATION_BACKENDS=["auth_tests.test_models.CustomModelBackend"]
)
def test_custom_backend(self):
for perm in ('auth.test', self.permission):
for perm in ("auth.test", self.permission):
with self.subTest(perm):
self.assertCountEqual(
User.objects.with_perm(perm),
[self.user_charlie, self.user_charlie_b],
)
@override_settings(AUTHENTICATION_BACKENDS=['auth_tests.test_models.CustomModelBackend'])
@override_settings(
AUTHENTICATION_BACKENDS=["auth_tests.test_models.CustomModelBackend"]
)
def test_custom_backend_pass_obj(self):
for perm in ('auth.test', self.permission):
for perm in ("auth.test", self.permission):
with self.subTest(perm):
self.assertSequenceEqual(
User.objects.with_perm(perm, obj=self.user_charlie_b),
[self.user_charlie_b],
)
@override_settings(AUTHENTICATION_BACKENDS=[
'auth_tests.test_models.CustomModelBackend',
'django.contrib.auth.backends.ModelBackend',
])
@override_settings(
AUTHENTICATION_BACKENDS=[
"auth_tests.test_models.CustomModelBackend",
"django.contrib.auth.backends.ModelBackend",
]
)
def test_multiple_backends(self):
msg = (
'You have multiple authentication backends configured and '
'therefore must provide the `backend` argument.'
"You have multiple authentication backends configured and "
"therefore must provide the `backend` argument."
)
with self.assertRaisesMessage(ValueError, msg):
User.objects.with_perm('auth.test')
User.objects.with_perm("auth.test")
backend = 'auth_tests.test_models.CustomModelBackend'
backend = "auth_tests.test_models.CustomModelBackend"
self.assertCountEqual(
User.objects.with_perm('auth.test', backend=backend),
User.objects.with_perm("auth.test", backend=backend),
[self.user_charlie, self.user_charlie_b],
)
@@ -435,7 +464,7 @@ class IsActiveTestCase(TestCase):
"""
def test_builtin_user_isactive(self):
user = User.objects.create(username='foo', email='foo@bar.com')
user = User.objects.create(username="foo", email="foo@bar.com")
# is_active is true by default
self.assertIs(user.is_active, True)
user.is_active = False
@@ -444,13 +473,13 @@ class IsActiveTestCase(TestCase):
# the is_active flag is saved
self.assertFalse(user_fetched.is_active)
@override_settings(AUTH_USER_MODEL='auth_tests.IsActiveTestUser1')
@override_settings(AUTH_USER_MODEL="auth_tests.IsActiveTestUser1")
def test_is_active_field_default(self):
"""
tests that the default value for is_active is provided
"""
UserModel = get_user_model()
user = UserModel(username='foo')
user = UserModel(username="foo")
self.assertIs(user.is_active, True)
# you can set the attribute - but it will not save
user.is_active = False
@@ -465,6 +494,7 @@ class TestCreateSuperUserSignals(TestCase):
"""
Simple test case for ticket #20541
"""
def post_save_listener(self, *args, **kwargs):
self.signals_count += 1
@@ -492,8 +522,8 @@ class AnonymousUserTests(SimpleTestCase):
def test_properties(self):
self.assertIsNone(self.user.pk)
self.assertEqual(self.user.username, '')
self.assertEqual(self.user.get_username(), '')
self.assertEqual(self.user.username, "")
self.assertEqual(self.user.get_username(), "")
self.assertIs(self.user.is_anonymous, True)
self.assertIs(self.user.is_authenticated, False)
self.assertIs(self.user.is_staff, False)
@@ -505,19 +535,19 @@ class AnonymousUserTests(SimpleTestCase):
self.assertEqual(self.user.get_group_permissions(), set())
def test_str(self):
self.assertEqual(str(self.user), 'AnonymousUser')
self.assertEqual(str(self.user), "AnonymousUser")
def test_eq(self):
self.assertEqual(self.user, AnonymousUser())
self.assertNotEqual(self.user, User('super', 'super@example.com', 'super'))
self.assertNotEqual(self.user, User("super", "super@example.com", "super"))
def test_hash(self):
self.assertEqual(hash(self.user), 1)
def test_int(self):
msg = (
'Cannot cast AnonymousUser to int. Are you trying to use it in '
'place of User?'
"Cannot cast AnonymousUser to int. Are you trying to use it in "
"place of User?"
)
with self.assertRaisesMessage(TypeError, msg):
int(self.user)
@@ -532,20 +562,22 @@ class AnonymousUserTests(SimpleTestCase):
def test_set_password(self):
with self.assertRaisesMessage(NotImplementedError, self.no_repr_msg):
self.user.set_password('password')
self.user.set_password("password")
def test_check_password(self):
with self.assertRaisesMessage(NotImplementedError, self.no_repr_msg):
self.user.check_password('password')
self.user.check_password("password")
class GroupTests(SimpleTestCase):
def test_str(self):
g = Group(name='Users')
self.assertEqual(str(g), 'Users')
g = Group(name="Users")
self.assertEqual(str(g), "Users")
class PermissionTests(TestCase):
def test_str(self):
p = Permission.objects.get(codename='view_customemailfield')
self.assertEqual(str(p), 'auth_tests | custom email field | Can view custom email field')
p = Permission.objects.get(codename="view_customemailfield")
self.assertEqual(
str(p), "auth_tests | custom email field | Can view custom email field"
)

View File

@@ -10,22 +10,22 @@ from django.test import Client, TestCase, modify_settings, override_settings
from django.utils import timezone
@override_settings(ROOT_URLCONF='auth_tests.urls')
@override_settings(ROOT_URLCONF="auth_tests.urls")
class RemoteUserTest(TestCase):
middleware = 'django.contrib.auth.middleware.RemoteUserMiddleware'
backend = 'django.contrib.auth.backends.RemoteUserBackend'
header = 'REMOTE_USER'
email_header = 'REMOTE_EMAIL'
middleware = "django.contrib.auth.middleware.RemoteUserMiddleware"
backend = "django.contrib.auth.backends.RemoteUserBackend"
header = "REMOTE_USER"
email_header = "REMOTE_EMAIL"
# Usernames to be passed in REMOTE_USER for the test_known_user test case.
known_user = 'knownuser'
known_user2 = 'knownuser2'
known_user = "knownuser"
known_user2 = "knownuser2"
def setUp(self):
self.patched_settings = modify_settings(
AUTHENTICATION_BACKENDS={'append': self.backend},
MIDDLEWARE={'append': self.middleware},
AUTHENTICATION_BACKENDS={"append": self.backend},
MIDDLEWARE={"append": self.middleware},
)
self.patched_settings.enable()
@@ -36,16 +36,16 @@ class RemoteUserTest(TestCase):
"""Users are not created when remote user is not specified."""
num_users = User.objects.count()
response = self.client.get('/remote_user/')
self.assertTrue(response.context['user'].is_anonymous)
response = self.client.get("/remote_user/")
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)
response = self.client.get("/remote_user/", **{self.header: None})
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)
response = self.client.get("/remote_user/", **{self.header: ""})
self.assertTrue(response.context["user"].is_anonymous)
self.assertEqual(User.objects.count(), num_users)
def test_csrf_validation_passes_after_process_request_login(self):
@@ -58,14 +58,14 @@ class RemoteUserTest(TestCase):
csrf_secret = _get_new_csrf_string()
csrf_token = _mask_cipher_secret(csrf_secret)
csrf_token_form = _mask_cipher_secret(csrf_secret)
headers = {self.header: 'fakeuser'}
data = {'csrfmiddlewaretoken': csrf_token_form}
headers = {self.header: "fakeuser"}
data = {"csrfmiddlewaretoken": csrf_token_form}
# Verify that CSRF is configured for the view
csrf_client.cookies.load({settings.CSRF_COOKIE_NAME: csrf_token})
response = csrf_client.post('/remote_user/', **headers)
response = csrf_client.post("/remote_user/", **headers)
self.assertEqual(response.status_code, 403)
self.assertIn(b'CSRF verification failed.', response.content)
self.assertIn(b"CSRF verification failed.", response.content)
# This request will call django.contrib.auth.login() which will call
# django.middleware.csrf.rotate_token() thus changing the value of
@@ -74,7 +74,7 @@ class RemoteUserTest(TestCase):
# by rotate_token(). Csrf validation should still pass when the view is
# later processed by CsrfViewMiddleware.process_view()
csrf_client.cookies.load({settings.CSRF_COOKIE_NAME: csrf_token})
response = csrf_client.post('/remote_user/', data, **headers)
response = csrf_client.post("/remote_user/", data, **headers)
self.assertEqual(response.status_code, 200)
def test_unknown_user(self):
@@ -83,31 +83,29 @@ class RemoteUserTest(TestCase):
as a User.
"""
num_users = User.objects.count()
response = self.client.get('/remote_user/', **{self.header: 'newuser'})
self.assertEqual(response.context['user'].username, 'newuser')
response = self.client.get("/remote_user/", **{self.header: "newuser"})
self.assertEqual(response.context["user"].username, "newuser")
self.assertEqual(User.objects.count(), num_users + 1)
User.objects.get(username='newuser')
User.objects.get(username="newuser")
# Another request with same user should not create any new users.
response = self.client.get('/remote_user/', **{self.header: 'newuser'})
response = self.client.get("/remote_user/", **{self.header: "newuser"})
self.assertEqual(User.objects.count(), num_users + 1)
def test_known_user(self):
"""
Tests the case where the username passed in the header is a valid User.
"""
User.objects.create(username='knownuser')
User.objects.create(username='knownuser2')
User.objects.create(username="knownuser")
User.objects.create(username="knownuser2")
num_users = User.objects.count()
response = self.client.get('/remote_user/',
**{self.header: self.known_user})
self.assertEqual(response.context['user'].username, 'knownuser')
response = self.client.get("/remote_user/", **{self.header: self.known_user})
self.assertEqual(response.context["user"].username, "knownuser")
self.assertEqual(User.objects.count(), num_users)
# A different user passed in the headers causes the new user
# to be logged in.
response = self.client.get('/remote_user/',
**{self.header: self.known_user2})
self.assertEqual(response.context['user'].username, 'knownuser2')
response = self.client.get("/remote_user/", **{self.header: self.known_user2})
self.assertEqual(response.context["user"].username, "knownuser2")
self.assertEqual(User.objects.count(), num_users)
def test_last_login(self):
@@ -115,7 +113,7 @@ class RemoteUserTest(TestCase):
A user's last_login is set the first time they make a
request but not updated in subsequent requests with the same session.
"""
user = User.objects.create(username='knownuser')
user = User.objects.create(username="knownuser")
# Set last_login to something so we can determine if it changes.
default_login = datetime(2000, 1, 1)
if settings.USE_TZ:
@@ -123,64 +121,60 @@ class RemoteUserTest(TestCase):
user.last_login = default_login
user.save()
response = self.client.get('/remote_user/',
**{self.header: self.known_user})
self.assertNotEqual(default_login, response.context['user'].last_login)
response = self.client.get("/remote_user/", **{self.header: self.known_user})
self.assertNotEqual(default_login, response.context["user"].last_login)
user = User.objects.get(username='knownuser')
user = User.objects.get(username="knownuser")
user.last_login = default_login
user.save()
response = self.client.get('/remote_user/',
**{self.header: self.known_user})
self.assertEqual(default_login, response.context['user'].last_login)
response = self.client.get("/remote_user/", **{self.header: self.known_user})
self.assertEqual(default_login, response.context["user"].last_login)
def test_header_disappears(self):
"""
A logged in user is logged out automatically when
the REMOTE_USER header disappears during the same browser session.
"""
User.objects.create(username='knownuser')
User.objects.create(username="knownuser")
# Known user authenticates
response = self.client.get('/remote_user/',
**{self.header: self.known_user})
self.assertEqual(response.context['user'].username, 'knownuser')
response = self.client.get("/remote_user/", **{self.header: self.known_user})
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.assertTrue(response.context['user'].is_anonymous)
response = self.client.get("/remote_user/")
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')
self.client.login(username='modeluser', password='foo')
authenticate(username='modeluser', password='foo')
response = self.client.get('/remote_user/')
self.assertEqual(response.context['user'].username, 'modeluser')
User.objects.create_user(username="modeluser", password="foo")
self.client.login(username="modeluser", password="foo")
authenticate(username="modeluser", password="foo")
response = self.client.get("/remote_user/")
self.assertEqual(response.context["user"].username, "modeluser")
def test_user_switch_forces_new_login(self):
"""
If the username in the header changes between requests
that the original user is logged out
"""
User.objects.create(username='knownuser')
User.objects.create(username="knownuser")
# Known user authenticates
response = self.client.get('/remote_user/',
**{self.header: self.known_user})
self.assertEqual(response.context['user'].username, 'knownuser')
response = self.client.get("/remote_user/", **{self.header: self.known_user})
self.assertEqual(response.context["user"].username, "knownuser")
# During the session, the REMOTE_USER changes to a different user.
response = self.client.get('/remote_user/',
**{self.header: "newnewuser"})
response = self.client.get("/remote_user/", **{self.header: "newnewuser"})
# The current user is not the prior remote_user.
# In backends that create a new user, username is "newnewuser"
# In backends that do not create new users, it is '' (anonymous user)
self.assertNotEqual(response.context['user'].username, 'knownuser')
self.assertNotEqual(response.context["user"].username, "knownuser")
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)
User.objects.create(username="knownuser", is_active=False)
response = self.client.get("/remote_user/", **{self.header: "knownuser"})
self.assertTrue(response.context["user"].is_anonymous)
class RemoteUserNoCreateBackend(RemoteUserBackend):
"""Backend that doesn't create unknown users."""
create_unknown_user = False
@@ -190,23 +184,24 @@ class RemoteUserNoCreateTest(RemoteUserTest):
class that doesn't create unknown users.
"""
backend = 'auth_tests.test_remote_user.RemoteUserNoCreateBackend'
backend = "auth_tests.test_remote_user.RemoteUserNoCreateBackend"
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)
response = self.client.get("/remote_user/", **{self.header: "newuser"})
self.assertTrue(response.context["user"].is_anonymous)
self.assertEqual(User.objects.count(), num_users)
class AllowAllUsersRemoteUserBackendTest(RemoteUserTest):
"""Backend that allows inactive users."""
backend = 'django.contrib.auth.backends.AllowAllUsersRemoteUserBackend'
backend = "django.contrib.auth.backends.AllowAllUsersRemoteUserBackend"
def test_inactive_user(self):
user = User.objects.create(username='knownuser', is_active=False)
response = self.client.get('/remote_user/', **{self.header: self.known_user})
self.assertEqual(response.context['user'].username, user.username)
user = User.objects.create(username="knownuser", is_active=False)
response = self.client.get("/remote_user/", **{self.header: self.known_user})
self.assertEqual(response.context["user"].username, user.username)
class CustomRemoteUserBackend(RemoteUserBackend):
@@ -218,13 +213,13 @@ class CustomRemoteUserBackend(RemoteUserBackend):
"""
Grabs username before the @ character.
"""
return username.split('@')[0]
return username.split("@")[0]
def configure_user(self, request, user):
"""
Sets user's email address using the email specified in an HTTP header.
"""
user.email = request.META.get(RemoteUserTest.email_header, '')
user.email = request.META.get(RemoteUserTest.email_header, "")
user.save()
return user
@@ -235,11 +230,11 @@ class RemoteUserCustomTest(RemoteUserTest):
and configure_user methods.
"""
backend = 'auth_tests.test_remote_user.CustomRemoteUserBackend'
backend = "auth_tests.test_remote_user.CustomRemoteUserBackend"
# REMOTE_USER strings with email addresses for the custom backend to
# clean.
known_user = 'knownuser@example.com'
known_user2 = 'knownuser2@example.com'
known_user = "knownuser@example.com"
known_user2 = "knownuser2@example.com"
def test_known_user(self):
"""
@@ -247,8 +242,8 @@ class RemoteUserCustomTest(RemoteUserTest):
should not have been configured with an email address.
"""
super().test_known_user()
self.assertEqual(User.objects.get(username='knownuser').email, '')
self.assertEqual(User.objects.get(username='knownuser2').email, '')
self.assertEqual(User.objects.get(username="knownuser").email, "")
self.assertEqual(User.objects.get(username="knownuser2").email, "")
def test_unknown_user(self):
"""
@@ -256,22 +251,26 @@ class RemoteUserCustomTest(RemoteUserTest):
provided in the request header.
"""
num_users = User.objects.count()
response = self.client.get('/remote_user/', **{
self.header: 'newuser',
self.email_header: 'user@example.com',
})
self.assertEqual(response.context['user'].username, 'newuser')
self.assertEqual(response.context['user'].email, 'user@example.com')
response = self.client.get(
"/remote_user/",
**{
self.header: "newuser",
self.email_header: "user@example.com",
},
)
self.assertEqual(response.context["user"].username, "newuser")
self.assertEqual(response.context["user"].email, "user@example.com")
self.assertEqual(User.objects.count(), num_users + 1)
newuser = User.objects.get(username='newuser')
self.assertEqual(newuser.email, 'user@example.com')
newuser = User.objects.get(username="newuser")
self.assertEqual(newuser.email, "user@example.com")
class CustomHeaderMiddleware(RemoteUserMiddleware):
"""
Middleware that overrides custom HTTP auth user header.
"""
header = 'HTTP_AUTHUSER'
header = "HTTP_AUTHUSER"
class CustomHeaderRemoteUserTest(RemoteUserTest):
@@ -279,10 +278,9 @@ class CustomHeaderRemoteUserTest(RemoteUserTest):
Tests a custom RemoteUserMiddleware subclass with custom HTTP auth user
header.
"""
middleware = (
'auth_tests.test_remote_user.CustomHeaderMiddleware'
)
header = 'HTTP_AUTHUSER'
middleware = "auth_tests.test_remote_user.CustomHeaderMiddleware"
header = "HTTP_AUTHUSER"
class PersistentRemoteUserTest(RemoteUserTest):
@@ -290,7 +288,8 @@ class PersistentRemoteUserTest(RemoteUserTest):
PersistentRemoteUserMiddleware keeps the user logged in even if the
subsequent calls do not contain the header value.
"""
middleware = 'django.contrib.auth.middleware.PersistentRemoteUserMiddleware'
middleware = "django.contrib.auth.middleware.PersistentRemoteUserMiddleware"
require_header = False
def test_header_disappears(self):
@@ -298,11 +297,11 @@ class PersistentRemoteUserTest(RemoteUserTest):
A logged in user is kept logged in even if the REMOTE_USER header
disappears during the same browser session.
"""
User.objects.create(username='knownuser')
User.objects.create(username="knownuser")
# Known user authenticates
response = self.client.get('/remote_user/', **{self.header: self.known_user})
self.assertEqual(response.context['user'].username, 'knownuser')
response = self.client.get("/remote_user/", **{self.header: self.known_user})
self.assertEqual(response.context["user"].username, "knownuser")
# Should stay logged in if the REMOTE_USER header disappears.
response = self.client.get('/remote_user/')
self.assertFalse(response.context['user'].is_anonymous)
self.assertEqual(response.context['user'].username, 'knownuser')
response = self.client.get("/remote_user/")
self.assertFalse(response.context["user"].is_anonymous)
self.assertEqual(response.context["user"].username, "knownuser")

View File

@@ -8,13 +8,12 @@ from django.test.client import RequestFactory
from .models import MinimalUser, UserWithDisabledLastLoginField
@override_settings(ROOT_URLCONF='auth_tests.urls')
@override_settings(ROOT_URLCONF="auth_tests.urls")
class SignalTestCase(TestCase):
@classmethod
def setUpTestData(cls):
cls.u1 = User.objects.create_user(username='testclient', password='password')
cls.u3 = User.objects.create_user(username='staff', password='password')
cls.u1 = User.objects.create_user(username="testclient", password="password")
cls.u3 = User.objects.create_user(username="staff", password="password")
def listener_login(self, user, **kwargs):
self.logged_in.append(user)
@@ -42,18 +41,18 @@ class SignalTestCase(TestCase):
def test_login(self):
# Only a successful login will trigger the success signal.
self.client.login(username='testclient', password='bad')
self.client.login(username="testclient", password="bad")
self.assertEqual(len(self.logged_in), 0)
self.assertEqual(len(self.login_failed), 1)
self.assertEqual(self.login_failed[0]['credentials']['username'], 'testclient')
self.assertEqual(self.login_failed[0]["credentials"]["username"], "testclient")
# verify the password is cleansed
self.assertIn('***', self.login_failed[0]['credentials']['password'])
self.assertIn('request', self.login_failed[0])
self.assertIn("***", self.login_failed[0]["credentials"]["password"])
self.assertIn("request", self.login_failed[0])
# Like this:
self.client.login(username='testclient', password='password')
self.client.login(username="testclient", password="password")
self.assertEqual(len(self.logged_in), 1)
self.assertEqual(self.logged_in[0].username, 'testclient')
self.assertEqual(self.logged_in[0].username, "testclient")
# Ensure there were no more failures.
self.assertEqual(len(self.login_failed), 1)
@@ -61,15 +60,15 @@ class SignalTestCase(TestCase):
def test_logout_anonymous(self):
# The log_out function will still trigger the signal for anonymous
# users.
self.client.get('/logout/next_page/')
self.client.get("/logout/next_page/")
self.assertEqual(len(self.logged_out), 1)
self.assertIsNone(self.logged_out[0])
def test_logout(self):
self.client.login(username='testclient', password='password')
self.client.get('/logout/next_page/')
self.client.login(username="testclient", password="password")
self.client.get("/logout/next_page/")
self.assertEqual(len(self.logged_out), 1)
self.assertEqual(self.logged_out[0].username, 'testclient')
self.assertEqual(self.logged_out[0].username, "testclient")
def test_update_last_login(self):
"""Only `last_login` is updated in `update_last_login`"""
@@ -77,15 +76,15 @@ class SignalTestCase(TestCase):
old_last_login = user.last_login
user.username = "This username shouldn't get saved"
request = RequestFactory().get('/login')
request = RequestFactory().get("/login")
signals.user_logged_in.send(sender=user.__class__, request=request, user=user)
user = User.objects.get(pk=user.pk)
self.assertEqual(user.username, 'staff')
self.assertEqual(user.username, "staff")
self.assertNotEqual(user.last_login, old_last_login)
def test_failed_login_without_request(self):
authenticate(username='testclient', password='bad')
self.assertIsNone(self.login_failed[0]['request'])
authenticate(username="testclient", password="bad")
self.assertIsNone(self.login_failed[0]["request"])
def test_login_with_custom_user_without_last_login_field(self):
"""
@@ -96,19 +95,21 @@ class SignalTestCase(TestCase):
try:
signals.user_logged_in.receivers = []
with self.assertRaises(FieldDoesNotExist):
MinimalUser._meta.get_field('last_login')
with self.settings(AUTH_USER_MODEL='auth_tests.MinimalUser'):
apps.get_app_config('auth').ready()
MinimalUser._meta.get_field("last_login")
with self.settings(AUTH_USER_MODEL="auth_tests.MinimalUser"):
apps.get_app_config("auth").ready()
self.assertEqual(signals.user_logged_in.receivers, [])
# last_login is a property whose value is None.
self.assertIsNone(UserWithDisabledLastLoginField().last_login)
with self.settings(AUTH_USER_MODEL='auth_tests.UserWithDisabledLastLoginField'):
apps.get_app_config('auth').ready()
with self.settings(
AUTH_USER_MODEL="auth_tests.UserWithDisabledLastLoginField"
):
apps.get_app_config("auth").ready()
self.assertEqual(signals.user_logged_in.receivers, [])
with self.settings(AUTH_USER_MODEL='auth.User'):
apps.get_app_config('auth').ready()
with self.settings(AUTH_USER_MODEL="auth.User"):
apps.get_app_config("auth").ready()
self.assertEqual(len(signals.user_logged_in.receivers), 1)
finally:
signals.user_logged_in.receivers = last_login_receivers

View File

@@ -4,8 +4,11 @@ from django.contrib.auth import authenticate
from django.contrib.auth.models import User
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.contrib.auth.views import (
PasswordChangeDoneView, PasswordChangeView, PasswordResetCompleteView,
PasswordResetDoneView, PasswordResetView,
PasswordChangeDoneView,
PasswordChangeView,
PasswordResetCompleteView,
PasswordResetDoneView,
PasswordResetView,
)
from django.test import RequestFactory, TestCase, override_settings
from django.urls import reverse
@@ -15,35 +18,43 @@ from .client import PasswordResetConfirmClient
from .models import CustomUser
@override_settings(ROOT_URLCONF='auth_tests.urls')
@override_settings(ROOT_URLCONF="auth_tests.urls")
class AuthTemplateTests(TestCase):
request_factory = RequestFactory()
@classmethod
def setUpTestData(cls):
user = User.objects.create_user('jsmith', 'jsmith@example.com', 'pass')
user = authenticate(username=user.username, password='pass')
request = cls.request_factory.get('/somepath/')
user = User.objects.create_user("jsmith", "jsmith@example.com", "pass")
user = authenticate(username=user.username, password="pass")
request = cls.request_factory.get("/somepath/")
request.user = user
cls.user, cls.request = user, request
def test_password_reset_view(self):
response = PasswordResetView.as_view(success_url='dummy/')(self.request)
self.assertContains(response, '<title>Password reset | Django site admin</title>')
self.assertContains(response, '<h1>Password reset</h1>')
response = PasswordResetView.as_view(success_url="dummy/")(self.request)
self.assertContains(
response, "<title>Password reset | Django site admin</title>"
)
self.assertContains(response, "<h1>Password reset</h1>")
def test_password_reset_done_view(self):
response = PasswordResetDoneView.as_view()(self.request)
self.assertContains(response, '<title>Password reset sent | Django site admin</title>')
self.assertContains(response, '<h1>Password reset sent</h1>')
self.assertContains(
response, "<title>Password reset sent | Django site admin</title>"
)
self.assertContains(response, "<h1>Password reset sent</h1>")
def test_password_reset_confirm_view_invalid_token(self):
# PasswordResetConfirmView invalid token
client = PasswordResetConfirmClient()
url = reverse('password_reset_confirm', kwargs={'uidb64': 'Bad', 'token': 'Bad-Token'})
url = reverse(
"password_reset_confirm", kwargs={"uidb64": "Bad", "token": "Bad-Token"}
)
response = client.get(url)
self.assertContains(response, '<title>Password reset unsuccessful | Django site admin</title>')
self.assertContains(response, '<h1>Password reset unsuccessful</h1>')
self.assertContains(
response, "<title>Password reset unsuccessful | Django site admin</title>"
)
self.assertContains(response, "<h1>Password reset unsuccessful</h1>")
def test_password_reset_confirm_view_valid_token(self):
# PasswordResetConfirmView valid token
@@ -51,10 +62,14 @@ class AuthTemplateTests(TestCase):
default_token_generator = PasswordResetTokenGenerator()
token = default_token_generator.make_token(self.user)
uidb64 = urlsafe_base64_encode(str(self.user.pk).encode())
url = reverse('password_reset_confirm', kwargs={'uidb64': uidb64, 'token': token})
url = reverse(
"password_reset_confirm", kwargs={"uidb64": uidb64, "token": token}
)
response = client.get(url)
self.assertContains(response, '<title>Enter new password | Django site admin</title>')
self.assertContains(response, '<h1>Enter new password</h1>')
self.assertContains(
response, "<title>Enter new password | Django site admin</title>"
)
self.assertContains(response, "<h1>Enter new password</h1>")
# The username is added to the password reset confirmation form to help
# browser's password managers.
self.assertContains(
@@ -62,24 +77,26 @@ class AuthTemplateTests(TestCase):
'<input class="hidden" autocomplete="username" value="jsmith">',
)
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUser')
@override_settings(AUTH_USER_MODEL="auth_tests.CustomUser")
def test_password_reset_confirm_view_custom_username_hint(self):
custom_user = CustomUser.custom_objects.create_user(
email='joe@example.com',
email="joe@example.com",
date_of_birth=date(1986, 11, 11),
first_name='Joe',
first_name="Joe",
)
client = PasswordResetConfirmClient()
default_token_generator = PasswordResetTokenGenerator()
token = default_token_generator.make_token(custom_user)
uidb64 = urlsafe_base64_encode(str(custom_user.pk).encode())
url = reverse('password_reset_confirm', kwargs={'uidb64': uidb64, 'token': token})
url = reverse(
"password_reset_confirm", kwargs={"uidb64": uidb64, "token": token}
)
response = client.get(url)
self.assertContains(
response,
'<title>Enter new password | Django site admin</title>',
"<title>Enter new password | Django site admin</title>",
)
self.assertContains(response, '<h1>Enter new password</h1>')
self.assertContains(response, "<h1>Enter new password</h1>")
# The username field is added to the password reset confirmation form
# to help browser's password managers.
self.assertContains(
@@ -89,15 +106,21 @@ class AuthTemplateTests(TestCase):
def test_password_reset_complete_view(self):
response = PasswordResetCompleteView.as_view()(self.request)
self.assertContains(response, '<title>Password reset complete | Django site admin</title>')
self.assertContains(response, '<h1>Password reset complete</h1>')
self.assertContains(
response, "<title>Password reset complete | Django site admin</title>"
)
self.assertContains(response, "<h1>Password reset complete</h1>")
def test_password_reset_change_view(self):
response = PasswordChangeView.as_view(success_url='dummy/')(self.request)
self.assertContains(response, '<title>Password change | Django site admin</title>')
self.assertContains(response, '<h1>Password change</h1>')
response = PasswordChangeView.as_view(success_url="dummy/")(self.request)
self.assertContains(
response, "<title>Password change | Django site admin</title>"
)
self.assertContains(response, "<h1>Password change</h1>")
def test_password_change_done_view(self):
response = PasswordChangeDoneView.as_view()(self.request)
self.assertContains(response, '<title>Password change successful | Django site admin</title>')
self.assertContains(response, '<h1>Password change successful</h1>')
self.assertContains(
response, "<title>Password change successful | Django site admin</title>"
)
self.assertContains(response, "<h1>Password change successful</h1>")

View File

@@ -20,9 +20,8 @@ class MockedPasswordResetTokenGenerator(PasswordResetTokenGenerator):
class TokenGeneratorTest(TestCase):
def test_make_token(self):
user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')
user = User.objects.create_user("tokentestuser", "test2@example.com", "testpw")
p0 = PasswordResetTokenGenerator()
tk1 = p0.make_token(user)
self.assertIs(p0.check_token(user, tk1), True)
@@ -32,8 +31,8 @@ class TokenGeneratorTest(TestCase):
The token generated for a user created in the same request
will work correctly.
"""
user = User.objects.create_user('comebackkid', 'test3@example.com', 'testpw')
user_reload = User.objects.get(username='comebackkid')
user = User.objects.create_user("comebackkid", "test3@example.com", "testpw")
user_reload = User.objects.get(username="comebackkid")
p0 = MockedPasswordResetTokenGenerator(datetime.now())
tk1 = p0.make_token(user)
tk2 = p0.make_token(user_reload)
@@ -43,20 +42,20 @@ class TokenGeneratorTest(TestCase):
"""Updating the user email address invalidates the token."""
tests = [
(CustomEmailField, None),
(CustomEmailField, 'test4@example.com'),
(User, 'test4@example.com'),
(CustomEmailField, "test4@example.com"),
(User, "test4@example.com"),
]
for model, email in tests:
with self.subTest(model=model.__qualname__, email=email):
user = model.objects.create_user(
'changeemailuser',
"changeemailuser",
email=email,
password='testpw',
password="testpw",
)
p0 = PasswordResetTokenGenerator()
tk1 = p0.make_token(user)
self.assertIs(p0.check_token(user, tk1), True)
setattr(user, user.get_email_field_name(), 'test4new@example.com')
setattr(user, user.get_email_field_name(), "test4new@example.com")
user.save()
self.assertIs(p0.check_token(user, tk1), False)
@@ -64,7 +63,7 @@ class TokenGeneratorTest(TestCase):
"""The token is valid after n seconds, but no greater."""
# Uses a mocked version of PasswordResetTokenGenerator so we can change
# the value of 'now'.
user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')
user = User.objects.create_user("tokentestuser", "test2@example.com", "testpw")
now = datetime.now()
p0 = MockedPasswordResetTokenGenerator(now)
tk1 = p0.make_token(user)
@@ -87,7 +86,7 @@ class TokenGeneratorTest(TestCase):
self.assertIs(p4.check_token(user, tk1), False)
def test_check_token_with_nonexistent_token_and_user(self):
user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')
user = User.objects.create_user("tokentestuser", "test2@example.com", "testpw")
p0 = PasswordResetTokenGenerator()
tk1 = p0.make_token(user)
self.assertIs(p0.check_token(None, tk1), False)
@@ -98,8 +97,8 @@ class TokenGeneratorTest(TestCase):
A valid token can be created with a secret other than SECRET_KEY by
using the PasswordResetTokenGenerator.secret attribute.
"""
user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')
new_secret = 'abcdefghijkl'
user = User.objects.create_user("tokentestuser", "test2@example.com", "testpw")
new_secret = "abcdefghijkl"
# Create and check a token with a different secret.
p0 = PasswordResetTokenGenerator()
p0.secret = new_secret
@@ -116,9 +115,9 @@ class TokenGeneratorTest(TestCase):
def test_token_with_different_secret_subclass(self):
class CustomPasswordResetTokenGenerator(PasswordResetTokenGenerator):
secret = 'test-secret'
secret = "test-secret"
user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')
user = User.objects.create_user("tokentestuser", "test2@example.com", "testpw")
custom_password_generator = CustomPasswordResetTokenGenerator()
tk_custom = custom_password_generator.make_token(user)
self.assertIs(custom_password_generator.check_token(user, tk_custom), True)
@@ -134,44 +133,44 @@ class TokenGeneratorTest(TestCase):
self.assertIs(custom_password_generator.check_token(user, tk_default), False)
self.assertIs(default_password_generator.check_token(user, tk_custom), False)
@override_settings(SECRET_KEY='')
@override_settings(SECRET_KEY="")
def test_secret_lazy_validation(self):
default_token_generator = PasswordResetTokenGenerator()
msg = 'The SECRET_KEY setting must not be empty.'
msg = "The SECRET_KEY setting must not be empty."
with self.assertRaisesMessage(ImproperlyConfigured, msg):
default_token_generator.secret
def test_check_token_secret_fallbacks(self):
user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')
user = User.objects.create_user("tokentestuser", "test2@example.com", "testpw")
p1 = PasswordResetTokenGenerator()
p1.secret = 'secret'
p1.secret = "secret"
tk = p1.make_token(user)
p2 = PasswordResetTokenGenerator()
p2.secret = 'newsecret'
p2.secret_fallbacks = ['secret']
p2.secret = "newsecret"
p2.secret_fallbacks = ["secret"]
self.assertIs(p1.check_token(user, tk), True)
self.assertIs(p2.check_token(user, tk), True)
@override_settings(
SECRET_KEY='secret',
SECRET_KEY_FALLBACKS=['oldsecret'],
SECRET_KEY="secret",
SECRET_KEY_FALLBACKS=["oldsecret"],
)
def test_check_token_secret_key_fallbacks(self):
user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')
user = User.objects.create_user("tokentestuser", "test2@example.com", "testpw")
p1 = PasswordResetTokenGenerator()
p1.secret = 'oldsecret'
p1.secret = "oldsecret"
tk = p1.make_token(user)
p2 = PasswordResetTokenGenerator()
self.assertIs(p2.check_token(user, tk), True)
@override_settings(
SECRET_KEY='secret',
SECRET_KEY_FALLBACKS=['oldsecret'],
SECRET_KEY="secret",
SECRET_KEY_FALLBACKS=["oldsecret"],
)
def test_check_token_secret_key_fallbacks_override(self):
user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')
user = User.objects.create_user("tokentestuser", "test2@example.com", "testpw")
p1 = PasswordResetTokenGenerator()
p1.secret = 'oldsecret'
p1.secret = "oldsecret"
tk = p1.make_token(user)
p2 = PasswordResetTokenGenerator()
p2.secret_fallbacks = []

View File

@@ -3,10 +3,15 @@ import os
from django.contrib.auth import validators
from django.contrib.auth.models import User
from django.contrib.auth.password_validation import (
CommonPasswordValidator, MinimumLengthValidator, NumericPasswordValidator,
UserAttributeSimilarityValidator, get_default_password_validators,
get_password_validators, password_changed,
password_validators_help_text_html, password_validators_help_texts,
CommonPasswordValidator,
MinimumLengthValidator,
NumericPasswordValidator,
UserAttributeSimilarityValidator,
get_default_password_validators,
get_password_validators,
password_changed,
password_validators_help_text_html,
password_validators_help_texts,
validate_password,
)
from django.core.exceptions import ValidationError
@@ -16,46 +21,57 @@ from django.test.utils import isolate_apps
from django.utils.html import conditional_escape
@override_settings(AUTH_PASSWORD_VALIDATORS=[
{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'},
{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 'OPTIONS': {
'min_length': 12,
}},
])
@override_settings(
AUTH_PASSWORD_VALIDATORS=[
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
"OPTIONS": {
"min_length": 12,
},
},
]
)
class PasswordValidationTest(SimpleTestCase):
def test_get_default_password_validators(self):
validators = get_default_password_validators()
self.assertEqual(len(validators), 2)
self.assertEqual(validators[0].__class__.__name__, 'CommonPasswordValidator')
self.assertEqual(validators[1].__class__.__name__, 'MinimumLengthValidator')
self.assertEqual(validators[0].__class__.__name__, "CommonPasswordValidator")
self.assertEqual(validators[1].__class__.__name__, "MinimumLengthValidator")
self.assertEqual(validators[1].min_length, 12)
def test_get_password_validators_custom(self):
validator_config = [{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'}]
validator_config = [
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"}
]
validators = get_password_validators(validator_config)
self.assertEqual(len(validators), 1)
self.assertEqual(validators[0].__class__.__name__, 'CommonPasswordValidator')
self.assertEqual(validators[0].__class__.__name__, "CommonPasswordValidator")
self.assertEqual(get_password_validators([]), [])
def test_validate_password(self):
self.assertIsNone(validate_password('sufficiently-long'))
msg_too_short = 'This password is too short. It must contain at least 12 characters.'
self.assertIsNone(validate_password("sufficiently-long"))
msg_too_short = (
"This password is too short. It must contain at least 12 characters."
)
with self.assertRaises(ValidationError) as cm:
validate_password('django4242')
validate_password("django4242")
self.assertEqual(cm.exception.messages, [msg_too_short])
self.assertEqual(cm.exception.error_list[0].code, 'password_too_short')
self.assertEqual(cm.exception.error_list[0].code, "password_too_short")
with self.assertRaises(ValidationError) as cm:
validate_password('password')
self.assertEqual(cm.exception.messages, ['This password is too common.', msg_too_short])
self.assertEqual(cm.exception.error_list[0].code, 'password_too_common')
validate_password("password")
self.assertEqual(
cm.exception.messages, ["This password is too common.", msg_too_short]
)
self.assertEqual(cm.exception.error_list[0].code, "password_too_common")
self.assertIsNone(validate_password('password', password_validators=[]))
self.assertIsNone(validate_password("password", password_validators=[]))
def test_password_changed(self):
self.assertIsNone(password_changed('password'))
self.assertIsNone(password_changed("password"))
def test_password_changed_with_custom_validator(self):
class Validator:
@@ -65,139 +81,151 @@ class PasswordValidationTest(SimpleTestCase):
user = object()
validator = Validator()
password_changed('password', user=user, password_validators=(validator,))
password_changed("password", user=user, password_validators=(validator,))
self.assertIs(validator.user, user)
self.assertEqual(validator.password, 'password')
self.assertEqual(validator.password, "password")
def test_password_validators_help_texts(self):
help_texts = password_validators_help_texts()
self.assertEqual(len(help_texts), 2)
self.assertIn('12 characters', help_texts[1])
self.assertIn("12 characters", help_texts[1])
self.assertEqual(password_validators_help_texts(password_validators=[]), [])
def test_password_validators_help_text_html(self):
help_text = password_validators_help_text_html()
self.assertEqual(help_text.count('<li>'), 2)
self.assertIn('12 characters', help_text)
self.assertEqual(help_text.count("<li>"), 2)
self.assertIn("12 characters", help_text)
def test_password_validators_help_text_html_escaping(self):
class AmpersandValidator:
def get_help_text(self):
return 'Must contain &'
return "Must contain &"
help_text = password_validators_help_text_html([AmpersandValidator()])
self.assertEqual(help_text, '<ul><li>Must contain &amp;</li></ul>')
self.assertEqual(help_text, "<ul><li>Must contain &amp;</li></ul>")
# help_text is marked safe and therefore unchanged by conditional_escape().
self.assertEqual(help_text, conditional_escape(help_text))
@override_settings(AUTH_PASSWORD_VALIDATORS=[])
def test_empty_password_validator_help_text_html(self):
self.assertEqual(password_validators_help_text_html(), '')
self.assertEqual(password_validators_help_text_html(), "")
class MinimumLengthValidatorTest(SimpleTestCase):
def test_validate(self):
expected_error = "This password is too short. It must contain at least %d characters."
self.assertIsNone(MinimumLengthValidator().validate('12345678'))
self.assertIsNone(MinimumLengthValidator(min_length=3).validate('123'))
expected_error = (
"This password is too short. It must contain at least %d characters."
)
self.assertIsNone(MinimumLengthValidator().validate("12345678"))
self.assertIsNone(MinimumLengthValidator(min_length=3).validate("123"))
with self.assertRaises(ValidationError) as cm:
MinimumLengthValidator().validate('1234567')
MinimumLengthValidator().validate("1234567")
self.assertEqual(cm.exception.messages, [expected_error % 8])
self.assertEqual(cm.exception.error_list[0].code, 'password_too_short')
self.assertEqual(cm.exception.error_list[0].code, "password_too_short")
with self.assertRaises(ValidationError) as cm:
MinimumLengthValidator(min_length=3).validate('12')
MinimumLengthValidator(min_length=3).validate("12")
self.assertEqual(cm.exception.messages, [expected_error % 3])
def test_help_text(self):
self.assertEqual(
MinimumLengthValidator().get_help_text(),
"Your password must contain at least 8 characters."
"Your password must contain at least 8 characters.",
)
class UserAttributeSimilarityValidatorTest(TestCase):
def test_validate(self):
user = User.objects.create_user(
username='testclient', password='password', email='testclient@example.com',
first_name='Test', last_name='Client',
username="testclient",
password="password",
email="testclient@example.com",
first_name="Test",
last_name="Client",
)
expected_error = "The password is too similar to the %s."
self.assertIsNone(UserAttributeSimilarityValidator().validate('testclient'))
self.assertIsNone(UserAttributeSimilarityValidator().validate("testclient"))
with self.assertRaises(ValidationError) as cm:
UserAttributeSimilarityValidator().validate('testclient', user=user),
UserAttributeSimilarityValidator().validate("testclient", user=user),
self.assertEqual(cm.exception.messages, [expected_error % "username"])
self.assertEqual(cm.exception.error_list[0].code, 'password_too_similar')
self.assertEqual(cm.exception.error_list[0].code, "password_too_similar")
with self.assertRaises(ValidationError) as cm:
UserAttributeSimilarityValidator().validate('example.com', user=user),
UserAttributeSimilarityValidator().validate("example.com", user=user),
self.assertEqual(cm.exception.messages, [expected_error % "email address"])
with self.assertRaises(ValidationError) as cm:
UserAttributeSimilarityValidator(
user_attributes=['first_name'],
user_attributes=["first_name"],
max_similarity=0.3,
).validate('testclient', user=user)
).validate("testclient", user=user)
self.assertEqual(cm.exception.messages, [expected_error % "first name"])
# max_similarity=1 doesn't allow passwords that are identical to the
# attribute's value.
with self.assertRaises(ValidationError) as cm:
UserAttributeSimilarityValidator(
user_attributes=['first_name'],
user_attributes=["first_name"],
max_similarity=1,
).validate(user.first_name, user=user)
self.assertEqual(cm.exception.messages, [expected_error % "first name"])
# Very low max_similarity is rejected.
msg = 'max_similarity must be at least 0.1'
msg = "max_similarity must be at least 0.1"
with self.assertRaisesMessage(ValueError, msg):
UserAttributeSimilarityValidator(max_similarity=0.09)
# Passes validation.
self.assertIsNone(
UserAttributeSimilarityValidator(user_attributes=['first_name']).validate('testclient', user=user)
UserAttributeSimilarityValidator(user_attributes=["first_name"]).validate(
"testclient", user=user
)
)
@isolate_apps('auth_tests')
@isolate_apps("auth_tests")
def test_validate_property(self):
class TestUser(models.Model):
pass
@property
def username(self):
return 'foobar'
return "foobar"
with self.assertRaises(ValidationError) as cm:
UserAttributeSimilarityValidator().validate('foobar', user=TestUser()),
self.assertEqual(cm.exception.messages, ['The password is too similar to the username.'])
UserAttributeSimilarityValidator().validate("foobar", user=TestUser()),
self.assertEqual(
cm.exception.messages, ["The password is too similar to the username."]
)
def test_help_text(self):
self.assertEqual(
UserAttributeSimilarityValidator().get_help_text(),
'Your password cant be too similar to your other personal information.'
"Your password cant be too similar to your other personal information.",
)
class CommonPasswordValidatorTest(SimpleTestCase):
def test_validate(self):
expected_error = "This password is too common."
self.assertIsNone(CommonPasswordValidator().validate('a-safe-password'))
self.assertIsNone(CommonPasswordValidator().validate("a-safe-password"))
with self.assertRaises(ValidationError) as cm:
CommonPasswordValidator().validate('godzilla')
CommonPasswordValidator().validate("godzilla")
self.assertEqual(cm.exception.messages, [expected_error])
def test_validate_custom_list(self):
path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'common-passwords-custom.txt')
path = os.path.join(
os.path.dirname(os.path.realpath(__file__)), "common-passwords-custom.txt"
)
validator = CommonPasswordValidator(password_list_path=path)
expected_error = "This password is too common."
self.assertIsNone(validator.validate('a-safe-password'))
self.assertIsNone(validator.validate("a-safe-password"))
with self.assertRaises(ValidationError) as cm:
validator.validate('from-my-custom-list')
validator.validate("from-my-custom-list")
self.assertEqual(cm.exception.messages, [expected_error])
self.assertEqual(cm.exception.error_list[0].code, 'password_too_common')
self.assertEqual(cm.exception.error_list[0].code, "password_too_common")
def test_validate_django_supplied_file(self):
validator = CommonPasswordValidator()
@@ -207,34 +235,37 @@ class CommonPasswordValidatorTest(SimpleTestCase):
def test_help_text(self):
self.assertEqual(
CommonPasswordValidator().get_help_text(),
'Your password cant be a commonly used password.'
"Your password cant be a commonly used password.",
)
class NumericPasswordValidatorTest(SimpleTestCase):
def test_validate(self):
expected_error = "This password is entirely numeric."
self.assertIsNone(NumericPasswordValidator().validate('a-safe-password'))
self.assertIsNone(NumericPasswordValidator().validate("a-safe-password"))
with self.assertRaises(ValidationError) as cm:
NumericPasswordValidator().validate('42424242')
NumericPasswordValidator().validate("42424242")
self.assertEqual(cm.exception.messages, [expected_error])
self.assertEqual(cm.exception.error_list[0].code, 'password_entirely_numeric')
self.assertEqual(cm.exception.error_list[0].code, "password_entirely_numeric")
def test_help_text(self):
self.assertEqual(
NumericPasswordValidator().get_help_text(),
'Your password cant be entirely numeric.'
"Your password cant be entirely numeric.",
)
class UsernameValidatorsTests(SimpleTestCase):
def test_unicode_validator(self):
valid_usernames = ['joe', 'René', 'ᴮᴵᴳᴮᴵᴿᴰ', 'أحمد']
valid_usernames = ["joe", "René", "ᴮᴵᴳᴮᴵᴿᴰ", "أحمد"]
invalid_usernames = [
"o'connell", "عبد ال",
"zerowidth\u200Bspace", "nonbreaking\u00A0space",
"en\u2013dash", 'trailingnewline\u000A',
"o'connell",
"عبد ال",
"zerowidth\u200Bspace",
"nonbreaking\u00A0space",
"en\u2013dash",
"trailingnewline\u000A",
]
v = validators.UnicodeUsernameValidator()
for valid in valid_usernames:
@@ -246,8 +277,14 @@ class UsernameValidatorsTests(SimpleTestCase):
v(invalid)
def test_ascii_validator(self):
valid_usernames = ['glenn', 'GLEnN', 'jean-marc']
invalid_usernames = ["o'connell", 'Éric', 'jean marc', "أحمد", 'trailingnewline\n']
valid_usernames = ["glenn", "GLEnN", "jean-marc"]
invalid_usernames = [
"o'connell",
"Éric",
"jean marc",
"أحمد",
"trailingnewline\n",
]
v = validators.ASCIIUsernameValidator()
for valid in valid_usernames:
with self.subTest(valid=valid):

File diff suppressed because it is too large Load Diff

View File

@@ -28,143 +28,175 @@ def remote_user_auth_view(request):
def auth_processor_no_attr_access(request):
render(request, 'context_processors/auth_attrs_no_access.html')
render(request, "context_processors/auth_attrs_no_access.html")
# *After* rendering, we check whether the session was accessed
return render(request,
'context_processors/auth_attrs_test_access.html',
{'session_accessed': request.session.accessed})
return render(
request,
"context_processors/auth_attrs_test_access.html",
{"session_accessed": request.session.accessed},
)
def auth_processor_attr_access(request):
render(request, 'context_processors/auth_attrs_access.html')
return render(request,
'context_processors/auth_attrs_test_access.html',
{'session_accessed': request.session.accessed})
render(request, "context_processors/auth_attrs_access.html")
return render(
request,
"context_processors/auth_attrs_test_access.html",
{"session_accessed": request.session.accessed},
)
def auth_processor_user(request):
return render(request, 'context_processors/auth_attrs_user.html')
return render(request, "context_processors/auth_attrs_user.html")
def auth_processor_perms(request):
return render(request, 'context_processors/auth_attrs_perms.html')
return render(request, "context_processors/auth_attrs_perms.html")
def auth_processor_perm_in_perms(request):
return render(request, 'context_processors/auth_attrs_perm_in_perms.html')
return render(request, "context_processors/auth_attrs_perm_in_perms.html")
def auth_processor_messages(request):
info(request, "Message 1")
return render(request, 'context_processors/auth_attrs_messages.html')
return render(request, "context_processors/auth_attrs_messages.html")
def userpage(request):
pass
@permission_required('unknown.permission')
@permission_required("unknown.permission")
def permission_required_redirect(request):
pass
@permission_required('unknown.permission', raise_exception=True)
@permission_required("unknown.permission", raise_exception=True)
def permission_required_exception(request):
pass
@login_required
@permission_required('unknown.permission', raise_exception=True)
@permission_required("unknown.permission", raise_exception=True)
def login_and_permission_required_exception(request):
pass
class CustomDefaultRedirectURLLoginView(LoginView):
def get_default_redirect_url(self):
return '/custom/'
return "/custom/"
# special urls for auth test cases
urlpatterns = auth_urlpatterns + [
path('logout/custom_query/', views.LogoutView.as_view(redirect_field_name='follow')),
path('logout/next_page/', views.LogoutView.as_view(next_page='/somewhere/')),
path('logout/next_page/named/', views.LogoutView.as_view(next_page='password_reset')),
path('logout/allowed_hosts/', views.LogoutView.as_view(success_url_allowed_hosts={'otherserver'})),
path('remote_user/', remote_user_auth_view),
path('password_reset_from_email/', views.PasswordResetView.as_view(from_email='staffmember@example.com')),
path(
'password_reset_extra_email_context/',
"logout/custom_query/", views.LogoutView.as_view(redirect_field_name="follow")
),
path("logout/next_page/", views.LogoutView.as_view(next_page="/somewhere/")),
path(
"logout/next_page/named/", views.LogoutView.as_view(next_page="password_reset")
),
path(
"logout/allowed_hosts/",
views.LogoutView.as_view(success_url_allowed_hosts={"otherserver"}),
),
path("remote_user/", remote_user_auth_view),
path(
"password_reset_from_email/",
views.PasswordResetView.as_view(from_email="staffmember@example.com"),
),
path(
"password_reset_extra_email_context/",
views.PasswordResetView.as_view(
extra_email_context={'greeting': 'Hello!', 'domain': 'custom.example.com'},
extra_email_context={"greeting": "Hello!", "domain": "custom.example.com"},
),
),
path(
'password_reset/custom_redirect/',
views.PasswordResetView.as_view(success_url='/custom/')),
"password_reset/custom_redirect/",
views.PasswordResetView.as_view(success_url="/custom/"),
),
path(
'password_reset/custom_redirect/named/',
views.PasswordResetView.as_view(success_url=reverse_lazy('password_reset'))),
"password_reset/custom_redirect/named/",
views.PasswordResetView.as_view(success_url=reverse_lazy("password_reset")),
),
path(
'password_reset/html_email_template/',
"password_reset/html_email_template/",
views.PasswordResetView.as_view(
html_email_template_name='registration/html_password_reset_email.html'
)),
path(
'reset/custom/<uidb64>/<token>/',
views.PasswordResetConfirmView.as_view(success_url='/custom/'),
html_email_template_name="registration/html_password_reset_email.html"
),
),
path(
'reset/custom/named/<uidb64>/<token>/',
views.PasswordResetConfirmView.as_view(success_url=reverse_lazy('password_reset')),
"reset/custom/<uidb64>/<token>/",
views.PasswordResetConfirmView.as_view(success_url="/custom/"),
),
path(
'reset/custom/token/<uidb64>/<token>/',
views.PasswordResetConfirmView.as_view(reset_url_token='set-passwordcustom'),
"reset/custom/named/<uidb64>/<token>/",
views.PasswordResetConfirmView.as_view(
success_url=reverse_lazy("password_reset")
),
),
path(
'reset/post_reset_login/<uidb64>/<token>/',
"reset/custom/token/<uidb64>/<token>/",
views.PasswordResetConfirmView.as_view(reset_url_token="set-passwordcustom"),
),
path(
"reset/post_reset_login/<uidb64>/<token>/",
views.PasswordResetConfirmView.as_view(post_reset_login=True),
),
path(
'reset/post_reset_login_custom_backend/<uidb64>/<token>/',
"reset/post_reset_login_custom_backend/<uidb64>/<token>/",
views.PasswordResetConfirmView.as_view(
post_reset_login=True,
post_reset_login_backend='django.contrib.auth.backends.AllowAllUsersModelBackend',
post_reset_login_backend="django.contrib.auth.backends.AllowAllUsersModelBackend",
),
),
path('reset/missing_parameters/', views.PasswordResetConfirmView.as_view()),
path('password_change/custom/',
views.PasswordChangeView.as_view(success_url='/custom/')),
path('password_change/custom/named/',
views.PasswordChangeView.as_view(success_url=reverse_lazy('password_reset'))),
path('login_required/', login_required(views.PasswordResetView.as_view())),
path('login_required_login_url/', login_required(views.PasswordResetView.as_view(), login_url='/somewhere/')),
path('auth_processor_no_attr_access/', auth_processor_no_attr_access),
path('auth_processor_attr_access/', auth_processor_attr_access),
path('auth_processor_user/', auth_processor_user),
path('auth_processor_perms/', auth_processor_perms),
path('auth_processor_perm_in_perms/', auth_processor_perm_in_perms),
path('auth_processor_messages/', auth_processor_messages),
path("reset/missing_parameters/", views.PasswordResetConfirmView.as_view()),
path(
'custom_request_auth_login/',
views.LoginView.as_view(authentication_form=CustomRequestAuthenticationForm)),
re_path('^userpage/(.+)/$', userpage, name='userpage'),
path('login/redirect_authenticated_user_default/', views.LoginView.as_view()),
path('login/redirect_authenticated_user/',
views.LoginView.as_view(redirect_authenticated_user=True)),
path('login/allowed_hosts/',
views.LoginView.as_view(success_url_allowed_hosts={'otherserver'})),
path('login/get_default_redirect_url/', CustomDefaultRedirectURLLoginView.as_view()),
path('login/next_page/', views.LoginView.as_view(next_page='/somewhere/')),
path('login/next_page/named/', views.LoginView.as_view(next_page='password_reset')),
path('permission_required_redirect/', permission_required_redirect),
path('permission_required_exception/', permission_required_exception),
path('login_and_permission_required_exception/', login_and_permission_required_exception),
path('setlang/', set_language, name='set_language'),
"password_change/custom/",
views.PasswordChangeView.as_view(success_url="/custom/"),
),
path(
"password_change/custom/named/",
views.PasswordChangeView.as_view(success_url=reverse_lazy("password_reset")),
),
path("login_required/", login_required(views.PasswordResetView.as_view())),
path(
"login_required_login_url/",
login_required(views.PasswordResetView.as_view(), login_url="/somewhere/"),
),
path("auth_processor_no_attr_access/", auth_processor_no_attr_access),
path("auth_processor_attr_access/", auth_processor_attr_access),
path("auth_processor_user/", auth_processor_user),
path("auth_processor_perms/", auth_processor_perms),
path("auth_processor_perm_in_perms/", auth_processor_perm_in_perms),
path("auth_processor_messages/", auth_processor_messages),
path(
"custom_request_auth_login/",
views.LoginView.as_view(authentication_form=CustomRequestAuthenticationForm),
),
re_path("^userpage/(.+)/$", userpage, name="userpage"),
path("login/redirect_authenticated_user_default/", views.LoginView.as_view()),
path(
"login/redirect_authenticated_user/",
views.LoginView.as_view(redirect_authenticated_user=True),
),
path(
"login/allowed_hosts/",
views.LoginView.as_view(success_url_allowed_hosts={"otherserver"}),
),
path(
"login/get_default_redirect_url/", CustomDefaultRedirectURLLoginView.as_view()
),
path("login/next_page/", views.LoginView.as_view(next_page="/somewhere/")),
path("login/next_page/named/", views.LoginView.as_view(next_page="password_reset")),
path("permission_required_redirect/", permission_required_redirect),
path("permission_required_exception/", permission_required_exception),
path(
"login_and_permission_required_exception/",
login_and_permission_required_exception,
),
path("setlang/", set_language, name="set_language"),
# This line is only required to render the password reset with is_admin=True
path('admin/', admin.site.urls),
path("admin/", admin.site.urls),
]

View File

@@ -9,10 +9,10 @@ from django.contrib.auth.urls import urlpatterns
from django.urls import path
# Create a silo'd admin site for just the user/group admins.
site = admin.AdminSite(name='auth_test_admin')
site = admin.AdminSite(name="auth_test_admin")
site.register(User, UserAdmin)
site.register(Group, GroupAdmin)
urlpatterns += [
path('admin/', site.urls),
path("admin/", site.urls),
]

View File

@@ -3,7 +3,7 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from django.urls import path
site = admin.AdminSite(name='custom_user_admin')
site = admin.AdminSite(name="custom_user_admin")
class CustomUserAdmin(UserAdmin):
@@ -19,5 +19,5 @@ class CustomUserAdmin(UserAdmin):
site.register(get_user_model(), CustomUserAdmin)
urlpatterns = [
path('admin/', site.urls),
path("admin/", site.urls),
]