diff --git a/AUTHORS b/AUTHORS index 62be95935a03b..129fce0941c7f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -310,6 +310,7 @@ answer newbie questions, and generally made Django that much better: Simon Litchfield Daniel Lindsley Trey Long + Laurent Luce Martin Mahner Matt McClanahan Stanislaus Madueke diff --git a/django/contrib/auth/management/commands/createsuperuser.py b/django/contrib/auth/management/commands/createsuperuser.py index aad6489b38691..87751527c8412 100644 --- a/django/contrib/auth/management/commands/createsuperuser.py +++ b/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") + diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py index 681cf1422ab0f..3d927d813e346 100644 --- a/django/contrib/auth/models.py +++ b/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): """ diff --git a/django/contrib/auth/tests/__init__.py b/django/contrib/auth/tests/__init__.py index a1d02b6014a43..bc67d16d8663a 100644 --- a/django/contrib/auth/tests/__init__.py +++ b/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, } diff --git a/django/contrib/auth/tests/basic.py b/django/contrib/auth/tests/basic.py index ffa11d5d0ec03..7493dc68dadc5 100644 --- a/django/contrib/auth/tests/basic.py +++ b/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'!' -"""