import hashlib import random import string from datetime import timedelta from odoo import fields class OtpService: def __init__(self, env): self.env = env def _hash_otp(self, otp_code): return hashlib.sha256(otp_code.encode()).hexdigest() def generate(self, email): """Create a 6-digit OTP, store its SHA-256 hash, return plaintext.""" otp_code = ''.join(random.choices(string.digits, k=6)) otp_hash = self._hash_otp(otp_code) expires_at = fields.Datetime.now() + timedelta(minutes=15) self.env['encoach.otp'].sudo().create({ 'email': email, 'otp_hash': otp_hash, 'expires_at': expires_at, }) return otp_code def verify(self, email, otp_code): """Find unexpired, unused record and check SHA-256 hash match.""" otp_hash = self._hash_otp(otp_code) now = fields.Datetime.now() record = self.env['encoach.otp'].sudo().search([ ('email', '=', email), ('otp_hash', '=', otp_hash), ('used', '=', False), ('expires_at', '>=', now), ], limit=1, order='created_at desc') if record: record.write({'used': True}) return True return False def can_resend(self, email): """Check if resend_count < 3 for the latest OTP.""" record = self.env['encoach.otp'].sudo().search([ ('email', '=', email), ], limit=1, order='created_at desc') return record and record.resend_count < 3 def mark_resend(self, email): """Increment resend_count on the latest OTP for this email.""" record = self.env['encoach.otp'].sudo().search([ ('email', '=', email), ], limit=1, order='created_at desc') if record: record.write({'resend_count': record.resend_count + 1})