57 lines
1.5 KiB
TypeScript
57 lines
1.5 KiB
TypeScript
|
|
import { getAuth } from "@clerk/react-router/server";
|
||
|
|
import type { database } from "~/database/context";
|
||
|
|
import { eq, and } from "drizzle-orm";
|
||
|
|
import * as schema from "~/database/schema";
|
||
|
|
import type { LoaderFunctionArgs } from "react-router";
|
||
|
|
|
||
|
|
type Db = ReturnType<typeof database>;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Verifies the request has an authenticated user who is either a commissioner
|
||
|
|
* or a team owner in the given league/season. Throws Response on failure.
|
||
|
|
*
|
||
|
|
* @param unauthMessage - 401 message when not logged in
|
||
|
|
* @param unauthorizedMessage - 403 message when logged in but not a member
|
||
|
|
*/
|
||
|
|
export async function requireLeagueAccess(
|
||
|
|
args: LoaderFunctionArgs,
|
||
|
|
{
|
||
|
|
leagueId,
|
||
|
|
seasonId,
|
||
|
|
db,
|
||
|
|
unauthMessage = "You must be logged in",
|
||
|
|
unauthorizedMessage = "You do not have access to this league",
|
||
|
|
}: {
|
||
|
|
leagueId: string;
|
||
|
|
seasonId: string;
|
||
|
|
db: Db;
|
||
|
|
unauthMessage?: string;
|
||
|
|
unauthorizedMessage?: string;
|
||
|
|
}
|
||
|
|
): Promise<void> {
|
||
|
|
const { userId } = await getAuth(args);
|
||
|
|
|
||
|
|
if (!userId) {
|
||
|
|
throw new Response(unauthMessage, { status: 401 });
|
||
|
|
}
|
||
|
|
|
||
|
|
const [commissioner, team] = await Promise.all([
|
||
|
|
db.query.commissioners.findFirst({
|
||
|
|
where: and(
|
||
|
|
eq(schema.commissioners.leagueId, leagueId),
|
||
|
|
eq(schema.commissioners.userId, userId)
|
||
|
|
),
|
||
|
|
}),
|
||
|
|
db.query.teams.findFirst({
|
||
|
|
where: and(
|
||
|
|
eq(schema.teams.seasonId, seasonId),
|
||
|
|
eq(schema.teams.ownerId, userId)
|
||
|
|
),
|
||
|
|
}),
|
||
|
|
]);
|
||
|
|
|
||
|
|
if (!commissioner && !team) {
|
||
|
|
throw new Response(unauthorizedMessage, { status: 403 });
|
||
|
|
}
|
||
|
|
}
|