its now media/users/USER_UUID/icon.webp every time. it also defaults to static/images/defaultuser.webp
177 lines
5.1 KiB
Python
177 lines
5.1 KiB
Python
# -*- encoding: utf-8 -*-
|
|
|
|
import uuid
|
|
|
|
import os
|
|
from django.db import models
|
|
from django.utils import timezone
|
|
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
|
|
from django.utils.translation import gettext_lazy as _
|
|
from django.core.files.storage import FileSystemStorage
|
|
from django.utils.deconstruct import deconstructible
|
|
|
|
|
|
class OverwriteStorage(FileSystemStorage):
|
|
def get_available_name(self, name, max_length=None):
|
|
|
|
if self.exists(name):
|
|
os.remove(os.path.join(self.location, name))
|
|
|
|
return name
|
|
|
|
|
|
@deconstructible
|
|
class IconPathGenerator:
|
|
def __call__(self, instance, filename: str) -> str:
|
|
return os.path.join("users", str(instance.id), "icon.webp")
|
|
|
|
|
|
class Department(models.Model):
|
|
title = models.CharField(max_length=150)
|
|
icon = models.CharField(max_length=32, null=True, blank=True)
|
|
|
|
def __str__(self):
|
|
return self.title
|
|
|
|
def serialize(self) -> dict:
|
|
return {
|
|
"title": self.title,
|
|
"icon": self.icon
|
|
}
|
|
|
|
|
|
class UserManager(BaseUserManager):
|
|
|
|
def create_user(self, email: str, forename: str, surname: str, password: str=None, **extra_fields):
|
|
if not email:
|
|
raise ValueError("Please provide an email address")
|
|
|
|
email = self.normalize_email(email)
|
|
user = self.model(email=email, forename=forename, surname=surname, **extra_fields)
|
|
user.set_password(password)
|
|
user.save()
|
|
|
|
return user
|
|
|
|
def create_superuser(self, email: str, forename: str, surname: str, password: str, **extra_fields):
|
|
extra_fields.setdefault("is_staff", True)
|
|
extra_fields.setdefault("is_superuser", True)
|
|
extra_fields.setdefault("is_active", True)
|
|
|
|
if not extra_fields.get("is_staff"):
|
|
raise ValueError("Superuser must have is_staff=True")
|
|
|
|
if not extra_fields.get("is_superuser"):
|
|
raise ValueError("Superuser must have is_superuser=True")
|
|
|
|
return self.create_user(email, forename, surname, password, **extra_fields)
|
|
|
|
|
|
class User(AbstractBaseUser, PermissionsMixin):
|
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
|
|
icon = models.ImageField(
|
|
_("profile picture"),
|
|
upload_to=IconPathGenerator(),
|
|
default="../static/assets/images/defaultuser.webp",
|
|
storage=OverwriteStorage()
|
|
)
|
|
email = models.EmailField(
|
|
_("email address"),
|
|
unique=True,
|
|
error_messages = {
|
|
"unique": _("A user with this email address already exists.")
|
|
}
|
|
)
|
|
forename = models.CharField(
|
|
_("first name"),
|
|
max_length=150,
|
|
help_text=_("This should be your real first name.")
|
|
)
|
|
surname = models.CharField(
|
|
_("last name"),
|
|
max_length=150,
|
|
help_text=_("This should be your real last name.")
|
|
)
|
|
|
|
department = models.ForeignKey(
|
|
Department,
|
|
blank=True,
|
|
null=True,
|
|
on_delete=models.SET_NULL,
|
|
verbose_name=_("department"),
|
|
help_text=_("Which department does this user belong to?")
|
|
)
|
|
|
|
create_timestamp = models.DateTimeField(
|
|
_("Creation Date"),
|
|
editable=True,
|
|
default=timezone.now,
|
|
help_text=_("When the user was created.")
|
|
)
|
|
edit_timestamp = models.DateTimeField(
|
|
_("Last Edited"),
|
|
editable=True,
|
|
default=timezone.now,
|
|
help_text=_("When the user was last edited.")
|
|
)
|
|
|
|
is_active = models.BooleanField(
|
|
_("active status"),
|
|
default=True,
|
|
help_text=_('Use as a "soft delete" rather than deleting the user.')
|
|
)
|
|
is_staff = models.BooleanField(
|
|
_("staff status"),
|
|
default=False,
|
|
help_text=_("Designates whether the user can log into this admin site.")
|
|
)
|
|
is_superuser = models.BooleanField(
|
|
_("superuser status"),
|
|
default=False,
|
|
help_text=_("Designates whether the user has unrestricted site control.")
|
|
)
|
|
|
|
USERNAME_FIELD = "email"
|
|
EMAIL_FIELD = "email"
|
|
REQUIRED_FIELDS = ["forename", "surname"]
|
|
|
|
objects = UserManager()
|
|
|
|
class Meta:
|
|
verbose_name = _('user')
|
|
verbose_name_plural = _('users')
|
|
|
|
def __str__(self):
|
|
return f"{self.id} • {self.email} • {self.formal_fullname}"
|
|
|
|
def save(self, *args, **kwargs):
|
|
self.edit_timestamp = timezone.now()
|
|
super().save(*args, **kwargs)
|
|
|
|
def clean(self):
|
|
super().clean()
|
|
self.email = self.__class__.objects.normalize_email(self.email)
|
|
|
|
@property
|
|
def fullname(self) -> str:
|
|
return f"{self.forename} {self.surname}"
|
|
|
|
@property
|
|
def formal_fullname(self) -> str:
|
|
return f"{self.surname}, {self.forename}"
|
|
|
|
def serialize(self) -> dict:
|
|
department = self.department.serialize() if self.department else None
|
|
|
|
return {
|
|
"id": self.id,
|
|
"icon": self.icon.url,
|
|
"email": self.email,
|
|
"forename": self.forename,
|
|
"surname": self.surname,
|
|
"department": department,
|
|
"create_timestamp": self.create_timestamp,
|
|
"edit_timestamp": self.edit_timestamp
|
|
}
|