Initial push
This commit is contained in:
74
app/api/server/control/route.ts
Normal file
74
app/api/server/control/route.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { auth } 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 auth.api.getSession({ headers: 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<typeof ActionSchema>;
|
||||
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 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user