Files
BillManager/routers/auth.py
2026-02-21 23:26:50 +01:00

163 lines
5.2 KiB
Python

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)