File size: 2,791 Bytes
98051f8
 
20e7f44
 
 
 
38c2b30
 
566c2fc
 
5882bc9
 
a2475e2
5882bc9
 
 
d7b4e1d
 
 
566c2fc
d7b4e1d
 
3b4aeb2
566c2fc
d7b4e1d
 
3b4aeb2
d7b4e1d
 
 
38c2b30
d7b4e1d
38c2b30
566c2fc
38c2b30
d7b4e1d
38c2b30
 
 
 
 
 
d7b4e1d
566c2fc
 
 
d7b4e1d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38c2b30
 
566c2fc
5882bc9
41442b0
 
 
 
 
20e7f44
41442b0
 
 
 
20e7f44
 
 
41442b0
 
5882bc9
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import { COOKIE_NAME } from "$env/static/private";
import type { Handle } from "@sveltejs/kit";
import {
	PUBLIC_GOOGLE_ANALYTICS_ID,
	PUBLIC_DEPRECATED_GOOGLE_ANALYTICS_ID,
} from "$env/static/public";
import { collections } from "$lib/server/database";
import { base } from "$app/paths";
import { refreshSessionCookie, requiresUser } from "$lib/server/auth";
import { ERROR_MESSAGES } from "$lib/stores/errors";

export const handle: Handle = async ({ event, resolve }) => {
	const token = event.cookies.get(COOKIE_NAME);

	event.locals.sessionId = token || crypto.randomUUID();

	const user = await collections.users.findOne({ sessionId: event.locals.sessionId });

	if (user) {
		event.locals.user = user;
	}

	if (
		!event.url.pathname.startsWith(`${base}/login`) &&
		!event.url.pathname.startsWith(`${base}/admin`) &&
		!["GET", "OPTIONS", "HEAD"].includes(event.request.method)
	) {
		const sendJson =
			event.request.headers.get("accept")?.includes("application/json") ||
			event.request.headers.get("content-type")?.includes("application/json");

		if (!user && requiresUser) {
			return new Response(
				sendJson ? JSON.stringify({ error: ERROR_MESSAGES.authOnly }) : ERROR_MESSAGES.authOnly,
				{
					status: 401,
					headers: {
						"content-type": sendJson ? "application/json" : "text/plain",
					},
				}
			);
		}

		// if login is not required and the call is not from /settings, we check if the user has accepted the ethics modal first.
		// If login is required, `ethicsModalAcceptedAt` is already true at this point, so do not pass this condition. This saves a DB call.
		if (!requiresUser && !event.url.pathname.startsWith(`${base}/settings`)) {
			const hasAcceptedEthicsModal = await collections.settings.countDocuments({
				sessionId: event.locals.sessionId,
				ethicsModalAcceptedAt: { $exists: true },
			});

			if (!hasAcceptedEthicsModal) {
				return new Response(
					sendJson
						? JSON.stringify({ error: "You need to accept the welcome modal first" })
						: "You need to accept the welcome modal first",
					{
						status: 405,
						headers: {
							"content-type": sendJson ? "application/json" : "text/plain",
						},
					}
				);
			}
		}
	}

	refreshSessionCookie(event.cookies, event.locals.sessionId);

	let replaced = false;

	const response = await resolve(event, {
		transformPageChunk: (chunk) => {
			// For some reason, Sveltekit doesn't let us load env variables from .env in the app.html template
			if (replaced || !chunk.html.includes("%gaId%") || !chunk.html.includes("%gaIdDeprecated%")) {
				return chunk.html;
			}
			replaced = true;

			return chunk.html
				.replace("%gaId%", PUBLIC_GOOGLE_ANALYTICS_ID)
				.replace("%gaIdDeprecated%", PUBLIC_DEPRECATED_GOOGLE_ANALYTICS_ID);
		},
	});

	return response;
};