this module allows importing abstractbaseuser even when django contrib auth is not in installedapps normalize the email address by lowercasing the domain part of it stores the raw password if setpassword is called so that it can be passed to passwordchanged after the model is saved return the username for this user return getattrself self usernamefield def cleanself setattrself self usernamefield self normalizeusernameself getusername def naturalkeyself return self getusername property def isanonymousself return false property def isauthenticatedself return true def setpasswordself rawpassword self password makepasswordrawpassword self password rawpassword def checkpasswordself rawpassword def setterrawpassword self setpasswordrawpassword password hash upgrades shouldn t be considered password changes self password none self saveupdatefieldspassword return checkpasswordrawpassword self password setter async def acheckpasswordself rawpassword password hash upgrades shouldn t be considered password changes set a value that will never be a valid hash return false if setunusablepassword has been called for this user return an hmac of the password field normalize the email address by lowercasing the domain part of it stores the raw password if set_password is called so that it can be passed to password_changed after the model is saved return the username for this user always return false this is a way of comparing user objects to anonymous users always return true this is a way to tell if the user has been authenticated in templates return a boolean of whether the raw_password was correct handles hashing formats behind the scenes password hash upgrades shouldn t be considered password changes see check_password password hash upgrades shouldn t be considered password changes set a value that will never be a valid hash return false if set_unusable_password has been called for this user return an hmac of the password field
import unicodedata

from django.conf import settings
from django.contrib.auth import password_validation
from django.contrib.auth.hashers import (
    acheck_password,
    check_password,
    is_password_usable,
    make_password,
)
from django.db import models
from django.utils.crypto import salted_hmac
from django.utils.translation import gettext_lazy as _


class BaseUserManager(models.Manager):
    @classmethod
    def normalize_email(cls, email):
        
        email = email or ""
        try:
            email_name, domain_part = email.strip().rsplit("@", 1)
        except ValueError:
            pass
        else:
            email = email_name + "@" + domain_part.lower()
        return email

    def get_by_natural_key(self, username):
        return self.get(**{self.model.USERNAME_FIELD: username})


class AbstractBaseUser(models.Model):
    password = models.CharField(_("password"), max_length=128)
    last_login = models.DateTimeField(_("last login"), blank=True, null=True)

    is_active = True

    REQUIRED_FIELDS = []

    
    
    _password = None

    class Meta:
        abstract = True

    def __str__(self):
        return self.get_username()

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        if self._password is not None:
            password_validation.password_changed(self._password, self)
            self._password = None

    def get_username(self):
        
        return getattr(self, self.USERNAME_FIELD)

    def clean(self):
        setattr(self, self.USERNAME_FIELD, self.normalize_username(self.get_username()))

    def natural_key(self):
        return (self.get_username(),)

    @property
    def is_anonymous(self):
        
        return False

    @property
    def is_authenticated(self):
        
        return True

    def set_password(self, raw_password):
        self.password = make_password(raw_password)
        self._password = raw_password

    def check_password(self, raw_password):
        

        def setter(raw_password):
            self.set_password(raw_password)
            
            self._password = None
            self.save(update_fields=["password"])

        return check_password(raw_password, self.password, setter)

    async def acheck_password(self, raw_password):
        

        async def setter(raw_password):
            self.set_password(raw_password)
            
            self._password = None
            await self.asave(update_fields=["password"])

        return await acheck_password(raw_password, self.password, setter)

    def set_unusable_password(self):
        
        self.password = make_password(None)

    def has_usable_password(self):
        
        return is_password_usable(self.password)

    def get_session_auth_hash(self):
        
        return self._get_session_auth_hash()

    def get_session_auth_fallback_hash(self):
        for fallback_secret in settings.SECRET_KEY_FALLBACKS:
            yield self._get_session_auth_hash(secret=fallback_secret)

    def _get_session_auth_hash(self, secret=None):
        key_salt = "django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash"
        return salted_hmac(
            key_salt,
            self.password,
            secret=secret,
            algorithm="sha256",
        ).hexdigest()

    @classmethod
    def get_email_field_name(cls):
        try:
            return cls.EMAIL_FIELD
        except AttributeError:
            return "email"

    @classmethod
    def normalize_username(cls, username):
        return (
            unicodedata.normalize("NFKC", username)
            if isinstance(username, str)
            else username
        )