mirror of https://github.com/django/django.git
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.
|
||||
"""
|
||||
|
||||
import getpass
|
||||
import locale
|
||||
import unicodedata
|
||||
from django.contrib.auth import models as auth_app
|
||||
from django.db.models import get_models, signals
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
|
||||
def _get_permission_codename(action, opts):
|
||||
return u'%s_%s' % (action, opts.object_name.lower())
|
||||
|
||||
|
||||
def _get_all_permissions(opts):
|
||||
"Returns (codename, name) for all permissions in the given opts."
|
||||
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)))
|
||||
return perms + list(opts.permissions)
|
||||
|
||||
|
||||
def create_permissions(app, created_models, verbosity, **kwargs):
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
|
@ -70,6 +75,54 @@ def create_superuser(app, created_models, verbosity, **kwargs):
|
|||
call_command("createsuperuser", interactive=True)
|
||||
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,
|
||||
dispatch_uid = "django.contrib.auth.management.create_permissions")
|
||||
signals.post_syncdb.connect(create_superuser,
|
||||
|
|
|
@ -7,6 +7,7 @@ import re
|
|||
import sys
|
||||
from optparse import make_option
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.management import get_default_username
|
||||
from django.core import exceptions
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.utils.translation import ugettext as _
|
||||
|
@ -56,28 +57,10 @@ class Command(BaseCommand):
|
|||
# If not provided, create the user with an unusable password
|
||||
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
|
||||
# try/except to trap for a keyboard interrupt and exit gracefully.
|
||||
if interactive:
|
||||
default_username = get_default_username()
|
||||
try:
|
||||
|
||||
# Get a username
|
||||
|
|
|
@ -8,6 +8,7 @@ from django.contrib.auth.tests.forms import (UserCreationFormTest,
|
|||
UserChangeFormTest, PasswordResetFormTest)
|
||||
from django.contrib.auth.tests.remote_user import (RemoteUserTest,
|
||||
RemoteUserNoCreateTest, RemoteUserCustomTest)
|
||||
from django.contrib.auth.tests.management import GetDefaultUsernameTestCase
|
||||
from django.contrib.auth.tests.models import ProfileTestCase
|
||||
from django.contrib.auth.tests.signals import SignalTestCase
|
||||
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