Files
hossein-por-shop/backend/account/models.py
T

200 lines
7.0 KiB
Python

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
from django.contrib import admin
from django.conf import settings
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, verbose_name='فعال بودن کاربر')
is_staff = models.BooleanField(default=False, verbose_name='کارمند')
gender_option = (
('مرد', 'مرد'),
('زن', 'زن')
)
gender = models.CharField(choices=gender_option, max_length=20, verbose_name='جنسیت')
birth_date = models.DateField()
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='تاریخ تمام شدن کد یک بار مصرف')
video_uploader = models.BooleanField(default=False, help_text='اپلود کننده ی ویدیویی اموزشی پنل ادمین', verbose_name='اپلودر اموزش')
objects = UserManager()
USERNAME_FIELD = 'phone'
REQUIRED_FIELDS = []
@property
def groups(self):
return None
@property
def full_name(self):
if self.first_name and self.last_name:
return f"{self.first_name} {self.last_name}"
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', verbose_name='کاربر')
name = models.CharField(max_length=30, verbose_name='نام ادرس')
address = models.TextField(verbose_name='ادرس کامل')
postal_code = models.CharField(max_length=10, verbose_name='کد پستی')
phone = models.CharField(max_length=11, verbose_name='شماره تماس برای ارسال', help_text='شماره تماس کاربر و شماره ی ارسالی میتواند متفاوت باشد')
city = models.CharField(max_length=30, verbose_name='شهر')
province = models.CharField(max_length=30, verbose_name='استان')
for_me = models.BooleanField(default=False, verbose_name='برای خود کاربر')
is_main = models.BooleanField(default=False)
def __str__(self):
return f"{self.user.phone}, {self.name}"
class Meta:
verbose_name = 'ادرس کاربر'
verbose_name_plural = 'ادرس های کاربر'
import os
import json
from pywebpush import webpush, WebPushException
class PushSubscription(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
endpoint = models.TextField(unique=True)
keys = models.JSONField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'{self.user} push'
def send_notif(self, title, body):
payload = {
"title": title,
"body": body,
"icon": ''
}
try:
webpush(
subscription_info={
"endpoint": self.endpoint,
"keys": self.keys
},
data=json.dumps(payload),
vapid_private_key=settings.VAPID_PRIVATE_KEY,
vapid_claims={
"sub": "mailto:admin@example.com"
}
)
except WebPushException as ex:
print("Failed to send notification:", ex)
@classmethod
def send_group_notification(cls, user, title, body):
payload = {
"title": title,
"body": body,
"icon": ''
}
subscriptions = PushSubscription.objects.filter(user=user)
for sub in subscriptions:
try:
webpush(
subscription_info={
"endpoint": sub.endpoint,
"keys": sub.keys
},
data=json.dumps(payload),
vapid_private_key=settings.VAPID_PRIVATE_KEY,
vapid_claims={
"sub": "mailto:admin@example.com",
'aud': 'https://mamalizz-cooked.vercel.app'
}
)
except WebPushException as ex:
print(f"Failed to send notification to {sub.user}:", ex)