Update friend code admin action

This commit is contained in:
Kalle 2024-08-05 23:45:19 +03:00
parent f6da215c4a
commit 43f3b93d7d
3 changed files with 56 additions and 27 deletions

View File

@ -4,6 +4,8 @@ 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 { refreshBannedCache } from "~/features/ban/core/banned.server";
import { FRIEND_CODE_REGEXP } from "~/features/sendouq/q-constants";
import * as UserRepository from "~/features/user-page/UserRepository.server";
import { isAdmin, isMod } from "~/permissions";
import { logger } from "~/utils/logger";
import { parseRequestPayload, validate } from "~/utils/remix";
@ -112,6 +114,17 @@ export const action = async ({ request }: ActionFunctionArgs) => {
break;
}
case "UPDATE_FRIEND_CODE": {
validate(isMod(user), "Mod needed", 401);
await UserRepository.insertFriendCode({
friendCode: data.friendCode,
submitterUserId: user.id,
userId: data.user,
});
break;
}
default: {
assertUnreachable(data);
}
@ -161,4 +174,9 @@ export const adminActionSchema = z.union([
_action: _action("UNBAN_USER"),
user: z.preprocess(actualNumber, z.number().positive()),
}),
z.object({
_action: _action("UPDATE_FRIEND_CODE"),
friendCode: z.string().regex(FRIEND_CODE_REGEXP),
user: z.preprocess(actualNumber, z.number().positive()),
}),
]);

View File

@ -8,10 +8,12 @@ import {
import * as React from "react";
import { Button } from "~/components/Button";
import { Catcher } from "~/components/Catcher";
import { Input } from "~/components/Input";
import { Main } from "~/components/Main";
import { SubmitButton } from "~/components/SubmitButton";
import { UserSearch } from "~/components/UserSearch";
import { useUser } from "~/features/auth/core/user";
import { FRIEND_CODE_REGEXP_PATTERN } from "~/features/sendouq/q-constants";
import { isAdmin, isMod } from "~/permissions";
import type { SendouRouteHandle } from "~/utils/remix";
import { makeTitle } from "~/utils/strings";
@ -39,6 +41,7 @@ export default function AdminPage() {
{isMod(user) ? <LinkPlayer /> : null}
{isMod(user) ? <GiveArtist /> : null}
{isMod(user) ? <GiveVideoAdder /> : null}
{isMod(user) ? <UpdateFriendCode /> : null}
{process.env.NODE_ENV !== "production" || isAdmin(user) ? (
<Impersonate />
@ -199,6 +202,41 @@ function GiveVideoAdder() {
);
}
function UpdateFriendCode() {
const fetcher = useFetcher();
return (
<fetcher.Form className="stack md" method="post">
<h2>Update friend code</h2>
<div className="stack horizontal md">
<div>
<label>User</label>
<UserSearch inputName="user" />
</div>
<div>
<label>Friend code</label>
<Input
leftAddon="SW-"
id="friendCode"
name="friendCode"
pattern={FRIEND_CODE_REGEXP_PATTERN}
placeholder="1234-5678-9012"
/>
</div>
</div>
<div className="stack horizontal md">
<SubmitButton
type="submit"
_action="UPDATE_FRIEND_CODE"
state={fetcher.state}
>
Submit
</SubmitButton>
</div>
</fetcher.Form>
);
}
function ForcePatron() {
const fetcher = useFetcher();

View File

@ -1,27 +0,0 @@
import "dotenv/config";
import { ADMIN_ID } from "~/constants";
import { FRIEND_CODE_REGEXP } from "~/features/sendouq/q-constants";
import * as UserRepository from "~/features/user-page/UserRepository.server";
import invariant from "~/utils/invariant";
import { logger } from "~/utils/logger";
async function main() {
const discordId = process.argv[2]?.trim();
invariant(discordId, "discord id is required (argument 1)");
const newFriendCode = process.argv[3]?.trim();
invariant(discordId, "friend code is required (argument 2)");
invariant(FRIEND_CODE_REGEXP.test(newFriendCode), "Invalid friend code");
await UserRepository.insertFriendCode({
friendCode: newFriendCode,
submitterUserId: ADMIN_ID,
userId: await UserRepository.findByIdentifier(discordId).then((u) => u!.id),
});
logger.info(`Friend code updated: ${discordId} - ${newFriendCode}`);
}
void main();