Files
LerNotaFiscal/app/main.py
T

90 lines
2.9 KiB
Python

"""Ponto de entrada FastAPI do Lernotafiscal."""
from __future__ import annotations
import logging
from contextlib import asynccontextmanager
from pathlib import Path
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.middleware.sessions import SessionMiddleware
from starlette.requests import Request
from starlette.responses import RedirectResponse
from . import auth, database
from .config import get_settings
from .routes import (
auth_routes,
dashboard_routes,
documents_routes,
files_routes,
upload_routes,
)
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s")
logger = logging.getLogger("lernotafiscal")
# Caminhos liberados sem sessão (login e assets da própria UI).
PUBLIC_PREFIXES = ("/login", "/static/", "/favicon.ico", "/healthz")
class AuthGuardMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
path = request.url.path
if any(path == p or path.startswith(p) for p in PUBLIC_PREFIXES):
return await call_next(request)
if not request.session.get("user"):
return RedirectResponse("/login", status_code=303)
return await call_next(request)
@asynccontextmanager
async def lifespan(app: FastAPI):
settings = get_settings()
with database.session() as conn:
database.init_db(conn)
if settings.secret_key_is_ephemeral:
logger.warning("SECRET_KEY não definido: sessões não sobrevivem a reinícios. Defina SECRET_KEY em produção.")
note = auth.seed_admin()
if note:
logger.warning(note)
logger.info("OpenAI %s.", "habilitado (" + settings.openai_model + ")" if settings.openai_enabled else "desabilitado — usando OCR/heurística local")
yield
def create_app() -> FastAPI:
settings = get_settings()
app = FastAPI(title="Lernotafiscal", lifespan=lifespan)
# Ordem importa: SessionMiddleware é adicionado por último para ser o mais
# externo e popular request.session ANTES da guarda de autenticação.
app.add_middleware(AuthGuardMiddleware)
app.add_middleware(
SessionMiddleware,
secret_key=settings.secret_key,
session_cookie=settings.session_cookie,
https_only=settings.session_https_only,
max_age=settings.session_max_age,
same_site="lax",
)
static_dir = Path(__file__).resolve().parent / "static"
app.mount("/static", StaticFiles(directory=str(static_dir)), name="static")
app.include_router(auth_routes.router)
app.include_router(dashboard_routes.router)
app.include_router(upload_routes.router)
app.include_router(documents_routes.router)
app.include_router(files_routes.router)
@app.get("/healthz")
def healthz():
return {"status": "ok"}
return app
app = create_app()