mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-08-28 06:08:13 -05:00
Timed bans feature
This commit is contained in:
149
app/features/admin/actions/admin.server.ts
Normal file
149
app/features/admin/actions/admin.server.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
import type { ActionFunctionArgs } from "@remix-run/node";
|
||||
import { z } from "zod";
|
||||
import * as AdminRepository from "~/features/admin/AdminRepository.server";
|
||||
import { makeArtist } from "~/features/art/queries/makeArtist.server";
|
||||
import { requireUserId } from "~/features/auth/core/user.server";
|
||||
import { isAdmin, isMod } from "~/permissions";
|
||||
import { parseRequestFormData, validate } from "~/utils/remix";
|
||||
import { assertUnreachable } from "~/utils/types";
|
||||
import { _action, actualNumber } from "~/utils/zod";
|
||||
import { plusTiersFromVotingAndLeaderboard } from "../core/plus-tier.server";
|
||||
import { refreshBannedCache } from "~/features/ban/core/banned.server";
|
||||
|
||||
export const action = async ({ request }: ActionFunctionArgs) => {
|
||||
const data = await parseRequestFormData({
|
||||
request,
|
||||
schema: adminActionSchema,
|
||||
});
|
||||
const user = await requireUserId(request);
|
||||
|
||||
switch (data._action) {
|
||||
case "MIGRATE": {
|
||||
validate(isAdmin(user), "Admin needed", 401);
|
||||
|
||||
await AdminRepository.migrate({
|
||||
oldUserId: data["old-user"],
|
||||
newUserId: data["new-user"],
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "REFRESH": {
|
||||
validate(isAdmin(user));
|
||||
|
||||
await AdminRepository.replacePlusTiers(
|
||||
await plusTiersFromVotingAndLeaderboard(),
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "FORCE_PATRON": {
|
||||
validate(isAdmin(user), "Admin needed", 401);
|
||||
|
||||
await AdminRepository.forcePatron({
|
||||
id: data["user"],
|
||||
patronSince: new Date(),
|
||||
patronTier: data.patronTier,
|
||||
patronTill: new Date(data.patronTill),
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "CLEAN_UP": {
|
||||
validate(isAdmin(user), "Admin needed", 401);
|
||||
|
||||
// on purpose sync
|
||||
AdminRepository.cleanUp();
|
||||
break;
|
||||
}
|
||||
case "ARTIST": {
|
||||
validate(isMod(user), "Mod needed", 401);
|
||||
|
||||
makeArtist(data["user"]);
|
||||
break;
|
||||
}
|
||||
case "VIDEO_ADDER": {
|
||||
validate(isMod(user), "Mod needed", 401);
|
||||
|
||||
await AdminRepository.makeVideoAdderByUserId(data["user"]);
|
||||
break;
|
||||
}
|
||||
case "LINK_PLAYER": {
|
||||
validate(isMod(user), "Mod needed", 401);
|
||||
|
||||
await AdminRepository.linkUserAndPlayer({
|
||||
userId: data["user"],
|
||||
playerId: data.playerId,
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
case "BAN_USER": {
|
||||
validate(isAdmin(user), "Admin needed", 401);
|
||||
|
||||
await AdminRepository.banUser({
|
||||
bannedReason: data.reason ?? null,
|
||||
userId: data["user"],
|
||||
banned: data.duration ? new Date(data.duration) : 1,
|
||||
});
|
||||
|
||||
refreshBannedCache();
|
||||
|
||||
break;
|
||||
}
|
||||
case "UNBAN_USER": {
|
||||
validate(isAdmin(user), "Admin needed", 401);
|
||||
|
||||
await AdminRepository.unbanUser(data["user"]);
|
||||
|
||||
refreshBannedCache();
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertUnreachable(data);
|
||||
}
|
||||
}
|
||||
|
||||
return { ok: true };
|
||||
};
|
||||
|
||||
export const adminActionSchema = z.union([
|
||||
z.object({
|
||||
_action: _action("MIGRATE"),
|
||||
"old-user": z.preprocess(actualNumber, z.number().positive()),
|
||||
"new-user": z.preprocess(actualNumber, z.number().positive()),
|
||||
}),
|
||||
z.object({
|
||||
_action: _action("REFRESH"),
|
||||
}),
|
||||
z.object({
|
||||
_action: _action("CLEAN_UP"),
|
||||
}),
|
||||
z.object({
|
||||
_action: _action("FORCE_PATRON"),
|
||||
user: z.preprocess(actualNumber, z.number().positive()),
|
||||
patronTier: z.preprocess(actualNumber, z.number()),
|
||||
patronTill: z.string(),
|
||||
}),
|
||||
z.object({
|
||||
_action: _action("VIDEO_ADDER"),
|
||||
user: z.preprocess(actualNumber, z.number().positive()),
|
||||
}),
|
||||
z.object({
|
||||
_action: _action("ARTIST"),
|
||||
user: z.preprocess(actualNumber, z.number().positive()),
|
||||
}),
|
||||
z.object({
|
||||
_action: _action("LINK_PLAYER"),
|
||||
user: z.preprocess(actualNumber, z.number().positive()),
|
||||
playerId: z.preprocess(actualNumber, z.number().positive()),
|
||||
}),
|
||||
z.object({
|
||||
_action: _action("BAN_USER"),
|
||||
user: z.preprocess(actualNumber, z.number().positive()),
|
||||
reason: z.string().nullish(),
|
||||
duration: z.string().nullish(),
|
||||
}),
|
||||
z.object({
|
||||
_action: _action("UNBAN_USER"),
|
||||
user: z.preprocess(actualNumber, z.number().positive()),
|
||||
}),
|
||||
]);
|
||||
Reference in New Issue
Block a user