22from datetime import datetime , timezone
33
44
5+ from core .models import AuditableModel
6+ from django .conf import settings
7+ from django .contrib .auth .models import AbstractBaseUser , PermissionsMixin
8+ from django .db import models
9+ from django .utils .translation import gettext_lazy as _
10+ from django .contrib .postgres .fields import ArrayField
11+ from .enums import TOKEN_TYPE_CHOICE , ROLE_CHOICE
12+ from .managers import CustomUserManager
13+
14+
15+ def default_role ():
16+ return ["CUSTOMER" ]
17+
18+
19+ class User (AbstractBaseUser , PermissionsMixin ):
20+ id = models .UUIDField (primary_key = True , default = uuid .uuid4 , editable = False )
21+ email = models .EmailField (
22+ _ ("email address" ), null = True , blank = True , unique = True )
23+ password = models .CharField (max_length = 255 , null = True )
24+ firstname = models .CharField (max_length = 255 , blank = True , null = True )
25+ lastname = models .CharField (max_length = 255 , blank = True , null = True )
26+ image = models .FileField (upload_to = "users/" , blank = True , null = True )
27+ phone = models .CharField (max_length = 30 , unique = True , blank = True , null = True )
28+ is_locked = models .BooleanField (default = False )
29+ is_staff = models .BooleanField (default = False )
30+ is_active = models .BooleanField (default = False )
31+ is_admin = models .BooleanField (default = False )
32+ last_login = models .DateTimeField (null = True , blank = True )
33+ created_at = models .DateTimeField (auto_now_add = True )
34+ updated_at = models .DateTimeField (auto_now = True )
35+ verified = models .BooleanField (default = False )
36+ USERNAME_FIELD = "phone"
37+ REQUIRED_FIELDS = []
38+ objects = CustomUserManager ()
39+ roles = ArrayField (models .CharField (max_length = 20 , blank = True ,
40+ choices = ROLE_CHOICE ), default = default_role , size = 6 )
41+
42+ class Meta :
43+ ordering = ("-created_at" ,)
44+
45+ def __str__ (self ) -> str :
46+ return self .phone
47+
48+ def save_last_login (self ) -> None :
49+ self .last_login = datetime .now ()
50+ self .save ()
51+
52+
53+ class PendingUser (AuditableModel ):
54+ phone = models .CharField (max_length = 20 )
55+ verification_code = models .CharField (max_length = 8 , blank = True , null = True )
56+ password = models .CharField (max_length = 255 , null = True )
57+
58+
59+ def __str__ (self ):
60+ return f"{ str (self .phone )} { self .verification_code } "
61+
62+ def is_valid (self ) -> bool :
63+ """10 mins OTP validation"""
64+ lifespan_in_seconds = float (settings .OTP_EXPIRE_TIME * 60 )
65+ now = datetime .now (timezone .utc )
66+ time_diff = now - self .created_at
67+ time_diff = time_diff .total_seconds ()
68+ if time_diff >= lifespan_in_seconds :
69+ return False
70+ return True
71+
72+
73+ class Token (models .Model ):
74+ id = models .UUIDField (primary_key = True , default = uuid .uuid4 , editable = False )
75+ user = models .ForeignKey (settings .AUTH_USER_MODEL ,
76+ on_delete = models .CASCADE )
77+ token = models .CharField (max_length = 8 )
78+ token_type = models .CharField (max_length = 100 , choices = TOKEN_TYPE_CHOICE )
79+ created_at = models .DateTimeField (auto_now_add = True )
80+
81+ def __str__ (self ):
82+ return f"{ str (self .user )} { self .token } "
83+
84+ def is_valid (self ) -> bool :
85+ lifespan_in_seconds = float (settings .TOKEN_LIFESPAN * 60 )
86+ now = datetime .now (timezone .utc )
87+ time_diff = now - self .created_at
88+ time_diff = time_diff .total_seconds ()
89+ if time_diff >= lifespan_in_seconds :
90+ return False
91+ return True
92+
93+ def reset_user_password (self , password : str ) -> None :
94+ self .user .set_password (password )
95+ self .user .save ()
0 commit comments