Commits

Valentin Golev committed 8991527

Management commands; __repr__; more tests.

  • Participants
  • Parent commits 95bd4aa

Comments (0)

Files changed (7)

File mon_django/auth/forms.py

         return password2
 
     def save(self, commit=True):
-        user = super(UserCreationForm, self).save(commit=False)
+        user = User(username=self.cleaned_data['username'])
         user.set_password(self.cleaned_data["password1"])
         if commit:
             user.save()
     class Meta:
         model = User
 
+    def __init__(self, *args, **kwargs):
+        if 'instance' in kwargs:
+            self.instance = kwargs['instance']
+            del kwargs['instance']
+        return super(UserChangeForm, self).__init__(self, *args, **kwargs)
+
 class AuthenticationForm(forms.Form):
     """
     Base class for authenticating users. Extend this to get a form that accepts

File mon_django/auth/management/__init__.py

+"""
+Creates permissions for all installed apps that need permissions.
+"""
+
+from django.db.models import get_models, signals
+from mon_django.auth import models as auth_app
+
+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 = []
+    for action in ('add', 'change', 'delete'):
+        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):
+    return False # NOT YET IMPLEMENTED!
+    from django.contrib.contenttypes.models import ContentType
+    from mon_django.auth.models import Permission
+    app_models = get_models(app)
+    if not app_models:
+        return
+    for klass in app_models:
+        ctype = ContentType.objects.get_for_model(klass)
+        for codename, name in _get_all_permissions(klass._meta):
+            p, created = Permission.objects.get_or_create(codename=codename, content_type__pk=ctype.id,
+                defaults={'name': name, 'content_type': ctype})
+            if created and verbosity >= 2:
+                print "Adding permission '%s'" % p
+
+def create_superuser(app, created_models, verbosity, **kwargs):
+    from mon_django.auth.models import User
+    from django.core.management import call_command
+    if User in created_models and kwargs.get('interactive', True):
+        msg = "\nYou just installed Django's auth system, which means you don't have " \
+                "any superusers defined.\nWould you like to create one now? (yes/no): "
+        confirm = raw_input(msg)
+        while 1:
+            if confirm not in ('yes', 'no'):
+                confirm = raw_input('Please enter either "yes" or "no": ')
+                continue
+            if confirm == 'yes':
+                call_command("createsuperuser", interactive=True)
+            break
+
+signals.post_syncdb.connect(create_permissions,
+    dispatch_uid = "mon_django.auth.management.create_permissions")
+signals.post_syncdb.connect(create_superuser,
+    sender=auth_app, dispatch_uid = "mon_django.auth.management.create_superuser")

File mon_django/auth/management/commands/__init__.py

Empty file added.

File mon_django/auth/management/commands/changepassword.py

+from django.core.management.base import BaseCommand, CommandError
+from mon_django.auth.models import User
+import getpass
+
+class Command(BaseCommand):
+    help = "Change a user's password for mon_django.auth."
+
+    requires_model_validation = False
+
+    def _get_pass(self, prompt="Password: "):
+        p = getpass.getpass(prompt=prompt)
+        if not p:
+            raise CommandError("aborted")
+        return p
+
+    def handle(self, *args, **options):
+        if len(args) > 1:
+            raise CommandError("need exactly one or zero arguments for username")
+
+        if args:
+            username, = args
+        else:
+            username = getpass.getuser()
+
+        try:
+            u = User.objects.get(username=username)
+        except User.DoesNotExist:
+            raise CommandError("user '%s' does not exist" % username)
+
+        print "Changing password for user '%s'" % u.username
+
+        MAX_TRIES = 3
+        count = 0
+        p1, p2 = 1, 2  # To make them initially mismatch.
+        while p1 != p2 and count < MAX_TRIES:
+            p1 = self._get_pass()
+            p2 = self._get_pass("Password (again): ")
+            if p1 != p2:
+                print "Passwords do not match. Please try again."
+                count = count + 1
+
+        if count == MAX_TRIES:
+            raise CommandError("Aborting password change for user '%s' after %s attempts" % (username, count))
+
+        u.set_password(p1)
+        u.save()
+
+        return "Password changed successfully for user '%s'" % u.username

File mon_django/auth/management/commands/createsuperuser.py

+"""
+Management utility to create superusers.
+"""
+
+import getpass
+import os
+import re
+import sys
+from optparse import make_option
+from mon_django.auth.models import User
+from django.core import exceptions
+from django.core.management.base import BaseCommand, CommandError
+from django.utils.translation import ugettext as _
+
+RE_VALID_USERNAME = re.compile('\w+$')
+EMAIL_RE = re.compile(
+    r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"  # dot-atom
+    r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"' # quoted-string
+    r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE)  # domain
+
+def is_valid_email(value):
+    if not EMAIL_RE.search(value):
+        raise exceptions.ValidationError(_('Enter a valid e-mail address.'))
+
+class Command(BaseCommand):
+    option_list = BaseCommand.option_list + (
+        make_option('--username', dest='username', default=None,
+            help='Specifies the username for the superuser.'),
+        make_option('--email', dest='email', default=None,
+            help='Specifies the email address for the superuser.'),
+        make_option('--noinput', action='store_false', dest='interactive', default=True,
+            help='Tells Django to NOT prompt the user for input of any kind. '    \
+                 'You must use --username and --email with --noinput, and '      \
+                 'superusers created with --noinput will not be able to log in '  \
+                 'until they\'re given a valid password.'),
+    )
+    help = 'Used to create a superuser.'
+
+    def handle(self, *args, **options):
+        username = options.get('username', None)
+        email = options.get('email', None)
+        interactive = options.get('interactive')
+        
+        # Do quick and dirty validation if --noinput
+        if not interactive:
+            if not username or not email:
+                raise CommandError("You must use --username and --email with --noinput.")
+            if not RE_VALID_USERNAME.match(username):
+                raise CommandError("Invalid username. Use only letters, digits, and underscores")
+            try:
+                is_valid_email(email)
+            except exceptions.ValidationError:
+                raise CommandError("Invalid email address.")
+
+        password = ''
+
+        # Try to determine the current system user's username to use as a default.
+        try:
+            import pwd
+            default_username = pwd.getpwuid(os.getuid())[0].replace(' ', '').lower()
+        except (ImportError, KeyError):
+            # KeyError will be raised by getpwuid() 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:
+            try:
+            
+                # Get a username
+                while 1:
+                    if not username:
+                        input_msg = 'Username'
+                        if default_username:
+                            input_msg += ' (Leave blank to use %r)' % default_username
+                        username = raw_input(input_msg + ': ')
+                    if default_username and username == '':
+                        username = default_username
+                    if not RE_VALID_USERNAME.match(username):
+                        sys.stderr.write("Error: That username is invalid. Use only letters, digits and underscores.\n")
+                        username = None
+                        continue
+                    try:
+                        User.objects.get(username=username)
+                    except User.DoesNotExist:
+                        break
+                    else:
+                        sys.stderr.write("Error: That username is already taken.\n")
+                        username = None
+            
+                # Get an email
+                while 1:
+                    if not email:
+                        email = raw_input('E-mail address: ')
+                    try:
+                        is_valid_email(email)
+                    except exceptions.ValidationError:
+                        sys.stderr.write("Error: That e-mail address is invalid.\n")
+                        email = None
+                    else:
+                        break
+            
+                # Get a password
+                while 1:
+                    if not password:
+                        password = getpass.getpass()
+                        password2 = getpass.getpass('Password (again): ')
+                        if password != password2:
+                            sys.stderr.write("Error: Your passwords didn't match.\n")
+                            password = None
+                            continue
+                    if password.strip() == '':
+                        sys.stderr.write("Error: Blank passwords aren't allowed.\n")
+                        password = None
+                        continue
+                    break
+            except KeyboardInterrupt:
+                sys.stderr.write("\nOperation cancelled.\n")
+                sys.exit(1)
+        
+        User.objects.create_superuser(username, email, password)
+        print "Superuser created successfully."

File mon_django/auth/models.py

 import datetime
 import re
 
-from django.utils.encoding import smart_str
+from django.utils.encoding import smart_str, force_unicode
 from django.utils.hashcompat import md5_constructor, sha_constructor
 
 from django.core import exceptions
 from mon_django.core.fields import AutoField, DateTimeField
 from mon_django.core.queryset import QuerySet
 
-UNUSABLE_PASSWORD = '!' # This will never be a valid hash
+UNUSABLE_PASSWORD = u'!' # This will never be a valid hash
 
 def get_hexdigest(algorithm, salt, raw_password):
     """
         obj.save()
         return obj
 
