88 lines
2.5 KiB
TypeScript
88 lines
2.5 KiB
TypeScript
import { auth } from "@/auth";
|
|
import { NextRequest, NextResponse } from "next/server";
|
|
import fs from "fs/promises";
|
|
import path from "path";
|
|
|
|
const UPLOADS_DIR = path.join(process.cwd(), ".dev-uploads");
|
|
|
|
function resolveFilePath(keySegments: string[]): string {
|
|
const relative = path.join(...keySegments);
|
|
const resolved = path.resolve(UPLOADS_DIR, relative);
|
|
// Prevent path traversal outside the uploads directory
|
|
if (!resolved.startsWith(path.resolve(UPLOADS_DIR))) {
|
|
throw new Error("Invalid path");
|
|
}
|
|
return resolved;
|
|
}
|
|
|
|
export async function PUT(
|
|
request: NextRequest,
|
|
{ params }: { params: Promise<{ key: string[] }> }
|
|
) {
|
|
if (process.env.NODE_ENV !== "development") {
|
|
return NextResponse.json({ error: "Not found" }, { status: 404 });
|
|
}
|
|
|
|
const session = await auth();
|
|
if (!session?.user) {
|
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
}
|
|
|
|
const { key } = await params;
|
|
let filePath: string;
|
|
try {
|
|
filePath = resolveFilePath(key);
|
|
} catch {
|
|
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
}
|
|
|
|
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
const buffer = await request.arrayBuffer();
|
|
await fs.writeFile(filePath, Buffer.from(buffer));
|
|
|
|
return new NextResponse(null, { status: 200 });
|
|
}
|
|
|
|
export async function GET(
|
|
request: NextRequest,
|
|
{ params }: { params: Promise<{ key: string[] }> }
|
|
) {
|
|
if (process.env.NODE_ENV !== "development") {
|
|
return NextResponse.json({ error: "Not found" }, { status: 404 });
|
|
}
|
|
|
|
const session = await auth();
|
|
if (!session?.user) {
|
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
}
|
|
|
|
const { key } = await params;
|
|
let filePath: string;
|
|
try {
|
|
filePath = resolveFilePath(key);
|
|
} catch {
|
|
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
}
|
|
|
|
let fileBuffer: Buffer;
|
|
try {
|
|
fileBuffer = await fs.readFile(filePath) as Buffer;
|
|
} catch {
|
|
return NextResponse.json({ error: "File not found" }, { status: 404 });
|
|
}
|
|
|
|
const ext = path.extname(filePath).toLowerCase();
|
|
const contentTypeMap: Record<string, string> = {
|
|
".pdf": "application/pdf",
|
|
".png": "image/png",
|
|
".jpg": "image/jpeg",
|
|
".jpeg": "image/jpeg",
|
|
".gif": "image/gif",
|
|
".webp": "image/webp",
|
|
};
|
|
const contentType = contentTypeMap[ext] ?? "application/octet-stream";
|
|
|
|
return new NextResponse(new Uint8Array(fileBuffer), {
|
|
headers: { "Content-Type": contentType },
|
|
});
|
|
}
|