from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin, Group from django.db import models from django.utils.translation import gettext_lazy as _ import random from datetime import datetime, timedelta from django.utils import timezone from rest_framework_simplejwt.token_blacklist.models import BlacklistedToken, OutstandingToken import hashlib class UserManager(BaseUserManager): def create_user(self, phone, password=None): if not phone: raise ValueError('Users must have a phone number') user = self.model( phone=phone, ) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, phone, password=None): user = self.create_user( phone=phone, ) user.is_staff = True user.is_superuser = True user.set_password(password) user.save(using=self._db) return user class User(AbstractBaseUser, PermissionsMixin): email = models.EmailField(max_length=255, verbose_name='ایمیل', blank=True, null=True) phone = models.CharField(max_length=12, verbose_name='شماره تماس', unique=True) first_name = models.CharField(max_length=50, blank=True, verbose_name='نام') last_name = models.CharField(max_length=50, blank=True, verbose_name='نام خانوادگی') profile_photo = models.ImageField(upload_to='profile_photos/', null=True, blank=True, verbose_name='عکس پروفایل') is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) date_joined = models.DateTimeField(auto_now_add=True, verbose_name='تاریخ ثبتنام') otp_hash = models.CharField(max_length=64, null=True, blank=True, verbose_name='کد یک بار مصرف') otp_expiry = models.DateTimeField(null=True, blank=True, verbose_name='تاریخ تمام شدن کد یک بار مصرف') objects = UserManager() USERNAME_FIELD = 'phone' REQUIRED_FIELDS = [] @property def groups(self): return None @property def user_permissions(self): return None class Meta: verbose_name = 'کاربر' verbose_name_plural = 'کاربران' def _hash_otp(self, otp): return hashlib.sha256(otp.encode()).hexdigest() def set_otp(self): raw_otp = str(random.randint(100000, 999999)) self.otp_hash = self._hash_otp(raw_otp) self.otp_expiry = timezone.now() + timedelta(minutes=5) self.save() return raw_otp def clear_otp(self): self.otp_hash = None self.otp_expiry = None self.save() def verify_otp(self, otp_code): if self.otp_hash and self.otp_expiry > timezone.now(): return self.otp_hash == self._hash_otp(otp_code) return False def blacklist_user_tokens(self): try: tokens = OutstandingToken.objects.filter(user=self) for token in tokens: BlacklistedToken.objects.get_or_create(token=token) except Exception as e: print(f"block list error: {e}") def __str__(self): if self.first_name and self.last_name: return f'{self.first_name} {self.last_name}' else: return self.phone def get_name(self): if self.first_name and self.last_name: return f'{self.first_name} {self.last_name}' else: return self.phone class UserAddressModel(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='address') name = models.CharField(max_length=30) address = models.TextField() postal_code = models.CharField(max_length=10) phone = models.CharField(max_length=11) city = models.CharField(max_length=30) province = models.CharField(max_length=30) for_me = models.BooleanField(default=False) def __str__(self): return f"{self.user.phone}, {self.name}"