242 lines
6.2 KiB
TypeScript
242 lines
6.2 KiB
TypeScript
import { eq, sql } from "drizzle-orm";
|
|
import { NextResponse } from "next/server";
|
|
import { withAdmin } from "@/lib/api-handler";
|
|
import { db, User } from "@/lib/db";
|
|
import { PERMS } from "@/lib/permissions";
|
|
import { rcon } from "@/lib/services/rcon";
|
|
import { logStaffActivity } from "@/lib/services/staff-activity";
|
|
|
|
export const POST = withAdmin(
|
|
{ permission: PERMS.USERS_EDIT },
|
|
async (request, context) => {
|
|
const staffId = context.session.user.id;
|
|
const staffRank = context.session.user.rank;
|
|
const formData = await request.formData();
|
|
const userId = Number(formData.get("userId"));
|
|
const username = String(formData.get("username") || "");
|
|
const action = String(formData.get("action") || "");
|
|
|
|
if (!userId || !username) {
|
|
return NextResponse.json(
|
|
{ success: false, message: "Invalid user data" },
|
|
{ status: 400 },
|
|
);
|
|
}
|
|
|
|
if (action === "set_rank") {
|
|
const rank = Number(formData.get("rank") || "0");
|
|
if (!Number.isInteger(rank) || rank < 1) {
|
|
return NextResponse.json(
|
|
{ success: false, message: "Invalid rank value" },
|
|
{ status: 400 },
|
|
);
|
|
}
|
|
|
|
const [rankExists] = (await db
|
|
.execute(
|
|
sql`SELECT id FROM permission_ranks WHERE id = ${rank} LIMIT 1`,
|
|
)
|
|
.catch(() => [[]] as unknown as [unknown[], unknown])) as unknown as [
|
|
{ id: number }[],
|
|
unknown,
|
|
];
|
|
if (rankExists.length === 0) {
|
|
return NextResponse.json(
|
|
{ success: false, message: "Rank does not exist" },
|
|
{ status: 400 },
|
|
);
|
|
}
|
|
|
|
const [target] = await db
|
|
.select({ rank: User.rank })
|
|
.from(User)
|
|
.where(eq(User.id, userId))
|
|
.limit(1);
|
|
if (!target) {
|
|
return NextResponse.json(
|
|
{ success: false, message: "User not found" },
|
|
{ status: 404 },
|
|
);
|
|
}
|
|
|
|
const isSuper = context.permissions.isSuperAdmin;
|
|
if (!isSuper) {
|
|
if (target.rank >= staffRank) {
|
|
return NextResponse.json(
|
|
{
|
|
success: false,
|
|
message: "Cannot change rank of a user at or above your rank",
|
|
},
|
|
{ status: 403 },
|
|
);
|
|
}
|
|
if (rank >= staffRank) {
|
|
return NextResponse.json(
|
|
{
|
|
success: false,
|
|
message: "Cannot set a rank equal to or above your own",
|
|
},
|
|
{ status: 403 },
|
|
);
|
|
}
|
|
}
|
|
|
|
await db.update(User).set({ rank }).where(eq(User.id, userId));
|
|
await rcon.setRank(userId, rank);
|
|
await logStaffActivity({
|
|
staffId,
|
|
action: "rank_change",
|
|
description: `Set rank of user #${userId} to ${rank}`,
|
|
targetType: "user",
|
|
targetId: userId,
|
|
});
|
|
|
|
return NextResponse.json(
|
|
{ success: true, message: `Set rank of user #${userId} to ${rank}` },
|
|
{ status: 200 },
|
|
);
|
|
}
|
|
|
|
if (action === "disconnect") {
|
|
await rcon.disconnectUser(userId, username);
|
|
await logStaffActivity({
|
|
staffId,
|
|
action: "disconnect",
|
|
description: `Disconnected user #${userId} (${username})`,
|
|
targetType: "user",
|
|
targetId: userId,
|
|
});
|
|
return NextResponse.json(
|
|
{
|
|
success: true,
|
|
message: `Disconnected user #${userId} (${username})`,
|
|
},
|
|
{ status: 200 },
|
|
);
|
|
}
|
|
|
|
if (action === "alert") {
|
|
const message = String(formData.get("message") || "")
|
|
.trim()
|
|
.slice(0, 512);
|
|
if (!message) {
|
|
return NextResponse.json(
|
|
{ success: false, message: "Alert message is required" },
|
|
{ status: 400 },
|
|
);
|
|
}
|
|
await rcon.alertUser(userId, message);
|
|
await logStaffActivity({
|
|
staffId,
|
|
action: "alert_user",
|
|
description: `Sent alert to user #${userId}`,
|
|
targetType: "user",
|
|
targetId: userId,
|
|
});
|
|
return NextResponse.json(
|
|
{ success: true, message: `Sent alert to user #${userId}` },
|
|
{ status: 200 },
|
|
);
|
|
}
|
|
|
|
if (action === "give_credits") {
|
|
const credits = Number(formData.get("credits") || "0");
|
|
if (!credits || credits <= 0) {
|
|
return NextResponse.json(
|
|
{ success: false, message: "Invalid credit amount" },
|
|
{ status: 400 },
|
|
);
|
|
}
|
|
await rcon.giveCredits(userId, credits);
|
|
await logStaffActivity({
|
|
staffId,
|
|
action: "give_currency",
|
|
description: `Gave ${credits} credits to user #${userId}`,
|
|
targetType: "user",
|
|
targetId: userId,
|
|
});
|
|
return NextResponse.json(
|
|
{
|
|
success: true,
|
|
message: `Gave ${credits} credits to user #${userId}`,
|
|
},
|
|
{ status: 200 },
|
|
);
|
|
}
|
|
|
|
if (action === "give_duckets") {
|
|
const amount = Number(formData.get("amount") || "0");
|
|
if (!amount || amount <= 0) {
|
|
return NextResponse.json(
|
|
{ success: false, message: "Invalid duckets amount" },
|
|
{ status: 400 },
|
|
);
|
|
}
|
|
await rcon.giveDuckets(userId, amount);
|
|
await logStaffActivity({
|
|
staffId,
|
|
action: "give_currency",
|
|
description: `Gave ${amount} duckets to user #${userId}`,
|
|
targetType: "user",
|
|
targetId: userId,
|
|
});
|
|
return NextResponse.json(
|
|
{ success: true, message: `Gave ${amount} duckets to user #${userId}` },
|
|
{ status: 200 },
|
|
);
|
|
}
|
|
|
|
if (action === "give_diamonds") {
|
|
const amount = Number(formData.get("amount") || "0");
|
|
if (!amount || amount <= 0) {
|
|
return NextResponse.json(
|
|
{ success: false, message: "Invalid diamonds amount" },
|
|
{ status: 400 },
|
|
);
|
|
}
|
|
await rcon.giveDiamonds(userId, amount);
|
|
await logStaffActivity({
|
|
staffId,
|
|
action: "give_currency",
|
|
description: `Gave ${amount} diamonds to user #${userId}`,
|
|
targetType: "user",
|
|
targetId: userId,
|
|
});
|
|
return NextResponse.json(
|
|
{
|
|
success: true,
|
|
message: `Gave ${amount} diamonds to user #${userId}`,
|
|
},
|
|
{ status: 200 },
|
|
);
|
|
}
|
|
|
|
if (action === "give_points") {
|
|
const amount = Number(formData.get("amount") || "0");
|
|
if (!amount || amount <= 0) {
|
|
return NextResponse.json(
|
|
{ success: false, message: "Invalid points amount" },
|
|
{ status: 400 },
|
|
);
|
|
}
|
|
await rcon.givePointsGotw(userId, amount);
|
|
await logStaffActivity({
|
|
staffId,
|
|
action: "give_currency",
|
|
description: `Gave ${amount} points to user #${userId}`,
|
|
targetType: "user",
|
|
targetId: userId,
|
|
});
|
|
return NextResponse.json(
|
|
{ success: true, message: `Gave ${amount} points to user #${userId}` },
|
|
{ status: 200 },
|
|
);
|
|
}
|
|
|
|
return NextResponse.json(
|
|
{ success: false, message: `Unknown action: ${action}` },
|
|
{ status: 400 },
|
|
);
|
|
},
|
|
);
|