Compare commits
2 Commits
d2e4f0ca3f
...
07388e30da
| Author | SHA1 | Date | |
|---|---|---|---|
| 07388e30da | |||
| b7d14be590 |
@@ -11,6 +11,7 @@
|
|||||||
import { createServerRootRoute } from '@tanstack/react-start/server'
|
import { createServerRootRoute } from '@tanstack/react-start/server'
|
||||||
|
|
||||||
import { Route as rootRouteImport } from './routes/__root'
|
import { Route as rootRouteImport } from './routes/__root'
|
||||||
|
import { Route as RefreshSessionRouteImport } from './routes/refresh-session'
|
||||||
import { Route as LogoutRouteImport } from './routes/logout'
|
import { Route as LogoutRouteImport } from './routes/logout'
|
||||||
import { Route as LoginRouteImport } from './routes/login'
|
import { Route as LoginRouteImport } from './routes/login'
|
||||||
import { Route as AuthedRouteImport } from './routes/_authed'
|
import { Route as AuthedRouteImport } from './routes/_authed'
|
||||||
@@ -33,6 +34,11 @@ import { ServerRoute as ApiFilesCollectionRecordIdFileServerRouteImport } from '
|
|||||||
|
|
||||||
const rootServerRouteImport = createServerRootRoute()
|
const rootServerRouteImport = createServerRootRoute()
|
||||||
|
|
||||||
|
const RefreshSessionRoute = RefreshSessionRouteImport.update({
|
||||||
|
id: '/refresh-session',
|
||||||
|
path: '/refresh-session',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
const LogoutRoute = LogoutRouteImport.update({
|
const LogoutRoute = LogoutRouteImport.update({
|
||||||
id: '/logout',
|
id: '/logout',
|
||||||
path: '/logout',
|
path: '/logout',
|
||||||
@@ -137,6 +143,7 @@ const ApiFilesCollectionRecordIdFileServerRoute =
|
|||||||
export interface FileRoutesByFullPath {
|
export interface FileRoutesByFullPath {
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/logout': typeof LogoutRoute
|
'/logout': typeof LogoutRoute
|
||||||
|
'/refresh-session': typeof RefreshSessionRoute
|
||||||
'/admin': typeof AuthedAdminRouteWithChildren
|
'/admin': typeof AuthedAdminRouteWithChildren
|
||||||
'/settings': typeof AuthedSettingsRoute
|
'/settings': typeof AuthedSettingsRoute
|
||||||
'/': typeof AuthedIndexRoute
|
'/': typeof AuthedIndexRoute
|
||||||
@@ -153,6 +160,7 @@ export interface FileRoutesByFullPath {
|
|||||||
export interface FileRoutesByTo {
|
export interface FileRoutesByTo {
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/logout': typeof LogoutRoute
|
'/logout': typeof LogoutRoute
|
||||||
|
'/refresh-session': typeof RefreshSessionRoute
|
||||||
'/settings': typeof AuthedSettingsRoute
|
'/settings': typeof AuthedSettingsRoute
|
||||||
'/': typeof AuthedIndexRoute
|
'/': typeof AuthedIndexRoute
|
||||||
'/admin/preview': typeof AuthedAdminPreviewRoute
|
'/admin/preview': typeof AuthedAdminPreviewRoute
|
||||||
@@ -170,6 +178,7 @@ export interface FileRoutesById {
|
|||||||
'/_authed': typeof AuthedRouteWithChildren
|
'/_authed': typeof AuthedRouteWithChildren
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/logout': typeof LogoutRoute
|
'/logout': typeof LogoutRoute
|
||||||
|
'/refresh-session': typeof RefreshSessionRoute
|
||||||
'/_authed/admin': typeof AuthedAdminRouteWithChildren
|
'/_authed/admin': typeof AuthedAdminRouteWithChildren
|
||||||
'/_authed/settings': typeof AuthedSettingsRoute
|
'/_authed/settings': typeof AuthedSettingsRoute
|
||||||
'/_authed/': typeof AuthedIndexRoute
|
'/_authed/': typeof AuthedIndexRoute
|
||||||
@@ -188,6 +197,7 @@ export interface FileRouteTypes {
|
|||||||
fullPaths:
|
fullPaths:
|
||||||
| '/login'
|
| '/login'
|
||||||
| '/logout'
|
| '/logout'
|
||||||
|
| '/refresh-session'
|
||||||
| '/admin'
|
| '/admin'
|
||||||
| '/settings'
|
| '/settings'
|
||||||
| '/'
|
| '/'
|
||||||
@@ -204,6 +214,7 @@ export interface FileRouteTypes {
|
|||||||
to:
|
to:
|
||||||
| '/login'
|
| '/login'
|
||||||
| '/logout'
|
| '/logout'
|
||||||
|
| '/refresh-session'
|
||||||
| '/settings'
|
| '/settings'
|
||||||
| '/'
|
| '/'
|
||||||
| '/admin/preview'
|
| '/admin/preview'
|
||||||
@@ -220,6 +231,7 @@ export interface FileRouteTypes {
|
|||||||
| '/_authed'
|
| '/_authed'
|
||||||
| '/login'
|
| '/login'
|
||||||
| '/logout'
|
| '/logout'
|
||||||
|
| '/refresh-session'
|
||||||
| '/_authed/admin'
|
| '/_authed/admin'
|
||||||
| '/_authed/settings'
|
| '/_authed/settings'
|
||||||
| '/_authed/'
|
| '/_authed/'
|
||||||
@@ -238,6 +250,7 @@ export interface RootRouteChildren {
|
|||||||
AuthedRoute: typeof AuthedRouteWithChildren
|
AuthedRoute: typeof AuthedRouteWithChildren
|
||||||
LoginRoute: typeof LoginRoute
|
LoginRoute: typeof LoginRoute
|
||||||
LogoutRoute: typeof LogoutRoute
|
LogoutRoute: typeof LogoutRoute
|
||||||
|
RefreshSessionRoute: typeof RefreshSessionRoute
|
||||||
}
|
}
|
||||||
export interface FileServerRoutesByFullPath {
|
export interface FileServerRoutesByFullPath {
|
||||||
'/api/auth/$': typeof ApiAuthSplatServerRoute
|
'/api/auth/$': typeof ApiAuthSplatServerRoute
|
||||||
@@ -288,6 +301,13 @@ export interface RootServerRouteChildren {
|
|||||||
|
|
||||||
declare module '@tanstack/react-router' {
|
declare module '@tanstack/react-router' {
|
||||||
interface FileRoutesByPath {
|
interface FileRoutesByPath {
|
||||||
|
'/refresh-session': {
|
||||||
|
id: '/refresh-session'
|
||||||
|
path: '/refresh-session'
|
||||||
|
fullPath: '/refresh-session'
|
||||||
|
preLoaderRoute: typeof RefreshSessionRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
'/logout': {
|
'/logout': {
|
||||||
id: '/logout'
|
id: '/logout'
|
||||||
path: '/logout'
|
path: '/logout'
|
||||||
@@ -475,6 +495,7 @@ const rootRouteChildren: RootRouteChildren = {
|
|||||||
AuthedRoute: AuthedRouteWithChildren,
|
AuthedRoute: AuthedRouteWithChildren,
|
||||||
LoginRoute: LoginRoute,
|
LoginRoute: LoginRoute,
|
||||||
LogoutRoute: LogoutRoute,
|
LogoutRoute: LogoutRoute,
|
||||||
|
RefreshSessionRoute: RefreshSessionRoute,
|
||||||
}
|
}
|
||||||
export const routeTree = rootRouteImport
|
export const routeTree = rootRouteImport
|
||||||
._addFileChildren(rootRouteChildren)
|
._addFileChildren(rootRouteChildren)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { HeaderConfig } from "@/features/core/types/header-config";
|
|||||||
import { playerQueries } from "@/features/players/queries";
|
import { playerQueries } from "@/features/players/queries";
|
||||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||||
import { ensureServerQueryData } from "@/lib/tanstack-query/utils/ensure";
|
import { ensureServerQueryData } from "@/lib/tanstack-query/utils/ensure";
|
||||||
|
import FullScreenLoader from "@/components/full-screen-loader";
|
||||||
|
|
||||||
export const Route = createRootRouteWithContext<{
|
export const Route = createRootRouteWithContext<{
|
||||||
queryClient: QueryClient;
|
queryClient: QueryClient;
|
||||||
@@ -70,7 +71,12 @@ export const Route = createRootRouteWithContext<{
|
|||||||
},
|
},
|
||||||
component: RootComponent,
|
component: RootComponent,
|
||||||
notFoundComponent: () => <Navigate to="/" />,
|
notFoundComponent: () => <Navigate to="/" />,
|
||||||
beforeLoad: async ({ context }) => {
|
beforeLoad: async ({ context, location }) => {
|
||||||
|
// Skip auth check for refresh-session route to avoid infinite loops
|
||||||
|
if (location.pathname === '/refresh-session') {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
// https://github.com/TanStack/router/discussions/3531
|
// https://github.com/TanStack/router/discussions/3531
|
||||||
const auth = await ensureServerQueryData(
|
const auth = await ensureServerQueryData(
|
||||||
context.queryClient,
|
context.queryClient,
|
||||||
@@ -78,7 +84,7 @@ export const Route = createRootRouteWithContext<{
|
|||||||
);
|
);
|
||||||
return { auth };
|
return { auth };
|
||||||
},
|
},
|
||||||
pendingComponent: () => <p>Loading...</p>,
|
pendingComponent: () => <Providers><FullScreenLoader /></Providers>,
|
||||||
});
|
});
|
||||||
|
|
||||||
function RootComponent() {
|
function RootComponent() {
|
||||||
|
|||||||
39
src/app/routes/refresh-session.tsx
Normal file
39
src/app/routes/refresh-session.tsx
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import { createFileRoute } from '@tanstack/react-router'
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
import FullScreenLoader from '@/components/full-screen-loader'
|
||||||
|
import { attemptRefreshingSession } from 'supertokens-web-js/recipe/session'
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/refresh-session')({
|
||||||
|
component: RouteComponent,
|
||||||
|
})
|
||||||
|
|
||||||
|
// https://supertokens.com/docs/additional-verification/session-verification/ssr?uiType=custom
|
||||||
|
function RouteComponent() {
|
||||||
|
useEffect(() => {
|
||||||
|
const handleRefresh = async () => {
|
||||||
|
try {
|
||||||
|
const refreshed = await attemptRefreshingSession()
|
||||||
|
|
||||||
|
if (refreshed) {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
|
const redirect = urlParams.get('redirect')
|
||||||
|
|
||||||
|
if (redirect) {
|
||||||
|
window.location.href = decodeURIComponent(redirect)
|
||||||
|
} else {
|
||||||
|
window.location.href = '/'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
window.location.href = '/login'
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
window.location.href = '/login'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeout = setTimeout(handleRefresh, 100)
|
||||||
|
return () => clearTimeout(timeout)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return <FullScreenLoader />
|
||||||
|
}
|
||||||
13
src/components/full-screen-loader.tsx
Normal file
13
src/components/full-screen-loader.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { Center, Container, Loader, Stack } from "@mantine/core";
|
||||||
|
|
||||||
|
const FullScreenLoader = () => (
|
||||||
|
<Container h="100dvh" w="100dvw">
|
||||||
|
<Center h="100%">
|
||||||
|
<Stack align="center" gap="md">
|
||||||
|
<Loader size="xl" />
|
||||||
|
</Stack>
|
||||||
|
</Center>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default FullScreenLoader;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Flex, Box, Text } from "@mantine/core";
|
import { Flex, Box, Text } from "@mantine/core";
|
||||||
import { Link, useRouterState } from "@tanstack/react-router";
|
import { Link, useRouterState } from "@tanstack/react-router";
|
||||||
import styles from './styles.module.css';
|
import styles from "./styles.module.css";
|
||||||
import { Icon } from "@phosphor-icons/react";
|
import { Icon } from "@phosphor-icons/react";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
|
|
||||||
@@ -9,21 +9,55 @@ interface NavLinkProps {
|
|||||||
label: string;
|
label: string;
|
||||||
Icon: Icon;
|
Icon: Icon;
|
||||||
include?: string[];
|
include?: string[];
|
||||||
|
exclude?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NavLink = ({ href, label, Icon, include }: NavLinkProps) => {
|
export const NavLink = ({
|
||||||
|
href,
|
||||||
|
label,
|
||||||
|
Icon,
|
||||||
|
include,
|
||||||
|
exclude,
|
||||||
|
}: NavLinkProps) => {
|
||||||
const router = useRouterState();
|
const router = useRouterState();
|
||||||
const isActive = useMemo(() => (router.location.pathname === href || (router.location.pathname.includes(href) && href !== '/')) || include?.includes(router.location.pathname), [router.location.pathname, href]);
|
const isActive = useMemo(
|
||||||
|
() =>
|
||||||
|
(!exclude?.some((e) => router.location.pathname.includes(e)) &&
|
||||||
|
(router.location.pathname === href ||
|
||||||
|
(router.location.pathname.includes(href) && href !== "/"))) ||
|
||||||
|
include?.includes(router.location.pathname),
|
||||||
|
[router.location.pathname, href]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box component={Link} to={href}
|
<Box
|
||||||
|
component={Link}
|
||||||
|
to={href}
|
||||||
className={styles.navLinkBox}
|
className={styles.navLinkBox}
|
||||||
p={{ base: 0, sm: 8 }}
|
p={{ base: 0, sm: 8 }}
|
||||||
>
|
>
|
||||||
<Flex direction={{ base: 'column', md: 'row' }} align='center' gap={{ base: 0, md: 'xs' }}>
|
<Flex
|
||||||
<Icon weight={isActive ? 'fill' : 'regular'} size={28} style={{ color: isActive ? 'var(--mantine-primary-color-filled)' : undefined }} />
|
direction={{ base: "column", md: "row" }}
|
||||||
<Text visibleFrom='md' ta='center' size='md' fw={isActive ? 800 : 500} c={isActive ? 'var(--mantine-primary-color-filled)' : undefined}>{label}</Text>
|
align="center"
|
||||||
|
gap={{ base: 0, md: "xs" }}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
weight={isActive ? "fill" : "regular"}
|
||||||
|
size={28}
|
||||||
|
style={{
|
||||||
|
color: isActive ? "var(--mantine-primary-color-filled)" : undefined,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Text
|
||||||
|
visibleFrom="md"
|
||||||
|
ta="center"
|
||||||
|
size="md"
|
||||||
|
fw={isActive ? 800 : 500}
|
||||||
|
c={isActive ? "var(--mantine-primary-color-filled)" : undefined}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ export const useLinks = (userId: string | undefined, roles: string[]) =>
|
|||||||
{
|
{
|
||||||
label: 'Tournaments',
|
label: 'Tournaments',
|
||||||
href: '/tournaments',
|
href: '/tournaments',
|
||||||
Icon: TrophyIcon
|
Icon: TrophyIcon,
|
||||||
|
exclude: ['/admin/tournaments']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Profile',
|
label: 'Profile',
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { setUserMetadata, superTokensFunctionMiddleware, verifySuperTokensSession } from "@/utils/supertokens";
|
import { setUserMetadata, superTokensFunctionMiddleware, getSessionContext } from "@/utils/supertokens";
|
||||||
import { createServerFn } from "@tanstack/react-start";
|
import { createServerFn } from "@tanstack/react-start";
|
||||||
import { Player, playerInputSchema, playerUpdateSchema } from "@/features/players/types";
|
import { Player, playerInputSchema, playerUpdateSchema } from "@/features/players/types";
|
||||||
import { pbAdmin } from "@/lib/pocketbase/client";
|
import { pbAdmin } from "@/lib/pocketbase/client";
|
||||||
@@ -8,20 +8,25 @@ import { getWebRequest } from "@tanstack/react-start/server";
|
|||||||
import { toServerResult } from "@/lib/tanstack-query/utils/to-server-result";
|
import { toServerResult } from "@/lib/tanstack-query/utils/to-server-result";
|
||||||
|
|
||||||
export const fetchMe = createServerFn()
|
export const fetchMe = createServerFn()
|
||||||
.handler(async ({ response }) =>
|
.handler(async () =>
|
||||||
toServerResult(async () => {
|
toServerResult(async () => {
|
||||||
const request = getWebRequest();
|
const request = getWebRequest();
|
||||||
const { context } = await verifySuperTokensSession(request, response);
|
|
||||||
|
try {
|
||||||
if (!context || !context.userAuthId) return { user: undefined, roles: [], metadata: {} };
|
const context = await getSessionContext(request);
|
||||||
|
|
||||||
await pbAdmin.authPromise;
|
await pbAdmin.authPromise;
|
||||||
const result = await pbAdmin.getPlayerByAuthId(context.userAuthId);
|
const result = await pbAdmin.getPlayerByAuthId(context.userAuthId);
|
||||||
return {
|
return {
|
||||||
user: result || undefined,
|
user: result || undefined,
|
||||||
roles: context.roles,
|
roles: context.roles,
|
||||||
metadata: context.metadata
|
metadata: context.metadata
|
||||||
};
|
};
|
||||||
|
} catch (error: any) {
|
||||||
|
// If getSessionContext throws (unauthenticated or redirect), return empty state
|
||||||
|
logger.info('fetchMe: No authenticated user or redirect needed');
|
||||||
|
return { user: undefined, roles: [], metadata: {} };
|
||||||
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,7 @@ export async function getSessionForStart(request: Request, options?: { sessionRe
|
|||||||
ensureSuperTokensBackend();
|
ensureSuperTokensBackend();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");
|
|
||||||
console.log("Getting session for request:", request);
|
|
||||||
const session = await getSessionForSSR(request);
|
const session = await getSessionForSSR(request);
|
||||||
console.log("Session from getSessionForSSR:", session);
|
|
||||||
console.log("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");
|
|
||||||
|
|
||||||
if (session.hasToken) {
|
if (session.hasToken) {
|
||||||
if (session.accessTokenPayload?.sub === undefined || session.accessTokenPayload?.sessionHandle === undefined) {
|
if (session.accessTokenPayload?.sub === undefined || session.accessTokenPayload?.sessionHandle === undefined) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
ServerFnResponseType,
|
ServerFnResponseType,
|
||||||
} from "@tanstack/react-start";
|
} from "@tanstack/react-start";
|
||||||
import { getWebRequest } from "@tanstack/react-start/server";
|
import { getWebRequest } from "@tanstack/react-start/server";
|
||||||
import { getSessionForSSR } from "supertokens-node/custom";
|
import { redirect as redirect } from "@tanstack/react-router";
|
||||||
import UserRoles from "supertokens-node/recipe/userroles";
|
import UserRoles from "supertokens-node/recipe/userroles";
|
||||||
import UserMetadata from "supertokens-node/recipe/usermetadata";
|
import UserMetadata from "supertokens-node/recipe/usermetadata";
|
||||||
import { getSessionForStart } from "@/lib/supertokens/recipes/start-session";
|
import { getSessionForStart } from "@/lib/supertokens/recipes/start-session";
|
||||||
@@ -21,9 +21,32 @@ export const verifySuperTokensSession = async (
|
|||||||
let session = await getSessionForStart(request, { sessionRequired: false });
|
let session = await getSessionForStart(request, { sessionRequired: false });
|
||||||
|
|
||||||
if (session?.needsRefresh) {
|
if (session?.needsRefresh) {
|
||||||
logger.info("Session refreshing...");
|
logger.info("Session needs refresh");
|
||||||
session = await getSessionForStart(request, { sessionRequired: false });
|
|
||||||
|
try {
|
||||||
|
// attempt refresh on backend
|
||||||
|
if (response) {
|
||||||
|
const refreshedSession = await refreshSession(request, response);
|
||||||
|
if (refreshedSession) {
|
||||||
|
session = await getSessionForStart(request, { sessionRequired: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session?.needsRefresh) {
|
||||||
|
// tryRefresh on frontend
|
||||||
|
return { context: { session: { tryRefresh: true } } };
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
logger.error("Session refresh error", error);
|
||||||
|
|
||||||
|
if (error.type === 'UNAUTHORISED' || error.type === 'TOKEN_THEFT_DETECTED') {
|
||||||
|
return { context: { userAuthId: null, roles: [] } };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { context: { session: { tryRefresh: true } } };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const userAuthId = session?.userId;
|
const userAuthId = session?.userId;
|
||||||
|
|
||||||
if (!userAuthId || !session) {
|
if (!userAuthId || !session) {
|
||||||
@@ -47,13 +70,20 @@ export const verifySuperTokensSession = async (
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const superTokensRequestMiddleware = createMiddleware({
|
export const getSessionContext = async (request: Request): Promise<any> => {
|
||||||
type: "request",
|
|
||||||
}).server(async ({ next, request }) => {
|
|
||||||
const session = await verifySuperTokensSession(request);
|
const session = await verifySuperTokensSession(request);
|
||||||
|
|
||||||
|
if (session.context.session?.tryRefresh) {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
const from = encodeURIComponent(url.pathname + url.search);
|
||||||
|
throw redirect({
|
||||||
|
to: "/refresh-session",
|
||||||
|
search: { redirect: from }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (!session.context.userAuthId) {
|
if (!session.context.userAuthId) {
|
||||||
logger.error("Unauthenticated user in API call.", session.context);
|
logger.error("Unauthenticated user", session.context);
|
||||||
throw new Error("Unauthenticated");
|
throw new Error("Unauthenticated");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,6 +93,13 @@ export const superTokensRequestMiddleware = createMiddleware({
|
|||||||
metadata: session.context.metadata,
|
metadata: session.context.metadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const superTokensRequestMiddleware = createMiddleware({
|
||||||
|
type: "request",
|
||||||
|
}).server(async ({ next, request }) => {
|
||||||
|
const context = await getSessionContext(request);
|
||||||
return next({ context });
|
return next({ context });
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -70,37 +107,15 @@ export const superTokensFunctionMiddleware = createMiddleware({
|
|||||||
type: "function",
|
type: "function",
|
||||||
}).server(async ({ next, response }) => {
|
}).server(async ({ next, response }) => {
|
||||||
const request = getWebRequest();
|
const request = getWebRequest();
|
||||||
const session = await verifySuperTokensSession(request, response);
|
const context = await getSessionContext(request);
|
||||||
|
|
||||||
if (!session.context.userAuthId) {
|
|
||||||
logger.error("Unauthenticated user in server function.", session.context);
|
|
||||||
throw new Error("Unauthenticated");
|
|
||||||
}
|
|
||||||
|
|
||||||
const context = {
|
|
||||||
userAuthId: session.context.userAuthId,
|
|
||||||
roles: session.context.roles,
|
|
||||||
metadata: session.context.metadata,
|
|
||||||
};
|
|
||||||
return next({ context });
|
return next({ context });
|
||||||
});
|
});
|
||||||
|
|
||||||
export const superTokensAdminFunctionMiddleware = createMiddleware({
|
export const superTokensAdminFunctionMiddleware = createMiddleware({
|
||||||
type: "function",
|
type: "function",
|
||||||
}).server(async ({ next, response }) => {
|
}).server(async ({ next }) => {
|
||||||
const request = getWebRequest();
|
const request = getWebRequest();
|
||||||
const session = await verifySuperTokensSession(request, response);
|
const context = await getSessionContext(request);
|
||||||
|
|
||||||
if (!session.context.userAuthId) {
|
|
||||||
logger.error("Unauthenticated user in admin function.", session.context);
|
|
||||||
throw new Error("Unauthenticated");
|
|
||||||
}
|
|
||||||
|
|
||||||
const context = {
|
|
||||||
userAuthId: session.context.userAuthId,
|
|
||||||
roles: session.context.roles,
|
|
||||||
metadata: session.context.metadata,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (context.roles?.includes("Admin")) {
|
if (context.roles?.includes("Admin")) {
|
||||||
return next({ context });
|
return next({ context });
|
||||||
|
|||||||
Reference in New Issue
Block a user