significant refactor
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
import { createMiddleware, createServerFn, ServerFnResponseType } from "@tanstack/react-start";
|
||||
import {
|
||||
createMiddleware,
|
||||
createServerFn,
|
||||
ServerFnResponseType,
|
||||
} from "@tanstack/react-start";
|
||||
import { getWebRequest } from "@tanstack/react-start/server";
|
||||
import { getSessionForSSR } from "supertokens-node/custom";
|
||||
import UserRoles from "supertokens-node/recipe/userroles";
|
||||
@@ -8,110 +12,134 @@ import { Logger } from "@/lib/logger";
|
||||
import z from "zod";
|
||||
import { refreshSession } from "supertokens-node/recipe/session";
|
||||
|
||||
const logger = new Logger('Middleware');
|
||||
const logger = new Logger("Middleware");
|
||||
|
||||
export const verifySuperTokensSession = async (request: Request, response?: ServerFnResponseType) => {
|
||||
const session = await getSessionForStart(request, { sessionRequired: false });
|
||||
|
||||
if (session?.needsRefresh && response) {
|
||||
logger.info("Session refreshing...");
|
||||
refreshSession(request, response);
|
||||
return { context: { needsRefresh: true } };
|
||||
}
|
||||
const userAuthId = session?.userId;
|
||||
|
||||
if (!userAuthId) {
|
||||
logger.info("No authenticated user");
|
||||
return { context: { userAuthId: null, roles: [] } };
|
||||
}
|
||||
|
||||
const { roles } = await fetchUserRoles(userAuthId);
|
||||
const { metadata } = await UserMetadata.getUserMetadata(userAuthId);
|
||||
|
||||
return {
|
||||
context: {
|
||||
userAuthId,
|
||||
roles,
|
||||
metadata,
|
||||
session: {
|
||||
accessTokenPayload: session.accessTokenPayload,
|
||||
sessionHandle: session.sessionHandle,
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
export const verifySuperTokensSession = async (
|
||||
request: Request,
|
||||
response?: ServerFnResponseType
|
||||
) => {
|
||||
let session = await getSessionForStart(request, { sessionRequired: false });
|
||||
|
||||
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");
|
||||
}
|
||||
if (session?.needsRefresh) {
|
||||
logger.info("Session refreshing...");
|
||||
await refreshSession(request, response);
|
||||
session = await getSessionForStart(request, { sessionRequired: false });
|
||||
}
|
||||
const userAuthId = session?.userId;
|
||||
|
||||
const context = {
|
||||
userAuthId: session.context.userAuthId,
|
||||
roles: session.context.roles,
|
||||
metadata: session.context.metadata
|
||||
}
|
||||
if (!userAuthId || !session) {
|
||||
logger.info("No authenticated user");
|
||||
return { context: { userAuthId: null, roles: [] } };
|
||||
}
|
||||
|
||||
return next({ context })
|
||||
});
|
||||
const { roles } = await fetchUserRoles(userAuthId);
|
||||
const { metadata } = await UserMetadata.getUserMetadata(userAuthId);
|
||||
|
||||
export const superTokensFunctionMiddleware = createMiddleware({ type: 'function' })
|
||||
.server(async ({ next, response }) => {
|
||||
const request = getWebRequest();
|
||||
const session = await verifySuperTokensSession(request, response);
|
||||
return {
|
||||
context: {
|
||||
userAuthId,
|
||||
roles,
|
||||
metadata,
|
||||
session: {
|
||||
accessTokenPayload: session.accessTokenPayload,
|
||||
sessionHandle: session.sessionHandle,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
if (!session.context.userAuthId) {
|
||||
logger.error('Unauthenticated user in server function.', session.context)
|
||||
throw new Error("Unauthenticated");
|
||||
}
|
||||
export const superTokensRequestMiddleware = createMiddleware({
|
||||
type: "request",
|
||||
}).server(async ({ next, request }) => {
|
||||
const session = await verifySuperTokensSession(request);
|
||||
|
||||
const context = {
|
||||
userAuthId: session.context.userAuthId,
|
||||
roles: session.context.roles,
|
||||
metadata: session.context.metadata
|
||||
}
|
||||
if (!session.context.userAuthId) {
|
||||
logger.error("Unauthenticated user in API call.", session.context);
|
||||
throw new Error("Unauthenticated");
|
||||
}
|
||||
|
||||
const context = {
|
||||
userAuthId: session.context.userAuthId,
|
||||
roles: session.context.roles,
|
||||
metadata: session.context.metadata,
|
||||
};
|
||||
|
||||
return next({ context });
|
||||
});
|
||||
|
||||
export const superTokensFunctionMiddleware = createMiddleware({
|
||||
type: "function",
|
||||
}).server(async ({ next, response }) => {
|
||||
const request = getWebRequest();
|
||||
const session = await verifySuperTokensSession(request, response);
|
||||
|
||||
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 });
|
||||
});
|
||||
|
||||
export const superTokensAdminFunctionMiddleware = createMiddleware({
|
||||
type: "function",
|
||||
}).server(async ({ next, response }) => {
|
||||
const request = getWebRequest();
|
||||
const session = await verifySuperTokensSession(request, response);
|
||||
|
||||
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")) {
|
||||
return next({ context });
|
||||
})
|
||||
}
|
||||
|
||||
export const superTokensAdminFunctionMiddleware = createMiddleware({ type: 'function' })
|
||||
.server(async ({ next, response }) => {
|
||||
const request = getWebRequest();
|
||||
const session = await verifySuperTokensSession(request, response);
|
||||
|
||||
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')) {
|
||||
return next(({ context }));
|
||||
}
|
||||
|
||||
logger.error('Unauthorized user in admin function.', context);
|
||||
throw new Error('Unauthorized');
|
||||
})
|
||||
logger.error("Unauthorized user in admin function.", context);
|
||||
throw new Error("Unauthorized");
|
||||
});
|
||||
|
||||
export const fetchUserRoles = async (userAuthId: string) => {
|
||||
const response = await UserRoles.getRolesForUser("public", userAuthId);
|
||||
return response;
|
||||
}
|
||||
};
|
||||
|
||||
export const setUserMetadata = createServerFn({ method: 'POST' })
|
||||
.validator(z.object({
|
||||
first_name: z.string().min(3).max(20).regex(/^[a-zA-Z0-9\s]+$/, "First name must be 3-20 characters long and contain only letters and spaces"),
|
||||
last_name: z.string().min(3).max(20).regex(/^[a-zA-Z0-9\s]+$/, "Last name must be 3-20 characters long and contain only letters and spaces"),
|
||||
player_id: z.string(),
|
||||
}).partial())
|
||||
export const setUserMetadata = createServerFn({ method: "POST" })
|
||||
.validator(
|
||||
z
|
||||
.object({
|
||||
first_name: z
|
||||
.string()
|
||||
.min(2)
|
||||
.max(20)
|
||||
.regex(
|
||||
/^[a-zA-Z0-9\s]+$/,
|
||||
"First name must be 2-20 characters long and contain only letters and spaces"
|
||||
),
|
||||
last_name: z
|
||||
.string()
|
||||
.min(2)
|
||||
.max(20)
|
||||
.regex(
|
||||
/^[a-zA-Z0-9\s]+$/,
|
||||
"Last name must be 2-20 characters long and contain only letters and spaces"
|
||||
),
|
||||
player_id: z.string(),
|
||||
})
|
||||
.partial()
|
||||
)
|
||||
.middleware([superTokensFunctionMiddleware])
|
||||
.handler(async ({ context, data }) => {
|
||||
const { userAuthId, metadata } = context;
|
||||
@@ -120,18 +148,18 @@ export const setUserMetadata = createServerFn({ method: 'POST' })
|
||||
await UserMetadata.updateUserMetadata(userAuthId, {
|
||||
first_name: data.first_name,
|
||||
last_name: data.last_name,
|
||||
player_id: data.player_id
|
||||
player_id: data.player_id,
|
||||
});
|
||||
|
||||
return {
|
||||
metadata: {
|
||||
...metadata,
|
||||
...data
|
||||
}
|
||||
...data,
|
||||
},
|
||||
};
|
||||
})
|
||||
});
|
||||
|
||||
export const updateUserColorScheme = createServerFn({ method: 'POST' })
|
||||
export const updateUserColorScheme = createServerFn({ method: "POST" })
|
||||
.validator((data: string) => data)
|
||||
.middleware([superTokensFunctionMiddleware])
|
||||
.handler(async ({ context, data }) => {
|
||||
@@ -139,18 +167,18 @@ export const updateUserColorScheme = createServerFn({ method: 'POST' })
|
||||
if (!userAuthId) return;
|
||||
|
||||
await UserMetadata.updateUserMetadata(userAuthId, {
|
||||
colorScheme: data
|
||||
colorScheme: data,
|
||||
});
|
||||
|
||||
return {
|
||||
metadata: {
|
||||
...metadata,
|
||||
colorScheme: data
|
||||
}
|
||||
colorScheme: data,
|
||||
},
|
||||
};
|
||||
})
|
||||
});
|
||||
|
||||
export const updateUserAccentColor = createServerFn({ method: 'POST' })
|
||||
export const updateUserAccentColor = createServerFn({ method: "POST" })
|
||||
.validator((data: string) => data)
|
||||
.middleware([superTokensFunctionMiddleware])
|
||||
.handler(async ({ context, data }) => {
|
||||
@@ -158,13 +186,13 @@ export const updateUserAccentColor = createServerFn({ method: 'POST' })
|
||||
if (!userAuthId) return;
|
||||
|
||||
await UserMetadata.updateUserMetadata(userAuthId, {
|
||||
accentColor: data
|
||||
accentColor: data,
|
||||
});
|
||||
|
||||
return {
|
||||
metadata: {
|
||||
...metadata,
|
||||
accentColor: data
|
||||
}
|
||||
accentColor: data,
|
||||
},
|
||||
};
|
||||
})
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user