From 27cd5e3321ecc7dae76333d3e1175830a466aad3 Mon Sep 17 00:00:00 2001 From: Adrian Bonpin Date: Mon, 27 Apr 2026 15:34:17 +0800 Subject: [PATCH] feat: add POST /api/performance/:id/report endpoint --- app/api/[[...slugs]]/route.ts | 2 ++ lib/api/index.ts | 1 + lib/api/reports.ts | 61 +++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 lib/api/reports.ts diff --git a/app/api/[[...slugs]]/route.ts b/app/api/[[...slugs]]/route.ts index 5712485..f31b43c 100644 --- a/app/api/[[...slugs]]/route.ts +++ b/app/api/[[...slugs]]/route.ts @@ -13,6 +13,7 @@ import { performanceSubmitRoutes, commentsRoutes, savedGamesRoutes, + reportRoutes, } from "@/lib/api" import { steamSearchRoutes } from "@/lib/api/steam-search" import { searchUnifiedRoutes } from "@/lib/api/search-unified" @@ -65,6 +66,7 @@ export const app = new Elysia({ prefix: "/api" }) .use(performanceRoutes) .use(performanceVerifyRoutes) .use(performanceSubmitRoutes) + .use(reportRoutes) // Comments .use(commentsRoutes) // Steam search proxy diff --git a/lib/api/index.ts b/lib/api/index.ts index 224a144..359b60b 100644 --- a/lib/api/index.ts +++ b/lib/api/index.ts @@ -8,3 +8,4 @@ export { commentsRoutes } from "./comments" export { gameStatsRoutes } from "./game-stats" export { hardwareStatsRoutes } from "./hardware-stats" export { savedGamesRoutes } from "./saved-games" +export { reportRoutes } from "./reports" diff --git a/lib/api/reports.ts b/lib/api/reports.ts new file mode 100644 index 0000000..137f177 --- /dev/null +++ b/lib/api/reports.ts @@ -0,0 +1,61 @@ +import { Elysia, t } from "elysia" +import { db } from "@/lib/db/index" +import { reports } from "@/lib/db/schema" +import { eq, and } from "drizzle-orm" +import { requireRole } from "@/lib/auth/guard" + +export const reportRoutes = new Elysia({ prefix: "/performance" }).post( + "/:id/report", + async ({ params, body, request, set }) => { + const guard = await requireRole(request.headers, [ + "user", + "contributor", + "admin", + ]) + if (!guard.ok) { + set.status = guard.status + return { error: guard.error } + } + + // Check if user already reported this entry + const [existing] = await db + .select() + .from(reports) + .where( + and( + eq(reports.entryId, params.id), + eq(reports.reporterId, guard.user.id), + ), + ) + .limit(1) + + if (existing) { + set.status = 409 + return { error: "You have already reported this entry" } + } + + const [created] = await db + .insert(reports) + .values({ + entryId: params.id, + reporterId: guard.user.id, + reason: body.reason, + details: body.details ?? null, + }) + .returning() + + return created + }, + { + params: t.Object({ id: t.String() }), + body: t.Object({ + reason: t.Union([ + t.Literal("inaccurate"), + t.Literal("spam"), + t.Literal("inappropriate"), + t.Literal("other"), + ]), + details: t.Optional(t.String()), + }), + }, +)