Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #14354 -- Normalized the handling of empty/null passwords in co…

…ntrib.auth. This also updates the createsuperuser command to be more testable, and migrates some auth doctests. Thanks to berryp for the report, and Laurent Luce for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@14053 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 8755fb15494b587436dc7a144417b45b2ea16355 1 parent 71a4c47
@freakboy3742 freakboy3742 authored
View
1  AUTHORS
@@ -310,6 +310,7 @@ answer newbie questions, and generally made Django that much better:
Simon Litchfield <simon@quo.com.au>
Daniel Lindsley <polarcowz@gmail.com>
Trey Long <trey@ktrl.com>
+ Laurent Luce <http://www.laurentluce.com>
Martin Mahner <http://www.mahner.org/>
Matt McClanahan <http://mmcc.cx/>
Stanislaus Madueke
View
15 django/contrib/auth/management/commands/createsuperuser.py
@@ -41,7 +41,8 @@ def handle(self, *args, **options):
username = options.get('username', None)
email = options.get('email', None)
interactive = options.get('interactive')
-
+ verbosity = int(options.get('verbosity', 1))
+
# Do quick and dirty validation if --noinput
if not interactive:
if not username or not email:
@@ -79,7 +80,7 @@ def handle(self, *args, **options):
# try/except to trap for a keyboard interrupt and exit gracefully.
if interactive:
try:
-
+
# Get a username
while 1:
if not username:
@@ -100,7 +101,7 @@ def handle(self, *args, **options):
else:
sys.stderr.write("Error: That username is already taken.\n")
username = None
-
+
# Get an email
while 1:
if not email:
@@ -112,7 +113,7 @@ def handle(self, *args, **options):
email = None
else:
break
-
+
# Get a password
while 1:
if not password:
@@ -130,6 +131,8 @@ def handle(self, *args, **options):
except KeyboardInterrupt:
sys.stderr.write("\nOperation cancelled.\n")
sys.exit(1)
-
+
User.objects.create_superuser(username, email, password)
- print "Superuser created successfully."
+ if verbosity >= 1:
+ self.stdout.write("Superuser created successfully.\n")
+
View
25 django/contrib/auth/models.py
@@ -106,7 +106,6 @@ def create_user(self, username, email, password=None):
"""
Creates and saves a User with the given username, e-mail and password.
"""
-
now = datetime.datetime.now()
# Normalize the address by lowercasing the domain part of the email
@@ -122,10 +121,7 @@ def create_user(self, username, email, password=None):
is_active=True, is_superuser=False, last_login=now,
date_joined=now)
- if password:
- user.set_password(password)
- else:
- user.set_unusable_password()
+ user.set_password(password)
user.save(using=self._db)
return user
@@ -238,11 +234,14 @@ def get_full_name(self):
return full_name.strip()
def set_password(self, raw_password):
- import random
- algo = 'sha1'
- salt = get_hexdigest(algo, str(random.random()), str(random.random()))[:5]
- hsh = get_hexdigest(algo, salt, raw_password)
- self.password = '%s$%s$%s' % (algo, salt, hsh)
+ if raw_password is None:
+ self.set_unusable_password()
+ else:
+ import random
+ algo = 'sha1'
+ salt = get_hexdigest(algo, str(random.random()), str(random.random()))[:5]
+ hsh = get_hexdigest(algo, salt, raw_password)
+ self.password = '%s$%s$%s' % (algo, salt, hsh)
def check_password(self, raw_password):
"""
@@ -265,7 +264,11 @@ def set_unusable_password(self):
self.password = UNUSABLE_PASSWORD
def has_usable_password(self):
- return self.password != UNUSABLE_PASSWORD
+ if self.password is None \
+ or self.password == UNUSABLE_PASSWORD:
+ return False
+ else:
+ return True
def get_group_permissions(self, obj=None):
"""
View
3  django/contrib/auth/tests/__init__.py
@@ -1,5 +1,5 @@
from django.contrib.auth.tests.auth_backends import BackendTest, RowlevelBackendTest, AnonymousUserBackendTest, NoAnonymousUserBackendTest
-from django.contrib.auth.tests.basic import BASIC_TESTS
+from django.contrib.auth.tests.basic import BasicTestCase
from django.contrib.auth.tests.decorators import LoginRequiredTestCase
from django.contrib.auth.tests.forms import UserCreationFormTest, AuthenticationFormTest, SetPasswordFormTest, PasswordChangeFormTest, UserChangeFormTest, PasswordResetFormTest
from django.contrib.auth.tests.remote_user \
@@ -12,6 +12,5 @@
# The password for the fixture data users is 'password'
__test__ = {
- 'BASIC_TESTS': BASIC_TESTS,
'TOKEN_GENERATOR_TESTS': TOKEN_GENERATOR_TESTS,
}
View
153 django/contrib/auth/tests/basic.py
@@ -1,77 +1,92 @@
+from django.test import TestCase
+from django.contrib.auth.models import User, AnonymousUser
+from django.core.management import call_command
+from StringIO import StringIO
-BASIC_TESTS = """
->>> from django.contrib.auth.models import User, AnonymousUser
->>> u = User.objects.create_user('testuser', 'test@example.com', 'testpw')
->>> u.has_usable_password()
-True
->>> u.check_password('bad')
-False
->>> u.check_password('testpw')
-True
->>> u.set_unusable_password()
->>> u.save()
->>> u.check_password('testpw')
-False
->>> u.has_usable_password()
-False
->>> u2 = User.objects.create_user('testuser2', 'test2@example.com')
->>> u2.has_usable_password()
-False
+class BasicTestCase(TestCase):
+ def test_user(self):
+ "Check that users can be created and can set their password"
+ u = User.objects.create_user('testuser', 'test@example.com', 'testpw')
+ self.assertTrue(u.has_usable_password())
+ self.assertFalse(u.check_password('bad'))
+ self.assertTrue(u.check_password('testpw'))
->>> u.is_authenticated()
-True
->>> u.is_staff
-False
->>> u.is_active
-True
->>> u.is_superuser
-False
+ # Check we can manually set an unusable password
+ u.set_unusable_password()
+ u.save()
+ self.assertFalse(u.check_password('testpw'))
+ self.assertFalse(u.has_usable_password())
+ u.set_password('testpw')
+ self.assertTrue(u.check_password('testpw'))
+ u.set_password(None)
+ self.assertFalse(u.has_usable_password())
->>> a = AnonymousUser()
->>> a.is_authenticated()
-False
->>> a.is_staff
-False
->>> a.is_active
-False
->>> a.is_superuser
-False
->>> a.groups.all()
-[]
->>> a.user_permissions.all()
-[]
+ # Check authentication/permissions
+ self.assertTrue(u.is_authenticated())
+ self.assertFalse(u.is_staff)
+ self.assertTrue(u.is_active)
+ self.assertFalse(u.is_superuser)
-# superuser tests.
->>> super = User.objects.create_superuser('super', 'super@example.com', 'super')
->>> super.is_superuser
-True
->>> super.is_active
-True
->>> super.is_staff
-True
+ # Check API-based user creation with no password
+ u2 = User.objects.create_user('testuser2', 'test2@example.com')
+ self.assertFalse(u.has_usable_password())
-#
-# Tests for createsuperuser management command.
-# It's nearly impossible to test the interactive mode -- a command test helper
-# would be needed (and *awesome*) -- so just test the non-interactive mode.
-# This covers most of the important validation, but not all.
-#
->>> from django.core.management import call_command
+ def test_anonymous_user(self):
+ "Check the properties of the anonymous user"
+ a = AnonymousUser()
+ self.assertFalse(a.is_authenticated())
+ self.assertFalse(a.is_staff)
+ self.assertFalse(a.is_active)
+ self.assertFalse(a.is_superuser)
+ self.assertEqual(a.groups.all().count(), 0)
+ self.assertEqual(a.user_permissions.all().count(), 0)
->>> call_command("createsuperuser", interactive=False, username="joe", email="joe@somewhere.org")
-Superuser created successfully.
+ def test_superuser(self):
+ "Check the creation and properties of a superuser"
+ super = User.objects.create_superuser('super', 'super@example.com', 'super')
+ self.assertTrue(super.is_superuser)
+ self.assertTrue(super.is_active)
+ self.assertTrue(super.is_staff)
->>> u = User.objects.get(username="joe")
->>> u.email
-u'joe@somewhere.org'
->>> u.password
-u'!'
->>> call_command("createsuperuser", interactive=False, username="joe+admin@somewhere.org", email="joe@somewhere.org")
-Superuser created successfully.
+ def test_createsuperuser_management_command(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="joe@somewhere.org",
+ stdout=new_io
+ )
+ command_output = new_io.getvalue().strip()
+ self.assertEqual(command_output, 'Superuser created successfully.')
+ u = User.objects.get(username="joe")
+ self.assertEquals(u.email, 'joe@somewhere.org')
+ self.assertTrue(u.check_password(''))
+
+ # We can supress output on the management command
+ new_io = StringIO()
+ call_command("createsuperuser",
+ interactive=False,
+ username="joe2",
+ email="joe2@somewhere.org",
+ verbosity=0,
+ stdout=new_io
+ )
+ command_output = new_io.getvalue().strip()
+ self.assertEqual(command_output, '')
+ u = User.objects.get(username="joe2")
+ self.assertEquals(u.email, 'joe2@somewhere.org')
+ self.assertTrue(u.check_password(''))
+
+ new_io = StringIO()
+ call_command("createsuperuser",
+ interactive=False,
+ username="joe+admin@somewhere.org",
+ email="joe@somewhere.org",
+ stdout=new_io
+ )
+ u = User.objects.get(username="joe+admin@somewhere.org")
+ self.assertEquals(u.email, 'joe@somewhere.org')
+ self.assertTrue(u.check_password(''))
->>> u = User.objects.get(username="joe+admin@somewhere.org")
->>> u.email
-u'joe@somewhere.org'
->>> u.password
-u'!'
-"""
Please sign in to comment.
Something went wrong with that request. Please try again.