This commit is contained in:
David Nguyen
2025-02-07 00:58:50 +11:00
parent e5cc6455dd
commit 8373af3f41
34 changed files with 193 additions and 143 deletions

View File

@ -1,24 +1,27 @@
import type { Context, Next } from 'hono';
import { extractSessionCookieFromHeaders } from '@documenso/auth/server/lib/session/session-cookies';
import { getSession } from '@documenso/auth/server/lib/utils/get-session';
import type { AppSession } from '@documenso/lib/client-only/providers/session';
import { type TGetTeamByUrlResponse, getTeamByUrl } from '@documenso/lib/server-only/team/get-team';
import { type TGetTeamsResponse, getTeams } from '@documenso/lib/server-only/team/get-teams';
import { extractRequestMetadata } from '@documenso/lib/universal/extract-request-metadata';
import {
type RequestMetadata,
extractRequestMetadata,
} from '@documenso/lib/universal/extract-request-metadata';
import { AppLogger } from '@documenso/lib/utils/debugger';
type GetLoadContextArgs = {
request: Request;
const logger = new AppLogger('Middleware');
export type AppContext = {
requestMetadata: RequestMetadata;
session: AppSession | null;
};
declare module 'react-router' {
interface AppLoadContext extends Awaited<ReturnType<typeof getLoadContext>> {}
}
const logger = new AppLogger('Context');
export async function getLoadContext(args: GetLoadContextArgs) {
export const appContext = async (c: Context, next: Next) => {
const initTime = Date.now();
const request = args.request;
const request = c.req.raw;
const url = new URL(request.url);
const noSessionCookie = extractSessionCookieFromHeaders(request.headers) === null;
@ -26,10 +29,12 @@ export async function getLoadContext(args: GetLoadContextArgs) {
if (!isPageRequest(request) || noSessionCookie || blacklistedPathsRegex.test(url.pathname)) {
logger.log('Pathname ignored', url.pathname);
return {
setAppContext(c, {
requestMetadata: extractRequestMetadata(request),
session: null,
};
});
return next();
}
const splitUrl = url.pathname.replace('.data', '').split('/');
@ -37,7 +42,7 @@ export async function getLoadContext(args: GetLoadContextArgs) {
let team: TGetTeamByUrlResponse | null = null;
let teams: TGetTeamsResponse = [];
const session = await getSession(args.request);
const session = await getSession(c);
if (session.isAuthenticated) {
let teamUrl = null;
@ -58,7 +63,7 @@ export async function getLoadContext(args: GetLoadContextArgs) {
const endTime = Date.now();
logger.log(`Pathname accepted in ${endTime - initTime}ms`, url.pathname);
return {
setAppContext(c, {
requestMetadata: extractRequestMetadata(request),
session: session.isAuthenticated
? {
@ -68,8 +73,14 @@ export async function getLoadContext(args: GetLoadContextArgs) {
teams,
}
: null,
};
}
});
return next();
};
const setAppContext = (c: Context, context: AppContext) => {
c.set('context', context);
};
const isPageRequest = (request: Request) => {
const url = new URL(request.url);

View File

@ -1,4 +1,5 @@
import { Hono } from 'hono';
import { contextStorage } from 'hono/context-storage';
import { PDFDocument } from 'pdf-lib';
import { tsRestHonoApp } from '@documenso/api/hono';
@ -11,10 +12,21 @@ import { putFile } from '@documenso/lib/universal/upload/put-file';
import { getPresignGetUrl } from '@documenso/lib/universal/upload/server-actions';
import { openApiDocument } from '@documenso/trpc/server/open-api';
import { type AppContext, appContext } from './context';
import { openApiTrpcServerHandler } from './trpc/hono-trpc-open-api';
import { reactRouterTrpcServer } from './trpc/hono-trpc-remix';
const app = new Hono();
export interface HonoEnv {
Variables: {
context: AppContext;
};
}
const app = new Hono<HonoEnv>();
app.use(contextStorage());
app.use(appContext);
// App middleware.
// app.use('*', appMiddleware);

View File

@ -12,6 +12,7 @@ export const openApiTrpcServerHandler = async (c: Context) => {
endpoint: API_V2_BETA_URL,
router: appRouter,
// Todo: Test this, since it's not using the createContext params.
// Todo: Reduce calls since we fetch on most request? maybe
createContext: async () => createTrpcContext({ c, requestSource: 'apiV2' }),
req: c.req.raw,
onError: (opts) => handleTrpcRouterError(opts, 'apiV2'),

View File

@ -1,31 +1,43 @@
import type { AppLoadContext } from 'react-router';
import { getContext } from 'hono/context-storage';
import { redirect } from 'react-router';
import type { HonoEnv } from 'server';
import type { AppSession } from '@documenso/lib/client-only/providers/session';
/**
* Returns the session context or throws a redirect to signin if it is not present.
*/
export const getRequiredLoaderSession = (context: AppLoadContext) => {
if (!context.session) {
export const getLoaderSession = (): AppSession => {
const session = getOptionalLoaderSession();
if (!session) {
throw redirect('/signin'); // Todo: Maybe add a redirect cookie to come back?
}
return session;
};
export const getOptionalLoaderSession = (): AppSession | null => {
const { context } = getContext<HonoEnv>().var;
return context.session;
};
/**
* Returns the team session context or throws a redirect to signin if it is not present.
*/
export const getRequiredLoaderTeamSession = (context: AppLoadContext) => {
if (!context.session) {
export const getLoaderTeamSession = () => {
const session = getOptionalLoaderSession();
if (!session) {
throw redirect('/signin'); // Todo: Maybe add a redirect cookie to come back?
}
if (!context.session.currentTeam) {
if (!session.currentTeam) {
throw new Response(null, { status: 404 }); // Todo: Test that 404 page shows up.
}
return {
...context.session,
currentTeam: context.session.currentTeam,
...session,
currentTeam: session.currentTeam,
};
};