feat(housekeeping): cut over administration to ase
This commit is contained in:
1 parent
c9e35cf602
commit
2b8f73a91d
457 files changed
+589
-55936
No files matched your search
@@ -1,283 +0,0 @@
|
||||
"use server";
|
||||
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { z } from "zod";
|
||||
import {
|
||||
type SystemMutationContext,
|
||||
type SystemMutationOperation,
|
||||
systemMutationService,
|
||||
} from "@/features/housekeeping/domains/system/services/mutations";
|
||||
import { createHousekeepingCapabilityContext } from "@/features/housekeeping/foundation/capability-context";
|
||||
import type { AdminActionContext } from "@/lib/foundation/types";
|
||||
import { PERMS } from "@/lib/permissions";
|
||||
import { adminAction } from "@/lib/safe-action";
|
||||
import { ActionError, actionOk } from "@/lib/safe-action-shared";
|
||||
|
||||
const PATH = "/admin/commandocentrum";
|
||||
const RCON_FAIL = "RCON command failed. Is the emulator running?";
|
||||
|
||||
function mutationContext(
|
||||
ctx: Pick<AdminActionContext, "session" | "permissions" | "requestId">,
|
||||
): SystemMutationContext {
|
||||
return {
|
||||
capability: createHousekeepingCapabilityContext(
|
||||
{
|
||||
id: Number(ctx.session.user.id),
|
||||
rank: Number(ctx.session.user.rank),
|
||||
username: ctx.session.user.username,
|
||||
},
|
||||
ctx.permissions,
|
||||
),
|
||||
correlationId: String(ctx.requestId),
|
||||
};
|
||||
}
|
||||
|
||||
async function runRconMutation(
|
||||
ctx: Pick<AdminActionContext, "session" | "permissions" | "requestId">,
|
||||
operation: SystemMutationOperation,
|
||||
input: unknown,
|
||||
): Promise<void> {
|
||||
const result = await systemMutationService.execute(
|
||||
mutationContext(ctx),
|
||||
operation,
|
||||
input,
|
||||
);
|
||||
if (result.ok) return;
|
||||
if (result.error.messageKey === "errors.housekeeping.system.userNotFound") {
|
||||
throw new ActionError("User not found");
|
||||
}
|
||||
if (result.error.messageKey === "errors.housekeeping.system.rankNotFound") {
|
||||
throw new ActionError("Rank does not exist");
|
||||
}
|
||||
if (
|
||||
result.error.messageKey ===
|
||||
"errors.housekeeping.system.cannotChangePeerRank"
|
||||
) {
|
||||
throw new ActionError("Cannot change rank of a user at or above your rank");
|
||||
}
|
||||
if (
|
||||
result.error.messageKey ===
|
||||
"errors.housekeeping.system.cannotAssignPeerRank"
|
||||
) {
|
||||
throw new ActionError("Cannot set a rank equal to or above your own");
|
||||
}
|
||||
throw new ActionError(RCON_FAIL);
|
||||
}
|
||||
|
||||
function revalidate(): void {
|
||||
revalidatePath(PATH);
|
||||
}
|
||||
|
||||
export const updateCatalog = adminAction(
|
||||
{ permission: PERMS.RCON_EXECUTE },
|
||||
async (ctx) => {
|
||||
await runRconMutation(ctx, "rcon.update-catalog", {});
|
||||
revalidate();
|
||||
return actionOk();
|
||||
},
|
||||
);
|
||||
|
||||
export const updateWordFilter = adminAction(
|
||||
{ permission: PERMS.RCON_EXECUTE },
|
||||
async (ctx) => {
|
||||
await runRconMutation(ctx, "rcon.update-word-filter", {});
|
||||
revalidate();
|
||||
return actionOk();
|
||||
},
|
||||
);
|
||||
|
||||
export const updateNavigator = adminAction(
|
||||
{ permission: PERMS.RCON_EXECUTE },
|
||||
async (ctx) => {
|
||||
await runRconMutation(ctx, "rcon.update-navigator", {});
|
||||
revalidate();
|
||||
return actionOk();
|
||||
},
|
||||
);
|
||||
|
||||
const hotelAlertSchema = z.object({
|
||||
message: z.string().trim().min(1).max(512),
|
||||
});
|
||||
|
||||
export const hotelAlert = adminAction(
|
||||
{ permission: PERMS.RCON_EXECUTE, schema: hotelAlertSchema },
|
||||
async (ctx) => {
|
||||
await runRconMutation(ctx, "rcon.hotel-alert", {
|
||||
message: ctx.data.message.normalize("NFC"),
|
||||
});
|
||||
revalidate();
|
||||
return actionOk();
|
||||
},
|
||||
);
|
||||
|
||||
const disconnectSchema = z.object({
|
||||
userId: z.coerce.number().int().positive(),
|
||||
username: z.string().trim().min(1),
|
||||
});
|
||||
|
||||
export const disconnectUser = adminAction(
|
||||
{ permission: PERMS.RCON_EXECUTE, schema: disconnectSchema },
|
||||
async (ctx) => {
|
||||
await runRconMutation(ctx, "rcon.disconnect-user", {
|
||||
userId: ctx.data.userId,
|
||||
username: ctx.data.username.normalize("NFC"),
|
||||
});
|
||||
revalidate();
|
||||
return actionOk();
|
||||
},
|
||||
);
|
||||
|
||||
const alertUserSchema = z.object({
|
||||
userId: z.coerce.number().int().positive(),
|
||||
message: z.string().trim().min(1).max(512),
|
||||
});
|
||||
|
||||
export const alertUser = adminAction(
|
||||
{ permission: PERMS.RCON_EXECUTE, schema: alertUserSchema },
|
||||
async (ctx) => {
|
||||
await runRconMutation(ctx, "rcon.alert-user", {
|
||||
userId: ctx.data.userId,
|
||||
message: ctx.data.message.normalize("NFC"),
|
||||
});
|
||||
revalidate();
|
||||
return actionOk();
|
||||
},
|
||||
);
|
||||
|
||||
const forwardUserSchema = z.object({
|
||||
userId: z.coerce.number().int().positive(),
|
||||
roomId: z.coerce.number().int().positive(),
|
||||
});
|
||||
|
||||
export const forwardUser = adminAction(
|
||||
{ permission: PERMS.RCON_EXECUTE, schema: forwardUserSchema },
|
||||
async (ctx) => {
|
||||
await runRconMutation(ctx, "rcon.forward-user", ctx.data);
|
||||
revalidate();
|
||||
return actionOk();
|
||||
},
|
||||
);
|
||||
|
||||
const giveCreditsSchema = z.object({
|
||||
userId: z.coerce.number().int().positive(),
|
||||
credits: z.coerce.number().int().positive(),
|
||||
});
|
||||
|
||||
export const giveCredits = adminAction(
|
||||
{ permission: PERMS.RCON_EXECUTE, schema: giveCreditsSchema },
|
||||
async (ctx) => {
|
||||
await runRconMutation(ctx, "rcon.give-credits", {
|
||||
userId: ctx.data.userId,
|
||||
amount: ctx.data.credits,
|
||||
});
|
||||
revalidate();
|
||||
return actionOk();
|
||||
},
|
||||
);
|
||||
|
||||
const giveAmountSchema = z.object({
|
||||
userId: z.coerce.number().int().positive(),
|
||||
amount: z.coerce.number().int().positive(),
|
||||
});
|
||||
|
||||
export const giveDuckets = adminAction(
|
||||
{ permission: PERMS.RCON_EXECUTE, schema: giveAmountSchema },
|
||||
async (ctx) => {
|
||||
await runRconMutation(ctx, "rcon.give-duckets", ctx.data);
|
||||
revalidate();
|
||||
return actionOk();
|
||||
},
|
||||
);
|
||||
|
||||
export const giveDiamonds = adminAction(
|
||||
{ permission: PERMS.RCON_EXECUTE, schema: giveAmountSchema },
|
||||
async (ctx) => {
|
||||
await runRconMutation(ctx, "rcon.give-diamonds", ctx.data);
|
||||
revalidate();
|
||||
return actionOk();
|
||||
},
|
||||
);
|
||||
|
||||
const giveBadgeSchema = z.object({
|
||||
userId: z.coerce.number().int().positive(),
|
||||
badge: z.string().trim().min(1).max(32),
|
||||
});
|
||||
|
||||
export const giveBadge = adminAction(
|
||||
{ permission: PERMS.RCON_EXECUTE, schema: giveBadgeSchema },
|
||||
async (ctx) => {
|
||||
await runRconMutation(ctx, "rcon.give-badge", {
|
||||
userId: ctx.data.userId,
|
||||
badge: ctx.data.badge.normalize("NFC"),
|
||||
});
|
||||
revalidate();
|
||||
return actionOk();
|
||||
},
|
||||
);
|
||||
|
||||
const setMottoSchema = z.object({
|
||||
userId: z.coerce.number().int().positive(),
|
||||
motto: z.string().trim().min(1).max(127),
|
||||
});
|
||||
|
||||
export const setMotto = adminAction(
|
||||
{ permission: PERMS.RCON_EXECUTE, schema: setMottoSchema },
|
||||
async (ctx) => {
|
||||
await runRconMutation(ctx, "rcon.set-motto", {
|
||||
userId: ctx.data.userId,
|
||||
motto: ctx.data.motto.normalize("NFC"),
|
||||
});
|
||||
revalidate();
|
||||
return actionOk();
|
||||
},
|
||||
);
|
||||
|
||||
const setRankSchema = z.object({
|
||||
userId: z.coerce.number().int().positive(),
|
||||
rank: z.coerce.number().int().min(1).max(9999),
|
||||
});
|
||||
|
||||
export const setRank = adminAction(
|
||||
{ permission: PERMS.RCON_EXECUTE, schema: setRankSchema },
|
||||
async (ctx) => {
|
||||
await runRconMutation(ctx, "rcon.set-rank", ctx.data);
|
||||
revalidate();
|
||||
return actionOk();
|
||||
},
|
||||
);
|
||||
|
||||
const executeCommandSchema = z.object({
|
||||
userId: z.coerce.number().int().positive(),
|
||||
command: z.string().trim().min(1).max(100),
|
||||
});
|
||||
|
||||
export const executeCommand = adminAction(
|
||||
{ permission: PERMS.RCON_EXECUTE, schema: executeCommandSchema },
|
||||
async (ctx) => {
|
||||
await runRconMutation(ctx, "rcon.execute-command", {
|
||||
userId: ctx.data.userId,
|
||||
command: ctx.data.command.normalize("NFC"),
|
||||
});
|
||||
revalidate();
|
||||
return actionOk();
|
||||
},
|
||||
);
|
||||
|
||||
const sendGiftSchema = z.object({
|
||||
userId: z.coerce.number().int().positive(),
|
||||
itemId: z.coerce.number().int().positive(),
|
||||
message: z.string().trim().max(255).optional().default("Here is a gift."),
|
||||
});
|
||||
|
||||
export const sendGift = adminAction(
|
||||
{ permission: PERMS.RCON_EXECUTE, schema: sendGiftSchema },
|
||||
async (ctx) => {
|
||||
await runRconMutation(ctx, "rcon.send-gift", {
|
||||
userId: ctx.data.userId,
|
||||
itemId: ctx.data.itemId,
|
||||
message: ctx.data.message.trim().slice(0, 255) || "Here is a gift.",
|
||||
});
|
||||
revalidate();
|
||||
return actionOk();
|
||||
},
|
||||
);
|
||||
Reference in new issue
Block a user