import { NextRequest, NextResponse } from "next/server"; import { getServerSession } from "next-auth"; import { authOptions } from "@/lib/auth"; import { isAdminEmail } from "@/lib/admin"; import { organizerRepo } from "@/server/repositories/organizer.repo"; import { isKycKind, mimeFromKey, readDecrypted, } from "@/lib/secure-storage"; export const runtime = "nodejs"; export const dynamic = "force-dynamic"; interface RouteCtx { params: Promise<{ id: string; kind: string }>; } export async function GET(_req: NextRequest, ctx: RouteCtx) { const session = await getServerSession(authOptions); if (!session?.user) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } const { id, kind } = await ctx.params; if (!isKycKind(kind)) { return NextResponse.json({ error: "Kind tidak valid" }, { status: 400 }); } const verification = await organizerRepo.findById(id); if (!verification) { return NextResponse.json({ error: "Tidak ditemukan" }, { status: 404 }); } const isOwner = verification.userId === session.user.id; const isAdmin = isAdminEmail(session.user.email); if (!isOwner && !isAdmin) { return NextResponse.json({ error: "Forbidden" }, { status: 403 }); } const key = kind === "ktp" ? verification.ktpImageKey : verification.selfieKey; if (!key) { return NextResponse.json({ error: "File belum diunggah" }, { status: 404 }); } let plain: Buffer; try { plain = await readDecrypted(kind, key); } catch { return NextResponse.json({ error: "File tidak dapat dibuka" }, { status: 500 }); } return new NextResponse(new Uint8Array(plain), { status: 200, headers: { "Content-Type": mimeFromKey(key), "Content-Length": String(plain.length), "Cache-Control": "private, no-store", "X-Content-Type-Options": "nosniff", "Content-Disposition": `inline; filename="${kind}-${id}"`, }, }); }