68 lines
2.2 KiB
TypeScript
68 lines
2.2 KiB
TypeScript
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 });
|
|
}
|
|
}
|