import stripe from django.apps import apps from django.db import models from django.urls import reverse from django.core.mail import send_mail from django.utils import timezone as tz from django.contrib.auth.hashers import make_password from django.contrib.auth.models import ( BaseUserManager, AbstractBaseUser, PermissionsMixin ) from localflavor.us.us_states import USPS_CHOICES class UserManager(BaseUserManager): use_in_migrations = True def _create_user(self, email, password, **extra_fields): """ Create and save a user with the given email and password. """ if not email: raise ValueError("The given email must be set") email = self.normalize_email(email) # Lookup the real model class from the global app registry so this # manager method can be used in migrations. This is fine because # managers are by definition working on the real model. GlobalUserModel = apps.get_model( self.model._meta.app_label, self.model._meta.object_name ) user = self.model(email=email, **extra_fields) user.password = make_password(password) user.save(using=self._db) return user def create_user(self, email, password=None, **extra_fields): extra_fields.setdefault("is_staff", False) extra_fields.setdefault("is_superuser", False) return self._create_user(email, password, **extra_fields) def create_superuser(self, email, password=None, **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(email, password, **extra_fields) def with_perm( self, perm, is_active=True, include_superusers=True, backend=None, obj=None ): if backend is None: backends = auth._get_backends(return_tuples=True) if len(backends) == 1: backend, _ = backends[0] else: raise ValueError( "You have multiple authentication backends configured and " "therefore must provide the `backend` argument." ) elif not isinstance(backend, str): raise TypeError( "backend must be a dotted import path string (got %r)." % backend ) else: backend = auth.load_backend(backend) if hasattr(backend, "with_perm"): return backend.with_perm( perm, is_active=is_active, include_superusers=include_superusers, obj=obj, ) return self.none() class User(AbstractBaseUser, PermissionsMixin): email = models.EmailField( verbose_name="email address", max_length=255, unique=True, ) first_name = models.CharField("first name", max_length=150, blank=True) last_name = models.CharField("last name", max_length=150, blank=True) # Shipping address shipping_street_address_1 = models.CharField(max_length=256, blank=True) shipping_street_address_2 = models.CharField(max_length=256, blank=True) shipping_city = models.CharField(max_length=256, blank=True) shipping_state = models.CharField( max_length=2, choices=USPS_CHOICES, blank=True ) shipping_postal_code = models.CharField(max_length=20, 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.\n" + "Unselect this instead of deleting accounts." ) date_joined = models.DateTimeField("date joined", default=tz.now) stripe_id = models.CharField(max_length=255, blank=True) USERNAME_FIELD = "email" REQUIRED_FIELDS = [] objects = UserManager() @property def has_shipping_address(self): if (self.shipping_street_address_1 != '' and self.shipping_street_address_2 != '' and self.shipping_city != '' and self.shipping_state != '' and self.shipping_postal_code != ''): return True return False 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) def get_or_create_stripe_id(self): if not self.stripe_id: response = stripe.Customer.create( name=self.get_full_name(), email=self.email ) self.stripe_id = response["id"] self.save() return self.stripe_id def get_absolute_url(self): return reverse("storefront:customer-detail", kwargs={"pk": self.pk})