|
- from __future__ import unicode_literals
-
- from django.contrib import auth
- from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
- from django.contrib.auth.signals import user_logged_in
- from django.contrib.contenttypes.models import ContentType
- from django.core import validators
- from django.core.exceptions import PermissionDenied
- from django.core.mail import send_mail
- from django.db import models
- from django.db.models.manager import EmptyManager
- from django.utils import six, timezone
- from django.utils.encoding import python_2_unicode_compatible
- from django.utils.translation import ugettext_lazy as _
-
-
- def update_last_login(sender, user, **kwargs):
- """
- A signal receiver which updates the last_login date for
- the user logging in.
- """
- user.last_login = timezone.now()
- user.save(update_fields=['last_login'])
- user_logged_in.connect(update_last_login)
-
-
- class PermissionManager(models.Manager):
- use_in_migrations = True
-
- def get_by_natural_key(self, codename, app_label, model):
- return self.get(
- codename=codename,
- content_type=ContentType.objects.db_manager(self.db).get_by_natural_key(app_label, model),
- )
-
-
- @python_2_unicode_compatible
- class Permission(models.Model):
- """
- The permissions system provides a way to assign permissions to specific
- users and groups of users.
-
- 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:
-
- - The "add" permission limits the user's ability to view the "add" form
- and add an object.
- - The "change" permission limits a user's ability to view the change
- list, view the "change" form and change an object.
- - The "delete" permission limits the ability to delete an object.
-
- Permissions are set globally per type of object, not per specific object
- instance. It is possible to say "Mary may change news stories," but it's
- not currently possible to say "Mary may change news stories, but only the
- ones she created herself" or "Mary may only change news stories that have a
- certain status or publication date."
-
- Three basic permissions -- add, change and delete -- are automatically
- created for each Django model.
- """
- name = models.CharField(_('name'), max_length=255)
- content_type = models.ForeignKey(
- ContentType,
- models.CASCADE,
- verbose_name=_('content type'),
- )
- codename = models.CharField(_('codename'), max_length=100)
- objects = PermissionManager()
-
- class Meta:
- verbose_name = _('permission')
- verbose_name_plural = _('permissions')
- unique_together = (('content_type', 'codename'),)
- ordering = ('content_type__app_label', 'content_type__model',
- 'codename')
-
- def __str__(self):
- return "%s | %s | %s" % (
- six.text_type(self.content_type.app_label),
- six.text_type(self.content_type),
- six.text_type(self.name))
-
- def natural_key(self):
- return (self.codename,) + self.content_type.natural_key()
- natural_key.dependencies = ['contenttypes.contenttype']
-
-
- class GroupManager(models.Manager):
- """
- The manager for the auth's Group model.
- """
- use_in_migrations = True
-
- def get_by_natural_key(self, name):
- return self.get(name=name)
-
-
- @python_2_unicode_compatible
- class Group(models.Model):
- """
- 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.
-
- 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.
-
- 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 email
- messages.
- """
- name = models.CharField(_('name'), max_length=80, unique=True)
- permissions = models.ManyToManyField(
- Permission,
- verbose_name=_('permissions'),
- blank=True,
- )
-
- objects = GroupManager()
-
- class Meta:
- verbose_name = _('group')
- verbose_name_plural = _('groups')
-
- def __str__(self):
- return self.name
-
- def natural_key(self):
- return (self.name,)
-
-
- class UserManager(BaseUserManager):
- use_in_migrations = True
-
- def _create_user(self, username, email, password, **extra_fields):
- """
- Creates and saves a User with the given username, email and password.
- """
- if not username:
- raise ValueError('The given username must be set')
- email = self.normalize_email(email)
- user = self.model(username=username, email=email, **extra_fields)
- user.set_password(password)
- user.save(using=self._db)
- return user
-
- def create_user(self, username, email=None, password=None, **extra_fields):
- extra_fields.setdefault('is_staff', False)
- extra_fields.setdefault('is_superuser', False)
- return self._create_user(username, email, password, **extra_fields)
-
- def create_superuser(self, username, email, password, **extra_fields):
- extra_fields.setdefault('is_staff', True)
- extra_fields.setdefault('is_superuser', True)
-
- if extra_fields.get('is_staff') is not True:
- raise ValueError('Superuser must have is_staff=True.')
- if extra_fields.get('is_superuser') is not True:
- raise ValueError('Superuser must have is_superuser=True.')
-
- return self._create_user(username, email, password, **extra_fields)
-
-
- # A few helper functions for common logic between User and AnonymousUser.
- def _user_get_all_permissions(user, obj):
- permissions = set()
- for backend in auth.get_backends():
- if hasattr(backend, "get_all_permissions"):
- permissions.update(backend.get_all_permissions(user, obj))
- return permissions
-
-
- def _user_has_perm(user, perm, obj):
- """
- A backend can raise `PermissionDenied` to short-circuit permission checking.
- """
- for backend in auth.get_backends():
- if not hasattr(backend, 'has_perm'):
- continue
- try:
- if backend.has_perm(user, perm, obj):
- return True
- except PermissionDenied:
- return False
- return False
-
-
- def _user_has_module_perms(user, app_label):
- """
- A backend can raise `PermissionDenied` to short-circuit permission checking.
- """
- for backend in auth.get_backends():
- if not hasattr(backend, 'has_module_perms'):
- continue
- try:
- if backend.has_module_perms(user, app_label):
- return True
- except PermissionDenied:
- return False
- return False
-
-
- class PermissionsMixin(models.Model):
- """
- A mixin class that adds the fields and methods necessary to support
- Django's Group and Permission model using the ModelBackend.
- """
- is_superuser = models.BooleanField(
- _('superuser status'),
- default=False,
- help_text=_(
- 'Designates that this user has all permissions without '
- 'explicitly assigning them.'
- ),
- )
- groups = models.ManyToManyField(
- Group,
- verbose_name=_('groups'),
- blank=True,
- help_text=_(
- 'The groups this user belongs to. A user will get all permissions '
- 'granted to each of their groups.'
- ),
- related_name="user_set",
- related_query_name="user",
- )
- user_permissions = models.ManyToManyField(
- Permission,
- verbose_name=_('user permissions'),
- blank=True,
- help_text=_('Specific permissions for this user.'),
- related_name="user_set",
- related_query_name="user",
- )
-
- class Meta:
- abstract = True
-
- def get_group_permissions(self, obj=None):
- """
- Returns a list of permission strings that this user has through their
- groups. This method queries all available auth backends. If an object
- is passed in, only permissions matching this object are returned.
- """
- permissions = set()
- for backend in auth.get_backends():
- if hasattr(backend, "get_group_permissions"):
- permissions.update(backend.get_group_permissions(self, obj))
- return permissions
-
- def get_all_permissions(self, obj=None):
- return _user_get_all_permissions(self, obj)
-
- def has_perm(self, perm, obj=None):
- """
- Returns True if the user has the specified permission. This method
- queries all available auth backends, but returns immediately if any
- backend returns True. Thus, a user who has permission from a single
- auth backend is assumed to have permission in general. If an object is
- provided, permissions for this specific object are checked.
- """
-
- # Active superusers have all permissions.
- if self.is_active and self.is_superuser:
- return True
-
- # Otherwise we need to check the backends.
- return _user_has_perm(self, perm, obj)
-
- def has_perms(self, perm_list, obj=None):
- """
- Returns True if the user has each of the specified permissions. If
- object is passed, it checks if the user has all required perms for this
- object.
- """
- for perm in perm_list:
- if not self.has_perm(perm, obj):
- return False
- return True
-
- def has_module_perms(self, app_label):
- """
- Returns True if the user has any permissions in the given app label.
- Uses pretty much the same logic as has_perm, above.
- """
- # Active superusers have all permissions.
- if self.is_active and self.is_superuser:
- return True
-
- return _user_has_module_perms(self, app_label)
-
-
- class AbstractUser(AbstractBaseUser, PermissionsMixin):
- """
- An abstract base class implementing a fully featured User model with
- admin-compliant permissions.
-
- Username and password are required. Other fields are optional.
- """
- username = models.CharField(
- _('username'),
- max_length=30,
- unique=True,
- help_text=_('Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.'),
- validators=[
- validators.RegexValidator(
- r'^[\w.@+-]+$',
- _('Enter a valid username. This value may contain only '
- 'letters, numbers ' 'and @/./+/-/_ characters.')
- ),
- ],
- error_messages={
- 'unique': _("A user with that username already exists."),
- },
- )
- first_name = models.CharField(_('first name'), max_length=30, blank=True)
- last_name = models.CharField(_('last name'), max_length=30, blank=True)
- email = models.EmailField(_('email address'), blank=True)
- is_staff = models.BooleanField(
- _('staff status'),
- default=False,
- help_text=_('Designates whether the user can log into this admin site.'),
- )
- is_active = models.BooleanField(
- _('active'),
- default=True,
- help_text=_(
- 'Designates whether this user should be treated as active. '
- 'Unselect this instead of deleting accounts.'
- ),
- )
- date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
-
- objects = UserManager()
-
- USERNAME_FIELD = 'username'
- REQUIRED_FIELDS = ['email']
-
- class Meta:
- verbose_name = _('user')
- verbose_name_plural = _('users')
- abstract = True
-
- def get_full_name(self):
- """
- Returns the first_name plus the last_name, with a space in between.
- """
- full_name = '%s %s' % (self.first_name, self.last_name)
- return full_name.strip()
-
- def get_short_name(self):
- "Returns the short name for the user."
- return self.first_name
-
- def email_user(self, subject, message, from_email=None, **kwargs):
- """
- Sends an email to this User.
- """
- send_mail(subject, message, from_email, [self.email], **kwargs)
-
-
- class User(AbstractUser):
- """
- Users within the Django authentication system are represented by this
- model.
-
- Username, password and email are required. Other fields are optional.
- """
- class Meta(AbstractUser.Meta):
- swappable = 'AUTH_USER_MODEL'
-
-
- @python_2_unicode_compatible
- class AnonymousUser(object):
- id = None
- pk = None
- username = ''
- is_staff = False
- is_active = False
- is_superuser = False
- _groups = EmptyManager(Group)
- _user_permissions = EmptyManager(Permission)
-
- def __init__(self):
- pass
-
- def __str__(self):
- return 'AnonymousUser'
-
- def __eq__(self, other):
- return isinstance(other, self.__class__)
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
- def __hash__(self):
- return 1 # instances always return the same hash value
-
- def save(self):
- raise NotImplementedError("Django doesn't provide a DB representation for AnonymousUser.")
-
- def delete(self):
- raise NotImplementedError("Django doesn't provide a DB representation for AnonymousUser.")
-
- def set_password(self, raw_password):
- raise NotImplementedError("Django doesn't provide a DB representation for AnonymousUser.")
-
- def check_password(self, raw_password):
- raise NotImplementedError("Django doesn't provide a DB representation for AnonymousUser.")
-
- def _get_groups(self):
- return self._groups
- groups = property(_get_groups)
-
- def _get_user_permissions(self):
- return self._user_permissions
- user_permissions = property(_get_user_permissions)
-
- def get_group_permissions(self, obj=None):
- return set()
-
- def get_all_permissions(self, obj=None):
- return _user_get_all_permissions(self, obj=obj)
-
- def has_perm(self, perm, obj=None):
- return _user_has_perm(self, perm, obj=obj)
-
- def has_perms(self, perm_list, obj=None):
- for perm in perm_list:
- if not self.has_perm(perm, obj):
- return False
- return True
-
- def has_module_perms(self, module):
- return _user_has_module_perms(self, module)
-
- def is_anonymous(self):
- return True
-
- def is_authenticated(self):
- return False
-
- def get_username(self):
- return self.username
|