This repository has been archived on 2026-02-06. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
serengo/src/hooks.server.ts
Zias van Nes 0754d62d0e fix:push notification UI, settings and API
Introduce NotificationManager, NotificationPrompt, NotificationSettings,
NotificationSettingsSheet and integrate into the profile panel. Add
server GET/POST endpoints for notification preferences. Add
lucide-svelte dependency and update CSP connect-src to allow
fcm.googleapis.com and android.googleapis.com
2025-11-08 14:27:21 +01:00

72 lines
2.3 KiB
TypeScript

import type { Handle } from '@sveltejs/kit';
import * as auth from '$lib/server/auth';
export const handle: Handle = async ({ event, resolve }) => {
// CSRF protection - verify origin header for state-changing requests
const method = event.request.method;
const origin = event.request.headers.get('origin');
// Skip CSRF check for GET/HEAD requests
if (method !== 'GET' && method !== 'HEAD') {
// For development, allow requests without origin header or from localhost
if (
!origin ||
origin.includes('localhost') ||
origin.includes('127.0.0.1') ||
origin.includes('serengo.ziasvannes.tech')
) {
// Allow in development and serengo.ziasvannes.tech
}
// In production, you would add: else if (origin !== 'yourdomain.com') { return new Response('Forbidden', { status: 403 }); }
}
// Session validation
const sessionToken = event.cookies.get(auth.sessionCookieName);
if (!sessionToken) {
event.locals.user = null;
event.locals.session = null;
return resolve(event);
}
const { session, user } = await auth.validateSessionToken(sessionToken);
if (session) {
auth.setSessionTokenCookie(event, sessionToken, session.expiresAt);
} else {
auth.deleteSessionTokenCookie(event);
}
event.locals.user = user;
event.locals.session = session;
const response = await resolve(event);
// Add security headers
response.headers.set(
'Content-Security-Policy',
"default-src 'self'; " +
"script-src 'self' 'unsafe-inline' 'unsafe-eval'; " +
"worker-src 'self' blob:; " +
"style-src 'self' 'unsafe-inline' fonts.googleapis.com; " +
"font-src 'self' fonts.gstatic.com; " +
"img-src 'self' data: blob: *.openstreetmap.org *.tile.openstreetmap.org *.r2.cloudflarestorage.com *.r2.dev; " +
"media-src 'self' *.r2.cloudflarestorage.com *.r2.dev; " +
"connect-src 'self' *.openstreetmap.org https://fcm.googleapis.com https://android.googleapis.com; " +
"frame-ancestors 'none'; " +
"base-uri 'self'; " +
"form-action 'self';"
);
response.headers.set('X-Frame-Options', 'DENY');
response.headers.set('X-Content-Type-Options', 'nosniff');
response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
// Add HSTS for HTTPS in production
if (event.url.protocol === 'https:') {
response.headers.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
}
return response;
};