import { NextRequest, NextResponse } from 'next/server'; import { and, eq, inArray } from 'drizzle-orm'; import { db } from '@/db'; import { documents } from '@/db/schema'; import { requireAuthContext } from '@/lib/server/auth/auth'; import { isValidDocumentId, presignGet } from '@/lib/server/documents/blobstore'; import { getOpenReaderTestNamespace, getUnclaimedUserIdForNamespace } from '@/lib/server/testing/test-namespace'; import { isS3Configured } from '@/lib/server/storage/s3'; export const dynamic = 'force-dynamic'; function s3NotConfiguredResponse(): NextResponse { return NextResponse.json( { error: 'Documents storage is not configured. Set S3_* environment variables.' }, { status: 503 }, ); } export async function GET(req: NextRequest) { try { if (!isS3Configured()) return s3NotConfiguredResponse(); const ctxOrRes = await requireAuthContext(req); if (ctxOrRes instanceof Response) return ctxOrRes; const testNamespace = getOpenReaderTestNamespace(req.headers); const unclaimedUserId = getUnclaimedUserIdForNamespace(testNamespace); const storageUserId = ctxOrRes.userId ?? unclaimedUserId; const allowedUserIds = ctxOrRes.authEnabled ? [storageUserId, unclaimedUserId] : [unclaimedUserId]; const url = new URL(req.url); const id = (url.searchParams.get('id') || '').trim().toLowerCase(); if (!isValidDocumentId(id)) { return NextResponse.json({ error: 'Invalid id' }, { status: 400 }); } const rows = (await db .select({ id: documents.id, userId: documents.userId }) .from(documents) .where(and(eq(documents.id, id), inArray(documents.userId, allowedUserIds)))) as Array<{ id: string; userId: string; }>; const doc = rows.find((row) => row.userId === storageUserId) ?? rows[0]; if (!doc) { return NextResponse.json({ error: 'Not found' }, { status: 404 }); } const fallbackUrl = `/api/documents/blob/get/fallback?id=${encodeURIComponent(doc.id)}`; const directUrl = await presignGet(doc.id, testNamespace).catch(() => null); if (!directUrl) { return NextResponse.redirect(fallbackUrl, { status: 307, headers: { 'Cache-Control': 'no-store' }, }); } return NextResponse.redirect(directUrl, { status: 307, headers: { 'Cache-Control': 'no-store' }, }); } catch (error) { console.error('Error creating document download signature:', error); return NextResponse.json({ error: 'Failed to prepare document download' }, { status: 500 }); } }