mirror of
https://github.com/documenso/documenso.git
synced 2025-11-13 00:03:33 +10:00
110 lines
2.9 KiB
TypeScript
110 lines
2.9 KiB
TypeScript
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 {
|
|
type RequestMetadata,
|
|
extractRequestMetadata,
|
|
} from '@documenso/lib/universal/extract-request-metadata';
|
|
import { AppLogger } from '@documenso/lib/utils/debugger';
|
|
|
|
const logger = new AppLogger('Middleware');
|
|
|
|
export type AppContext = {
|
|
requestMetadata: RequestMetadata;
|
|
session: AppSession | null;
|
|
};
|
|
|
|
export const appContext = async (c: Context, next: Next) => {
|
|
const initTime = Date.now();
|
|
|
|
const request = c.req.raw;
|
|
const url = new URL(request.url);
|
|
|
|
const noSessionCookie = extractSessionCookieFromHeaders(request.headers) === null;
|
|
|
|
if (!isPageRequest(request) || noSessionCookie || blacklistedPathsRegex.test(url.pathname)) {
|
|
// logger.log('Pathname ignored', url.pathname);
|
|
|
|
setAppContext(c, {
|
|
requestMetadata: extractRequestMetadata(request),
|
|
session: null,
|
|
});
|
|
|
|
return next();
|
|
}
|
|
|
|
const splitUrl = url.pathname.replace('.data', '').split('/');
|
|
|
|
let team: TGetTeamByUrlResponse | null = null;
|
|
let teams: TGetTeamsResponse = [];
|
|
|
|
const session = await getSession(c);
|
|
|
|
if (session.isAuthenticated) {
|
|
let teamUrl = null;
|
|
|
|
if (splitUrl[1] === 't' && splitUrl[2]) {
|
|
teamUrl = splitUrl[2];
|
|
}
|
|
|
|
const result = await Promise.all([
|
|
getTeams({ userId: session.user.id }),
|
|
teamUrl ? getTeamByUrl({ userId: session.user.id, teamUrl }).catch(() => null) : null,
|
|
]);
|
|
|
|
teams = result[0];
|
|
team = result[1];
|
|
}
|
|
|
|
const endTime = Date.now();
|
|
logger.log(`Pathname accepted in ${endTime - initTime}ms`, url.pathname);
|
|
|
|
setAppContext(c, {
|
|
requestMetadata: extractRequestMetadata(request),
|
|
session: session.isAuthenticated
|
|
? {
|
|
session: session.session,
|
|
user: session.user,
|
|
currentTeam: team,
|
|
teams,
|
|
}
|
|
: null,
|
|
});
|
|
|
|
return next();
|
|
};
|
|
|
|
const setAppContext = (c: Context, context: AppContext) => {
|
|
c.set('context', context);
|
|
};
|
|
|
|
const isPageRequest = (request: Request) => {
|
|
const url = new URL(request.url);
|
|
|
|
if (request.method !== 'GET') {
|
|
return false;
|
|
}
|
|
|
|
// If it ends with .data it's the loader which we need to pass context for.
|
|
if (url.pathname.endsWith('.data')) {
|
|
return true;
|
|
}
|
|
|
|
if (request.headers.get('Accept')?.includes('text/html')) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* List of paths to reject
|
|
* - Urls that start with /api
|
|
* - Urls that start with _
|
|
*/
|
|
const blacklistedPathsRegex = new RegExp('^/api/|^/__');
|