from functools import wraps from flask import abort, redirect, url_for, request, flash from flask_login import current_user from flask_babel import gettext as _ def permission_required(module, min_level='read'): """ Decorator to restrict view access based on RBAC permissions. Hierarchy: 'read_write' > 'read' > 'none'. Administrators have implicit access to all modules. """ def decorator(f): @wraps(f) def decorated_function(*args, **kwargs): if not current_user.is_authenticated: return redirect(url_for('auth.login', next=request.url)) if not current_user.has_permission(module, min_level): flash(_('No tienes los permisos necesarios para acceder a esta sección.'), 'error') abort(403) return f(*args, **kwargs) return decorated_function return decorator def admin_required(f): """ Decorator requiring administrative privileges or 'users' management access. """ @wraps(f) def decorated_function(*args, **kwargs): if not current_user.is_authenticated: return redirect(url_for('auth.login', next=request.url)) if not current_user.can_manage(): flash(_('Esta sección requiere privilegios de administrador.'), 'error') abort(403) return f(*args, **kwargs) return decorated_function def can_edit_reservation_required(f): """ Decorator requiring permission to modify a specific reservation. Allows administrators, Bedelía, or the creator/teacher of the reservation. """ @wraps(f) def decorated_function(*args, **kwargs): if not current_user.is_authenticated: return redirect(url_for('auth.login', next=request.url)) res_id = kwargs.get('id') if res_id: from app.models.reservation import Reservation reservation = Reservation.query.get_or_404(res_id) if not current_user.can_edit_reservation(reservation): flash(_('No tienes los permisos necesarios para modificar esta reserva.'), 'error') abort(403) return f(*args, **kwargs) return decorated_function