import { moduleGuard } from "@/server/action-guard"; import { storage } from "@/server/storage/adapter"; import { ctxFromGuard } from "@/server/services/context"; import { getImportFile } from "@/server/services/imports/queries"; /** * GET /imports/[id]/file — original document of an import for the review mask preview. * Authorisation: session + DB-authoritative permission import:write + module + document * visibility (getImportFile). Unknown/foreign ids → 404. `?download=1` forces a download. * Inline delivery only for the allowlisted types stored by the import (PDF/JPEG/PNG) and * only framable by the own origin. */ const INLINE = new Set(["application/pdf", "image/jpeg", "image/png"]); export async function GET(req: Request, { params }: { params: Promise<{ id: string }> }) { let file: { storageKey: string; mimeType: string; fileName: string }; try { const ctx = ctxFromGuard(await moduleGuard("imports")("import:write")); const { id } = await params; file = await getImportFile(ctx, id); } catch { return new Response("Nicht gefunden.", { status: 404 }); } const content = await storage.get(file.storageKey); if (!content) return new Response("Datei nicht verfügbar.", { status: 404 }); const download = new URL(req.url).searchParams.get("download") === "1"; const inline = !download && INLINE.has(file.mimeType); const asciiName = file.fileName.replace(/[^\x20-\x7e]/g, "_").replace(/["\\]/g, "_"); const headers = new Headers({ "Content-Type": INLINE.has(file.mimeType) ? file.mimeType : "application/octet-stream", "Content-Disposition": `${inline ? "inline" : "attachment"}; filename="${asciiName}"; filename*=UTF-8''${encodeURIComponent(file.fileName)}`, "X-Content-Type-Options": "nosniff", "Cache-Control": "private, no-store", "Content-Security-Policy": "frame-ancestors 'self'", "X-Frame-Options": "SAMEORIGIN", }); if (content.size != null) headers.set("Content-Length", String(content.size)); return new Response(content.stream, { headers }); }