app/django/contrib/auth/models.py
changeset 323 ff1a9aa48cfd
parent 54 03e267d67478
equal deleted inserted replaced
322:6641e941ef1e 323:ff1a9aa48cfd
       
     1 import datetime
       
     2 import urllib
       
     3 
     1 from django.contrib import auth
     4 from django.contrib import auth
     2 from django.core import validators
       
     3 from django.core.exceptions import ImproperlyConfigured
     5 from django.core.exceptions import ImproperlyConfigured
     4 from django.db import models
     6 from django.db import models
     5 from django.db.models.manager import EmptyManager
     7 from django.db.models.manager import EmptyManager
     6 from django.contrib.contenttypes.models import ContentType
     8 from django.contrib.contenttypes.models import ContentType
     7 from django.utils.encoding import smart_str
     9 from django.utils.encoding import smart_str
       
    10 from django.utils.hashcompat import md5_constructor, sha_constructor
     8 from django.utils.translation import ugettext_lazy as _
    11 from django.utils.translation import ugettext_lazy as _
     9 import datetime
       
    10 import urllib
       
    11 
    12 
    12 UNUSABLE_PASSWORD = '!' # This will never be a valid hash
    13 UNUSABLE_PASSWORD = '!' # This will never be a valid hash
    13 
    14 
    14 try:
    15 try:
    15     set
    16     set
    26         try:
    27         try:
    27             import crypt
    28             import crypt
    28         except ImportError:
    29         except ImportError:
    29             raise ValueError('"crypt" password algorithm not supported in this environment')
    30             raise ValueError('"crypt" password algorithm not supported in this environment')
    30         return crypt.crypt(raw_password, salt)
    31         return crypt.crypt(raw_password, salt)
    31     # The rest of the supported algorithms are supported by hashlib, but
    32 
    32     # hashlib is only available in Python 2.5.
    33     if algorithm == 'md5':
    33     try:
    34         return md5_constructor(salt + raw_password).hexdigest()
    34         import hashlib
    35     elif algorithm == 'sha1':
    35     except ImportError:
    36         return sha_constructor(salt + raw_password).hexdigest()
    36         if algorithm == 'md5':
       
    37             import md5
       
    38             return md5.new(salt + raw_password).hexdigest()
       
    39         elif algorithm == 'sha1':
       
    40             import sha
       
    41             return sha.new(salt + raw_password).hexdigest()
       
    42     else:
       
    43         if algorithm == 'md5':
       
    44             return hashlib.md5(salt + raw_password).hexdigest()
       
    45         elif algorithm == 'sha1':
       
    46             return hashlib.sha1(salt + raw_password).hexdigest()
       
    47     raise ValueError("Got unknown password algorithm type in password.")
    37     raise ValueError("Got unknown password algorithm type in password.")
    48 
    38 
    49 def check_password(raw_password, enc_password):
    39 def check_password(raw_password, enc_password):
    50     """
    40     """
    51     Returns a boolean of whether the raw_password was correct. Handles
    41     Returns a boolean of whether the raw_password was correct. Handles
    76 
    66 
    77     class Meta:
    67     class Meta:
    78         verbose_name = _('permission')
    68         verbose_name = _('permission')
    79         verbose_name_plural = _('permissions')
    69         verbose_name_plural = _('permissions')
    80         unique_together = (('content_type', 'codename'),)
    70         unique_together = (('content_type', 'codename'),)
    81         ordering = ('content_type', 'codename')
    71         ordering = ('content_type__app_label', 'codename')
    82 
    72 
    83     def __unicode__(self):
    73     def __unicode__(self):
    84         return u"%s | %s | %s" % (self.content_type.app_label, self.content_type, self.name)
    74         return u"%s | %s | %s" % (
       
    75             unicode(self.content_type.app_label),
       
    76             unicode(self.content_type),
       
    77             unicode(self.name))
    85 
    78 
    86 class Group(models.Model):
    79 class Group(models.Model):
    87     """Groups are a generic way of categorizing users to apply permissions, or some other label, to those users. A user can belong to any number of groups.
    80     """Groups are a generic way of categorizing users to apply permissions, or some other label, to those users. A user can belong to any number of groups.
    88 
    81 
    89     A user in a group automatically has all the permissions granted to that group. For example, if the group Site editors has the permission can_edit_home_page, any user in that group will have that permission.
    82     A user in a group automatically has all the permissions granted to that group. For example, if the group Site editors has the permission can_edit_home_page, any user in that group will have that permission.
    90 
    83 
    91     Beyond permissions, groups are a convenient way to categorize users to apply some label, or extended functionality, to them. For example, you could create a group 'Special users', and you could write code that would do special things to those users -- such as giving them access to a members-only portion of your site, or sending them members-only e-mail messages.
    84     Beyond permissions, groups are a convenient way to categorize users to apply some label, or extended functionality, to them. For example, you could create a group 'Special users', and you could write code that would do special things to those users -- such as giving them access to a members-only portion of your site, or sending them members-only e-mail messages.
    92     """
    85     """
    93     name = models.CharField(_('name'), max_length=80, unique=True)
    86     name = models.CharField(_('name'), max_length=80, unique=True)
    94     permissions = models.ManyToManyField(Permission, verbose_name=_('permissions'), blank=True, filter_interface=models.HORIZONTAL)
    87     permissions = models.ManyToManyField(Permission, verbose_name=_('permissions'), blank=True)
    95 
    88 
    96     class Meta:
    89     class Meta:
    97         verbose_name = _('group')
    90         verbose_name = _('group')
    98         verbose_name_plural = _('groups')
    91         verbose_name_plural = _('groups')
    99         ordering = ('name',)
       
   100 
       
   101     class Admin:
       
   102         search_fields = ('name',)
       
   103 
    92 
   104     def __unicode__(self):
    93     def __unicode__(self):
   105         return self.name
    94         return self.name
   106 
    95 
   107 class UserManager(models.Manager):
    96 class UserManager(models.Manager):
   114         else:
   103         else:
   115             user.set_unusable_password()
   104             user.set_unusable_password()
   116         user.save()
   105         user.save()
   117         return user
   106         return user
   118 
   107 
       
   108     def create_superuser(self, username, email, password):
       
   109         u = self.create_user(username, email, password)
       
   110         u.is_staff = True
       
   111         u.is_active = True
       
   112         u.is_superuser = True
       
   113         u.save()
       
   114 
   119     def make_random_password(self, length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'):
   115     def make_random_password(self, length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'):
   120         "Generates a random password with the given length and given allowed_chars"
   116         "Generates a random password with the given length and given allowed_chars"
   121         # Note that default value of allowed_chars does not have "I" or letters
   117         # Note that default value of allowed_chars does not have "I" or letters
   122         # that look like it -- just to avoid confusion.
   118         # that look like it -- just to avoid confusion.
   123         from random import choice
   119         from random import choice
   126 class User(models.Model):
   122 class User(models.Model):
   127     """Users within the Django authentication system are represented by this model.
   123     """Users within the Django authentication system are represented by this model.
   128 
   124 
   129     Username and password are required. Other fields are optional.
   125     Username and password are required. Other fields are optional.
   130     """
   126     """
   131     username = models.CharField(_('username'), max_length=30, unique=True, validator_list=[validators.isAlphaNumeric], help_text=_("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."))
   127     username = models.CharField(_('username'), max_length=30, unique=True, help_text=_("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."))
   132     first_name = models.CharField(_('first name'), max_length=30, blank=True)
   128     first_name = models.CharField(_('first name'), max_length=30, blank=True)
   133     last_name = models.CharField(_('last name'), max_length=30, blank=True)
   129     last_name = models.CharField(_('last name'), max_length=30, blank=True)
   134     email = models.EmailField(_('e-mail address'), blank=True)
   130     email = models.EmailField(_('e-mail address'), blank=True)
   135     password = models.CharField(_('password'), max_length=128, help_text=_("Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>."))
   131     password = models.CharField(_('password'), max_length=128, help_text=_("Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>."))
   136     is_staff = models.BooleanField(_('staff status'), default=False, help_text=_("Designates whether the user can log into this admin site."))
   132     is_staff = models.BooleanField(_('staff status'), default=False, help_text=_("Designates whether the user can log into this admin site."))
   138     is_superuser = models.BooleanField(_('superuser status'), default=False, help_text=_("Designates that this user has all permissions without explicitly assigning them."))
   134     is_superuser = models.BooleanField(_('superuser status'), default=False, help_text=_("Designates that this user has all permissions without explicitly assigning them."))
   139     last_login = models.DateTimeField(_('last login'), default=datetime.datetime.now)
   135     last_login = models.DateTimeField(_('last login'), default=datetime.datetime.now)
   140     date_joined = models.DateTimeField(_('date joined'), default=datetime.datetime.now)
   136     date_joined = models.DateTimeField(_('date joined'), default=datetime.datetime.now)
   141     groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True,
   137     groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True,
   142         help_text=_("In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in."))
   138         help_text=_("In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in."))
   143     user_permissions = models.ManyToManyField(Permission, verbose_name=_('user permissions'), blank=True, filter_interface=models.HORIZONTAL)
   139     user_permissions = models.ManyToManyField(Permission, verbose_name=_('user permissions'), blank=True)
   144     objects = UserManager()
   140     objects = UserManager()
   145 
   141 
   146     class Meta:
   142     class Meta:
   147         verbose_name = _('user')
   143         verbose_name = _('user')
   148         verbose_name_plural = _('users')
   144         verbose_name_plural = _('users')
   149         ordering = ('username',)
       
   150 
       
   151     class Admin:
       
   152         fields = (
       
   153             (None, {'fields': ('username', 'password')}),
       
   154             (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
       
   155             (_('Permissions'), {'fields': ('is_staff', 'is_active', 'is_superuser', 'user_permissions')}),
       
   156             (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
       
   157             (_('Groups'), {'fields': ('groups',)}),
       
   158         )
       
   159         list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
       
   160         list_filter = ('is_staff', 'is_superuser')
       
   161         search_fields = ('username', 'first_name', 'last_name', 'email')
       
   162 
   145 
   163     def __unicode__(self):
   146     def __unicode__(self):
   164         return self.username
   147         return self.username
   165 
   148 
   166     def get_absolute_url(self):
   149     def get_absolute_url(self):
   291         Returns site-specific profile for this user. Raises
   274         Returns site-specific profile for this user. Raises
   292         SiteProfileNotAvailable if this site does not allow profiles.
   275         SiteProfileNotAvailable if this site does not allow profiles.
   293         """
   276         """
   294         if not hasattr(self, '_profile_cache'):
   277         if not hasattr(self, '_profile_cache'):
   295             from django.conf import settings
   278             from django.conf import settings
   296             if not settings.AUTH_PROFILE_MODULE:
   279             if not getattr(settings, 'AUTH_PROFILE_MODULE', False):
   297                 raise SiteProfileNotAvailable
   280                 raise SiteProfileNotAvailable
   298             try:
   281             try:
   299                 app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
   282                 app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
   300                 model = models.get_model(app_label, model_name)
   283                 model = models.get_model(app_label, model_name)
   301                 self._profile_cache = model._default_manager.get(user__id__exact=self.id)
   284                 self._profile_cache = model._default_manager.get(user__id__exact=self.id)
       
   285                 self._profile_cache.user = self
   302             except (ImportError, ImproperlyConfigured):
   286             except (ImportError, ImproperlyConfigured):
   303                 raise SiteProfileNotAvailable
   287                 raise SiteProfileNotAvailable
   304         return self._profile_cache
   288         return self._profile_cache
   305 
   289 
   306 class Message(models.Model):
   290 class Message(models.Model):
   366     user_permissions = property(_get_user_permissions)
   350     user_permissions = property(_get_user_permissions)
   367 
   351 
   368     def has_perm(self, perm):
   352     def has_perm(self, perm):
   369         return False
   353         return False
   370 
   354 
       
   355     def has_perms(self, perm_list):
       
   356         return False
       
   357 
   371     def has_module_perms(self, module):
   358     def has_module_perms(self, module):
   372         return False
   359         return False
   373 
   360 
   374     def get_and_delete_messages(self):
   361     def get_and_delete_messages(self):
   375         return []
   362         return []