fix(): Ajustado endpoint de visualização de arquivo

This commit is contained in:
Kenio 2025-11-12 17:00:35 -03:00
parent 4b208ad03e
commit 76bbc71fc6

View file

@ -1,7 +1,8 @@
from fastapi import APIRouter, Query, HTTPException from fastapi import APIRouter, Query, HTTPException
from fastapi.responses import FileResponse from fastapi.responses import FileResponse
from jose import jwt, JWTError from jose import jwt, JWTError
from database.mysql import SessionLocal, get_database_settings from datetime import datetime, timedelta
from database.mysql import get_database_settings
from pathlib import Path from pathlib import Path
router = APIRouter() router = APIRouter()
@ -15,31 +16,49 @@ ALGORITHM = "HS256"
STORAGE_DIR = Path("storage") STORAGE_DIR = Path("storage")
@router.get("/{file_id}/{file_path:path}") @router.get("/{hash}/{file_path:path}")
def visualizar_arquivo(file_id: str, file_path: str, token: str = Query(...)): def visualizar_arquivo(hash: str, file_path: str, token: str = Query(...)):
""" """
Valida o token e retorna o arquivo do storage, se autorizado. Valida o token JWT e retorna o arquivo PDF, se autorizado.
Exemplo de URL: URL esperada:
/view/d7e8f9g0h1i2/100/57/documento.pdf?token=xxxx /view/<hash>/<caminho_relativo>?token=<jwt>
Exemplo real:
/view/d7e8f9g0h1i2/100/57/documento.pdf?token=xxxxx
""" """
# --- 1. Valida token JWT ---
try: try:
# Decodifica o token usando a chave e algoritmo definidos
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
if payload["sub"] != file_id or payload["filename"] != file_path:
raise HTTPException(status_code=403, detail="Token inválido.") # Extrai os campos esperados do token
faixa_superior = payload.get("faixa_superior")
ato_id = payload.get("ato_id")
file_name = payload.get("file_name")
# Se algum campo essencial estiver faltando → token inválido
if not all([faixa_superior, ato_id, file_name]):
raise HTTPException(status_code=400, detail="Token malformado.")
# Reconstrói o caminho esperado a partir do token
expected_path = f"{faixa_superior}/{ato_id}/{file_name}"
# Se o caminho do arquivo solicitado não bate com o token → bloqueia
if expected_path != file_path:
raise HTTPException(
status_code=403, detail="Token não corresponde ao arquivo."
)
except JWTError: except JWTError:
raise HTTPException(status_code=401, detail="Token expirado ou inválido.") raise HTTPException(status_code=401, detail="Token expirado ou inválido.")
# --- 2. Monta caminho real no disco --- # Monta o caminho físico no disco
full_path = STORAGE_DIR / file_path full_path = STORAGE_DIR / file_path
# --- 3. Retorna arquivo, se existir ---
if not full_path.exists(): if not full_path.exists():
raise HTTPException(status_code=404, detail="Arquivo não encontrado.") raise HTTPException(status_code=404, detail="Arquivo não encontrado.")
# Retorna o arquivo inline (abre no navegador)
return FileResponse( return FileResponse(
full_path, full_path,
media_type="application/pdf", media_type="application/pdf",
headers={"Content-Disposition": "inline"}, # abre no navegador headers={"Content-Disposition": "inline"},
) )