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:
committed by
Mariusz Felisiak
parent
f68fa8b45d
commit
9c19aff7c7
@@ -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"]
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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",
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -3,4 +3,4 @@ from django.db import models
|
||||
|
||||
class MinimalUser(models.Model):
|
||||
REQUIRED_FIELDS = ()
|
||||
USERNAME_FIELD = 'id'
|
||||
USERNAME_FIELD = "id"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"),)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>'********************'</pre></td></tr>',
|
||||
"<pre>'********************'</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>'********************'</pre></td></tr>',
|
||||
"<pre>'********************'</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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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"])
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>")
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
@@ -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 &</li></ul>')
|
||||
self.assertEqual(help_text, "<ul><li>Must contain &</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 can’t be too similar to your other personal information.'
|
||||
"Your password can’t 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 can’t be a commonly used password.'
|
||||
"Your password can’t 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 can’t be entirely numeric.'
|
||||
"Your password can’t 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
@@ -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),
|
||||
]
|
||||
|
||||
@@ -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),
|
||||
]
|
||||
|
||||
@@ -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),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user