|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434 |
- from django.contrib import auth
- from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
- from django.contrib.contenttypes.models import ContentType
- 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 timezone
- from django.utils.translation import gettext_lazy as _
-
- from .validators import UnicodeUsernameValidator
-
-
- 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'])
-
-
- 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),
- )
-
-
- 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.
- - The "view" permission limits the ability to view 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."
-
- The permissions listed above are automatically created for each 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" % (
- self.content_type.app_label,
- self.content_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)
-
-
- 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=150, 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):
- """
- Create and save 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)
- username = self.model.normalize_username(username)
- 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):
- """
- Add the fields and methods necessary to support the Group and Permission
- models 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):
- """
- Return a list of permission strings that this user has through their
- groups. Query all available auth backends. If an object is passed in,
- return only permissions matching this object.
- """
- 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):
- """
- Return True if the user has the specified permission. Query all
- available auth backends, but return 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, check
- permissions for that object.
- """
- # 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):
- """
- Return True if the user has each of the specified permissions. If
- object is passed, check if the user has all required perms for it.
- """
- return all(self.has_perm(perm, obj) for perm in perm_list)
-
- def has_module_perms(self, app_label):
- """
- Return True if the user has any permissions in the given app label.
- Use similar 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_validator = UnicodeUsernameValidator()
-
- username = models.CharField(
- _('username'),
- max_length=150,
- unique=True,
- help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
- validators=[username_validator],
- 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=150, 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()
-
- EMAIL_FIELD = 'email'
- USERNAME_FIELD = 'username'
- REQUIRED_FIELDS = ['email']
-
- class Meta:
- verbose_name = _('user')
- verbose_name_plural = _('users')
- abstract = True
-
- def clean(self):
- super().clean()
- self.email = self.__class__.objects.normalize_email(self.email)
-
- def get_full_name(self):
- """
- Return 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):
- """Return the short name for the user."""
- return self.first_name
-
- def email_user(self, subject, message, from_email=None, **kwargs):
- """Send 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 and password are required. Other fields are optional.
- """
- class Meta(AbstractUser.Meta):
- swappable = 'AUTH_USER_MODEL'
-
-
- class AnonymousUser:
- id = None
- pk = None
- username = ''
- is_staff = False
- is_active = False
- is_superuser = False
- _groups = EmptyManager(Group)
- _user_permissions = EmptyManager(Permission)
-
- def __str__(self):
- return 'AnonymousUser'
-
- def __eq__(self, other):
- return isinstance(other, self.__class__)
-
- def __hash__(self):
- return 1 # instances always return the same hash value
-
- def __int__(self):
- raise TypeError('Cannot cast AnonymousUser to int. Are you trying to use it in place of User?')
-
- 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.")
-
- @property
- def groups(self):
- return self._groups
-
- @property
- def user_permissions(self):
- return self._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):
- return all(self.has_perm(perm, obj) for perm in perm_list)
-
- def has_module_perms(self, module):
- return _user_has_module_perms(self, module)
-
- @property
- def is_anonymous(self):
- return True
-
- @property
- def is_authenticated(self):
- return False
-
- def get_username(self):
- return self.username
|