diff --git a/compose/demo.yml b/compose/demo.yml index 2955c1c..bd036b4 100644 --- a/compose/demo.yml +++ b/compose/demo.yml @@ -57,6 +57,7 @@ services: environment: INTERNAL_API_BASE: http://backend:3000 API_BASE: ${API_BASE:-http://localhost:3001} + PUBLIC_DEMO_SITE: ${PUBLIC_DEMO_SITE:-false} depends_on: - backend diff --git a/frontend/src/layouts/Layout.astro b/frontend/src/layouts/Layout.astro index 9630c5a..839bcdd 100644 --- a/frontend/src/layouts/Layout.astro +++ b/frontend/src/layouts/Layout.astro @@ -7,8 +7,16 @@ import { DEFAULT_THEME, themes as themeRegistry } from '../lib/themes'; import { API_BASE as apiBase } from '../lib/api'; import VotingIcons from '../components/icons/VotingIcons.astro'; +function isEnabled(v: string | undefined): boolean { + if (!v) return false; + const n = v.trim().toLowerCase(); + return n === '1' || n === 'true' || n === 'yes' || n === 'on'; +} + const { title } = Astro.props; +const publicDemoSite = isEnabled((globalThis as any).process?.env?.PUBLIC_DEMO_SITE); + const themes = Object.fromEntries( Object.entries(themeRegistry).map(([id, t]) => [id, { isDark: t.isDark, colors: t.colors }]), ); @@ -84,7 +92,7 @@ const { title } = Astro.props;
diff --git a/frontend/src/layouts/PublicLayout.astro b/frontend/src/layouts/PublicLayout.astro index de1f65a..e1b1404 100644 --- a/frontend/src/layouts/PublicLayout.astro +++ b/frontend/src/layouts/PublicLayout.astro @@ -6,8 +6,16 @@ interface Props { import { DEFAULT_THEME, themes as themeRegistry } from '../lib/themes'; +function isEnabled(v: string | undefined): boolean { + if (!v) return false; + const n = v.trim().toLowerCase(); + return n === '1' || n === 'true' || n === 'yes' || n === 'on'; +} + const { title, description = "Likwid is a modular governance engine for distributed organizations, open source communities, and civic movements." } = Astro.props; +const publicDemoSite = isEnabled((globalThis as any).process?.env?.PUBLIC_DEMO_SITE); + const themes = Object.fromEntries( Object.entries(themeRegistry).map(([id, t]) => [id, { isDark: t.isDark, colors: t.colors }]), ); @@ -83,7 +91,7 @@ const defaultTheme = DEFAULT_THEME; diff --git a/frontend/src/middleware.ts b/frontend/src/middleware.ts new file mode 100644 index 0000000..aa03b18 --- /dev/null +++ b/frontend/src/middleware.ts @@ -0,0 +1,65 @@ +import { defineMiddleware } from 'astro:middleware'; + +function isEnabled(v: string | undefined): boolean { + if (!v) return false; + const n = v.trim().toLowerCase(); + return n === '1' || n === 'true' || n === 'yes' || n === 'on'; +} + +const DEMO_COOKIE = 'likwid_demo_unlocked'; + +export const onRequest = defineMiddleware(async (context, next) => { + const publicDemoSite = isEnabled((globalThis as any).process?.env?.PUBLIC_DEMO_SITE); + if (!publicDemoSite) { + return next(); + } + + const url = new URL(context.request.url); + const path = url.pathname; + + if (path === '/demo' && url.searchParams.get('enter') === '1') { + let nextPath = url.searchParams.get('next') || '/communities'; + if (!nextPath.startsWith('/')) { + nextPath = '/communities'; + } + + context.cookies.set(DEMO_COOKIE, '1', { + path: '/', + httpOnly: true, + sameSite: 'lax', + maxAge: 60 * 60 * 12, + }); + + return context.redirect(nextPath); + } + + if (path.startsWith('/_astro') || path.startsWith('/favicon') || path.startsWith('/robots')) { + return next(); + } + + if (path === '/setup' || path === '/register') { + return context.redirect('/demo'); + } + + const isProtected = + path === '/login' || + path === '/dashboard' || + path === '/delegations' || + path === '/notifications' || + path === '/settings' || + path.startsWith('/admin') || + path.startsWith('/communities') || + path.startsWith('/proposals') || + path.startsWith('/users'); + + if (!isProtected) { + return next(); + } + + const unlocked = context.cookies.get(DEMO_COOKIE)?.value === '1'; + if (!unlocked) { + return context.redirect('/demo'); + } + + return next(); +}); diff --git a/frontend/src/pages/communities.astro b/frontend/src/pages/communities.astro index d9220a9..6c21d97 100644 --- a/frontend/src/pages/communities.astro +++ b/frontend/src/pages/communities.astro @@ -1,4 +1,5 @@ --- +export const prerender = false; import Layout from '../layouts/Layout.astro'; import { API_BASE as apiBase } from '../lib/api'; --- diff --git a/frontend/src/pages/demo.astro b/frontend/src/pages/demo.astro index 6b3a326..96f1d52 100644 --- a/frontend/src/pages/demo.astro +++ b/frontend/src/pages/demo.astro @@ -1,4 +1,5 @@ --- +export const prerender = false; import PublicLayout from '../layouts/PublicLayout.astro'; import { API_BASE } from '../lib/api'; --- @@ -55,7 +56,7 @@ import { API_BASE } from '../lib/api';- Don't have an account? Register -
+ {!publicDemoSite ? ( ++ Don't have an account? Register +
+ ) : null}