from flask import Blueprint, render_template, redirect, url_for, flash, request, session from flask_login import login_user, logout_user, login_required, current_user from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, BooleanField, SubmitField from wtforms.validators import DataRequired, Length from services.auth_service import authenticate_user # Definir Blueprint auth_bp = Blueprint('auth', __name__, url_prefix='/auth') # Formularios class LoginForm(FlaskForm): """Formulario de inicio de sesión.""" username = StringField('Usuario', validators=[DataRequired(), Length(1, 64)]) password = PasswordField('Contraseña', validators=[DataRequired()]) remember_me = BooleanField('Mantener sesión iniciada') submit = SubmitField('Iniciar sesión') class PasswordResetRequestForm(FlaskForm): """Formulario de solicitud de reinicio de contraseña.""" email = StringField('Email', validators=[DataRequired(), Length(1, 64)]) submit = SubmitField('Enviar solicitud') class PasswordResetForm(FlaskForm): """Formulario de reinicio de contraseña.""" password = PasswordField('Nueva contraseña', validators=[DataRequired(), Length(8, 64)]) password2 = PasswordField('Confirmar contraseña', validators=[DataRequired()]) submit = SubmitField('Restablecer contraseña') # Rutas @auth_bp.route('/login', methods=['GET', 'POST']) def login(): """Página de inicio de sesión.""" # Redirigir si ya está autenticado if current_user.is_authenticated: return redirect(url_for('projects.list')) form = LoginForm() if form.validate_on_submit(): user = authenticate_user(form.username.data, form.password.data) if user: login_user(user, remember=form.remember_me.data) next_page = request.args.get('next') # Registrar en la sesión el idioma del usuario session['language'] = user.idioma if next_page: return redirect(next_page) return redirect(url_for('projects.list')) flash('Usuario o contraseña incorrectos.', 'danger') return render_template('auth/login.html', form=form) @auth_bp.route('/logout') @login_required def logout(): """Cerrar sesión.""" logout_user() flash('Has cerrado sesión correctamente.', 'success') return redirect(url_for('auth.login')) @auth_bp.route('/reset_password_request', methods=['GET', 'POST']) def reset_password_request(): """Solicitar reinicio de contraseña.""" if current_user.is_authenticated: return redirect(url_for('projects.list')) form = PasswordResetRequestForm() if form.validate_on_submit(): # En un sistema real, aquí se enviaría un correo # Por ahora, solo mostramos un mensaje flash('Se ha enviado un correo con instrucciones para restablecer tu contraseña.', 'info') return redirect(url_for('auth.login')) return render_template('auth/reset_password.html', form=form) @auth_bp.route('/reset_password/', methods=['GET', 'POST']) def reset_password(token): """Restablecer contraseña con token.""" if current_user.is_authenticated: return redirect(url_for('projects.list')) # En un sistema real, aquí se verificaría el token # Por ahora, siempre mostramos el formulario form = PasswordResetForm() if form.validate_on_submit(): if form.password.data != form.password2.data: flash('Las contraseñas no coinciden.', 'danger') return render_template('auth/reset_password.html', form=form) # En un sistema real, aquí se cambiaría la contraseña flash('Tu contraseña ha sido restablecida.', 'success') return redirect(url_for('auth.login')) return render_template('auth/reset_password.html', form=form) @auth_bp.route('/profile') @login_required def profile(): """Ver perfil de usuario.""" return render_template('auth/profile.html')