Files
MineGeo/lib/moderator-users-api.ts

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 });
}