from flask import session, flash, redirect, url_for, request from flask_login import login_user, logout_user, current_user from datetime import datetime import pyotp import qrcode from io import BytesIO import base64 from models.entities.usuario import Usuario from services.database_service import DatabaseService class AuthController: """Controlador para funções de autenticação""" @staticmethod def login(): """Processa o login de usuário""" if request.method != "POST": return False email_or_username = request.form.get("email") password = request.form.get("password") otp = request.form.get("otp") if not all([email_or_username, password]): flash("Email/usuário e senha são obrigatórios.", "danger") return False db = DatabaseService.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): flash("Email/usuário ou senha incorretos.", "danger") return False # Verificar OTP se o usuário tiver configurado if user.otp_secret and not otp: flash("Código OTP é obrigatório para sua conta.", "danger") return False if user.otp_secret and not user.verify_otp(otp): flash("Código OTP inválido.", "danger") return False # Atualizar último login user.ultimo_login = datetime.utcnow() db.commit() # Fazer login e setar sessão login_user(user) session['user_id'] = user.id session['username'] = user.username session['is_admin'] = user.is_admin return True finally: db.close() @staticmethod def logout(): """Processa o logout de usuário""" db = DatabaseService.get_db_connection() try: user = current_user if user.is_authenticated: user.logout() db.commit() logout_user() flash('Logout realizado com sucesso!', 'success') return True finally: db.close() @staticmethod def alterar_senha(user_id, senha_atual, nova_senha, confirmar_senha): """Altera a senha do usuário""" if not all([senha_atual, nova_senha, confirmar_senha]): flash("Todos os campos são obrigatórios.", "error") return False if nova_senha != confirmar_senha: flash("As senhas não coincidem.", "error") return False db = DatabaseService.get_db_connection() try: user = db.query(Usuario).get(user_id) if not user: flash("Usuário não encontrado.", "error") return False if not user.check_password(senha_atual): flash("Senha atual incorreta.", "error") return False user.set_password(nova_senha) db.commit() flash("Senha alterada com sucesso!", "success") return True finally: db.close() @staticmethod def generate_qr_code(user): """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