90 lines
2.9 KiB
Python
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()
|