62 lines
2.1 KiB
Python
62 lines
2.1 KiB
Python
from fastapi import APIRouter, Query, HTTPException
|
|
from fastapi.responses import FileResponse
|
|
from jose import jwt, JWTError
|
|
from datetime import datetime, timedelta
|
|
from database.mysql import get_database_settings
|
|
from pathlib import Path
|
|
|
|
router = APIRouter()
|
|
|
|
# === Configuração do token temporário ===
|
|
DB_SETTINGS = get_database_settings()
|
|
SECRET_KEY = getattr(DB_SETTINGS, "aeskey", None)
|
|
ALGORITHM = "HS256"
|
|
|
|
# Pasta base onde os arquivos são armazenados
|
|
STORAGE_DIR = Path("storage")
|
|
|
|
|
|
@router.get("/{hash}/{file_name}")
|
|
def visualizar_arquivo(hash: str, file_name: str, token: str = Query(...)):
|
|
"""
|
|
Valida o token JWT e retorna o arquivo PDF, se autorizado.
|
|
URL esperada:
|
|
/view/<hash>/<file_name>?token=<jwt>
|
|
Exemplo real:
|
|
/view/d7e8f9g0h1i2/documento.pdf?token=xxxxx
|
|
"""
|
|
try:
|
|
# Decodifica o token
|
|
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
|
|
|
faixa_superior = payload.get("faixa_superior")
|
|
ato_id = payload.get("ato_id")
|
|
file_name_token = payload.get("file_name")
|
|
|
|
# Validação mínima do payload
|
|
if not all([faixa_superior, ato_id, file_name_token]):
|
|
raise HTTPException(status_code=400, detail="Token malformado.")
|
|
|
|
# Verifica se o nome do arquivo bate
|
|
if file_name_token != file_name:
|
|
raise HTTPException(
|
|
status_code=403, detail="Token não corresponde ao arquivo solicitado."
|
|
)
|
|
|
|
# Monta o caminho real do arquivo no storage
|
|
# (estrutura física oculta do cliente)
|
|
full_path = STORAGE_DIR / faixa_superior / ato_id / file_name_token
|
|
|
|
except JWTError:
|
|
raise HTTPException(status_code=401, detail="Token expirado ou inválido.")
|
|
|
|
# Garante que o arquivo exista fisicamente
|
|
if not full_path.exists():
|
|
raise HTTPException(status_code=404, detail="Arquivo não encontrado.")
|
|
|
|
# Retorna o PDF inline no navegador
|
|
return FileResponse(
|
|
full_path,
|
|
media_type="application/pdf",
|
|
headers={"Content-Disposition": "inline"},
|
|
)
|