diff --git a/app/features/api-public/api-public-utils.server.ts b/app/features/api-public/api-public-utils.server.ts index 598355925..5a9aea612 100644 --- a/app/features/api-public/api-public-utils.server.ts +++ b/app/features/api-public/api-public-utils.server.ts @@ -1,3 +1,5 @@ +import { cors } from "remix-utils/cors"; + const apiTokens = process.env["PUBLIC_API_TOKENS"]?.split(",") ?? []; export function requireBearerAuth(req: Request) { const authHeader = req.headers.get("Authorization"); @@ -9,3 +11,12 @@ export function requireBearerAuth(req: Request) { throw new Response("Invalid token", { status: 401 }); } } + +export async function handleOptionsRequest(req: Request) { + if (req.method === "OPTIONS") { + throw await cors(req, new Response("OK", { status: 204 }), { + origin: "*", + credentials: true, + }); + } +} diff --git a/app/features/api-public/routes/tournament-match.$id.ts b/app/features/api-public/routes/tournament-match.$id.ts index 54af84911..00be2fd60 100644 --- a/app/features/api-public/routes/tournament-match.$id.ts +++ b/app/features/api-public/routes/tournament-match.$id.ts @@ -6,7 +6,10 @@ import { id } from "~/utils/zod"; import type { GetTournamentMatchResponse } from "../schema"; import { jsonArrayFrom } from "kysely/helpers/sqlite"; import { resolveMapList } from "~/features/tournament-bracket/core/mapList.server"; -import { requireBearerAuth } from "../api-public-utils.server"; +import { + handleOptionsRequest, + requireBearerAuth, +} from "../api-public-utils.server"; import i18next from "~/modules/i18n/i18next.server"; import * as TournamentRepository from "~/features/tournament/TournamentRepository.server"; import { cors } from "remix-utils/cors"; @@ -16,6 +19,7 @@ const paramsSchema = z.object({ }); export const loader = async ({ params, request }: LoaderFunctionArgs) => { + await handleOptionsRequest(request); requireBearerAuth(request); const t = await i18next.getFixedT("en", ["game-misc"]); diff --git a/app/features/api-public/routes/tournament.$id.brackets.$bidx.ts b/app/features/api-public/routes/tournament.$id.brackets.$bidx.ts index b18e7dd22..3b7c8fbef 100644 --- a/app/features/api-public/routes/tournament.$id.brackets.$bidx.ts +++ b/app/features/api-public/routes/tournament.$id.brackets.$bidx.ts @@ -3,7 +3,10 @@ import { z } from "zod"; import { tournamentFromDB } from "~/features/tournament-bracket/core/Tournament.server"; import { notFoundIfFalsy, parseParams } from "~/utils/remix"; import { id } from "~/utils/zod"; -import { requireBearerAuth } from "../api-public-utils.server"; +import { + handleOptionsRequest, + requireBearerAuth, +} from "../api-public-utils.server"; import type { GetTournamentBracketResponse } from "../schema"; import { cors } from "remix-utils/cors"; @@ -13,6 +16,7 @@ const paramsSchema = z.object({ }); export const loader = async ({ params, request }: LoaderFunctionArgs) => { + await handleOptionsRequest(request); requireBearerAuth(request); const { id, bidx } = parseParams({ params, schema: paramsSchema }); diff --git a/app/features/api-public/routes/tournament.$id.teams.ts b/app/features/api-public/routes/tournament.$id.teams.ts index 38f5e6f2a..1d60d8bd6 100644 --- a/app/features/api-public/routes/tournament.$id.teams.ts +++ b/app/features/api-public/routes/tournament.$id.teams.ts @@ -6,7 +6,10 @@ import { id } from "~/utils/zod"; import type { GetTournamentTeamsResponse } from "../schema"; import { databaseTimestampToDate } from "~/utils/dates"; import { jsonArrayFrom } from "kysely/helpers/sqlite"; -import { requireBearerAuth } from "../api-public-utils.server"; +import { + handleOptionsRequest, + requireBearerAuth, +} from "../api-public-utils.server"; import i18next from "~/modules/i18n/i18next.server"; import { cors } from "remix-utils/cors"; @@ -15,6 +18,7 @@ const paramsSchema = z.object({ }); export const loader = async ({ params, request }: LoaderFunctionArgs) => { + await handleOptionsRequest(request); requireBearerAuth(request); const t = await i18next.getFixedT("en", ["game-misc"]); diff --git a/app/features/api-public/routes/tournament.$id.ts b/app/features/api-public/routes/tournament.$id.ts index 117e848d7..8f26d3b12 100644 --- a/app/features/api-public/routes/tournament.$id.ts +++ b/app/features/api-public/routes/tournament.$id.ts @@ -7,7 +7,10 @@ import type { GetTournamentResponse } from "../schema"; import { databaseTimestampToDate } from "~/utils/dates"; import { HACKY_resolvePicture } from "~/features/tournament/tournament-utils"; import { jsonArrayFrom } from "kysely/helpers/sqlite"; -import { requireBearerAuth } from "../api-public-utils.server"; +import { + handleOptionsRequest, + requireBearerAuth, +} from "../api-public-utils.server"; import { cors } from "remix-utils/cors"; const paramsSchema = z.object({ @@ -15,6 +18,7 @@ const paramsSchema = z.object({ }); export const loader = async ({ params, request }: LoaderFunctionArgs) => { + await handleOptionsRequest(request); requireBearerAuth(request); const { id } = parseParams({ params, schema: paramsSchema }); diff --git a/app/features/api-public/routes/user.$identifier.ts b/app/features/api-public/routes/user.$identifier.ts index 87a0dc607..23578d3fc 100644 --- a/app/features/api-public/routes/user.$identifier.ts +++ b/app/features/api-public/routes/user.$identifier.ts @@ -7,7 +7,10 @@ import type { GetUserResponse } from "../schema"; import { jsonArrayFrom } from "kysely/helpers/sqlite"; import { i18next } from "~/modules/i18n/i18next.server"; ("~/modules/i18n"); -import { requireBearerAuth } from "../api-public-utils.server"; +import { + handleOptionsRequest, + requireBearerAuth, +} from "../api-public-utils.server"; import { cors } from "remix-utils/cors"; const paramsSchema = z.object({ @@ -15,6 +18,7 @@ const paramsSchema = z.object({ }); export const loader = async ({ params, request }: LoaderFunctionArgs) => { + await handleOptionsRequest(request); requireBearerAuth(request); const t = await i18next.getFixedT("en", ["weapons"]);