from django.contrib.auth.models import AbstractUser from django.db import models class User(AbstractUser): """Custom User model using email as the unique identifier.""" email = models.EmailField( unique=True, max_length=254, help_text="Email address used for authentication.", ) username = models.CharField( max_length=150, blank=True, null=True, help_text="Optional display name. Not used for authentication.", ) USERNAME_FIELD = "email" REQUIRED_FIELDS: list[str] = [] class Meta: db_table = "accounts_user" verbose_name = "User" verbose_name_plural = "Users" def __str__(self) -> str: return self.email @property def is_admin(self) -> bool: """Check if user belongs to the admin group.""" return self.groups.filter(name="admin").exists() or self.is_superuser class BlacklistedToken(models.Model): """Stores blacklisted JWT tokens for revocation.""" jti = models.UUIDField(unique=True, help_text="JWT ID from the token payload") user = models.ForeignKey( User, on_delete=models.CASCADE, related_name="blacklisted_tokens", ) created_at = models.DateTimeField(auto_now_add=True) expires_at = models.DateTimeField(help_text="When the token would have naturally expired") class Meta: db_table = "accounts_blacklisted_token" verbose_name = "Blacklisted Token" verbose_name_plural = "Blacklisted Tokens" indexes = [ models.Index(fields=["jti"]), models.Index(fields=["expires_at"]), ] def __str__(self) -> str: return f"Blacklisted {self.jti} (user {self.user_id})"