from template_helper import render from fastapi import APIRouter, Depends, Request, Form, HTTPException from fastapi.responses import HTMLResponse, RedirectResponse, Response from fastapi.templating import Jinja2Templates from sqlalchemy.orm import Session from database import get_db from models import User from auth import ( hasher_mot_de_passe, verifier_mot_de_passe, creer_session, get_current_admin, COOKIE_NAME ) from config import settings router = APIRouter(tags=["auth"]) templates = Jinja2Templates(directory="templates") # ── Login / Logout ───────────────────────────────────────────────────────────── @router.get("/login", response_class=HTMLResponse) def login_form(request: Request): return render(templates, "auth/login.html", request, { "erreur": None }) @router.post("/login") def login( request: Request, username: str = Form(...), password: str = Form(...), db: Session = Depends(get_db) ): user = db.query(User).filter( User.username == username, User.actif == True ).first() if not user or not verifier_mot_de_passe(password, user.hashed_password): return render(templates, "auth/login.html", request, { "erreur": "Identifiants incorrects." }, status_code=401) token = creer_session(user.id) response = RedirectResponse("/factures/", status_code=303) response.set_cookie( key=COOKIE_NAME, value=token, max_age=settings.session_max_age, httponly=True, samesite="lax", secure=False # Passer à True si HTTPS (recommandé en prod) ) return response @router.post("/logout") def logout(): response = RedirectResponse("/login", status_code=303) response.delete_cookie(COOKIE_NAME) return response # ── Gestion utilisateurs (admin) ─────────────────────────────────────────────── @router.get("/admin/utilisateurs", response_class=HTMLResponse) def liste_utilisateurs( request: Request, db: Session = Depends(get_db), current_user=Depends(get_current_admin) ): users = db.query(User).order_by(User.username).all() return render(templates, "auth/utilisateurs.html", request, { "users": users, "current_user": current_user }) @router.get("/admin/utilisateurs/nouveau", response_class=HTMLResponse) def nouveau_user_form(request: Request, current_user=Depends(get_current_admin)): return render(templates, "auth/user_form.html", request, { "user": None, "titre": "Nouvel utilisateur", "current_user": current_user }) @router.post("/admin/utilisateurs/nouveau") def creer_user( username: str = Form(...), email: str = Form(""), password: str = Form(...), is_admin: bool = Form(False), db: Session = Depends(get_db), current_user=Depends(get_current_admin) ): if db.query(User).filter(User.username == username).first(): raise HTTPException(status_code=400, detail="Ce nom d'utilisateur existe déjà.") user = User( username=username, email=email, hashed_password=hasher_mot_de_passe(password), is_admin=is_admin ) db.add(user) db.commit() return RedirectResponse("/admin/utilisateurs", status_code=303) @router.get("/admin/utilisateurs/{user_id}/modifier", response_class=HTMLResponse) def modifier_user_form( request: Request, user_id: int, db: Session = Depends(get_db), current_user=Depends(get_current_admin) ): user = db.query(User).get(user_id) if not user: raise HTTPException(status_code=404) return render(templates, "auth/user_form.html", request, { "user": user, "titre": "Modifier l'utilisateur", "current_user": current_user }) @router.post("/admin/utilisateurs/{user_id}/modifier") def modifier_user( user_id: int, username: str = Form(...), email: str = Form(""), password: str = Form(""), is_admin: bool = Form(False), db: Session = Depends(get_db), current_user=Depends(get_current_admin) ): user = db.query(User).get(user_id) if not user: raise HTTPException(status_code=404) # Empêcher de se retirer les droits admin à soi-même if user.id == current_user.id and not is_admin: raise HTTPException(status_code=400, detail="Vous ne pouvez pas retirer vos propres droits admin.") user.username = username user.email = email user.is_admin = is_admin if password: user.hashed_password = hasher_mot_de_passe(password) db.commit() return RedirectResponse("/admin/utilisateurs", status_code=303) @router.post("/admin/utilisateurs/{user_id}/desactiver") def desactiver_user( user_id: int, db: Session = Depends(get_db), current_user=Depends(get_current_admin) ): user = db.query(User).get(user_id) if not user: raise HTTPException(status_code=404) if user.id == current_user.id: raise HTTPException(status_code=400, detail="Impossible de se désactiver soi-même.") user.actif = not user.actif db.commit() return RedirectResponse("/admin/utilisateurs", status_code=303)