diff --git a/teressa-copeland-homes/src/app/api/sign/download/[token]/route.ts b/teressa-copeland-homes/src/app/api/sign/download/[token]/route.ts new file mode 100644 index 0000000..569babc --- /dev/null +++ b/teressa-copeland-homes/src/app/api/sign/download/[token]/route.ts @@ -0,0 +1,46 @@ +import { NextRequest } from 'next/server'; +import { verifySignerDownloadToken } from '@/lib/signing/token'; +import { db } from '@/lib/db'; +import { documents } from '@/lib/db/schema'; +import { eq } from 'drizzle-orm'; +import path from 'node:path'; +import { readFile } from 'node:fs/promises'; + +const UPLOADS_DIR = path.join(process.cwd(), 'uploads'); + +// Public route — no auth session required +export async function GET( + _req: NextRequest, + { params }: { params: Promise<{ token: string }> } +) { + const { token } = await params; + + let documentId: string; + try { + ({ documentId } = await verifySignerDownloadToken(token)); + } catch { + return new Response('Invalid or expired download link', { status: 401 }); + } + + const doc = await db.query.documents.findFirst({ + where: eq(documents.id, documentId), + columns: { signedFilePath: true, status: true, name: true }, + }); + + if (!doc || doc.status !== 'Signed' || !doc.signedFilePath) { + return new Response('Document not yet complete', { status: 404 }); + } + + const absPath = path.join(UPLOADS_DIR, doc.signedFilePath); + if (!absPath.startsWith(UPLOADS_DIR)) { + return new Response('Forbidden', { status: 403 }); + } + + const fileBytes = await readFile(absPath); + return new Response(fileBytes, { + headers: { + 'Content-Type': 'application/pdf', + 'Content-Disposition': `attachment; filename="${doc.name}-signed.pdf"`, + }, + }); +}