diff --git a/apps/backend/.env.example b/apps/backend/.env.example index fa7d9288..f1cf6fc4 100644 --- a/apps/backend/.env.example +++ b/apps/backend/.env.example @@ -1,10 +1,9 @@ PUBLIC_SUPABASE_ANON_KEY= PUBLIC_SUPABASE_URL= -# https://cdn.example.com +# Not required - https://cdn.example.com CLOUDFLARE_BUCKET_DOMAIN= -CLOUDFLARE_TOKEN_VALUE= CLOUDFLARE_ACCESS_KEY= CLOUDFLARE_SECRET_ACCESS_KEY= CLOUDFLARE_ACCOUNT_ID= diff --git a/apps/dashboard/.env.example b/apps/dashboard/.env.example index f7d6be54..16f3ccac 100644 --- a/apps/dashboard/.env.example +++ b/apps/dashboard/.env.example @@ -4,6 +4,9 @@ PUBLIC_SUPABASE_URL=http://localhost:54321 PUBLIC_SUPABASE_ANON_KEY= PRIVATE_SUPABASE_SERVICE_ROLE= +# Selfhosting +IS_SELFHOSTED=false + # Unsplash setup - Optional if you want to use Unsplash images UNSPLASH_API_KEY= @@ -22,7 +25,8 @@ PUBLIC_SERVER_URL= # For getting metadata for signup users. PUBLIC_IP_REGISTRY_KEY= -# Subdomain for admin dashboard +# Domain management +PRIVATE_APP_HOST=classroomio.com PRIVATE_APP_SUBDOMAINS=app LEMON_SQUEEZY_API_KEY= diff --git a/apps/dashboard/src/routes/+layout.server.ts b/apps/dashboard/src/routes/+layout.server.ts index 4cef8357..1f143521 100644 --- a/apps/dashboard/src/routes/+layout.server.ts +++ b/apps/dashboard/src/routes/+layout.server.ts @@ -5,7 +5,7 @@ import { getCurrentOrg } from '$lib/utils/services/org'; import { getSupabase, supabase } from '$lib/utils/functions/supabase'; import { loadTranslations } from '$lib/utils/functions/translations'; import type { CurrentOrg } from '$lib/utils/types/org'; -import { PRIVATE_APP_SUBDOMAINS } from '$env/static/private'; +import { PRIVATE_APP_SUBDOMAINS, IS_SELFHOSTED, PRIVATE_APP_HOST } from '$env/static/private'; if (!supabase) { getSupabase(); @@ -26,6 +26,27 @@ export const load = async ({ url, cookies }): Promise => { org: null }; + // Selfhosted usecase would be here + if (IS_SELFHOSTED === 'true') { + const subdomain = getSubdomain(url); + + // Student dashboard + if (subdomain) { + const org = (await getCurrentOrg(subdomain, true)) || null; + + // Organization by subdomain not found + if (!org) { + return response; + } + + response.org = org; + response.isOrgSite = true; + response.orgSiteName = subdomain; + } + + return response; + } + const isLocalHost = url.host.includes('localhost'); const tempSiteName = url.searchParams.get('org'); @@ -64,6 +85,7 @@ export const load = async ({ url, cookies }): Promise => { } else if (subdomain === 'play' || debugPlay === 'true') { response.skipAuth = true; } else if (!PRIVATE_APP_SUBDOMAINS.split(',').includes(subdomain) && !isDev) { + // This case is for anything in our blockedSubdomains throw redirect(307, 'https://app.classroomio.com'); } @@ -87,3 +109,11 @@ function getInitialLocale(): string { return 'en'; } + +function getSubdomain(url: URL) { + const parts = url.host.split('.'); + if (url.host.endsWith(PRIVATE_APP_HOST)) { + return parts.length >= 3 ? parts[0] : null; + } + return null; +}