61 lines
2.0 KiB
TypeScript
61 lines
2.0 KiB
TypeScript
import "server-only";
|
|
import { NextRequest, NextResponse } from "next/server";
|
|
import { z } from "zod";
|
|
import { admin, required } from "./supabase";
|
|
import { ServiceError, checkServiceError } from "./service-error";
|
|
import { prefixUpdateSchema } from "@/shared/profile-appearance";
|
|
|
|
export async function moderatorUsersApi(
|
|
request: NextRequest,
|
|
path: string[],
|
|
reviewer: string,
|
|
jsonBody: (request: NextRequest) => Promise<unknown>,
|
|
) {
|
|
const db = admin();
|
|
const columns =
|
|
"id,display_name,name_glow,glow_color,role,bug_finder,custom_prefix,custom_prefix_icon" as const;
|
|
const respond = (body: unknown) =>
|
|
NextResponse.json(body, { headers: { "Cache-Control": "no-store" } });
|
|
if (request.method === "GET" && path.length === 2) {
|
|
const search = (request.nextUrl.searchParams.get("q") ?? "")
|
|
.trim()
|
|
.slice(0, 64);
|
|
let query = db
|
|
.from("profiles")
|
|
.select(columns)
|
|
.order("display_name")
|
|
.order("id")
|
|
.limit(50);
|
|
if (search) {
|
|
if (z.string().uuid().safeParse(search).success)
|
|
query = query.eq("id", search);
|
|
else
|
|
query = query.ilike(
|
|
"display_name",
|
|
"%" + search.replace(/[\\%_]/g, "\\$&") + "%",
|
|
);
|
|
}
|
|
return respond({ users: required(await query) });
|
|
}
|
|
if (request.method === "PATCH" && path.length === 3) {
|
|
const id = z.string().uuid().parse(path[2]),
|
|
body = prefixUpdateSchema.parse(await jsonBody(request));
|
|
const updated = await db.rpc("set_user_prefix", {
|
|
p_reviewer: reviewer,
|
|
p_user: id,
|
|
p_prefix: body.prefix,
|
|
p_icon: body.icon,
|
|
});
|
|
checkServiceError(updated.error);
|
|
const result = await db
|
|
.from("profiles")
|
|
.select(columns)
|
|
.eq("id", id)
|
|
.maybeSingle();
|
|
if (result.error) required(result);
|
|
if (!result.data) throw new ServiceError("Player not found", 404);
|
|
return respond({ user: result.data });
|
|
}
|
|
return NextResponse.json({ error: "Not found" }, { status: 404 });
|
|
}
|