fix(storage): use runtime env vars instead of hardcoded localhost URLs

The storage web app had hardcoded localhost:3001 (auth) and localhost:3016
(backend) URLs, causing production to try connecting to localhost. Added
hooks.server.ts for runtime URL injection and CSP headers, matching the
pattern used by calendar/chat apps.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-03-22 17:59:36 +01:00
parent 6b2b7035cf
commit 97b610020c
3 changed files with 80 additions and 2 deletions

View file

@ -0,0 +1,55 @@
/**
* Server Hooks for SvelteKit
* - Injects runtime environment variables for client-side use
* - Adds security headers
* - Auth is handled client-side via Mana Core Auth
*/
import type { Handle } from '@sveltejs/kit';
// Get client-side URLs from environment (Docker runtime)
const PUBLIC_MANA_CORE_AUTH_URL_CLIENT =
process.env.PUBLIC_MANA_CORE_AUTH_URL_CLIENT ||
process.env.PUBLIC_MANA_CORE_AUTH_URL ||
'http://localhost:3001';
const PUBLIC_BACKEND_URL_CLIENT =
process.env.PUBLIC_BACKEND_URL_CLIENT ||
process.env.PUBLIC_BACKEND_URL ||
'http://localhost:3016';
export const handle: Handle = async ({ event, resolve }) => {
const response = await resolve(event, {
transformPageChunk: ({ html }) => {
// Inject runtime environment variables into the HTML
// These will be available on window.__PUBLIC_*__ for client-side code
const envScript = `<script>
window.__PUBLIC_MANA_CORE_AUTH_URL__ = "${PUBLIC_MANA_CORE_AUTH_URL_CLIENT}";
window.__PUBLIC_BACKEND_URL__ = "${PUBLIC_BACKEND_URL_CLIENT}";
</script>`;
return html.replace('<head>', `<head>${envScript}`);
},
});
// Security headers
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');
response.headers.set('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');
response.headers.set(
'Content-Security-Policy',
[
"default-src 'self'",
"script-src 'self' 'unsafe-inline' https://stats.mana.how",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: https:",
`connect-src 'self' ${PUBLIC_MANA_CORE_AUTH_URL_CLIENT} ${PUBLIC_BACKEND_URL_CLIENT} https://stats.mana.how`,
"font-src 'self'",
"object-src 'none'",
"base-uri 'self'",
"form-action 'self'",
"frame-ancestors 'none'",
].join('; ')
);
return response;
};

View file

@ -3,10 +3,21 @@
* Uses @manacore/shared-api-client for consistent error handling
*/
import { browser } from '$app/environment';
import { createApiClient, type ApiResult } from '@manacore/shared-api-client';
import { authStore } from '$lib/stores/auth.svelte';
const API_URL = 'http://localhost:3016';
// Use client URL in browser (injected by hooks.server.ts), SSR URL on server
function getApiUrl(): string {
if (browser && typeof window !== 'undefined') {
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
.__PUBLIC_BACKEND_URL__;
if (injectedUrl) return injectedUrl;
}
return process.env.PUBLIC_BACKEND_URL || 'http://localhost:3016';
}
const API_URL = getApiUrl();
/**
* Storage API client instance

View file

@ -6,7 +6,19 @@
import { browser } from '$app/environment';
import { initializeWebAuth, type UserData } from '@manacore/shared-auth';
const MANA_AUTH_URL = 'http://localhost:3001';
// Get auth URL dynamically at runtime - fallback for SSR and client
function getAuthUrl(): string {
if (browser && typeof window !== 'undefined') {
// Client-side: use injected window variable (set by hooks.server.ts)
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
.__PUBLIC_MANA_CORE_AUTH_URL__;
return injectedUrl || 'http://localhost:3001';
}
// Server-side (SSR): use Docker internal URL for container-to-container communication
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
}
const MANA_AUTH_URL = getAuthUrl();
let _authService: ReturnType<typeof initializeWebAuth>['authService'] | null = null;
let _tokenManager: ReturnType<typeof initializeWebAuth>['tokenManager'] | null = null;