Fixes #15778 -- createsuperuser fails on international characters in system user names. Thanks for the patch, Hynek Cernoch.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@16182 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
688abe3b8d
commit
161b94ef7b
|
@ -1,14 +1,18 @@
|
||||||
"""
|
"""
|
||||||
Creates permissions for all installed apps that need permissions.
|
Creates permissions for all installed apps that need permissions.
|
||||||
"""
|
"""
|
||||||
|
import getpass
|
||||||
|
import locale
|
||||||
|
import unicodedata
|
||||||
from django.contrib.auth import models as auth_app
|
from django.contrib.auth import models as auth_app
|
||||||
from django.db.models import get_models, signals
|
from django.db.models import get_models, signals
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
|
||||||
def _get_permission_codename(action, opts):
|
def _get_permission_codename(action, opts):
|
||||||
return u'%s_%s' % (action, opts.object_name.lower())
|
return u'%s_%s' % (action, opts.object_name.lower())
|
||||||
|
|
||||||
|
|
||||||
def _get_all_permissions(opts):
|
def _get_all_permissions(opts):
|
||||||
"Returns (codename, name) for all permissions in the given opts."
|
"Returns (codename, name) for all permissions in the given opts."
|
||||||
perms = []
|
perms = []
|
||||||
|
@ -16,6 +20,7 @@ def _get_all_permissions(opts):
|
||||||
perms.append((_get_permission_codename(action, opts), u'Can %s %s' % (action, opts.verbose_name_raw)))
|
perms.append((_get_permission_codename(action, opts), u'Can %s %s' % (action, opts.verbose_name_raw)))
|
||||||
return perms + list(opts.permissions)
|
return perms + list(opts.permissions)
|
||||||
|
|
||||||
|
|
||||||
def create_permissions(app, created_models, verbosity, **kwargs):
|
def create_permissions(app, created_models, verbosity, **kwargs):
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
|
||||||
|
@ -70,6 +75,54 @@ def create_superuser(app, created_models, verbosity, **kwargs):
|
||||||
call_command("createsuperuser", interactive=True)
|
call_command("createsuperuser", interactive=True)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
|
def get_system_username():
|
||||||
|
"""
|
||||||
|
Try to determine the current system user's username.
|
||||||
|
|
||||||
|
:returns: The username as a unicode string, or an empty string if the
|
||||||
|
username could not be determined.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return getpass.getuser().decode(locale.getdefaultlocale()[1])
|
||||||
|
except (ImportError, KeyError, UnicodeDecodeError):
|
||||||
|
# KeyError will be raised by os.getpwuid() (called by getuser())
|
||||||
|
# if there is no corresponding entry in the /etc/passwd file
|
||||||
|
# (a very restricted chroot environment, for example).
|
||||||
|
# UnicodeDecodeError - preventive treatment for non-latin Windows.
|
||||||
|
return u''
|
||||||
|
|
||||||
|
|
||||||
|
def get_default_username(check_db=True):
|
||||||
|
"""
|
||||||
|
Try to determine the current system user's username to use as a default.
|
||||||
|
|
||||||
|
:param check_db: If ``True``, requires that the username does not match an
|
||||||
|
existing ``auth.User`` (otherwise returns an empty string).
|
||||||
|
:returns: The username, or an empty string if no username can be
|
||||||
|
determined.
|
||||||
|
"""
|
||||||
|
from django.contrib.auth.management.commands.createsuperuser import \
|
||||||
|
RE_VALID_USERNAME
|
||||||
|
default_username = get_system_username()
|
||||||
|
try:
|
||||||
|
default_username = unicodedata.normalize('NFKD', default_username)\
|
||||||
|
.encode('ascii', 'ignore').replace(' ', '').lower()
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
return ''
|
||||||
|
if not RE_VALID_USERNAME.match(default_username):
|
||||||
|
return ''
|
||||||
|
# Don't return the default username if it is already taken.
|
||||||
|
if check_db and default_username:
|
||||||
|
try:
|
||||||
|
User.objects.get(username=default_username)
|
||||||
|
except User.DoesNotExist:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
return default_username
|
||||||
|
|
||||||
|
|
||||||
signals.post_syncdb.connect(create_permissions,
|
signals.post_syncdb.connect(create_permissions,
|
||||||
dispatch_uid = "django.contrib.auth.management.create_permissions")
|
dispatch_uid = "django.contrib.auth.management.create_permissions")
|
||||||
signals.post_syncdb.connect(create_superuser,
|
signals.post_syncdb.connect(create_superuser,
|
||||||
|
|
|
@ -7,6 +7,7 @@ import re
|
||||||
import sys
|
import sys
|
||||||
from optparse import make_option
|
from optparse import make_option
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
from django.contrib.auth.management import get_default_username
|
||||||
from django.core import exceptions
|
from django.core import exceptions
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
@ -56,28 +57,10 @@ class Command(BaseCommand):
|
||||||
# If not provided, create the user with an unusable password
|
# If not provided, create the user with an unusable password
|
||||||
password = None
|
password = None
|
||||||
|
|
||||||
# Try to determine the current system user's username to use as a default.
|
|
||||||
try:
|
|
||||||
default_username = getpass.getuser().replace(' ', '').lower()
|
|
||||||
except (ImportError, KeyError):
|
|
||||||
# KeyError will be raised by os.getpwuid() (called by getuser())
|
|
||||||
# if there is no corresponding entry in the /etc/passwd file
|
|
||||||
# (a very restricted chroot environment, for example).
|
|
||||||
default_username = ''
|
|
||||||
|
|
||||||
# Determine whether the default username is taken, so we don't display
|
|
||||||
# it as an option.
|
|
||||||
if default_username:
|
|
||||||
try:
|
|
||||||
User.objects.get(username=default_username)
|
|
||||||
except User.DoesNotExist:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
default_username = ''
|
|
||||||
|
|
||||||
# Prompt for username/email/password. Enclose this whole thing in a
|
# Prompt for username/email/password. Enclose this whole thing in a
|
||||||
# try/except to trap for a keyboard interrupt and exit gracefully.
|
# try/except to trap for a keyboard interrupt and exit gracefully.
|
||||||
if interactive:
|
if interactive:
|
||||||
|
default_username = get_default_username()
|
||||||
try:
|
try:
|
||||||
|
|
||||||
# Get a username
|
# Get a username
|
||||||
|
|
|
@ -8,6 +8,7 @@ from django.contrib.auth.tests.forms import (UserCreationFormTest,
|
||||||
UserChangeFormTest, PasswordResetFormTest)
|
UserChangeFormTest, PasswordResetFormTest)
|
||||||
from django.contrib.auth.tests.remote_user import (RemoteUserTest,
|
from django.contrib.auth.tests.remote_user import (RemoteUserTest,
|
||||||
RemoteUserNoCreateTest, RemoteUserCustomTest)
|
RemoteUserNoCreateTest, RemoteUserCustomTest)
|
||||||
|
from django.contrib.auth.tests.management import GetDefaultUsernameTestCase
|
||||||
from django.contrib.auth.tests.models import ProfileTestCase
|
from django.contrib.auth.tests.models import ProfileTestCase
|
||||||
from django.contrib.auth.tests.signals import SignalTestCase
|
from django.contrib.auth.tests.signals import SignalTestCase
|
||||||
from django.contrib.auth.tests.tokens import TokenGeneratorTest
|
from django.contrib.auth.tests.tokens import TokenGeneratorTest
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
from django.contrib.auth import models, management
|
||||||
|
|
||||||
|
|
||||||
|
class GetDefaultUsernameTestCase(TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self._getpass_getuser = management.get_system_username
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
management.get_system_username = self._getpass_getuser
|
||||||
|
|
||||||
|
def test_simple(self):
|
||||||
|
management.get_system_username = lambda: u'joe'
|
||||||
|
self.assertEqual(management.get_default_username(), 'joe')
|
||||||
|
|
||||||
|
def test_existing(self):
|
||||||
|
models.User.objects.create(username='joe')
|
||||||
|
management.get_system_username = lambda: u'joe'
|
||||||
|
self.assertEqual(management.get_default_username(), '')
|
||||||
|
self.assertEqual(
|
||||||
|
management.get_default_username(check_db=False), 'joe')
|
||||||
|
|
||||||
|
def test_i18n(self):
|
||||||
|
# 'Julia' with accented 'u':
|
||||||
|
management.get_system_username = lambda: u'J\xfalia'
|
||||||
|
self.assertEqual(management.get_default_username(), 'julia')
|
Loading…
Reference in New Issue