from django.contrib.gis.db import models from django.contrib.gis.geos import Point from django.contrib.auth.models import AbstractBaseUser, BaseUserManager from django.contrib.auth import get_user_model from django.utils import timezone from django_countries.fields import CountryField from phonenumber_field.modelfields import PhoneNumberField from polymorphic.models import PolymorphicModel from .helpers import profile_to_coords, upload_path from frontend.fields import LanguageField class UserManager(BaseUserManager): use_in_migrations = True def _create_user(self, email, password, **extra_fields): values = [email] field_value_map = dict(zip(self.model.REQUIRED_FIELDS, values)) for field_name, value in field_value_map.items(): if not value: raise ValueError('The {} value must be set'.format(field_name)) email = self.normalize_email(email) user = self.model( email=email, **extra_fields ) user.set_password(password) user.save(using=self._db) return user def create_user(self, email, password=None, **extra_fields): return self._create_user(email, password, **extra_fields) def create_superuser(self, email, password=None, **extra_fields): extra_fields.setdefault('is_superuser', True) return self._create_user(email, password, **extra_fields) class User(AbstractBaseUser): email = models.EmailField(unique=True) is_active = models.BooleanField(default=True) date_joined = models.DateTimeField(default=timezone.now) last_login = models.DateTimeField(null=True) is_superuser = models.BooleanField(default=False) language = LanguageField(max_length=16, default="de") objects = UserManager() USERNAME_FIELD = 'email' def get_full_name(self): return self.email def get_short_name(self): return self.email def has_permission(self, *args, **kwargs): return self.is_superuser @property def is_staff(self): return self.is_superuser has_module_perms = has_permission has_perm = has_permission @property def phone(self): try: return self.clientprofile.phone except: try: return self.partnerprofile.phone except: return None class AddressMixin(models.Model): street = models.CharField("Straße", max_length=64) city = models.CharField("Stadt", max_length=64) zip = models.CharField("PLZ", max_length=16) state = models.CharField("Bundesland", max_length=64, null=True, blank=True) country = CountryField("Staat") @property def full_address(self): return f"{self.street}, {self.city}, {self.zip}, {self.state}, {self.country}" class Meta: abstract = True class LocationMixin(AddressMixin): coords = models.PointField() def save(self, *args, **kwargs): if not self.coords: lat, lon = profile_to_coords(self) self.coords = Point(lon, lat) super().save(*args, **kwargs) class Meta: abstract = True class ImageMixin(models.Model): image = models.ImageField(upload_to=upload_path, null=True, blank=True) class Meta: abstract = True class PhoneMixin(models.Model): phone = PhoneNumberField("Mobiltelefon") class Meta: abstract = True class PersonMixin(models.Model): company = models.CharField("Firma", max_length=64, null=True, blank=True) vat_id = models.CharField("UID-Nummer", max_length=32, null=True, blank=True) first_name = models.CharField("Vorname", max_length=64) last_name = models.CharField("Nachname", max_length=64) @property def full_name(self): name = self.full_name_only if self.company: name += f" ({self.company})" return name @property def full_name_only(self): name = " ".join([self.first_name, self.last_name]) return name class Meta: abstract = True class Profile(PersonMixin, AddressMixin, PhoneMixin): user = models.OneToOneField(get_user_model(), models.CASCADE) verified = models.BooleanField(default=False) enabled = models.BooleanField(default=True) class Meta: abstract = True class TwoFactor(PolymorphicModel): user = models.ForeignKey(User, models.CASCADE) @classmethod def initiate(cls, user): raise NotImplementedError("%s does not implement initiate()" % cls.__name__) def send_token(self, description=""): return True def validate_token(self, token): raise NotImplementedError("%s does not implement validate_token()" % cls.__name__)