74 lines
2.6 KiB
TypeScript
74 lines
2.6 KiB
TypeScript
import { randomBytes } from 'node:crypto';
|
|
import { redirect } from '@sveltejs/kit';
|
|
import type { Handle } from '@sveltejs/kit/hooks';
|
|
import { deleteSession, getSessionUser, hasUsers, SESSION_COOKIE } from '#lib/server/auth.js';
|
|
import { startFeedScheduler } from '#lib/server/feeds.js';
|
|
|
|
const publicPaths = new Set([
|
|
'/',
|
|
'/healthz',
|
|
'/login',
|
|
'/setup',
|
|
'/einladung',
|
|
'/passwort-vergessen',
|
|
'/passwort-zuruecksetzen'
|
|
]);
|
|
|
|
export const handle: Handle = async ({ event, resolve }) => {
|
|
startFeedScheduler();
|
|
const presentationPath = event.url.pathname.startsWith('/heinzlive/');
|
|
const sharePath = event.url.pathname.startsWith('/freigabe/');
|
|
const shareMediaPath = /^\/freigabe\/[^/]+\/media\/[^/]+$/.test(event.url.pathname);
|
|
const apiPath = event.url.pathname.startsWith('/api/v1/');
|
|
const presentationTestPath = /^\/fundus\/[^/]+\/praesentation(?:\/|$)/.test(event.url.pathname);
|
|
const token = event.cookies.get(SESSION_COOKIE);
|
|
event.locals.user = getSessionUser(token);
|
|
if (token && !event.locals.user) deleteSession(event.cookies);
|
|
|
|
if (
|
|
!presentationPath &&
|
|
!sharePath &&
|
|
!publicPaths.has(event.url.pathname) &&
|
|
!apiPath &&
|
|
!event.locals.user
|
|
) {
|
|
redirect(303, hasUsers() ? '/login' : '/setup');
|
|
}
|
|
|
|
const sharePageNonce = sharePath && !shareMediaPath ? randomBytes(16).toString('base64') : null;
|
|
const response = await resolve(
|
|
event,
|
|
sharePageNonce
|
|
? {
|
|
transformPageChunk: ({ html }) =>
|
|
html.replaceAll('<script', `<script nonce="${sharePageNonce}"`)
|
|
}
|
|
: undefined
|
|
);
|
|
response.headers.set('Referrer-Policy', 'same-origin');
|
|
response.headers.set('X-Content-Type-Options', 'nosniff');
|
|
response.headers.set('X-Frame-Options', 'DENY');
|
|
if (presentationPath || presentationTestPath) {
|
|
response.headers.set('Cache-Control', 'no-store');
|
|
response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
|
|
response.headers.set(
|
|
'Content-Security-Policy',
|
|
"frame-src https://www.youtube-nocookie.com https://www.youtube.com https://www.tiktok.com; frame-ancestors 'none'"
|
|
);
|
|
}
|
|
if (sharePath) {
|
|
response.headers.set('Cache-Control', 'private, no-store');
|
|
response.headers.set('Referrer-Policy', 'same-origin');
|
|
if (!shareMediaPath) {
|
|
response.headers.set(
|
|
'Content-Security-Policy',
|
|
`default-src 'self'; script-src 'self' 'nonce-${sharePageNonce}'; style-src 'self' 'unsafe-inline'; img-src 'self'; frame-ancestors 'none'`
|
|
);
|
|
}
|
|
}
|
|
if (event.url.pathname === '/einladung' || event.url.pathname === '/passwort-zuruecksetzen') {
|
|
response.headers.set('Cache-Control', 'no-store');
|
|
}
|
|
return response;
|
|
};
|