Ticket #3011: 3011.7.diff

File 3011.7.diff, 18.1 KB (added by hvendelbo, 7 years ago)

Nearly there

  • django/conf/global_settings.py

    a b LOGIN_REDIRECT_URL = '/accounts/profile/' 
    375375# The number of days a password reset link is valid for
    376376PASSWORD_RESET_TIMEOUT_DAYS = 3
    377377
     378# The class to use as the default AUTH_USER for the authentication system.
     379AUTH_USER_MODULE = 'django.contrib.auth.user_model.User'
     380
     381# Trigger superuser creation after syncdb
     382AUTH_AUTO_CREATE_SUPERUSER = True
     383
     384# Trigger permissions creation after syncdb
     385AUTH_AUTO_CREATE_PERMISSIONS = True
     386
    378387###########
    379388# TESTING #
    380389###########
  • django/contrib/auth/admin.py

    
            
    a b  
    11
    2 from django.contrib.auth.models import User, Group
     2from django.contrib.auth.models import Permission, User, Group, Message
    33from django.core.exceptions import PermissionDenied
    44from django import template
    55from django.shortcuts import render_to_response, get_object_or_404
    from django.http import HttpResponseRedirect 
    99from django.utils.translation import ugettext, ugettext_lazy as _
    1010from django.contrib.auth.forms import UserCreationForm, UserChangeForm, AdminPasswordChangeForm
    1111from django.contrib import admin
     12from django.conf import settings, global_settings
    1213
    1314class GroupAdmin(admin.ModelAdmin):
    1415    search_fields = ('name',)
    class UserAdmin(admin.ModelAdmin): 
    108111            'root_path': self.admin_site.root_path,
    109112        }, context_instance=RequestContext(request))
    110113
    111 
    112114admin.site.register(Group, GroupAdmin)
    113 admin.site.register(User, UserAdmin)
     115if settings.AUTH_USER_MODULE == global_settings.AUTH_USER_MODULE:
     116    admin.site.register(User, UserAdmin)
    114117
  • django/contrib/auth/management/__init__.py

    diff --git a/django/contrib/auth/management/__init__.py b/django/contrib/auth/management/__init__.py
    index 01fa524..15abbec 100644
    a b Creates permissions for all installed apps that need permissions. 
    44
    55from django.db.models import get_models, signals
    66from django.contrib.auth import models as auth_app
     7from django.conf import settings
    78
    89def _get_permission_codename(action, opts):
    910    return u'%s_%s' % (action, opts.object_name.lower())
    def create_superuser(app, created_models, verbosity, **kwargs): 
    4445                call_command("createsuperuser", interactive=True)
    4546            break
    4647
    47 signals.post_syncdb.connect(create_permissions,
    48     dispatch_uid = "django.contrib.auth.management.create_permissions")
    49 signals.post_syncdb.connect(create_superuser,
    50     sender=auth_app, dispatch_uid = "django.contrib.auth.management.create_superuser")
     48if settings.AUTH_AUTO_CREATE_PERMISSIONS:
     49    signals.post_syncdb.connect(create_permissions,
     50        dispatch_uid = "django.contrib.auth.management.create_permissions")
     51if settings.AUTH_AUTO_CREATE_SUPERUSER:
     52    signals.post_syncdb.connect(create_superuser,
     53        sender=auth_app, dispatch_uid = "django.contrib.auth.management.create_superuser")
  • django/contrib/auth/models.py

    diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py
    index 4d3189b..57b36ba 100644
    a b from django.db.models.manager import EmptyManager 
    55from django.contrib.contenttypes.models import ContentType
    66from django.utils.encoding import smart_str
    77from django.utils.translation import ugettext_lazy as _
     8from django.conf import settings, global_settings
    89import datetime
    910import urllib
    1011
    class Group(models.Model): 
    102103    def __unicode__(self):
    103104        return self.name
    104105
    105 class UserManager(models.Manager):
    106     def create_user(self, username, email, password=None):
    107         "Creates and saves a User with the given username, e-mail and password."
    108         now = datetime.datetime.now()
    109         user = self.model(None, username, '', '', email.strip().lower(), 'placeholder', False, True, False, now, now)
    110         if password:
    111             user.set_password(password)
    112         else:
    113             user.set_unusable_password()
    114         user.save()
    115         return user
    116 
    117     def create_superuser(self, username, email, password):
    118         u = self.create_user(username, email, password)
    119         u.is_staff = True
    120         u.is_active = True
    121         u.is_superuser = True
    122         u.save()
    123 
    124     def make_random_password(self, length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'):
    125         "Generates a random password with the given length and given allowed_chars"
    126         # Note that default value of allowed_chars does not have "I" or letters
    127         # that look like it -- just to avoid confusion.
    128         from random import choice
    129         return ''.join([choice(allowed_chars) for i in range(length)])
    130 
    131 class User(models.Model):
    132     """Users within the Django authentication system are represented by this model.
    133 
    134     Username and password are required. Other fields are optional.
    135     """
    136     username = models.CharField(_('username'), max_length=30, unique=True, help_text=_("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."))
    137     first_name = models.CharField(_('first name'), max_length=30, blank=True)
    138     last_name = models.CharField(_('last name'), max_length=30, blank=True)
    139     email = models.EmailField(_('e-mail address'), blank=True)
    140     password = models.CharField(_('password'), max_length=128, help_text=_("Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>."))
    141     is_staff = models.BooleanField(_('staff status'), default=False, help_text=_("Designates whether the user can log into this admin site."))
    142     is_active = models.BooleanField(_('active'), default=True, help_text=_("Designates whether this user should be treated as active. Unselect this instead of deleting accounts."))
    143     is_superuser = models.BooleanField(_('superuser status'), default=False, help_text=_("Designates that this user has all permissions without explicitly assigning them."))
    144     last_login = models.DateTimeField(_('last login'), default=datetime.datetime.now)
    145     date_joined = models.DateTimeField(_('date joined'), default=datetime.datetime.now)
    146     groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True,
    147         help_text=_("In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in."))
    148     user_permissions = models.ManyToManyField(Permission, verbose_name=_('user permissions'), blank=True)
    149     objects = UserManager()
     106class UserTemplate(models.Model):
     107    """ Base class from which all User models inherit.  """
    150108
    151109    class Meta:
     110        abstract = True
     111        app_label = "auth"
    152112        verbose_name = _('user')
    153113        verbose_name_plural = _('users')
    154114
    155     def __unicode__(self):
    156         return self.username
    157 
    158     def get_absolute_url(self):
    159         return "/users/%s/" % urllib.quote(smart_str(self.username))
    160 
    161115    def is_anonymous(self):
    162116        "Always returns False. This is a way of comparing User objects to anonymous users."
    163117        return False
    class User(models.Model): 
    167121        """
    168122        return True
    169123
    170     def get_full_name(self):
    171         "Returns the first_name plus the last_name, with a space in between."
    172         full_name = u'%s %s' % (self.first_name, self.last_name)
    173         return full_name.strip()
    174 
    175     def set_password(self, raw_password):
    176         import random
    177         algo = 'sha1'
    178         salt = get_hexdigest(algo, str(random.random()), str(random.random()))[:5]
    179         hsh = get_hexdigest(algo, salt, raw_password)
    180         self.password = '%s$%s$%s' % (algo, salt, hsh)
    181 
    182     def check_password(self, raw_password):
    183         """
    184         Returns a boolean of whether the raw_password was correct. Handles
    185         encryption formats behind the scenes.
    186         """
    187         # Backwards-compatibility check. Older passwords won't include the
    188         # algorithm or salt.
    189         if '$' not in self.password:
    190             is_correct = (self.password == get_hexdigest('md5', '', raw_password))
    191             if is_correct:
    192                 # Convert the password to the new, more secure format.
    193                 self.set_password(raw_password)
    194                 self.save()
    195             return is_correct
    196         return check_password(raw_password, self.password)
    197 
    198     def set_unusable_password(self):
    199         # Sets a value that will never be a valid hash
    200         self.password = UNUSABLE_PASSWORD
    201 
    202     def has_usable_password(self):
    203         return self.password != UNUSABLE_PASSWORD
    204 
    205124    def get_group_permissions(self):
    206125        """
    207126        Returns a list of permission strings that this user has through
    class User(models.Model): 
    273192            m.delete()
    274193        return messages
    275194
    276     def email_user(self, subject, message, from_email=None):
    277         "Sends an e-mail to this User."
    278         from django.core.mail import send_mail
    279         send_mail(subject, message, from_email, [self.email])
    280 
    281195    def get_profile(self):
    282196        """
    283197        Returns site-specific profile for this user. Raises
    class User(models.Model): 
    295209                raise SiteProfileNotAvailable
    296210        return self._profile_cache
    297211
     212# Implement the User model according to settings
     213from django.db.models import import_model
     214User = import_model('auth',settings.AUTH_USER_MODULE)
     215
     216# Add the User model to the django models cache
     217# These two lines allow the custom auth_user model to play nicely with syncdb
     218# and other systems that rely on functions like
     219# django.db.models.loading.get_model(...)
     220#from django.db.models.loading import cache
     221#cache.register_models('auth', User)
     222
     223# We need to remove whatever we used as the AUTH_USER_MODUlE from the
     224# db cache so apps like contenttypes don't think that it's part
     225# of contrib.auth
     226#if settings.AUTH_USER_MODULE != global_settings.AUTH_USER_MODULE:
     227#    del cache.app_models['auth'][auth_user_module_parts[1].lower()]
     228
    298229class Message(models.Model):
    299230    """
    300231    The message system is a lightweight way to queue messages for given
  • django/contrib/auth/tests/basic.py

    diff --git a/django/contrib/auth/tests/basic.py b/django/contrib/auth/tests/basic.py
    index 2071710..d7b32ef 100644
    a b  
    11
    22BASIC_TESTS = """
     3>>> from django.contrib.auth.models import User
     4>>> User._meta.app_label
     5'auth'
     6>>> User._meta.object_name
     7'User'
     8
    39>>> from django.contrib.auth.models import User, AnonymousUser
    410>>> u = User.objects.create_user('testuser', 'test@example.com', 'testpw')
    511>>> u.has_usable_password()
  • new file django/contrib/auth/user_model.py

    diff --git a/django/contrib/auth/user_model.py b/django/contrib/auth/user_model.py
    new file mode 100644
    index 0000000..76b821b
    - +  
     1from django.db import models
     2from django.utils.translation import gettext_lazy as _
     3
     4from django.contrib.auth.models import Group, Permission, UserTemplate, get_hexdigest, check_password, UNUSABLE_PASSWORD
     5
     6import datetime, urllib
     7
     8
     9class UserManager(models.Manager):
     10    def create_user(self, username, email, password=None):
     11        "Creates and saves a User with the given username, e-mail and password."
     12        now = datetime.datetime.now()
     13        user = self.model(None, username, '', '', email.strip().lower(), 'placeholder', False, True, False, now, now)
     14        if password:
     15            user.set_password(password)
     16        else:
     17            user.set_unusable_password()
     18        user.save()
     19        return user
     20
     21    def create_superuser(self, username, email, password):
     22        u = self.create_user(username, email, password)
     23        u.is_staff = True
     24        u.is_active = True
     25        u.is_superuser = True
     26        u.save()
     27        return u
     28
     29    def make_random_password(self, length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'):
     30        "Generates a random password with the given length and given allowed_chars"
     31        # Note that default value of allowed_chars does not have "I" or letters
     32        # that look like it -- just to avoid confusion.
     33        from random import choice
     34        return ''.join([choice(allowed_chars) for i in range(length)])
     35
     36
     37class User(UserTemplate):
     38    """Users within the Django authentication system are represented by this model.
     39
     40    Username and password are required. Other fields are optional.
     41    """
     42    username = models.CharField(_('username'), max_length=30, unique=True, help_text=_("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."))
     43    first_name = models.CharField(_('first name'), max_length=30, blank=True)
     44    last_name = models.CharField(_('last name'), max_length=30, blank=True)
     45    email = models.EmailField(_('e-mail address'), blank=True)
     46    password = models.CharField(_('password'), max_length=128, help_text=_("Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>."))
     47    is_staff = models.BooleanField(_('staff status'), default=False, help_text=_("Designates whether the user can log into this admin site."))
     48    is_active = models.BooleanField(_('active'), default=True, help_text=_("Designates whether this user should be treated as active. Unselect this instead of deleting accounts."))
     49    is_superuser = models.BooleanField(_('superuser status'), default=False, help_text=_("Designates that this user has all permissions without explicitly assigning them."))
     50    last_login = models.DateTimeField(_('last login'), default=datetime.datetime.now)
     51    date_joined = models.DateTimeField(_('date joined'), default=datetime.datetime.now)
     52    groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True,
     53        help_text=_("In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in."))
     54    user_permissions = models.ManyToManyField(Permission, verbose_name=_('user permissions'), blank=True)
     55    objects = UserManager()
     56   
     57    class Meta(UserTemplate.Meta):
     58        db_table = "auth_user"
     59
     60    def __unicode__(self):
     61        return self.username
     62
     63    def get_absolute_url(self):
     64        return "/users/%s/" % urllib.quote(smart_str(self.username))
     65
     66    def get_full_name(self):
     67        "Returns the first_name plus the last_name, with a space in between."
     68        full_name = u'%s %s' % (self.first_name, self.last_name)
     69        return full_name.strip()
     70
     71    def set_password(self, raw_password):
     72        import random
     73        algo = 'sha1'
     74        salt = get_hexdigest(algo, str(random.random()), str(random.random()))[:5]
     75        hsh = get_hexdigest(algo, salt, raw_password)
     76        self.password = '%s$%s$%s' % (algo, salt, hsh)
     77
     78    def check_password(self, raw_password):
     79        """
     80        Returns a boolean of whether the raw_password was correct. Handles
     81        encryption formats behind the scenes.
     82        """
     83        # Backwards-compatibility check. Older passwords won't include the
     84        # algorithm or salt.
     85        if '$' not in self.password:
     86            is_correct = (self.password == get_hexdigest('md5', '', raw_password))
     87            if is_correct:
     88                # Convert the password to the new, more secure format.
     89                self.set_password(raw_password)
     90                self.save()
     91            return is_correct
     92        return check_password(raw_password, self.password)
     93
     94    def set_unusable_password(self):
     95        # Sets a value that will never be a valid hash
     96        self.password = UNUSABLE_PASSWORD
     97
     98    def has_usable_password(self):
     99        return self.password != UNUSABLE_PASSWORD
     100
     101    def email_user(self, subject, message, from_email=None):
     102        "Sends an e-mail to this User."
     103        from django.core.mail import send_mail
     104        send_mail(subject, message, from_email, [self.email])
     105 No newline at end of file
  • django/db/models/__init__.py

    diff --git a/django/db/models/__init__.py b/django/db/models/__init__.py
    index 5413133..9a39cb1 100644
    a b  
    11from django.conf import settings
    22from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
    33from django.db import connection
    4 from django.db.models.loading import get_apps, get_app, get_models, get_model, register_models
     4from django.db.models.loading import get_apps, get_app, get_models, get_model, register_models, import_model
    55from django.db.models.query import Q
    66from django.db.models.manager import Manager
    77from django.db.models.base import Model
  • django/db/models/loading.py

    diff --git a/django/db/models/loading.py b/django/db/models/loading.py
    index 6837e07..bcb5d26 100644
    a b import sys 
    88import os
    99import threading
    1010
    11 __all__ = ('get_apps', 'get_app', 'get_models', 'get_model', 'register_models',
     11__all__ = ('get_apps', 'get_app', 'get_models', 'get_model', 'register_models', 'import_model',
    1212        'load_app', 'app_cache_ready')
    1313
    1414class AppCache(object):
Back to Top