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

112 lines
3.9 KiB
Python

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from fastapi.exceptions import HTTPException
from starlette.middleware.base import BaseHTTPMiddleware
from database import init_db
from routers import clients, devis, factures
from routers import auth as auth_router
from config import settings
app = FastAPI(title=settings.app_name)
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")
app.include_router(auth_router.router)
app.include_router(clients.router)
app.include_router(devis.router)
app.include_router(factures.router)
# ── Middleware : current_user dans request.state ───────────────────────────────
class AuthMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
from database import SessionLocal
from auth import redirect_if_not_logged
db = SessionLocal()
try:
request.state.current_user = redirect_if_not_logged(request, db)
except Exception:
request.state.current_user = None
finally:
db.close()
try:
return await call_next(request)
except Exception:
request.state.current_user = None
raise
app.add_middleware(AuthMiddleware)
# ── Startup ────────────────────────────────────────────────────────────────────
@app.on_event("startup")
def startup():
init_db()
_creer_admin_si_absent()
def _creer_admin_si_absent():
from database import SessionLocal
from models import User
from auth import hasher_mot_de_passe
db = SessionLocal()
try:
if db.query(User).count() == 0:
admin = User(
username="admin",
hashed_password=hasher_mot_de_passe("admin"),
is_admin=True,
)
db.add(admin)
db.commit()
print("⚠️ Compte admin créé : admin / admin — À changer immédiatement !")
finally:
db.close()
# ── Gestion erreurs ────────────────────────────────────────────────────────────
@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
if exc.status_code == 302:
return RedirectResponse(url=exc.headers["Location"])
return templates.TemplateResponse("erreur.html", {
"request": request,
"status_code": exc.status_code,
"detail": exc.detail,
"current_user": getattr(request.state, "current_user", None),
}, status_code=exc.status_code)
@app.get("/", response_class=HTMLResponse)
def accueil():
return RedirectResponse("/factures/")
# ── Filtres Jinja2 ─────────────────────────────────────────────────────────────
def format_montant(valeur):
if valeur is None:
return "0,00 €"
return f"{valeur:,.2f}".replace(",", " ").replace(".", ",")
def format_date_fr(d):
if d is None:
return ""
mois = ["janvier", "février", "mars", "avril", "mai", "juin",
"juillet", "août", "septembre", "octobre", "novembre", "décembre"]
return f"{d.day} {mois[d.month - 1]} {d.year}"
for tpl in [templates, clients.templates, devis.templates,
factures.templates, auth_router.templates]:
tpl.env.filters["montant"] = format_montant
tpl.env.filters["date_fr"] = format_date_fr