Files
qlockify-backend-deployment/apps/users/models.py

103 lines
3.4 KiB
Python

from django.contrib.auth.models import AbstractUser
from django.db import models
from core.models.base import BaseModel
from core.utils import calculate_age, common_datetime_str
from apps.users.services.managers import UserManager
class User(AbstractUser, BaseModel):
username = None
mobile = models.CharField(max_length=11, unique=True)
email = models.EmailField(blank=True, default="")
description = models.TextField(blank=True, default="")
profile_picture = models.ImageField(upload_to="profile/users/", blank=True, null=True)
birth_date = models.DateField(blank=True, null=True)
password_updated_at = models.DateTimeField(blank=True, null=True)
is_verified = models.BooleanField(default=False)
USERNAME_FIELD = "mobile"
REQUIRED_FIELDS = []
objects = UserManager(alive_only=True)
@property
def full_name(self):
full_name = f"{self.first_name} {self.last_name}".strip()
return full_name if full_name else "Anonymous"
@property
def age(self):
return calculate_age(self.birth_date)
@property
def created_at_display(self):
return common_datetime_str(self.created_at)
def __str__(self):
return self.full_name or self.mobile
class Meta:
verbose_name = "user"
verbose_name_plural = "users"
db_table = "user"
ordering = ("-updated_at", "-created_at")
indexes = (
models.Index(fields=["id"], name="user_id_idx"),
models.Index(fields=["mobile"], name="user_mobile_idx"),
)
class LoginAttempt(BaseModel):
class StatusType(models.IntegerChoices):
FAILED = 0, "failed"
SUCCESS = 1, "success"
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
status = models.PositiveSmallIntegerField(choices=StatusType.choices, default=StatusType.FAILED)
ip_address = models.GenericIPAddressField(null=True, blank=True)
class Meta:
verbose_name = "login_attempts"
verbose_name_plural = "login_attempts"
db_table = "login_attempt"
ordering = ("-updated_at", "-created_at")
def __str__(self):
return f"LoginAttempt for User: {self.user} ({'' if self.status else ''})"
class UserSocialAccount(BaseModel):
class ProviderType(models.TextChoices):
GOOGLE = "google", "google"
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="social_accounts")
provider = models.CharField(max_length=32, choices=ProviderType.choices)
provider_user_id = models.CharField(max_length=255)
email = models.EmailField(blank=True, default="")
email_verified = models.BooleanField(default=False)
avatar_url = models.URLField(blank=True, default="")
class Meta:
verbose_name = "user_social_account"
verbose_name_plural = "user_social_accounts"
db_table = "user_social_account"
ordering = ("-updated_at", "-created_at")
constraints = (
models.UniqueConstraint(
fields=("provider", "provider_user_id"),
name="user_social_account_provider_uid_uniq",
),
)
indexes = (
models.Index(fields=["provider", "provider_user_id"], name="user_social_provider_uid_idx"),
models.Index(fields=["provider", "email"], name="user_social_provider_email_idx"),
)
def __str__(self):
return f"{self.provider}:{self.provider_user_id}"