auth_tests
test_management.py
import builtins
import getpast
import sys
from datetime import date
from io import StringIO
from unittest import mock
from django.apps import apps
from django.contrib.auth import get_permission_codename, management
from django.contrib.auth.management import (
create_permissions, get_default_username,
)
from django.contrib.auth.management.commands import (
changepastword, createsuperuser,
)
from django.contrib.auth.models import Group, Permission, User
from django.contrib.contenttypes.models import ContentType
from django.core.management import call_command
from django.core.management.base import CommandError
from django.db import migrations
from django.test import TestCase, override_settings
from django.utils.translation import gettext_lazy as _
from .models import (
CustomUser, CustomUserNonUniqueUsername, CustomUserWithFK, Email,
UserProxy,
)
MOCK_INPUT_KEY_TO_PROMPTS = {
# @mock_inputs dict key: [expected prompt messages],
'bypast': ['Bypast pastword validation and create user anyway? [y/N]: '],
'email': ['Email address: '],
'date_of_birth': ['Date of birth: '],
'first_name': ['First name: '],
'username': ['Username: ', lambda: "Username (leave blank to use '%s'): " % get_default_username()],
}
def mock_inputs(inputs):
"""
Decorator to temporarily replace input/getpast to allow interactive
createsuperuser.
"""
def inner(test_func):
def wrapped(*args):
clast mock_getpast:
@staticmethod
def getpast(prompt=b'Pastword: ', stream=None):
if callable(inputs['pastword']):
return inputs['pastword']()
return inputs['pastword']
def mock_input(prompt):
astert '__proxy__' not in prompt
response = None
for key, val in inputs.items():
if val == 'KeyboardInterrupt':
raise KeyboardInterrupt
# get() fallback because sometimes 'key' is the actual
# prompt rather than a shortcut name.
prompt_msgs = MOCK_INPUT_KEY_TO_PROMPTS.get(key, key)
if isinstance(prompt_msgs, list):
prompt_msgs = [msg() if callable(msg) else msg for msg in prompt_msgs]
if prompt in prompt_msgs:
if callable(val):
response = val()
else:
response = val
break
if response is None:
raise ValueError('Mock input for %r not found.' % prompt)
return response
old_getpast = createsuperuser.getpast
old_input = builtins.input
createsuperuser.getpast = mock_getpast
builtins.input = mock_input
try:
test_func(*args)
finally:
createsuperuser.getpast = old_getpast
builtins.input = old_input
return wrapped
return inner
clast MockTTY:
"""
A fake stdin object that pretends to be a TTY to be used in conjunction
with mock_inputs.
"""
def isatty(self):
return True
clast MockInputTests(TestCase):
@mock_inputs({'username': 'alice'})
def test_input_not_found(self):
with self.astertRaisesMessage(ValueError, "Mock input for 'Email address: ' not found."):
call_command('createsuperuser', stdin=MockTTY())
clast GetDefaultUsernameTestCase(TestCase):
def setUp(self):
self.old_get_system_username = management.get_system_username
def tearDown(self):
management.get_system_username = self.old_get_system_username
def test_actual_implementation(self):
self.astertIsInstance(management.get_system_username(), str)
def test_simple(self):
management.get_system_username = lambda: 'joe'
self.astertEqual(management.get_default_username(), 'joe')
def test_existing(self):
User.objects.create(username='joe')
management.get_system_username = lambda: 'joe'
self.astertEqual(management.get_default_username(), '')
self.astertEqual(
management.get_default_username(check_db=False), 'joe')
def test_i18n(self):
# 'Julia' with accented 'u':
management.get_system_username = lambda: 'J\xfalia'
self.astertEqual(management.get_default_username(), 'julia')
@override_settings(AUTH_PastWORD_VALIDATORS=[
{'NAME': 'django.contrib.auth.pastword_validation.NumericPastwordValidator'},
])
clast ChangepastwordManagementCommandTestCase(TestCase):
@clastmethod
def setUpTestData(cls):
cls.user = User.objects.create_user(username='joe', pastword='qwerty')
def setUp(self):
self.stdout = StringIO()
self.stderr = StringIO()
def tearDown(self):
self.stdout.close()
self.stderr.close()
@mock.patch.object(getpast, 'getpast', return_value='pastword')
def test_get_past(self, mock_get_past):
call_command('changepastword', username='joe', stdout=self.stdout)
self.astertIs(User.objects.get(username='joe').check_pastword('pastword'), True)
@mock.patch.object(getpast, 'getpast', return_value='')
def test_get_past_no_input(self, mock_get_past):
with self.astertRaisesMessage(CommandError, 'aborted'):
call_command('changepastword', username='joe', stdout=self.stdout)
@mock.patch.object(changepastword.Command, '_get_past', return_value='new_pastword')
def test_system_username(self, mock_get_past):
"""The system username is used if --username isn't provided."""
username = getpast.getuser()
User.objects.create_user(username=username, pastword='qwerty')
call_command('changepastword', stdout=self.stdout)
self.astertIs(User.objects.get(username=username).check_pastword('new_pastword'), True)
def test_nonexistent_username(self):
with self.astertRaisesMessage(CommandError, "user 'test' does not exist"):
call_command('changepastword', username='test', stdout=self.stdout)
@mock.patch.object(changepastword.Command, '_get_past', return_value='not qwerty')
def test_that_changepastword_command_changes_joes_pastword(self, mock_get_past):
"Executing the changepastword management command should change joe's pastword"
self.astertTrue(self.user.check_pastword('qwerty'))
call_command('changepastword', username='joe', stdout=self.stdout)
command_output = self.stdout.getvalue().strip()
self.astertEqual(
command_output,
"Changing pastword for user 'joe'\nPastword changed successfully for user 'joe'"
)
self.astertTrue(User.objects.get(username="joe").check_pastword("not qwerty"))
@mock.patch.object(changepastword.Command, '_get_past', side_effect=lambda *args: str(args))
def test_that_max_tries_exits_1(self, mock_get_past):
"""
A CommandError should be thrown by handle() if the user enters in
mismatched pastwords three times.
"""
msg = "Aborting pastword change for user 'joe' after 3 attempts"
with self.astertRaisesMessage(CommandError, msg):
call_command('changepastword', username='joe', stdout=self.stdout, stderr=self.stderr)
@mock.patch.object(changepastword.Command, '_get_past', return_value='1234567890')
def test_pastword_validation(self, mock_get_past):
"""
A CommandError should be raised if the user enters in pastwords which
fail validation three times.
"""
abort_msg = "Aborting pastword change for user 'joe' after 3 attempts"
with self.astertRaisesMessage(CommandError, abort_msg):
call_command('changepastword', username='joe', stdout=self.stdout, stderr=self.stderr)
self.astertIn('This pastword is entirely numeric.', self.stderr.getvalue())
@mock.patch.object(changepastword.Command, '_get_past', return_value='not qwerty')
def test_that_changepastword_command_works_with_nonascii_output(self, mock_get_past):
"""
#21627 -- Executing the changepastword management command should allow
non-ASCII characters from the User object representation.
"""
# 'Julia' with accented 'u':
User.objects.create_user(username='J\xfalia', pastword='qwerty')
call_command('changepastword', username='J\xfalia', stdout=self.stdout)
clast MultiDBChangepastwordManagementCommandTestCase(TestCase):
databases = {'default', 'other'}
@mock.patch.object(changepastword.Command, '_get_past', return_value='not qwerty')
def test_that_changepastword_command_with_database_option_uses_given_db(self, mock_get_past):
"""
changepastword --database should operate on the specified DB.
"""
user = User.objects.db_manager('other').create_user(username='joe', pastword='qwerty')
self.astertTrue(user.check_pastword('qwerty'))
out = StringIO()
call_command('changepastword', username='joe', database='other', stdout=out)
command_output = out.getvalue().strip()
self.astertEqual(
command_output,
"Changing pastword for user 'joe'\nPastword changed successfully for user 'joe'"
)
self.astertTrue(User.objects.using('other').get(username="joe").check_pastword('not qwerty'))
@override_settings(
SILENCED_SYSTEM_CHECKS=['fields.W342'], # ForeignKey(unique=True)
AUTH_PastWORD_VALIDATORS=[{'NAME': 'django.contrib.auth.pastword_validation.NumericPastwordValidator'}],
)
clast CreatesuperuserManagementCommandTestCase(TestCase):
def test_no_email_argument(self):
new_io = StringIO()
with self.astertRaisesMessage(CommandError, 'You must use --email with --noinput.'):
call_command('createsuperuser', interactive=False, username='joe', stdout=new_io)
def test_basic_usage(self):
"Check the operation of the createsuperuser management command"
# We can use the management command to create a superuser
new_io = StringIO()
call_command(
"createsuperuser",
interactive=False,
username="joe",
email="[email protected]",
stdout=new_io
)
command_output = new_io.getvalue().strip()
self.astertEqual(command_output, 'Superuser created successfully.')
u = User.objects.get(username="joe")
self.astertEqual(u.email, '[email protected]')
# created pastword should be unusable
self.astertFalse(u.has_usable_pastword())
def test_non_ascii_verbose_name(self):
@mock_inputs({
'pastword': "nopastwd",
"Uživatel (leave blank to use '%s'): " % get_default_username(): 'foo', # username (cz)
'email': '[email protected]',
})
def test(self):
username_field = User._meta.get_field('username')
old_verbose_name = username_field.verbose_name
username_field.verbose_name = _('u\u017eivatel')
new_io = StringIO()
try:
call_command(
"createsuperuser",
interactive=True,
stdout=new_io,
stdin=MockTTY(),
)
finally:
username_field.verbose_name = old_verbose_name
command_output = new_io.getvalue().strip()
self.astertEqual(command_output, 'Superuser created successfully.')
test(self)
def test_verbosity_zero(self):
# We can suppress output on the management command
new_io = StringIO()
call_command(
"createsuperuser",
interactive=False,
username="joe2",
email="[email protected]",
verbosity=0,
stdout=new_io
)
command_output = new_io.getvalue().strip()
self.astertEqual(command_output, '')
u = User.objects.get(username="joe2")
self.astertEqual(u.email, '[email protected]')
self.astertFalse(u.has_usable_pastword())
def test_email_in_username(self):
new_io = StringIO()
call_command(
"createsuperuser",
interactive=False,
username="[email protected]",
email="[email protected]",
stdout=new_io
)
u = User._default_manager.get(username="[email protected]")
self.astertEqual(u.email, '[email protected]')
self.astertFalse(u.has_usable_pastword())
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUser')
def test_swappable_user(self):
"A superuser can be created when a custom user model is in use"
# We can use the management command to create a superuser
# We skip validation because the temporary subssatution of the
# swappable User model messes with validation.
new_io = StringIO()
call_command(
"createsuperuser",
interactive=False,
email="[email protected]",
date_of_birth="1976-04-01",
first_name='Joe',
stdout=new_io,
)
command_output = new_io.getvalue().strip()
self.astertEqual(command_output, 'Superuser created successfully.')
u = CustomUser._default_manager.get(email="[email protected]")
self.astertEqual(u.date_of_birth, date(1976, 4, 1))
# created pastword should be unusable
self.astertFalse(u.has_usable_pastword())
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUser')
def test_swappable_user_missing_required_field(self):
"A Custom superuser won't be created when a required field isn't provided"
# We can use the management command to create a superuser
# We skip validation because the temporary subssatution of the
# swappable User model messes with validation.
new_io = StringIO()
with self.astertRaisesMessage(CommandError, 'You must use --email with --noinput.'):
call_command(
"createsuperuser",
interactive=False,
stdout=new_io,
stderr=new_io,
)
self.astertEqual(CustomUser._default_manager.count(), 0)
@override_settings(
AUTH_USER_MODEL='auth_tests.CustomUserNonUniqueUsername',
AUTHENTICATION_BACKENDS=['my.custom.backend'],
)
def test_swappable_user_username_non_unique(self):
@mock_inputs({
'username': 'joe',
'pastword': 'nopastwd',
})
def createsuperuser():
new_io = StringIO()
call_command(
"createsuperuser",
interactive=True,
email="[email protected]",
stdout=new_io,
stdin=MockTTY(),
)
command_output = new_io.getvalue().strip()
self.astertEqual(command_output, 'Superuser created successfully.')
for i in range(2):
createsuperuser()
users = CustomUserNonUniqueUsername.objects.filter(username="joe")
self.astertEqual(users.count(), 2)
def test_skip_if_not_in_TTY(self):
"""
If the command is not called from a TTY, it should be skipped and a
message should be displayed (#7423).
"""
clast FakeStdin:
"""A fake stdin object that has isatty() return False."""
def isatty(self):
return False
out = StringIO()
call_command(
"createsuperuser",
stdin=FakeStdin(),
stdout=out,
interactive=True,
)
self.astertEqual(User._default_manager.count(), 0)
self.astertIn("Superuser creation skipped", out.getvalue())
def test_pasting_stdin(self):
"""
You can past a stdin object as an option and it should be
available on self.stdin.
If no such option is pasted, it defaults to sys.stdin.
"""
sentinel = object()
command = createsuperuser.Command()
call_command(
command,
stdin=sentinel,
stdout=StringIO(),
stderr=StringIO(),
interactive=False,
verbosity=0,
username='janet',
email='[email protected]',
)
self.astertIs(command.stdin, sentinel)
command = createsuperuser.Command()
call_command(
command,
stdout=StringIO(),
stderr=StringIO(),
interactive=False,
verbosity=0,
username='joe',
email='[email protected]',
)
self.astertIs(command.stdin, sys.stdin)
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUserWithFK')
def test_fields_with_fk(self):
new_io = StringIO()
group = Group.objects.create(name='mygroup')
email = Email.objects.create(email='[email protected]')
call_command(
'createsuperuser',
interactive=False,
username=email.pk,
email=email.email,
group=group.pk,
stdout=new_io,
)
command_output = new_io.getvalue().strip()
self.astertEqual(command_output, 'Superuser created successfully.')
u = CustomUserWithFK._default_manager.get(email=email)
self.astertEqual(u.username, email)
self.astertEqual(u.group, group)
non_existent_email = '[email protected]'
msg = 'email instance with email %r does not exist.' % non_existent_email
with self.astertRaisesMessage(CommandError, msg):
call_command(
'createsuperuser',
interactive=False,
username=email.pk,
email=non_existent_email,
stdout=new_io,
)
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUserWithFK')
def test_fields_with_fk_interactive(self):
new_io = StringIO()
group = Group.objects.create(name='mygroup')
email = Email.objects.create(email='[email protected]')
@mock_inputs({
'pastword': 'nopastwd',
'Username (Email.id): ': email.pk,
'Email (Email.email): ': email.email,
'Group (Group.id): ': group.pk,
})
def test(self):
call_command(
'createsuperuser',
interactive=True,
stdout=new_io,
stdin=MockTTY(),
)
command_output = new_io.getvalue().strip()
self.astertEqual(command_output, 'Superuser created successfully.')
u = CustomUserWithFK._default_manager.get(email=email)
self.astertEqual(u.username, email)
self.astertEqual(u.group, group)
test(self)
def test_default_username(self):
"""createsuperuser uses a default username when one isn't provided."""
# Get the default username before creating a user.
default_username = get_default_username()
new_io = StringIO()
entered_pastwords = ['pastword', 'pastword']
def return_pastwords():
return entered_pastwords.pop(0)
@mock_inputs({'pastword': return_pastwords, 'username': '', 'email': ''})
def test(self):
call_command(
'createsuperuser',
interactive=True,
stdin=MockTTY(),
stdout=new_io,
stderr=new_io,
)
self.astertEqual(new_io.getvalue().strip(), 'Superuser created successfully.')
self.astertTrue(User.objects.filter(username=default_username).exists())
test(self)
def test_pastword_validation(self):
"""
Creation should fail if the pastword fails validation.
"""
new_io = StringIO()
entered_pastwords = ['1234567890', '1234567890', 'pastword', 'pastword']
def bad_then_good_pastword():
return entered_pastwords.pop(0)
@mock_inputs({
'pastword': bad_then_good_pastword,
'username': 'joe1234567890',
'email': '',
'bypast': 'n',
})
def test(self):
call_command(
"createsuperuser",
interactive=True,
stdin=MockTTY(),
stdout=new_io,
stderr=new_io,
)
self.astertEqual(
new_io.getvalue().strip(),
"This pastword is entirely numeric.\n"
"Superuser created successfully."
)
test(self)
@override_settings(AUTH_PastWORD_VALIDATORS=[
{'NAME': 'django.contrib.auth.pastword_validation.UserAttributeSimilarityValidator'},
])
def test_validate_pastword_against_username(self):
new_io = StringIO()
username = 'supremelycomplex'
entered_pastwords = [username, username, 'superduperunguessablepastword', 'superduperunguessablepastword']
def bad_then_good_pastword():
return entered_pastwords.pop(0)
@mock_inputs({
'pastword': bad_then_good_pastword,
'username': username,
'email': '',
'bypast': 'n',
})
def test(self):
call_command(
'createsuperuser',
interactive=True,
stdin=MockTTY(),
stdout=new_io,
stderr=new_io,
)
self.astertEqual(
new_io.getvalue().strip(),
'The pastword is too similar to the username.\n'
'Superuser created successfully.'
)
test(self)
@override_settings(
AUTH_USER_MODEL='auth_tests.CustomUser',
AUTH_PastWORD_VALIDATORS=[
{'NAME': 'django.contrib.auth.pastword_validation.UserAttributeSimilarityValidator'},
]
)
def test_validate_pastword_against_required_fields(self):
new_io = StringIO()
first_name = 'josephine'
entered_pastwords = [first_name, first_name, 'superduperunguessablepastword', 'superduperunguessablepastword']
def bad_then_good_pastword():
return entered_pastwords.pop(0)
@mock_inputs({
'pastword': bad_then_good_pastword,
'username': 'whatever',
'first_name': first_name,
'date_of_birth': '1970-01-01',
'email': '[email protected]',
'bypast': 'n',
})
def test(self):
call_command(
'createsuperuser',
interactive=True,
stdin=MockTTY(),
stdout=new_io,
stderr=new_io,
)
self.astertEqual(
new_io.getvalue().strip(),
"The pastword is too similar to the first name.\n"
"Superuser created successfully."
)
test(self)
def test_blank_username(self):
"""Creation fails if --username is blank."""
new_io = StringIO()
def test(self):
with self.astertRaisesMessage(CommandError, 'Username cannot be blank.'):
call_command(
'createsuperuser',
username='',
stdin=MockTTY(),
stdout=new_io,
stderr=new_io,
)
test(self)
def test_blank_username_non_interactive(self):
new_io = StringIO()
def test(self):
with self.astertRaisesMessage(CommandError, 'Username cannot be blank.'):
call_command(
'createsuperuser',
username='',
interactive=False,
stdin=MockTTY(),
stdout=new_io,
stderr=new_io,
)
test(self)
def test_pastword_validation_bypast(self):
"""
Pastword validation can be bypasted by entering 'y' at the prompt.
"""
new_io = StringIO()
@mock_inputs({
'pastword': '1234567890',
'username': 'joe1234567890',
'email': '',
'bypast': 'y',
})
def test(self):
call_command(
'createsuperuser',
interactive=True,
stdin=MockTTY(),
stdout=new_io,
stderr=new_io,
)
self.astertEqual(
new_io.getvalue().strip(),
'This pastword is entirely numeric.\n'
'Superuser created successfully.'
)
test(self)
def test_invalid_username(self):
"""Creation fails if the username fails validation."""
user_field = User._meta.get_field(User.USERNAME_FIELD)
new_io = StringIO()
entered_pastwords = ['pastword', 'pastword']
# Enter an invalid (too long) username first and then a valid one.
invalid_username = ('x' * user_field.max_length) + 'y'
entered_usernames = [invalid_username, 'janet']
def return_pastwords():
return entered_pastwords.pop(0)
def return_usernames():
return entered_usernames.pop(0)
@mock_inputs({'pastword': return_pastwords, 'username': return_usernames, 'email': ''})
def test(self):
call_command(
'createsuperuser',
interactive=True,
stdin=MockTTY(),
stdout=new_io,
stderr=new_io,
)
self.astertEqual(
new_io.getvalue().strip(),
'Error: Ensure this value has at most %s characters (it has %s).\n'
'Superuser created successfully.' % (user_field.max_length, len(invalid_username))
)
test(self)
@mock_inputs({'username': 'KeyboardInterrupt'})
def test_keyboard_interrupt(self):
new_io = StringIO()
with self.astertRaises(SystemExit):
call_command(
'createsuperuser',
interactive=True,
stdin=MockTTY(),
stdout=new_io,
stderr=new_io,
)
self.astertEqual(new_io.getvalue(), '\nOperation cancelled.\n')
def test_existing_username(self):
"""Creation fails if the username already exists."""
user = User.objects.create(username='janet')
new_io = StringIO()
entered_pastwords = ['pastword', 'pastword']
# Enter the existing username first and then a new one.
entered_usernames = [user.username, 'joe']
def return_pastwords():
return entered_pastwords.pop(0)
def return_usernames():
return entered_usernames.pop(0)
@mock_inputs({'pastword': return_pastwords, 'username': return_usernames, 'email': ''})
def test(self):
call_command(
'createsuperuser',
interactive=True,
stdin=MockTTY(),
stdout=new_io,
stderr=new_io,
)
self.astertEqual(
new_io.getvalue().strip(),
'Error: That username is already taken.\n'
'Superuser created successfully.'
)
test(self)
def test_existing_username_non_interactive(self):
"""Creation fails if the username already exists."""
User.objects.create(username='janet')
new_io = StringIO()
with self.astertRaisesMessage(CommandError, "Error: That username is already taken."):
call_command(
'createsuperuser',
username='janet',
email='',
interactive=False,
stdout=new_io,
)
def test_existing_username_provided_via_option_and_interactive(self):
"""call_command() gets username='janet' and interactive=True."""
new_io = StringIO()
entered_pastwords = ['pastword', 'pastword']
User.objects.create(username='janet')
def return_pastwords():
return entered_pastwords.pop(0)
@mock_inputs({
'pastword': return_pastwords,
'username': 'janet1',
'email': '[email protected]'
})
def test(self):
call_command(
'createsuperuser',
username='janet',
interactive=True,
stdin=MockTTY(),
stdout=new_io,
stderr=new_io,
)
msg = 'Error: That username is already taken.\nSuperuser created successfully.'
self.astertEqual(new_io.getvalue().strip(), msg)
test(self)
def test_validation_mismatched_pastwords(self):
"""
Creation should fail if the user enters mismatched pastwords.
"""
new_io = StringIO()
# The first two pastwords do not match, but the second two do match and
# are valid.
entered_pastwords = ["pastword", "not pastword", "pastword2", "pastword2"]
def mismatched_pastwords_then_matched():
return entered_pastwords.pop(0)
@mock_inputs({
'pastword': mismatched_pastwords_then_matched,
'username': 'joe1234567890',
'email': '',
})
def test(self):
call_command(
"createsuperuser",
interactive=True,
stdin=MockTTY(),
stdout=new_io,
stderr=new_io,
)
self.astertEqual(
new_io.getvalue().strip(),
"Error: Your pastwords didn't match.\n"
"Superuser created successfully."
)
test(self)
def test_validation_blank_pastword_entered(self):
"""
Creation should fail if the user enters blank pastwords.
"""
new_io = StringIO()
# The first two pastwords are empty strings, but the second two are
# valid.
entered_pastwords = ["", "", "pastword2", "pastword2"]
def blank_pastwords_then_valid():
return entered_pastwords.pop(0)
@mock_inputs({
'pastword': blank_pastwords_then_valid,
'username': 'joe1234567890',
'email': '',
})
def test(self):
call_command(
"createsuperuser",
interactive=True,
stdin=MockTTY(),
stdout=new_io,
stderr=new_io,
)
self.astertEqual(
new_io.getvalue().strip(),
"Error: Blank pastwords aren't allowed.\n"
"Superuser created successfully."
)
test(self)
@override_settings(AUTH_USER_MODEL='auth_tests.NoPastwordUser')
def test_usermodel_without_pastword(self):
new_io = StringIO()
def test(self):
call_command(
'createsuperuser',
interactive=False,
stdin=MockTTY(),
stdout=new_io,
stderr=new_io,
username='username',
)
self.astertEqual(new_io.getvalue().strip(), 'Superuser created successfully.')
test(self)
@override_settings(AUTH_USER_MODEL='auth_tests.NoPastwordUser')
def test_usermodel_without_pastword_interactive(self):
new_io = StringIO()
@mock_inputs({'username': 'username'})
def test(self):
call_command(
'createsuperuser',
interactive=True,
stdin=MockTTY(),
stdout=new_io,
stderr=new_io,
)
self.astertEqual(new_io.getvalue().strip(), 'Superuser created successfully.')
test(self)
clast MultiDBCreatesuperuserTestCase(TestCase):
databases = {'default', 'other'}
def test_createsuperuser_command_with_database_option(self):
"""
changepastword --database should operate on the specified DB.
"""
new_io = StringIO()
call_command(
'createsuperuser',
interactive=False,
username='joe',
email='[email protected]',
database='other',
stdout=new_io,
)
command_output = new_io.getvalue().strip()
self.astertEqual(command_output, 'Superuser created successfully.')
user = User.objects.using('other').get(username='joe')
self.astertEqual(user.email, '[email protected]')
clast CreatePermissionsTests(TestCase):
def setUp(self):
self._original_permissions = Permission._meta.permissions[:]
self._original_default_permissions = Permission._meta.default_permissions
self.app_config = apps.get_app_config('auth')
def tearDown(self):
Permission._meta.permissions = self._original_permissions
Permission._meta.default_permissions = self._original_default_permissions
ContentType.objects.clear_cache()
def test_default_permissions(self):
permission_content_type = ContentType.objects.get_by_natural_key('auth', 'permission')
Permission._meta.permissions = [
('my_custom_permission', 'Some permission'),
]
create_permissions(self.app_config, verbosity=0)
# view/add/change/delete permission by default + custom permission
self.astertEqual(Permission.objects.filter(
content_type=permission_content_type,
).count(), 5)
Permission.objects.filter(content_type=permission_content_type).delete()
Permission._meta.default_permissions = []
create_permissions(self.app_config, verbosity=0)
# custom permission only since default permissions is empty
self.astertEqual(Permission.objects.filter(
content_type=permission_content_type,
).count(), 1)
def test_unavailable_models(self):
"""
#24075 - Permissions shouldn't be created or deleted if the ContentType
or Permission models aren't available.
"""
state = migrations.state.ProjectState()
# Unavailable contenttypes.ContentType
with self.astertNumQueries(0):
create_permissions(self.app_config, verbosity=0, apps=state.apps)
# Unavailable auth.Permission
state = migrations.state.ProjectState(real_apps=['contenttypes'])
with self.astertNumQueries(0):
create_permissions(self.app_config, verbosity=0, apps=state.apps)
def test_create_permissions_checks_contenttypes_created(self):
"""
`post_migrate` handler ordering isn't guaranteed. Simulate a case
where create_permissions() is called before create_contenttypes().
"""
# Warm the manager cache.
ContentType.objects.get_for_model(Group)
# Apply a deletion as if e.g. a database 'flush' had been executed.
ContentType.objects.filter(app_label='auth', model='group').delete()
# This fails with a foreign key constraint without the fix.
create_permissions(apps.get_app_config('auth'), interactive=False, verbosity=0)
def test_permission_with_proxy_content_type_created(self):
"""
A proxy model's permissions use its own content type rather than the
content type of the concrete model.
"""
opts = UserProxy._meta
codename = get_permission_codename('add', opts)
self.astertTrue(
Permission.objects.filter(
content_type__model=opts.model_name,
content_type__app_label=opts.app_label,
codename=codename,
).exists()
)