import datetime from abc import ABC, abstractmethod from utils.services.sms import SmsProviderABC from django.db import models from django.contrib.auth import authenticate from typing import Protocol, Any import random class DjangoAuthProtocol(Protocol): def authenticate(self, username:str, password:str) -> Any: pass class SmsOtpService: def __init__(self, sms_provider: SmsProviderABC): self.provider = sms_provider def send_code(self, mobile: str, otp_code: int): message = f'کد ورود شما در باشگاه مجریان لوله گستر گلپایگان: {otp_code} @mojrian.loolegostar.com #{otp_code}' return self.provider.send_sms(mobile, message) class AuthenticatorABC(ABC): @abstractmethod def authenticate(self) -> bool: pass class SMSAuth(AuthenticatorABC): def __init__(self, mobile: str, otp_code: int, otp_model: models.Model): self.mobile = int(mobile) self.otp_code = otp_code self.otp_model = otp_model def authenticate(self) -> models.Model | bool: # check code is in DB try: datetime_now = datetime.datetime.now() otp_obj = self.otp_model.objects.get( mobile=self.mobile, otp=self.otp_code, expire__gte=datetime_now ) except Exception as exp: self.otp_model.objects.filter(mobile=self.mobile).delete() return False return otp_obj class UsernameAuth(AuthenticatorABC): def __init__(self, username: str, password: str, auth_class: DjangoAuthProtocol): self.username = username self.password = password self.auth_class = auth_class def authenticate(self) -> bool: user = self.auth_class.authenticate(username=self.username, password=self.password) if user: return True