import { NextRequest, NextResponse } from 'next/server' import { readFile, stat } from 'fs/promises' import path from 'path' import { auth } from '@/auth' import { canAccessUploadedNoteImage } from '@/lib/upload-access' const UPLOAD_DIR = path.join(process.cwd(), 'data', 'uploads') const MIME_MAP: Record = { '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.png': 'image/png', '.gif': 'image/gif', '.webp': 'image/webp', } export async function GET( _req: NextRequest, { params }: { params: Promise<{ path: string[] }> } ) { const session = await auth() const { path: segments } = await params // Only serve from uploads/notes/ subdirectory if (segments[0] !== 'notes') { return new NextResponse('Not found', { status: 404 }) } const filename = segments[segments.length - 1] const allowed = await canAccessUploadedNoteImage(filename, session?.user?.id) if (!allowed) { return new NextResponse(session?.user?.id ? 'Forbidden' : 'Unauthorized', { status: session?.user?.id ? 403 : 401, }) } const ext = path.extname(filename).toLowerCase() const contentType = MIME_MAP[ext] if (!contentType) { return new NextResponse('Unsupported file type', { status: 400 }) } // Prevent path traversal const safePath = path.join(UPLOAD_DIR, ...segments) if (!safePath.startsWith(UPLOAD_DIR)) { return new NextResponse('Forbidden', { status: 403 }) } try { const fileStats = await stat(safePath) if (!fileStats.isFile()) { return new NextResponse('Not found', { status: 404 }) } const buffer = await readFile(safePath) return new NextResponse(buffer, { headers: { 'Content-Type': contentType, 'Cache-Control': 'public, max-age=31536000, immutable', 'Content-Length': String(buffer.length), }, }) } catch { return new NextResponse('Not found', { status: 404 }) } }