Fix PDF viewing: cookie auth fallback + .mjs MIME type

- /file and /pdf endpoints: make token optional, fall back to hnf_session
  cookie auth when no valid JWT token provided. Kitchen frontend passes the
  literal '__session__' compat shim so token-only auth always 401'd.
- Add Request injection so cookie-based fallback path can read hnf_session.
- nginx: add types block mapping .mjs → text/javascript so pdf.worker.min.mjs
  passes browser strict MIME check for ES module scripts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-07-12 21:34:51 +00:00
parent cd9e7dbfef
commit 742bc91b3b
2 changed files with 31 additions and 12 deletions

View file

@ -6,7 +6,7 @@ from datetime import date, timedelta
from decimal import Decimal
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, BackgroundTasks
from fastapi import APIRouter, Depends, HTTPException, Request, UploadFile, File, BackgroundTasks
from fastapi.responses import FileResponse
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, text
@ -1233,17 +1233,25 @@ async def get_invoice_image(
@router.get("/{invoice_id}/file")
async def get_invoice_file(
invoice_id: int,
token: str,
request: Request,
token: Optional[str] = None,
db: AsyncSession = Depends(get_db)
):
"""Get invoice file (image or PDF) with token in query param - works through proxies"""
"""Get invoice file (image or PDF) — supports both cookie auth and ?token= JWT"""
from starlette.responses import Response
from services.file_archival_service import FileArchivalService
# Verify token and get user
current_user = await get_current_user_from_token(token, db)
# Try JWT token param first, fall back to hnf_session cookie
current_user = None
if token:
current_user = await get_current_user_from_token(token, db)
if not current_user:
raise HTTPException(status_code=401, detail="Invalid token")
try:
current_user = await get_current_user(request)
except HTTPException:
pass
if not current_user:
raise HTTPException(status_code=401, detail="Authentication required")
invoice = await get_invoice_or_404(invoice_id, current_user, db)
@ -1282,17 +1290,23 @@ async def get_invoice_file(
@router.get("/{invoice_id}/pdf")
async def get_invoice_pdf(
invoice_id: int,
token: str,
request: Request,
token: Optional[str] = None,
db: AsyncSession = Depends(get_db)
):
"""Get invoice PDF with token in query param (for iframe embedding) - DEPRECATED, use /file"""
from auth import get_current_user, require_cap_from_token
"""Get invoice PDF — DEPRECATED, use /file"""
from starlette.responses import Response
# Verify token and get user
current_user = await get_current_user_from_token(token, db)
current_user = None
if token:
current_user = await get_current_user_from_token(token, db)
if not current_user:
raise HTTPException(status_code=401, detail="Invalid token")
try:
current_user = await get_current_user(request)
except HTTPException:
pass
if not current_user:
raise HTTPException(status_code=401, detail="Authentication required")
invoice = await get_invoice_or_404(invoice_id, current_user, db)