File size: 2,703 Bytes
9e798a1 8450c71 b856986 9e798a1 b856986 9e798a1 8450c71 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 b856986 9e798a1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
from tortoise import fields, models
from passlib.context import CryptContext
import datetime
import uuid
import random
import string
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def generate_short_uuid() -> str:
return "".join(random.choices(string.ascii_letters + string.digits, k=5))
class User(models.Model):
id = fields.CharField(primary_key=True, max_length=5, default=generate_short_uuid)
name = fields.CharField(max_length=100)
password = fields.CharField(max_length=100)
phoneNumber = fields.CharField(max_length=15, unique=True)
balance = fields.DecimalField(max_digits=10, decimal_places=2, default=0.00)
mac_address = fields.CharField(max_length=17)
createdAt = fields.DatetimeField(auto_now_add=True)
updatedAt = fields.DatetimeField(auto_now=True)
lastLogin = fields.DatetimeField(default=datetime.datetime.now)
failed_attempts = fields.IntField(default=0)
account_locked = fields.BooleanField(default=False)
reset_token = fields.CharField(max_length=6, null=True, unique=True)
reset_token_expiration = fields.DatetimeField(null=True)
class Meta:
table = "users"
def hash_password(self, plain_password: str) -> str:
return pwd_context.hash(plain_password)
def verify_password(self, plain_password: str) -> bool:
if (
self.account_locked
and datetime.datetime.now()
< self.lastLogin + datetime.timedelta(minutes=15)
):
print("Account is locked due to too many failed attempts. Try again later.")
return False
if pwd_context.verify(plain_password, self.password):
self.failed_attempts = 0
self.account_locked = False
self.lastLogin = datetime.datetime.now()
self.save()
return True
else:
self.failed_attempts += 1
if self.failed_attempts >= 5:
self.account_locked = True
self.save()
return False
async def initiate_password_reset(self):
self.reset_token = f"{random.randint(100000, 999999)}"
self.reset_token_expiration = datetime.datetime.now() + datetime.timedelta(
minutes=15
)
await self.save()
async def reset_password(self, reset_token: str, new_password: str):
if (
self.reset_token != reset_token
or datetime.datetime.now() > self.reset_token_expiration
):
return False
self.password = self.hash_password(new_password)
self.reset_token = None
self.reset_token_expiration = None
await self.save()
return True
|