gmao/app_new/core/routes/auth.py

197 lines
7.5 KiB
Python
Raw Permalink Normal View History

2026-08-14 18:02:25 +02:00
"""
Core Routes - Authentification
GMAO Collège
"""
from flask import Blueprint, render_template, redirect, url_for, request, flash
from flask_login import login_user, logout_user, login_required, current_user
from ...extensions import db
from ..models.user import User
from ..forms import LoginForm, UserForm, PasswordForm
from ...constants import ROLES
from ..models.rbac import Role
from ..services.rbac import replace_user_roles
from ..authorization import has_permission
2026-08-14 18:02:25 +02:00
auth_bp = Blueprint('auth', __name__)
@auth_bp.route('/login', methods=['GET', 'POST'])
def login():
"""Page de connexion."""
if current_user.is_authenticated:
return redirect(url_for('dashboard.index'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user and user.check_password(form.password.data):
if not user.is_active:
flash("Votre compte est désactivé.", "danger")
return render_template("auth/login.html", form=form)
login_user(user)
flash(f"Bienvenue, {user.username} !", "success")
next_page = request.args.get('next', '')
if not next_page.startswith('/') or next_page.startswith('//'):
next_page = ''
return redirect(next_page or url_for('dashboard.index'))
flash("Nom d'utilisateur ou mot de passe incorrect.", "danger")
return render_template('auth/login.html', form=form)
@auth_bp.route('/logout')
@login_required
def logout():
"""Déconnexion."""
logout_user()
flash("Vous avez été déconnecté.", "info")
return redirect(url_for('auth.login'))
@auth_bp.route('/users')
@login_required
def list_users():
"""Liste des utilisateurs."""
if not has_permission('user.view', current_user):
2026-08-14 18:02:25 +02:00
flash("Accès réservé aux administrateurs.", "danger")
return redirect(url_for('dashboard.index'))
users = User.query.order_by(User.full_name).all()
return render_template('auth/users.html', users=users)
@auth_bp.route('/users/new', methods=['GET', 'POST'])
@login_required
def create_user():
"""Créer un utilisateur."""
if not has_permission('user.create', current_user):
2026-08-14 18:02:25 +02:00
flash("Accès réservé aux administrateurs.", "danger")
return redirect(url_for('dashboard.index'))
form = UserForm()
if form.validate_on_submit():
selected_role_slugs = request.form.getlist('role_ids') or ([form.role.data] if form.role.data else [])
2026-08-14 18:02:25 +02:00
user = User(
username=form.username.data,
email=form.email.data,
full_name=form.full_name.data,
role=form.role.data,
is_active=form.is_active.data,
)
if not form.password.data:
form.password.errors.append("Un mot de passe initial est obligatoire.")
return render_template('auth/user_form.html', form=form, title="Nouvel utilisateur"), 400
user.set_password(form.password.data)
db.session.add(user)
db.session.flush()
selected_roles = Role.query.filter(Role.slug.in_(selected_role_slugs), Role.is_active.is_(True)).all() if selected_role_slugs else []
replace_user_roles(user, [role.id for role in selected_roles], assigned_by=current_user)
2026-08-14 18:02:25 +02:00
db.session.commit()
flash(f"Utilisateur {user.full_name} créé.", "success")
return redirect(url_for('auth.list_users'))
return render_template('auth/user_form.html', form=form, title="Nouvel utilisateur", roles_list=Role.query.filter_by(is_active=True).order_by(Role.name).all())
2026-08-14 18:02:25 +02:00
@auth_bp.route('/profile')
@login_required
def profile():
"""Profil utilisateur."""
return render_template('auth/profile.html', user=current_user)
@auth_bp.route('/users/<int:id>/edit', methods=['GET', 'POST'])
@login_required
def edit_user(id):
"""Modifier un utilisateur."""
if not has_permission('user.edit', current_user):
2026-08-14 18:02:25 +02:00
flash("Accès réservé aux administrateurs.", "danger")
return redirect(url_for('dashboard.index'))
user = User.query.get_or_404(id)
form = UserForm(obj=user)
if form.validate_on_submit():
selected_role_slugs = request.form.getlist('role_ids') or ([form.role.data] if form.role.data else [])
2026-08-14 18:02:25 +02:00
user.username = form.username.data
user.email = form.email.data
user.full_name = form.full_name.data
user.is_active = form.is_active.data
if form.password.data:
user.set_password(form.password.data)
selected_roles = Role.query.filter(Role.slug.in_(selected_role_slugs), Role.is_active.is_(True)).all() if selected_role_slugs else []
replace_user_roles(user, [role.id for role in selected_roles], assigned_by=current_user)
2026-08-14 18:02:25 +02:00
db.session.commit()
flash(f"Utilisateur {user.full_name} modifié.", "success")
return redirect(url_for('auth.list_users'))
return render_template('auth/user_form.html', form=form, title="Modifier l'utilisateur", roles_list=Role.query.filter_by(is_active=True).order_by(Role.name).all())
2026-08-14 18:02:25 +02:00
@auth_bp.route('/change-password', methods=['GET', 'POST'])
@login_required
def change_own_password():
"""Changement de mot de passe."""
form = PasswordForm()
if form.validate_on_submit():
if not current_user.check_password(form.current_password.data):
flash("Mot de passe actuel incorrect.", "danger")
else:
current_user.set_password(form.new_password.data)
db.session.commit()
flash("Mot de passe modifié avec succès.", "success")
return redirect(url_for('dashboard.index'))
return render_template('auth/change_own_password.html', form=form)
@auth_bp.route('/users/<int:id>/delete', methods=['POST'])
@login_required
def delete_user(id):
"""Supprimer un utilisateur."""
if not has_permission('user.delete', current_user):
2026-08-14 18:02:25 +02:00
flash("Accès réservé aux administrateurs.", "danger")
return redirect(url_for('dashboard.index'))
user = User.query.get_or_404(id)
if user.id == current_user.id:
flash("Vous ne pouvez pas supprimer votre propre compte.", "danger")
else:
db.session.delete(user)
db.session.commit()
flash(f"Utilisateur {user.username} supprimé.", "success")
return redirect(url_for('auth.list_users'))
@auth_bp.route('/users/<int:id>/password', methods=['GET', 'POST'])
@login_required
def change_user_password(id):
"""Changer le mot de passe d'un utilisateur (admin only)."""
if not has_permission('user.edit', current_user):
2026-08-14 18:02:25 +02:00
flash("Accès réservé aux administrateurs.", "danger")
return redirect(url_for('dashboard.index'))
user = User.query.get_or_404(id)
if request.method == 'POST':
new_password = request.form.get('new_password')
confirm_password = request.form.get('confirm_password')
if not new_password:
flash("Le mot de passe est requis.", "danger")
elif new_password != confirm_password:
flash("Les mots de passe ne correspondent pas.", "danger")
elif len(new_password) < 12:
flash("Le mot de passe doit contenir au moins 12 caractères.", "danger")
else:
user.set_password(new_password)
db.session.commit()
flash(f"Mot de passe de {user.username} modifié.", "success")
return redirect(url_for('auth.list_users'))
return render_template('auth/change_user_password.html', user=user)