48 lines
1.6 KiB
TypeScript
48 lines
1.6 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { auth } from "@/lib/auth";
|
|
import { sanitizeFilePath } from "@/lib/security/sanitize";
|
|
import { db } from "@/lib/db";
|
|
import { auditLogs } from "@/lib/db/schema";
|
|
import { nanoid } from "nanoid";
|
|
import { getClientIp } from "@/lib/security/rateLimit";
|
|
import * as fs from "node:fs";
|
|
import * as path from "node:path";
|
|
|
|
export async function DELETE(req: NextRequest) {
|
|
const session = await auth.api.getSession({ headers: req.headers });
|
|
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
if (!["superadmin", "admin"].includes(session.user.role ?? "")) {
|
|
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
|
}
|
|
|
|
const mcBase = path.resolve(process.env.MC_SERVER_PATH ?? "/opt/minecraft/server");
|
|
const { filePath } = await req.json();
|
|
|
|
let resolvedPath: string;
|
|
try {
|
|
resolvedPath = sanitizeFilePath(filePath, mcBase);
|
|
} catch {
|
|
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
}
|
|
|
|
if (!fs.existsSync(resolvedPath)) {
|
|
return NextResponse.json({ error: "File not found" }, { status: 404 });
|
|
}
|
|
|
|
const stat = fs.statSync(resolvedPath);
|
|
if (stat.isDirectory()) {
|
|
fs.rmSync(resolvedPath, { recursive: true });
|
|
} else {
|
|
fs.unlinkSync(resolvedPath);
|
|
}
|
|
|
|
const ip = getClientIp(req);
|
|
await db.insert(auditLogs).values({
|
|
id: nanoid(), userId: session.user.id,
|
|
action: "file.delete", target: "file", targetId: path.relative(mcBase, resolvedPath),
|
|
details: null, ipAddress: ip, createdAt: Date.now(),
|
|
});
|
|
|
|
return NextResponse.json({ success: true });
|
|
}
|