from functions.database import get_db_connection, Usuario from flask_login import login_user, logout_user from datetime import datetime from typing import Dict, Optional import pyotp import qrcode import base64 from io import BytesIO class AuthService: """Service para operações de autenticação""" @staticmethod def autenticar_usuario(email_or_username: str, password: str, otp: str = None) -> Dict: """Autentica um usuário""" db = get_db_connection() try: # Tenta encontrar o usuário por email ou username user = db.query(Usuario).filter( (Usuario.email == email_or_username) | (Usuario.username == email_or_username) ).first() if not user or not user.check_password(password): return { 'status': 'error', 'message': 'Email/usuário ou senha incorretos.' } # Verificar OTP se o usuário tiver configurado if user.otp_secret and not otp: return { 'status': 'error', 'message': 'Código OTP é obrigatório para sua conta.' } if user.otp_secret and not user.verify_otp(otp): return { 'status': 'error', 'message': 'Código OTP inválido.' } # Atualizar último login user.ultimo_login = datetime.utcnow() db.commit() # Fazer login login_user(user) return { 'status': 'success', 'user': user } except Exception as e: db.rollback() return { 'status': 'error', 'message': f'Erro na autenticação: {str(e)}' } finally: db.close() @staticmethod def desautenticar_usuario(user) -> Dict: """Desautentica um usuário""" db = get_db_connection() try: if user: user.logout() db.commit() logout_user() return { 'status': 'success', 'message': 'Logout realizado com sucesso!' } except Exception as e: db.rollback() return { 'status': 'error', 'message': f'Erro no logout: {str(e)}' } finally: db.close() @staticmethod def alterar_senha(user_id: int, senha_atual: str, nova_senha: str) -> Dict: """Altera a senha de um usuário""" db = get_db_connection() try: user = db.query(Usuario).get(user_id) if not user: return { 'status': 'error', 'message': 'Usuário não encontrado.' } if not user.check_password(senha_atual): return { 'status': 'error', 'message': 'Senha atual incorreta.' } user.set_password(nova_senha) db.commit() return { 'status': 'success', 'message': 'Senha alterada com sucesso!' } except Exception as e: db.rollback() return { 'status': 'error', 'message': f'Erro ao alterar senha: {str(e)}' } finally: db.close() @staticmethod def gerar_qr_code(user) -> str: """Gera um QR code para o usuário""" if not user.otp_secret: user.otp_secret = pyotp.random_base32() totp = pyotp.TOTP(user.otp_secret) qr = qrcode.QRCode(version=1, box_size=10, border=5) qr.add_data(totp.provisioning_uri(user.email, issuer_name="Sistema de Controles")) qr.make(fit=True) img = qr.make_image(fill_color="black", back_color="white") buffer = BytesIO() img.save(buffer, format="PNG") qr_code = base64.b64encode(buffer.getvalue()).decode('utf-8') return qr_code @staticmethod def verificar_sessao(user) -> Dict: """Verifica se a sessão do usuário ainda é válida""" if not user.is_authenticated: return { 'valid': False, 'message': 'Usuário não autenticado' } if user.is_session_expired(): return { 'valid': False, 'message': 'Sessão expirada' } return { 'valid': True }