"""Account models""" from django.conf import settings from django.contrib.auth.models import AbstractUser, UserManager as BaseUserManager from django.contrib.auth.tokens import default_token_generator as password_token_generator from django.core.mail import send_mail from django.db import models from django.template.loader import render_to_string from django.utils import timezone from django.utils.encoding import force_bytes from django.utils.html import mark_safe from django.utils.http import urlsafe_base64_encode from django.utils.translation import ugettext_lazy as _ from rest_framework.authtoken.models import Token from authorization.models import Application from utils.models import GMTokenGenerator from utils.models import ImageMixin, ProjectBaseMixin, PlatformMixin from utils.tokens import GMRefreshToken class UserManager(BaseUserManager): """Extended manager for User model.""" use_in_migrations = False def make(self, username: str, email: str, password: str, newsletter: bool) -> object: """Register new user""" obj = self.model( username=username, email=email, newsletter=newsletter) obj.set_password(password) obj.save() return obj class UserQuerySet(models.QuerySet): """Extended queryset for User model.""" def active(self, switcher=True): """Filter only active users.""" return self.filter(is_active=switcher) def by_oauth2_access_token(self, token): """Find users by access token""" return self.filter(oauth2_provider_accesstoken__token=token, oauth2_provider_accesstoken__expires__gt=timezone.now()) def by_oauth2_refresh_token(self, token): """Find users by access token""" return self.filter(oauth2_provider_refreshtoken__token=token, oauth2_provider_refreshtoken__expires__gt=timezone.now()) class User(AbstractUser): """Base user model.""" image_url = models.URLField(verbose_name=_('Image URL path'), blank=True, null=True, default=None) cropped_image_url = models.URLField(verbose_name=_('Cropped image URL path'), blank=True, null=True, default=None) email = models.EmailField(_('email address'), blank=True, null=True, default=None) unconfirmed_email = models.EmailField(_('unconfirmed email'), blank=True, null=True, default=None) email_confirmed = models.BooleanField(_('email status'), default=False) newsletter = models.NullBooleanField(default=True) EMAIL_FIELD = 'email' USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['email'] objects = UserManager.from_queryset(UserQuerySet)() class Meta: """Meta class.""" verbose_name = _('User') verbose_name_plural = _('Users') def __str__(self): """String method.""" return "%s:%s" % (self.email, self.get_short_name()) def get_user_info(self): """Get information about user""" return { "username": self.username, "first_name": self.first_name if self.first_name else None, "last_name": self.last_name if self.last_name else None, "email": self.email if self.email else None, "newsletter": self.newsletter, "is_active": self.is_active } def change_status(self, switcher: bool = False): """Method to set user status to active or inactive""" self.is_active = switcher self.save() def create_jwt_tokens(self, source: int = None): """Create JWT tokens for user""" token = GMRefreshToken.for_user(self, source) return { 'access_token': str(token.access_token), 'refresh_token': str(token), } def expire_access_tokens(self): """Expire all access tokens""" self.access_tokens.update(expires_at=timezone.now()) def expire_refresh_tokens(self): """Expire all refresh tokens""" self.refresh_tokens.update(expires_at=timezone.now()) def confirm_email(self): """Method to confirm user email address""" self.email = self.unconfirmed_email self.unconfirmed_email = None self.email_confirmed = True self.save() def approve(self): """Set user is_active status to True""" self.is_active = True self.save() def get_body_email_message(self, subject: str, message: str): """Prepare the body of the email message""" return { 'subject': subject, 'message': str(message), 'from_email': settings.EMAIL_HOST_USER, 'recipient_list': [self.email, ] } def send_email(self, subject: str, message: str): """Send an email to reset user password""" send_mail(**self.get_body_email_message(subject=subject, message=message)) @property def confirm_email_token(self): """Make a token for finish signup.""" return GMTokenGenerator(purpose=GMTokenGenerator.CONFIRM_EMAIL).make_token(self) @property def change_email_token(self): """Make a token for change email.""" return GMTokenGenerator(purpose=GMTokenGenerator.CHANGE_EMAIL).make_token(self) @property def reset_password_token(self): """Make a token for finish signup.""" return password_token_generator.make_token(self) @property def get_user_uidb64(self): """Get base64 value for user by primary key identifier""" return urlsafe_base64_encode(force_bytes(self.pk)) @property def base_template(self): """Base email template""" return {'domain_uri': settings.DOMAIN_URI, 'uidb64': self.get_user_uidb64, 'site_name': settings.SITE_NAME} @property def image_tag(self): return mark_safe(f'') @property def cropped_image_tag(self): return mark_safe(f'') def reset_password_template(self, country_code): """Get reset password template""" context = {'token': self.reset_password_token, 'country_code': country_code} context.update(self.base_template) return render_to_string( template_name=settings.RESETTING_TOKEN_TEMPLATE, context=context) def confirm_email_template(self, country_code): """Get confirm email template""" context = {'token': self.confirm_email_token, 'country_code': country_code} context.update(self.base_template) return render_to_string( template_name=settings.CONFIRM_EMAIL_TEMPLATE, context=context) def change_email_template(self, country_code): """Get change email template""" context = {'token': self.change_email_token, 'country_code': country_code} context.update(self.base_template) return render_to_string( template_name=settings.CHANGE_EMAIL_TEMPLATE, context=context)