web/lib/django/contrib/auth/models.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
     8 from django.contrib.contenttypes.models import ContentType
     8 from django.contrib.contenttypes.models import ContentType
     9 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
    10 from django.utils.hashcompat import md5_constructor, sha_constructor
    11 from django.utils.translation import ugettext_lazy as _
    11 from django.utils.translation import ugettext_lazy as _
    12 
    12 
       
    13 
    13 UNUSABLE_PASSWORD = '!' # This will never be a valid hash
    14 UNUSABLE_PASSWORD = '!' # This will never be a valid hash
    14 
       
    15 try:
       
    16     set
       
    17 except NameError:
       
    18     from sets import Set as set   # Python 2.3 fallback
       
    19 
    15 
    20 def get_hexdigest(algorithm, salt, raw_password):
    16 def get_hexdigest(algorithm, salt, raw_password):
    21     """
    17     """
    22     Returns a string of the hexdigest of the given plaintext password and salt
    18     Returns a string of the hexdigest of the given plaintext password and salt
    23     using the given algorithm ('md5', 'sha1' or 'crypt').
    19     using the given algorithm ('md5', 'sha1' or 'crypt').
    45     return hsh == get_hexdigest(algo, salt, raw_password)
    41     return hsh == get_hexdigest(algo, salt, raw_password)
    46 
    42 
    47 class SiteProfileNotAvailable(Exception):
    43 class SiteProfileNotAvailable(Exception):
    48     pass
    44     pass
    49 
    45 
       
    46 class PermissionManager(models.Manager):
       
    47     def get_by_natural_key(self, codename, app_label, model):
       
    48         return self.get(
       
    49             codename=codename,
       
    50             content_type=ContentType.objects.get_by_natural_key(app_label, model)
       
    51         )
       
    52 
    50 class Permission(models.Model):
    53 class Permission(models.Model):
    51     """The permissions system provides a way to assign permissions to specific users and groups of users.
    54     """The permissions system provides a way to assign permissions to specific users and groups of users.
    52 
    55 
    53     The permission system is used by the Django admin site, but may also be useful in your own code. The Django admin site uses permissions as follows:
    56     The permission system is used by the Django admin site, but may also be useful in your own code. The Django admin site uses permissions as follows:
    54 
    57 
    61     Three basic permissions -- add, change and delete -- are automatically created for each Django model.
    64     Three basic permissions -- add, change and delete -- are automatically created for each Django model.
    62     """
    65     """
    63     name = models.CharField(_('name'), max_length=50)
    66     name = models.CharField(_('name'), max_length=50)
    64     content_type = models.ForeignKey(ContentType)
    67     content_type = models.ForeignKey(ContentType)
    65     codename = models.CharField(_('codename'), max_length=100)
    68     codename = models.CharField(_('codename'), max_length=100)
       
    69     objects = PermissionManager()
    66 
    70 
    67     class Meta:
    71     class Meta:
    68         verbose_name = _('permission')
    72         verbose_name = _('permission')
    69         verbose_name_plural = _('permissions')
    73         verbose_name_plural = _('permissions')
    70         unique_together = (('content_type', 'codename'),)
    74         unique_together = (('content_type', 'codename'),)
    71         ordering = ('content_type__app_label', 'codename')
    75         ordering = ('content_type__app_label', 'content_type__model', 'codename')
    72 
    76 
    73     def __unicode__(self):
    77     def __unicode__(self):
    74         return u"%s | %s | %s" % (
    78         return u"%s | %s | %s" % (
    75             unicode(self.content_type.app_label),
    79             unicode(self.content_type.app_label),
    76             unicode(self.content_type),
    80             unicode(self.content_type),
    77             unicode(self.name))
    81             unicode(self.name))
    78 
    82 
       
    83     def natural_key(self):
       
    84         return (self.codename,) + self.content_type.natural_key()
       
    85     natural_key.dependencies = ['contenttypes.contenttype']
       
    86 
    79 class Group(models.Model):
    87 class Group(models.Model):
    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     """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.
    81 
    89 
    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     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.
    83 
    91 
    93     def __unicode__(self):
   101     def __unicode__(self):
    94         return self.name
   102         return self.name
    95 
   103 
    96 class UserManager(models.Manager):
   104 class UserManager(models.Manager):
    97     def create_user(self, username, email, password=None):
   105     def create_user(self, username, email, password=None):
    98         "Creates and saves a User with the given username, e-mail and password."
   106         """
       
   107         Creates and saves a User with the given username, e-mail and password.
       
   108         """
       
   109 
    99         now = datetime.datetime.now()
   110         now = datetime.datetime.now()
   100         user = self.model(None, username, '', '', email.strip().lower(), 'placeholder', False, True, False, now, now)
   111         
       
   112         # Normalize the address by lowercasing the domain part of the email
       
   113         # address.
       
   114         try:
       
   115             email_name, domain_part = email.strip().split('@', 1)
       
   116         except ValueError:
       
   117             pass
       
   118         else:
       
   119             email = '@'.join([email_name, domain_part.lower()])
       
   120 
       
   121         user = self.model(username=username, email=email, is_staff=False,
       
   122                          is_active=True, is_superuser=False, last_login=now,
       
   123                          date_joined=now)
       
   124 
   101         if password:
   125         if password:
   102             user.set_password(password)
   126             user.set_password(password)
   103         else:
   127         else:
   104             user.set_unusable_password()
   128             user.set_unusable_password()
   105         user.save()
   129         user.save(using=self._db)
   106         return user
   130         return user
   107 
   131 
   108     def create_superuser(self, username, email, password):
   132     def create_superuser(self, username, email, password):
   109         u = self.create_user(username, email, password)
   133         u = self.create_user(username, email, password)
   110         u.is_staff = True
   134         u.is_staff = True
   111         u.is_active = True
   135         u.is_active = True
   112         u.is_superuser = True
   136         u.is_superuser = True
   113         u.save()
   137         u.save(using=self._db)
   114         return u
   138         return u
   115 
   139 
   116     def make_random_password(self, length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'):
   140     def make_random_password(self, length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'):
   117         "Generates a random password with the given length and given allowed_chars"
   141         "Generates a random password with the given length and given allowed_chars"
   118         # Note that default value of allowed_chars does not have "I" or letters
   142         # Note that default value of allowed_chars does not have "I" or letters
   119         # that look like it -- just to avoid confusion.
   143         # that look like it -- just to avoid confusion.
   120         from random import choice
   144         from random import choice
   121         return ''.join([choice(allowed_chars) for i in range(length)])
   145         return ''.join([choice(allowed_chars) for i in range(length)])
   122 
   146 
       
   147 
       
   148 # A few helper functions for common logic between User and AnonymousUser.
       
   149 def _user_get_all_permissions(user, obj):
       
   150     permissions = set()
       
   151     anon = user.is_anonymous()
       
   152     for backend in auth.get_backends():
       
   153         if not anon or backend.supports_anonymous_user:
       
   154             if hasattr(backend, "get_all_permissions"):
       
   155                 if obj is not None:
       
   156                     if backend.supports_object_permissions:
       
   157                         permissions.update(
       
   158                             backend.get_all_permissions(user, obj)
       
   159                         )
       
   160                 else:
       
   161                     permissions.update(backend.get_all_permissions(user))
       
   162     return permissions
       
   163 
       
   164 
       
   165 def _user_has_perm(user, perm, obj):
       
   166     anon = user.is_anonymous()
       
   167     for backend in auth.get_backends():
       
   168         if not anon or backend.supports_anonymous_user:
       
   169             if hasattr(backend, "has_perm"):
       
   170                 if obj is not None:
       
   171                     if (backend.supports_object_permissions and
       
   172                         backend.has_perm(user, perm, obj)):
       
   173                             return True
       
   174                 else:
       
   175                     if backend.has_perm(user, perm):
       
   176                         return True
       
   177     return False
       
   178 
       
   179 
       
   180 def _user_has_module_perms(user, app_label):
       
   181     anon = user.is_anonymous()
       
   182     for backend in auth.get_backends():
       
   183         if not anon or backend.supports_anonymous_user:
       
   184             if hasattr(backend, "has_module_perms"):
       
   185                 if backend.has_module_perms(user, app_label):
       
   186                     return True
       
   187     return False
       
   188 
       
   189 
   123 class User(models.Model):
   190 class User(models.Model):
   124     """Users within the Django authentication system are represented by this model.
   191     """
       
   192     Users within the Django authentication system are represented by this model.
   125 
   193 
   126     Username and password are required. Other fields are optional.
   194     Username and password are required. Other fields are optional.
   127     """
   195     """
   128     username = models.CharField(_('username'), max_length=30, unique=True, help_text=_("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."))
   196     username = models.CharField(_('username'), max_length=30, unique=True, help_text=_("Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters"))
   129     first_name = models.CharField(_('first name'), max_length=30, blank=True)
   197     first_name = models.CharField(_('first name'), max_length=30, blank=True)
   130     last_name = models.CharField(_('last name'), max_length=30, blank=True)
   198     last_name = models.CharField(_('last name'), max_length=30, blank=True)
   131     email = models.EmailField(_('e-mail address'), blank=True)
   199     email = models.EmailField(_('e-mail address'), blank=True)
   132     password = models.CharField(_('password'), max_length=128, help_text=_("Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>."))
   200     password = models.CharField(_('password'), max_length=128, help_text=_("Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>."))
   133     is_staff = models.BooleanField(_('staff status'), default=False, help_text=_("Designates whether the user can log into this admin site."))
   201     is_staff = models.BooleanField(_('staff status'), default=False, help_text=_("Designates whether the user can log into this admin site."))
   149 
   217 
   150     def get_absolute_url(self):
   218     def get_absolute_url(self):
   151         return "/users/%s/" % urllib.quote(smart_str(self.username))
   219         return "/users/%s/" % urllib.quote(smart_str(self.username))
   152 
   220 
   153     def is_anonymous(self):
   221     def is_anonymous(self):
   154         "Always returns False. This is a way of comparing User objects to anonymous users."
   222         """
       
   223         Always returns False. This is a way of comparing User objects to
       
   224         anonymous users.
       
   225         """
   155         return False
   226         return False
   156 
   227 
   157     def is_authenticated(self):
   228     def is_authenticated(self):
   158         """Always return True. This is a way to tell if the user has been authenticated in templates.
   229         """
       
   230         Always return True. This is a way to tell if the user has been
       
   231         authenticated in templates.
   159         """
   232         """
   160         return True
   233         return True
   161 
   234 
   162     def get_full_name(self):
   235     def get_full_name(self):
   163         "Returns the first_name plus the last_name, with a space in between."
   236         "Returns the first_name plus the last_name, with a space in between."
   192         self.password = UNUSABLE_PASSWORD
   265         self.password = UNUSABLE_PASSWORD
   193 
   266 
   194     def has_usable_password(self):
   267     def has_usable_password(self):
   195         return self.password != UNUSABLE_PASSWORD
   268         return self.password != UNUSABLE_PASSWORD
   196 
   269 
   197     def get_group_permissions(self):
   270     def get_group_permissions(self, obj=None):
   198         """
   271         """
   199         Returns a list of permission strings that this user has through
   272         Returns a list of permission strings that this user has through
   200         his/her groups. This method queries all available auth backends.
   273         his/her groups. This method queries all available auth backends.
       
   274         If an object is passed in, only permissions matching this object
       
   275         are returned.
   201         """
   276         """
   202         permissions = set()
   277         permissions = set()
   203         for backend in auth.get_backends():
   278         for backend in auth.get_backends():
   204             if hasattr(backend, "get_group_permissions"):
   279             if hasattr(backend, "get_group_permissions"):
   205                 permissions.update(backend.get_group_permissions(self))
   280                 if obj is not None:
       
   281                     if backend.supports_object_permissions:
       
   282                         permissions.update(
       
   283                             backend.get_group_permissions(self, obj)
       
   284                         )
       
   285                 else:
       
   286                     permissions.update(backend.get_group_permissions(self))
   206         return permissions
   287         return permissions
   207 
   288 
   208     def get_all_permissions(self):
   289     def get_all_permissions(self, obj=None):
   209         permissions = set()
   290         return _user_get_all_permissions(self, obj)
   210         for backend in auth.get_backends():
   291 
   211             if hasattr(backend, "get_all_permissions"):
   292     def has_perm(self, perm, obj=None):
   212                 permissions.update(backend.get_all_permissions(self))
       
   213         return permissions
       
   214 
       
   215     def has_perm(self, perm):
       
   216         """
   293         """
   217         Returns True if the user has the specified permission. This method
   294         Returns True if the user has the specified permission. This method
   218         queries all available auth backends, but returns immediately if any
   295         queries all available auth backends, but returns immediately if any
   219         backend returns True. Thus, a user who has permission from a single
   296         backend returns True. Thus, a user who has permission from a single
   220         auth backend is assumed to have permission in general.
   297         auth backend is assumed to have permission in general. If an object
       
   298         is provided, permissions for this specific object are checked.
   221         """
   299         """
   222         # Inactive users have no permissions.
   300         # Inactive users have no permissions.
   223         if not self.is_active:
   301         if not self.is_active:
   224             return False
   302             return False
   225 
   303 
   226         # Superusers have all permissions.
   304         # Superusers have all permissions.
   227         if self.is_superuser:
   305         if self.is_superuser:
   228             return True
   306             return True
   229 
   307 
   230         # Otherwise we need to check the backends.
   308         # Otherwise we need to check the backends.
   231         for backend in auth.get_backends():
   309         return _user_has_perm(self, perm, obj)
   232             if hasattr(backend, "has_perm"):
   310 
   233                 if backend.has_perm(self, perm):
   311     def has_perms(self, perm_list, obj=None):
   234                     return True
   312         """
   235         return False
   313         Returns True if the user has each of the specified permissions.
   236 
   314         If object is passed, it checks if the user has all required perms
   237     def has_perms(self, perm_list):
   315         for this object.
   238         """Returns True if the user has each of the specified permissions."""
   316         """
   239         for perm in perm_list:
   317         for perm in perm_list:
   240             if not self.has_perm(perm):
   318             if not self.has_perm(perm, obj):
   241                 return False
   319                 return False
   242         return True
   320         return True
   243 
   321 
   244     def has_module_perms(self, app_label):
   322     def has_module_perms(self, app_label):
   245         """
   323         """
   250             return False
   328             return False
   251 
   329 
   252         if self.is_superuser:
   330         if self.is_superuser:
   253             return True
   331             return True
   254 
   332 
   255         for backend in auth.get_backends():
   333         return _user_has_module_perms(self, app_label)
   256             if hasattr(backend, "has_module_perms"):
       
   257                 if backend.has_module_perms(self, app_label):
       
   258                     return True
       
   259         return False
       
   260 
   334 
   261     def get_and_delete_messages(self):
   335     def get_and_delete_messages(self):
   262         messages = []
   336         messages = []
   263         for m in self.message_set.all():
   337         for m in self.message_set.all():
   264             messages.append(m.message)
   338             messages.append(m.message)
   276         SiteProfileNotAvailable if this site does not allow profiles.
   350         SiteProfileNotAvailable if this site does not allow profiles.
   277         """
   351         """
   278         if not hasattr(self, '_profile_cache'):
   352         if not hasattr(self, '_profile_cache'):
   279             from django.conf import settings
   353             from django.conf import settings
   280             if not getattr(settings, 'AUTH_PROFILE_MODULE', False):
   354             if not getattr(settings, 'AUTH_PROFILE_MODULE', False):
   281                 raise SiteProfileNotAvailable
   355                 raise SiteProfileNotAvailable('You need to set AUTH_PROFILE_MO'
       
   356                                               'DULE in your project settings')
   282             try:
   357             try:
   283                 app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
   358                 app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
       
   359             except ValueError:
       
   360                 raise SiteProfileNotAvailable('app_label and model_name should'
       
   361                         ' be separated by a dot in the AUTH_PROFILE_MODULE set'
       
   362                         'ting')
       
   363 
       
   364             try:
   284                 model = models.get_model(app_label, model_name)
   365                 model = models.get_model(app_label, model_name)
   285                 self._profile_cache = model._default_manager.get(user__id__exact=self.id)
   366                 if model is None:
       
   367                     raise SiteProfileNotAvailable('Unable to load the profile '
       
   368                         'model, check AUTH_PROFILE_MODULE in your project sett'
       
   369                         'ings')
       
   370                 self._profile_cache = model._default_manager.using(self._state.db).get(user__id__exact=self.id)
   286                 self._profile_cache.user = self
   371                 self._profile_cache.user = self
   287             except (ImportError, ImproperlyConfigured):
   372             except (ImportError, ImproperlyConfigured):
   288                 raise SiteProfileNotAvailable
   373                 raise SiteProfileNotAvailable
   289         return self._profile_cache
   374         return self._profile_cache
       
   375 
       
   376     def _get_message_set(self):
       
   377         import warnings
       
   378         warnings.warn('The user messaging API is deprecated. Please update'
       
   379                       ' your code to use the new messages framework.',
       
   380                       category=PendingDeprecationWarning)
       
   381         return self._message_set
       
   382     message_set = property(_get_message_set)
   290 
   383 
   291 class Message(models.Model):
   384 class Message(models.Model):
   292     """
   385     """
   293     The message system is a lightweight way to queue messages for given
   386     The message system is a lightweight way to queue messages for given
   294     users. A message is associated with a User instance (so it is only
   387     users. A message is associated with a User instance (so it is only
   295     applicable for registered users). There's no concept of expiration or
   388     applicable for registered users). There's no concept of expiration or
   296     timestamps. Messages are created by the Django admin after successful
   389     timestamps. Messages are created by the Django admin after successful
   297     actions. For example, "The poll Foo was created successfully." is a
   390     actions. For example, "The poll Foo was created successfully." is a
   298     message.
   391     message.
   299     """
   392     """
   300     user = models.ForeignKey(User)
   393     user = models.ForeignKey(User, related_name='_message_set')
   301     message = models.TextField(_('message'))
   394     message = models.TextField(_('message'))
   302 
   395 
   303     def __unicode__(self):
   396     def __unicode__(self):
   304         return self.message
   397         return self.message
   305 
   398 
   348 
   441 
   349     def _get_user_permissions(self):
   442     def _get_user_permissions(self):
   350         return self._user_permissions
   443         return self._user_permissions
   351     user_permissions = property(_get_user_permissions)
   444     user_permissions = property(_get_user_permissions)
   352 
   445 
   353     def has_perm(self, perm):
   446     def get_group_permissions(self, obj=None):
   354         return False
   447         return set()
   355 
   448 
   356     def has_perms(self, perm_list):
   449     def get_all_permissions(self, obj=None):
   357         return False
   450         return _user_get_all_permissions(self, obj=obj)
       
   451 
       
   452     def has_perm(self, perm, obj=None):
       
   453         return _user_has_perm(self, perm, obj=obj)
       
   454 
       
   455     def has_perms(self, perm_list, obj=None):
       
   456         for perm in perm_list:
       
   457             if not self.has_perm(perm, obj):
       
   458                 return False
       
   459         return True
   358 
   460 
   359     def has_module_perms(self, module):
   461     def has_module_perms(self, module):
   360         return False
   462         return _user_has_module_perms(self, module)
   361 
   463 
   362     def get_and_delete_messages(self):
   464     def get_and_delete_messages(self):
   363         return []
   465         return []
   364 
   466 
   365     def is_anonymous(self):
   467     def is_anonymous(self):