fix: support token query param for file download endpoints

Browser-initiated downloads (window.open) cannot set Authorization
headers. Accept ?token= query parameter as fallback on the report
download and coding-template endpoints.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
CCS Admin 2026-02-24 09:20:14 +00:00
parent f12f664ce5
commit 590125073c
2 changed files with 49 additions and 6 deletions

View file

@ -100,16 +100,35 @@ def list_pending_coding(
@router.get("/coding-template") @router.get("/coding-template")
def download_coding_template( def download_coding_template(
request: Request,
token: Optional[str] = Query(None),
jahr: Optional[int] = Query(None), jahr: Optional[int] = Query(None),
fallgruppe: Optional[str] = Query(None), fallgruppe: Optional[str] = Query(None),
db: Session = Depends(get_db), db: Session = Depends(get_db),
user: User = Depends(get_current_user),
): ):
"""Download an Excel template for ICD coding. """Download an Excel template for ICD coding.
The template contains all cases that still need ICD codes, with an Supports both ``Authorization: Bearer`` header and ``?token=`` query
empty ICD column for DAK users to fill in. parameter for direct browser downloads.
""" """
from app.core.security import decode_access_token
from jose import JWTError
raw_token = token
if not raw_token:
auth = request.headers.get("authorization", "")
if auth.lower().startswith("bearer "):
raw_token = auth[7:]
if not raw_token:
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Not authenticated")
try:
payload = decode_access_token(raw_token)
user_id = int(payload["sub"])
except (JWTError, KeyError, ValueError):
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Invalid token")
user = db.query(User).filter(User.id == user_id, User.is_active == True).first() # noqa: E712
if not user:
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "User not found")
xlsx_bytes = generate_coding_template(db, jahr=jahr, fallgruppe=fallgruppe) xlsx_bytes = generate_coding_template(db, jahr=jahr, fallgruppe=fallgruppe)
from io import BytesIO from io import BytesIO

View file

@ -5,7 +5,7 @@ import os
from datetime import date from datetime import date
from io import BytesIO from io import BytesIO
from fastapi import APIRouter, Depends, HTTPException, Query from fastapi import APIRouter, Depends, HTTPException, Query, Request, status
from fastapi.responses import StreamingResponse from fastapi.responses import StreamingResponse
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
@ -141,13 +141,37 @@ def generate_report(
@router.get("/download/{report_id}") @router.get("/download/{report_id}")
def download_report( def download_report(
report_id: int, report_id: int,
request: Request,
token: str | None = Query(None),
db: Session = Depends(get_db), db: Session = Depends(get_db),
user: User = Depends(get_current_user),
): ):
"""Download a previously generated Berichtswesen Excel file. """Download a previously generated Berichtswesen Excel file.
Accessible to both admin and dak_mitarbeiter users. Supports both ``Authorization: Bearer`` header and ``?token=`` query
parameter so the browser can open the URL directly in a new tab.
""" """
from app.core.security import decode_access_token
from jose import JWTError
# Resolve token from header or query param
raw_token = token
if not raw_token:
auth = request.headers.get("authorization", "")
if auth.lower().startswith("bearer "):
raw_token = auth[7:]
if not raw_token:
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Not authenticated")
try:
payload = decode_access_token(raw_token)
user_id = int(payload["sub"])
except (JWTError, KeyError, ValueError):
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Invalid token")
user = db.query(User).filter(User.id == user_id, User.is_active == True).first() # noqa: E712
if not user:
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "User not found")
report = db.query(WeeklyReport).filter(WeeklyReport.id == report_id).first() report = db.query(WeeklyReport).filter(WeeklyReport.id == report_id).first()
if not report or not report.report_file_path: if not report or not report.report_file_path:
raise HTTPException(404, "Report not found") raise HTTPException(404, "Report not found")