+    def create_superuser(self, username, email, password):
+        u = self.create_user(username, email, password)
+        u.is_staff = True
+        u.is_active = True
+        u.is_superuser = True
+        u.save()
+        return u
+
     def create_user(self, username, email, password=None):
         """
         Creates and saves a User with the given username, e-mail and password.
                     'is_staff', 'is_active', 'is_superuser', 'last_login',
                     'date_joined', 'groups', 'user_permissions', '_id')
 
-    valid_attrs = ('_params', 'backend')
+    valid_attrs = ('_params', 'backend', '_profile_cache')
 
     field_types = {
         'last_login' : DateTimeField(),
             else:
                 raise TypeError("'%s' is an invalid keyword argument for this function" % p) 
 
+    def __str__(self):
+        return force_unicode(self).encode('utf-8')
+
+    def __unicode__(self):
+        return self.username
+
+    def __repr__(self):
+        try:
+            u = unicode(self)
+        except (UnicodeEncodeError, UnicodeDecodeError):
+            u = '[Bad Unicode data]'
+        return smart_str(u'<%s: %s>' % (self.__class__.__name__, u))
+
+
     def __getattr__(self, name):
         if name == 'id' or name == 'pk':
             name = '_id'
             raise AttributeError("'User' object has no attribute '%s'" % name)
         self._params[name] = value
 
+    def is_authenticated(self):
+        return True
+
+    def has_usable_password(self):
+        return self.password != UNUSABLE_PASSWORD
+
+    def set_unusable_password(self):
+        self.password = UNUSABLE_PASSWORD
+
     def get_profile(self):
         """
         Returns site-specific profile for this user. Raises
 class EmptyManager(UserManager):
     def get_query_set(self):
         return self.get_empty_query_set()
+    def all(self):
+        return []
 
 class AnonymousUser(object):
     id = None

File mon_django/auth/tests/forms.py

 ...     'password2': 'test123',
 ... }
 >>> form = UserCreationForm(data)
->>> form.is_valid()
+>>> form.is_valid() # hi
 True
 >>> form.save()
 <User: jsmith2@example.com>