Kaydet (Commit) 161b94ef authored tarafından Chris Beaven's avatar Chris Beaven

Fixes #15778 -- createsuperuser fails on international characters in system user…

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
üst 688abe3b
"""
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
......
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')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment