import { NextRequest, NextResponse } from "next/server"; import { auth, getAuthSession } from "@/lib/auth"; import { mcProcessManager } from "@/lib/minecraft/process"; import { db } from "@/lib/db"; import { auditLogs } from "@/lib/db/schema"; import { checkRateLimit, getClientIp } from "@/lib/security/rateLimit"; import { z } from "zod"; import { nanoid } from "nanoid"; const ActionSchema = z.object({ action: z.enum(["start", "stop", "restart"]), force: z.boolean().optional().default(false), }); export async function POST(req: NextRequest) { // Auth const session = await getAuthSession(req.headers); if (!session) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } // Role check — only admin+ if (!["superadmin", "admin"].includes(session.user.role ?? "")) { return NextResponse.json({ error: "Forbidden" }, { status: 403 }); } // Rate limiting const ip = getClientIp(req); const { allowed } = checkRateLimit(ip, 20); // stricter limit for control actions if (!allowed) { return NextResponse.json({ error: "Too many requests" }, { status: 429 }); } // Validate body let body: z.infer; try { body = ActionSchema.parse(await req.json()); } catch { return NextResponse.json({ error: "Invalid request body" }, { status: 400 }); } const { action, force } = body; try { switch (action) { case "start": await mcProcessManager.start(); break; case "stop": await mcProcessManager.stop(force); break; case "restart": await mcProcessManager.restart(force); break; } // Audit log await db.insert(auditLogs).values({ id: nanoid(), userId: session.user.id, action: `server.${action}${force ? ".force" : ""}`, target: "server", targetId: null, details: JSON.stringify({ action, force }), ipAddress: ip, createdAt: Date.now(), }); return NextResponse.json({ success: true, action }); } catch (err) { const message = err instanceof Error ? err.message : "Unknown error"; return NextResponse.json({ error: message }, { status: 500 }); } }