mirror of https://github.com/django/django.git
Fixed #27801 -- Made createsuperuser fall back to environment variables for password and required fields.
This commit is contained in:
parent
4b32d039db
commit
a5308514fb
|
@ -2,6 +2,7 @@
|
|||
Management utility to create superusers.
|
||||
"""
|
||||
import getpass
|
||||
import os
|
||||
import sys
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
|
@ -138,6 +139,13 @@ class Command(BaseCommand):
|
|||
user_data[PASSWORD_FIELD] = password
|
||||
else:
|
||||
# Non-interactive mode.
|
||||
# Use password from environment variable, if provided.
|
||||
if PASSWORD_FIELD in user_data and 'DJANGO_SUPERUSER_PASSWORD' in os.environ:
|
||||
user_data[PASSWORD_FIELD] = os.environ['DJANGO_SUPERUSER_PASSWORD']
|
||||
# Use username from environment variable, if not provided in
|
||||
# options.
|
||||
if username is None:
|
||||
username = os.environ.get('DJANGO_SUPERUSER_' + self.UserModel.USERNAME_FIELD.upper())
|
||||
if username is None:
|
||||
raise CommandError('You must use --%s with --noinput.' % self.UserModel.USERNAME_FIELD)
|
||||
else:
|
||||
|
@ -147,11 +155,12 @@ class Command(BaseCommand):
|
|||
|
||||
user_data[self.UserModel.USERNAME_FIELD] = username
|
||||
for field_name in self.UserModel.REQUIRED_FIELDS:
|
||||
if options[field_name]:
|
||||
field = self.UserModel._meta.get_field(field_name)
|
||||
user_data[field_name] = field.clean(options[field_name], None)
|
||||
else:
|
||||
env_var = 'DJANGO_SUPERUSER_' + field_name.upper()
|
||||
value = options[field_name] or os.environ.get(env_var)
|
||||
if not value:
|
||||
raise CommandError('You must use --%s with --noinput.' % field_name)
|
||||
field = self.UserModel._meta.get_field(field_name)
|
||||
user_data[field_name] = field.clean(value, None)
|
||||
|
||||
self.UserModel._default_manager.db_manager(database).create_superuser(**user_data)
|
||||
if options['verbosity'] >= 1:
|
||||
|
|
|
@ -1560,9 +1560,23 @@ useful if you need to create an initial superuser account or if you need to
|
|||
programmatically generate superuser accounts for your site(s).
|
||||
|
||||
When run interactively, this command will prompt for a password for
|
||||
the new superuser account. When run non-interactively, no password
|
||||
will be set, and the superuser account will not be able to log in until
|
||||
a password has been manually set for it.
|
||||
the new superuser account. When run non-interactively, you can provide
|
||||
a password by setting the ``DJANGO_SUPERUSER_PASSWORD`` environment variable.
|
||||
Otherwise, no password will be set, and the superuser account will not be able
|
||||
to log in until a password has been manually set for it.
|
||||
|
||||
In non-interactive mode, the
|
||||
:attr:`~django.contrib.auth.models.CustomUser.USERNAME_FIELD` and required
|
||||
fields (listed in
|
||||
:attr:`~django.contrib.auth.models.CustomUser.REQUIRED_FIELDS`) fall back to
|
||||
``DJANGO_SUPERUSER_<uppercase_field_name>`` environment variables, unless they
|
||||
are overridden by a command line argument. For example, to provide an ``email``
|
||||
field, you can use ``DJANGO_SUPERUSER_EMAIL`` environment variable.
|
||||
|
||||
.. versionchanged:: 3.0
|
||||
|
||||
Support for using ``DJANGO_SUPERUSER_PASSWORD`` and
|
||||
``DJANGO_SUPERUSER_<uppercase_field_name>`` environment variables was added.
|
||||
|
||||
.. django-admin-option:: --username USERNAME
|
||||
.. django-admin-option:: --email EMAIL
|
||||
|
|
|
@ -102,6 +102,10 @@ Minor features
|
|||
password fields in :mod:`django.contrib.auth.forms` for better interaction
|
||||
with browser password managers.
|
||||
|
||||
* :djadmin:`createsuperuser` now falls back to environment variables for
|
||||
password and required fields, when a corresponding command line argument
|
||||
isn't provided in non-interactive mode.
|
||||
|
||||
:mod:`django.contrib.contenttypes`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import builtins
|
||||
import getpass
|
||||
import os
|
||||
import sys
|
||||
from datetime import date
|
||||
from io import StringIO
|
||||
|
@ -905,6 +906,61 @@ class CreatesuperuserManagementCommandTestCase(TestCase):
|
|||
|
||||
test(self)
|
||||
|
||||
@mock.patch.dict(os.environ, {
|
||||
'DJANGO_SUPERUSER_PASSWORD': 'test_password',
|
||||
'DJANGO_SUPERUSER_USERNAME': 'test_superuser',
|
||||
'DJANGO_SUPERUSER_EMAIL': 'joe@somewhere.org',
|
||||
'DJANGO_SUPERUSER_FIRST_NAME': 'ignored_first_name',
|
||||
})
|
||||
def test_environment_variable_non_interactive(self):
|
||||
call_command('createsuperuser', interactive=False, stdout=StringIO())
|
||||
user = User.objects.get(username='test_superuser')
|
||||
self.assertEqual(user.email, 'joe@somewhere.org')
|
||||
self.assertTrue(user.check_password('test_password'))
|
||||
# Environment variables are ignored for non-required fields.
|
||||
self.assertEqual(user.first_name, '')
|
||||
|
||||
@mock.patch.dict(os.environ, {
|
||||
'DJANGO_SUPERUSER_USERNAME': 'test_superuser',
|
||||
'DJANGO_SUPERUSER_EMAIL': 'joe@somewhere.org',
|
||||
})
|
||||
def test_ignore_environment_variable_non_interactive(self):
|
||||
# Environment variables are ignored in non-interactive mode, if
|
||||
# provided by a command line arguments.
|
||||
call_command(
|
||||
'createsuperuser',
|
||||
interactive=False,
|
||||
username='cmd_superuser',
|
||||
email='cmd@somewhere.org',
|
||||
stdout=StringIO(),
|
||||
)
|
||||
user = User.objects.get(username='cmd_superuser')
|
||||
self.assertEqual(user.email, 'cmd@somewhere.org')
|
||||
self.assertFalse(user.has_usable_password())
|
||||
|
||||
@mock.patch.dict(os.environ, {
|
||||
'DJANGO_SUPERUSER_PASSWORD': 'test_password',
|
||||
'DJANGO_SUPERUSER_USERNAME': 'test_superuser',
|
||||
'DJANGO_SUPERUSER_EMAIL': 'joe@somewhere.org',
|
||||
})
|
||||
def test_ignore_environment_variable_interactive(self):
|
||||
# Environment variables are ignored in interactive mode.
|
||||
@mock_inputs({'password': 'cmd_password'})
|
||||
def test(self):
|
||||
call_command(
|
||||
'createsuperuser',
|
||||
interactive=True,
|
||||
username='cmd_superuser',
|
||||
email='cmd@somewhere.org',
|
||||
stdin=MockTTY(),
|
||||
stdout=StringIO(),
|
||||
)
|
||||
user = User.objects.get(username='cmd_superuser')
|
||||
self.assertEqual(user.email, 'cmd@somewhere.org')
|
||||
self.assertTrue(user.check_password('cmd_password'))
|
||||
|
||||
test(self)
|
||||
|
||||
|
||||
class MultiDBCreatesuperuserTestCase(TestCase):
|
||||
databases = {'default', 'other'}
|
||||
|
|
Loading…
Reference in New Issue