feat: add prelaunch site controls and refresh branding
Validate and deploy production / validate (push) Successful in 23s
Validate and deploy staging / validate (push) Successful in 19s
Validate and deploy production / deploy (push) Successful in 1m0s
Validate and deploy staging / deploy (push) Successful in 36s

This commit is contained in:
JB
2026-07-27 02:24:13 -04:00
parent 7b3aff30d8
commit 5a67b252aa
37 changed files with 1738 additions and 100 deletions
+20 -1
View File
@@ -2,6 +2,7 @@ import { json, type Handle, type HandleServerError } from '@sveltejs/kit';
import { stringify } from 'devalue';
import { randomUUID } from 'node:crypto';
import { getSessionUser } from '$lib/server/auth/session';
import { getSiteAccessBlock, getSiteAccessSettings } from '$lib/server/site-access';
import { DATA_MODULES, proposalActionResult, queueDataProposal, shouldModerateDataMutation, type DataModule } from '$lib/server/data-moderation';
export const handle: Handle = async ({ event, resolve }) => {
@@ -9,6 +10,24 @@ export const handle: Handle = async ({ event, resolve }) => {
const location = `/isac${event.url.pathname.slice('/admin'.length)}${event.url.search}`;
return new Response(null, { status: 308, headers: { location } });
}
const siteSettings = await getSiteAccessSettings();
const sessionUser = await getSessionUser(event.cookies);
const accessBlock = getSiteAccessBlock(siteSettings, event.url.pathname, Boolean(sessionUser));
if (accessBlock) {
const target = new URL('/coming-soon', event.url);
if (accessBlock.kind === 'section') target.searchParams.set('unavailable', accessBlock.section);
if (event.request.method === 'GET' || event.request.method === 'HEAD') {
return new Response(null, { status: 303, headers: { location: `${target.pathname}${target.search}` } });
}
return json(
{
error: accessBlock.kind === 'section'
? 'This section is not available.'
: 'The public site is not available yet.'
},
{ status: 404 }
);
}
if (event.request.method === 'POST') {
const match = event.url.pathname.match(/^\/isac\/([^/]+)$/);
const module = match?.[1] as DataModule | undefined;
@@ -17,7 +36,7 @@ export const handle: Handle = async ({ event, resolve }) => {
// Publishing calculation rules is never a contributor proposal. The
// action has its own dedicated permission and confirmation contract.
if (module === 'calculations' && action === 'publishRevision') return resolve(event);
const user = await getSessionUser(event.cookies);
const user = sessionUser;
const access = await shouldModerateDataMutation(user);
if (!access.canManage && access.canPropose && user) {
if (!access.contributorEnabled) {