40 lines
1.2 KiB
Python
40 lines
1.2 KiB
Python
"""Servir arquivos enviados SOMENTE via rota autenticada.
|
|
|
|
Documentos fiscais contêm CPF/CNPJ, endereços e valores — nunca ficam num
|
|
static mount público. O acesso passa pela guarda de sessão do middleware.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from fastapi import APIRouter, Request
|
|
from starlette.responses import FileResponse, Response
|
|
|
|
from .. import database as db
|
|
from ..config import get_settings
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/files/{upload_id}")
|
|
def serve_file(request: Request, upload_id: int):
|
|
settings = get_settings()
|
|
with db.session() as conn:
|
|
row = db.get_upload(conn, upload_id)
|
|
if row is None:
|
|
return Response("Arquivo não encontrado.", status_code=404)
|
|
|
|
stored = Path(row["stored_path"]).resolve()
|
|
upload_root = settings.upload_dir.resolve()
|
|
# trava contra path traversal: o arquivo precisa estar dentro de data/uploads
|
|
if upload_root not in stored.parents or not stored.is_file():
|
|
return Response("Arquivo indisponível.", status_code=404)
|
|
|
|
return FileResponse(
|
|
str(stored),
|
|
media_type=row["content_type"] or "application/octet-stream",
|
|
filename=row["original_name"],
|
|
content_disposition_type="inline",
|
|
)
|