From 466a3365f08c9eec90e799f1357763041e50009c Mon Sep 17 00:00:00 2001 From: yohlo Date: Sun, 24 Aug 2025 12:53:34 -0500 Subject: [PATCH] random imporvements --- .../_authed/tournaments/$tournamentId.tsx | 2 +- src/components/DefaultCatchBoundary.tsx | 168 ++++++++++++++---- .../players/components/profile/index.tsx | 16 +- src/features/players/server.ts | 9 +- src/lib/pocketbase/services/tournaments.ts | 1 - src/utils/supertokens.ts | 6 +- 6 files changed, 154 insertions(+), 48 deletions(-) diff --git a/src/app/routes/_authed/tournaments/$tournamentId.tsx b/src/app/routes/_authed/tournaments/$tournamentId.tsx index 687b0ce..05cff52 100644 --- a/src/app/routes/_authed/tournaments/$tournamentId.tsx +++ b/src/app/routes/_authed/tournaments/$tournamentId.tsx @@ -17,7 +17,7 @@ export const Route = createFileRoute('/_authed/tournaments/$tournamentId')({ header: { collapsed: true, withBackButton: true, - settingsLink: context.auth.roles?.includes("Admin") ? `/admin/tournaments/${params.tournamentId}` : undefined + settingsLink: context.auth.roles.includes("Admin") ? `/admin/tournaments/${params.tournamentId}` : undefined }, refresh: { toRefresh: tournamentQueries.details(params.tournamentId).queryKey, diff --git a/src/components/DefaultCatchBoundary.tsx b/src/components/DefaultCatchBoundary.tsx index f750e7b..eb0892c 100644 --- a/src/components/DefaultCatchBoundary.tsx +++ b/src/components/DefaultCatchBoundary.tsx @@ -1,53 +1,159 @@ import { - ErrorComponent, Link, rootRouteId, useMatch, useRouter, + useNavigate, } from '@tanstack/react-router' import type { ErrorComponentProps } from '@tanstack/react-router' +import { + Box, + Button, + Text, + Title, + Stack, + Group, + Alert, + Collapse, + Code, + ThemeIcon +} from '@mantine/core' +import { useDisclosure } from '@mantine/hooks' +import { useEffect } from 'react' +import toast from '@/lib/sonner' +import { logger } from '@/lib/logger' +import { ExclamationMarkIcon, XCircleIcon } from '@phosphor-icons/react' export function DefaultCatchBoundary({ error }: ErrorComponentProps) { const router = useRouter() + const navigate = useNavigate() const isRoot = useMatch({ strict: false, select: (state) => state.id === rootRouteId, }) + const [detailsOpened, { toggle: toggleDetails }] = useDisclosure(false) - console.error('DefaultCatchBoundary Error:', error) + const errorMessage = error?.message || 'Unknown error' + const errorStack = error?.stack || 'No stack trace available' + + useEffect(() => { + logger.error('DefaultCatchBoundary | ', error) + + if (errorMessage.toLowerCase().includes('unauthenticated')) { + toast.error('You\'ve been logged out') + navigate({ to: '/login' }) + return + } + }, [error, errorMessage, navigate]) + + if (errorMessage.toLowerCase().includes('unauthorized')) { + return ( + + + + + + Access Denied + + You don't have permission to access this. + + + + + + + + ) + } return ( -
- -
- - {isRoot ? ( - {errorMessage} + + + + {errorStack} + + + + + +
-
+ Try Again + + {isRoot ? ( + + ) : ( + + )} + + + ) } diff --git a/src/features/players/components/profile/index.tsx b/src/features/players/components/profile/index.tsx index e7acc85..c58024e 100644 --- a/src/features/players/components/profile/index.tsx +++ b/src/features/players/components/profile/index.tsx @@ -1,4 +1,4 @@ -import { Box, Button, Text } from "@mantine/core"; +import { Box, Button, Text, Title } from "@mantine/core"; import Header from "./header"; import { testEvent } from "@/utils/test-event"; import { Player } from "@/features/players/types"; @@ -17,10 +17,12 @@ const Profile = ({ player }: ProfileProps) => { }, { label: "Teams", - content: Panel 2 content + content: <> + + }, { - label: "Stats", + label: "Tournaments", content: Panel 3 content } ]; @@ -28,13 +30,7 @@ const Profile = ({ player }: ProfileProps) => { return <>
- { - console.log(`Switched to ${tab.label} tab`); - }} - /> + ; }; diff --git a/src/features/players/server.ts b/src/features/players/server.ts index 3c92255..0356aae 100644 --- a/src/features/players/server.ts +++ b/src/features/players/server.ts @@ -1,13 +1,16 @@ -import { setUserMetadata, superTokensFunctionMiddleware } from "@/utils/supertokens"; +import { setUserMetadata, superTokensFunctionMiddleware, verifySuperTokensSession } from "@/utils/supertokens"; import { createServerFn } from "@tanstack/react-start"; import { playerInputSchema, playerUpdateSchema } from "@/features/players/types"; import { pbAdmin } from "@/lib/pocketbase/client"; import { z } from "zod"; import { logger } from "."; +import { getWebRequest } from "@tanstack/react-start/server"; export const fetchMe = createServerFn() - .middleware([superTokensFunctionMiddleware]) - .handler(async ({ context }) => { + .handler(async ({ response }) => { + const request = getWebRequest(); + const { context } = await verifySuperTokensSession(request, response); + if (!context || !context.userAuthId) return { user: undefined, roles: [], metadata: {} }; try { diff --git a/src/lib/pocketbase/services/tournaments.ts b/src/lib/pocketbase/services/tournaments.ts index f368b23..879f2bf 100644 --- a/src/lib/pocketbase/services/tournaments.ts +++ b/src/lib/pocketbase/services/tournaments.ts @@ -28,7 +28,6 @@ export function createTournamentsService(pb: PocketBase) { sort: "-created", }); - console.log(result); return result.map(transformTournament); }, async createTournament(data: TournamentInput): Promise { diff --git a/src/utils/supertokens.ts b/src/utils/supertokens.ts index f0cbcd1..c5e9d99 100644 --- a/src/utils/supertokens.ts +++ b/src/utils/supertokens.ts @@ -10,7 +10,7 @@ import { refreshSession } from "supertokens-node/recipe/session"; const logger = new Logger('Middleware'); -const verifySuperTokensSession = async (request: Request, response?: ServerFnResponseType) => { +export const verifySuperTokensSession = async (request: Request, response?: ServerFnResponseType) => { const session = await getSessionForStart(request, { sessionRequired: false }); if (session?.needsRefresh && response) { @@ -44,9 +44,10 @@ const verifySuperTokensSession = async (request: Request, response?: ServerFnRes export const superTokensRequestMiddleware = createMiddleware({ type: 'request' }) .server(async ({ next, request }) => { const session = await verifySuperTokensSession(request); - + if (!session.context.userAuthId) { logger.error('Unauthenticated user in API call.', session.context) + throw new Error("Unauthenticated"); } const context = { @@ -65,6 +66,7 @@ export const superTokensFunctionMiddleware = createMiddleware({ type: 'function' if (!session.context.userAuthId) { logger.error('Unauthenticated user in server function.', session.context) + throw new Error("Unauthenticated"); } const context = {