Ticket #17327: auth-management-commands-database-option.diff

File auth-management-commands-database-option.diff, 11.6 KB (added by Brian Riley, 12 years ago)

Patch to add --database option to both createsuperuser and change password management commands

  • django/contrib/auth/management/commands/changepassword.py

    diff --git a/django/contrib/auth/management/commands/changepassword.py b/django/contrib/auth/management/commands/changepassword.py
    index 56448f1..e2815ed 100644
    a b  
     1import getpass
     2from optparse import make_option
     3
    14from django.core.management.base import BaseCommand, CommandError
    25from django.contrib.auth.models import User
    3 import getpass
     6from django.db import DEFAULT_DB_ALIAS
     7
    48
    59class Command(BaseCommand):
     10    option_list = BaseCommand.option_list + (
     11        make_option('--database', action='store', dest='database',
     12            default=DEFAULT_DB_ALIAS, help='Nominates a database to query for the user. '
     13                    'Defaults to the "default" database.'),
     14    )
    615    help = "Change a user's password for django.contrib.auth."
    716
    817    requires_model_validation = False
    class Command(BaseCommand):  
    2332            username = getpass.getuser()
    2433
    2534        try:
    26             u = User.objects.get(username=username)
     35            u = User.objects.using(options.get('database')).get(username=username)
    2736        except User.DoesNotExist:
    2837            raise CommandError("user '%s' does not exist" % username)
    2938
    30         print "Changing password for user '%s'" % u.username
     39        self.stdout.write("Changing password for user '%s'\n" % u.username)
    3140
    3241        MAX_TRIES = 3
    3342        count = 0
    class Command(BaseCommand):  
    3645            p1 = self._get_pass()
    3746            p2 = self._get_pass("Password (again): ")
    3847            if p1 != p2:
    39                 print "Passwords do not match. Please try again."
     48                self.stdout.write("Passwords do not match. Please try again.\n")
    4049                count = count + 1
    4150
    4251        if count == MAX_TRIES:
  • django/contrib/auth/management/commands/createsuperuser.py

    diff --git a/django/contrib/auth/management/commands/createsuperuser.py b/django/contrib/auth/management/commands/createsuperuser.py
    index b3a3479..89a76b3 100644
    a b import getpass  
    66import re
    77import sys
    88from optparse import make_option
     9
    910from django.contrib.auth.models import User
    1011from django.contrib.auth.management import get_default_username
    1112from django.core import exceptions
    1213from django.core.management.base import BaseCommand, CommandError
     14from django.db import DEFAULT_DB_ALIAS
    1315from django.utils.translation import ugettext as _
    1416
    1517RE_VALID_USERNAME = re.compile('[\w.@+-]+$')
    EMAIL_RE = re.compile(  
    1921    r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"' # quoted-string
    2022    r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE)  # domain
    2123
     24
    2225def is_valid_email(value):
    2326    if not EMAIL_RE.search(value):
    2427        raise exceptions.ValidationError(_('Enter a valid e-mail address.'))
    2528
     29
    2630class Command(BaseCommand):
    2731    option_list = BaseCommand.option_list + (
    2832        make_option('--username', dest='username', default=None,
    class Command(BaseCommand):  
    3438                  'You must use --username and --email with --noinput, and '
    3539                  'superusers created with --noinput will not be able to log '
    3640                  'in until they\'re given a valid password.')),
     41        make_option('--database', action='store', dest='database',
     42            default=DEFAULT_DB_ALIAS, help='Nominates a database to save the user to. '
     43                    'Defaults to the "default" database.'),
    3744    )
    3845    help = 'Used to create a superuser.'
    3946
    class Command(BaseCommand):  
    4249        email = options.get('email', None)
    4350        interactive = options.get('interactive')
    4451        verbosity = int(options.get('verbosity', 1))
     52        database = options.get('database')
    4553
    4654        # Do quick and dirty validation if --noinput
    4755        if not interactive:
    class Command(BaseCommand):  
    7785                        username = None
    7886                        continue
    7987                    try:
    80                         User.objects.get(username=username)
     88                        User.objects.using(database).get(username=username)
    8189                    except User.DoesNotExist:
    8290                        break
    8391                    else:
    class Command(BaseCommand):  
    114122                sys.stderr.write("\nOperation cancelled.\n")
    115123                sys.exit(1)
    116124
    117         User.objects.create_superuser(username, email, password)
     125        User.objects.db_manager(database).create_superuser(username, email, password)
    118126        if verbosity >= 1:
    119127          self.stdout.write("Superuser created successfully.\n")
    120128
  • django/contrib/auth/tests/__init__.py

    diff --git a/django/contrib/auth/tests/__init__.py b/django/contrib/auth/tests/__init__.py
    index 7cb0dcb..cde5c8d 100644
    a b from django.contrib.auth.tests.forms import (UserCreationFormTest,  
    99    UserChangeFormTest, PasswordResetFormTest)
    1010from django.contrib.auth.tests.remote_user import (RemoteUserTest,
    1111    RemoteUserNoCreateTest, RemoteUserCustomTest)
    12 from django.contrib.auth.tests.management import GetDefaultUsernameTestCase
     12from django.contrib.auth.tests.management import GetDefaultUsernameTestCase, ChangepasswordManagementCommandTestCase, MultiDBChangepasswordManagementCommandTestCase,  MultiDBCreatesuperuserTestCase
    1313from django.contrib.auth.tests.models import ProfileTestCase
    1414from django.contrib.auth.tests.signals import SignalTestCase
    1515from django.contrib.auth.tests.tokens import TokenGeneratorTest
  • django/contrib/auth/tests/basic.py

    diff --git a/django/contrib/auth/tests/basic.py b/django/contrib/auth/tests/basic.py
    index 9f94c2a..2a7685b 100644
    a b  
     1from StringIO import StringIO
     2
    13from django.test import TestCase
    24from django.utils.unittest import skipUnless
    35from django.contrib.auth.models import User, AnonymousUser
    46from django.contrib.auth import utils
    57from django.core.management import call_command
    6 from StringIO import StringIO
    78
    89try:
    910    import crypt as crypt_module
    class BasicTestCase(TestCase):  
    100101        self.assertEqual(u.email, 'joe2@somewhere.org')
    101102        self.assertFalse(u.has_usable_password())
    102103
    103 
    104104        new_io = StringIO()
    105105        call_command("createsuperuser",
    106106            interactive=False,
  • django/contrib/auth/tests/management.py

    diff --git a/django/contrib/auth/tests/management.py b/django/contrib/auth/tests/management.py
    index 0af6873..2287ab9 100644
    a b  
    1 from django.test import TestCase
     1from StringIO import StringIO
     2
    23from django.contrib.auth import models, management
     4from django.contrib.auth.management.commands import changepassword
     5from django.core.management import call_command
     6from django.test import TestCase
    37
    48
    59class GetDefaultUsernameTestCase(TestCase):
    class GetDefaultUsernameTestCase(TestCase):  
    2529        # 'Julia' with accented 'u':
    2630        management.get_system_username = lambda: u'J\xfalia'
    2731        self.assertEqual(management.get_default_username(), 'julia')
     32
     33
     34class ChangepasswordManagementCommandTestCase(TestCase):
     35
     36    def setUp(self):
     37        self.user = models.User.objects.create_user(username='joe', password='qwerty')
     38        self.stdout = StringIO()
     39        self.stderr = StringIO()
     40
     41    def tearDown(self):
     42        self.stdout.close()
     43        self.stderr.close()
     44
     45    def test_that_changepassword_command_changes_joes_password(self):
     46        " Executing the changepassword management command should change joe's password "
     47        self.assertTrue(self.user.check_password('qwerty'))
     48        command = changepassword.Command()
     49        command._get_pass = lambda *args: 'not qwerty'
     50
     51        command.execute("joe", stdout=self.stdout)
     52        command_output = self.stdout.getvalue().strip()
     53
     54        self.assertEquals(command_output, "Changing password for user 'joe'\nPassword changed successfully for user 'joe'")
     55        self.assertTrue(models.User.objects.get(username="joe").check_password("not qwerty"))
     56
     57    def test_that_max_tries_exits_1(self):
     58        """
     59        A CommandError should be thrown by handle() if the user enters in
     60        mismatched passwords three times. This should be caught by execute() and
     61        converted to a SystemExit
     62        """
     63        command = changepassword.Command()
     64        command._get_pass = lambda *args: args or 'foo'
     65
     66        self.assertRaises(
     67            SystemExit,
     68            command.execute,
     69            "joe",
     70            stdout=self.stdout,
     71            stderr=self.stderr
     72        )
     73
     74
     75class MultiDBChangepasswordManagementCommandTestCase(TestCase):
     76    multi_db = True
     77
     78    def setUp(self):
     79        self.user = models.User.objects.db_manager('other').create_user(username='joe', password='qwerty')
     80        self.stdout = StringIO()
     81
     82    def tearDown(self):
     83        self.stdout.close()
     84
     85    def test_that_changepassword_command_with_database_option_uses_given_db(self):
     86        """
     87        Executing the changepassword management command with a database option
     88        should operate on the specified DB
     89        """
     90        self.assertTrue(self.user.check_password('qwerty'))
     91        command = changepassword.Command()
     92        command._get_pass = lambda *args: 'not qwerty'
     93
     94        command.execute("joe", database='other', stdout=self.stdout)
     95        command_output = self.stdout.getvalue().strip()
     96
     97        self.assertEquals(command_output, "Changing password for user 'joe'\nPassword changed successfully for user 'joe'")
     98        self.assertTrue(models.User.objects.using('other').get(username="joe").check_password("not qwerty"))
     99
     100
     101class MultiDBCreatesuperuserTestCase(TestCase):
     102    multi_db = True
     103
     104    def test_createsuperuser_command_with_database_option(self):
     105        " createsuperuser command should operate on specified DB"
     106        new_io = StringIO()
     107
     108        call_command("createsuperuser",
     109            interactive=False,
     110            username="joe",
     111            email="joe@somewhere.org",
     112            database='other',
     113            stdout=new_io
     114        )
     115        command_output = new_io.getvalue().strip()
     116
     117        self.assertEqual(command_output, 'Superuser created successfully.')
     118
     119        u = models.User.objects.using('other').get(username="joe")
     120        self.assertEqual(u.email, 'joe@somewhere.org')
     121
     122        new_io.close()
  • docs/ref/django-admin.txt

    diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt
    index 8b83a43..6eff2ab 100644
    a b the user given as parameter. If they both match, the new password will be  
    10841084changed immediately. If you do not supply a user, the command will attempt to
    10851085change the password whose username matches the current user.
    10861086
     1087.. django-admin-option:: --database
     1088
     1089The ``--database`` option can be used to specify the database to query for the
     1090user. If it is not supplied the ``default`` database will be used.
     1091
    10871092Example usage::
    10881093
    10891094    django-admin.py changepassword ringo
    a password has been manually set for it.  
    11081113
    11091114.. django-admin-option:: --username
    11101115.. django-admin-option:: --email
     1116.. django-admin-option:: --database
    11111117
    11121118The username and email address for the new account can be supplied by
    11131119using the ``--username`` and ``--email`` arguments on the command
    11141120line. If either of those is not supplied, ``createsuperuser`` will prompt for
    11151121it when running interactively.
    11161122
     1123The ``--database`` option can be used to specify the database into which the
     1124superuser object will be saved.
     1125
    11171126``django.contrib.gis``
    11181127----------------------
    11191128
Back to Top