mirror of
https://github.com/complexcaresolutions/dak.c2s.git
synced 2026-03-17 19:33:41 +00:00
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:
parent
f12f664ce5
commit
590125073c
2 changed files with 49 additions and 6 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue