import { open } from "node:fs/promises"; import { constants } from "node:fs"; import { attachmentPath, attachmentDisposition, detectAttachmentType, MAX_ATTACHMENT_SIZE } from "@/lib/attachments"; import { NextResponse } from "next/server"; import { getKitaSession } from "@/lib/auth-utils"; import { prisma } from "@/lib/prisma"; import { visibleAnnouncementAudiences } from "@/lib/announcement-access"; export const runtime = "nodejs"; export async function GET( _request: Request, { params }: { params: Promise<{ id: string }> }, ) { const session = await getKitaSession(); const user = session?.user; if (!user?.id || !user.kitaId) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } const { id } = await params; try { attachmentPath(id); } catch { return NextResponse.json({ error: "Not found" }, { status: 404 }); } const attachment = await prisma.attachment.findFirst({ where: { id, announcement: { kitaId: user.kitaId, audience: { in: visibleAnnouncementAudiences(user) }, }, }, select: { id: true, fileName: true, fileType: true, }, }); if (!attachment) { return NextResponse.json({ error: "Not found" }, { status: 404 }); } try { const filePath = attachmentPath(attachment.id); const handle = await open(filePath, constants.O_RDONLY | constants.O_NOFOLLOW); let file: Buffer; try { const info = await handle.stat(); if (!info.isFile() || info.size > MAX_ATTACHMENT_SIZE) throw new Error("Invalid attachment"); file = await handle.readFile(); } finally { await handle.close(); } return new Response(new Uint8Array(file), { headers: { "Content-Type": detectAttachmentType(file) ?? "application/octet-stream", "Content-Disposition": attachmentDisposition(attachment.fileName), "Cache-Control": "private, no-store", "X-Content-Type-Options": "nosniff", "Content-Security-Policy": "default-src 'none'; sandbox", "Referrer-Policy": "no-referrer", }, }); } catch (error) { console.error("Anhang konnte nicht gelesen werden:", error); return NextResponse.json({ error: "File not found" }, { status: 404 }); } }