fix(dashboard): use verified custom domain for view-as-student handoff (#677)

* fix(dashboard): use verified custom domain for view-as-student handoff

Prefer the org's verified custom domain over window.location.origin when
resolving the public tenant host. This prevents admin URLs like
app.example.com from being used for the student login-link handoff when
the org's public site is example.com.

Co-authored-by: Rotimi Best <[email protected]>

* fix(dashboard): keep self-hosted org origin on window.location

Self-hosted deployments serve admin and LMS from the same URL, so
getOrgPublicOrigin should always return window.location.origin there
rather than preferring a configured custom domain.

Co-authored-by: Rotimi Best <[email protected]>

---------

Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: Rotimi Best <[email protected]>
This commit is contained in:
Rotimi Best
2026-06-19 14:50:37 +01:00
committed by GitHub
co-authored by Rotimi Best Cursor Agent
parent 0a6db37566
commit 5320f1eb44
2 changed files with 30 additions and 13 deletions
@@ -1,7 +1,9 @@
import { get } from 'svelte/store';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { resolve } from '$app/paths'; import { resolve } from '$app/paths';
import { snackbar } from '$features/ui/snackbar/store'; import { snackbar } from '$features/ui/snackbar/store';
import { accountApi } from '$features/account/api/account.svelte'; import { accountApi } from '$features/account/api/account.svelte';
import { currentOrg, getOrgPublicOrigin } from '$lib/utils/store/org';
interface OpenCoursePreviewOptions { interface OpenCoursePreviewOptions {
courseId: string; courseId: string;
@@ -21,7 +23,7 @@ export function getPublicCoursePageUrl(courseSlug: string, currentOrgDomain = ''
} }
const trimmedDomain = currentOrgDomain?.trim(); const trimmedDomain = currentOrgDomain?.trim();
const origin = trimmedDomain || window.location.origin; const origin = trimmedDomain || getOrgPublicOrigin(get(currentOrg));
return new URL(resolve(`/course/${courseSlug}`, {}), origin).toString(); return new URL(resolve(`/course/${courseSlug}`, {}), origin).toString();
} }
@@ -73,7 +75,7 @@ export async function viewAsStudent({ courseId, currentOrgDomain = '' }: ViewAsS
return false; return false;
} }
const origin = currentOrgDomain?.trim() || window.location.origin; const origin = currentOrgDomain?.trim() || getOrgPublicOrigin(get(currentOrg));
const loginLinkUrl = new URL('/api/auth/login-link', origin); const loginLinkUrl = new URL('/api/auth/login-link', origin);
loginLinkUrl.searchParams.set('token', token); loginLinkUrl.searchParams.set('token', token);
loginLinkUrl.searchParams.set('redirect', `/courses/${courseId}/lessons?next=true`); loginLinkUrl.searchParams.set('redirect', `/courses/${courseId}/lessons?next=true`);
+26 -11
View File
@@ -77,19 +77,34 @@ export const currentOrgPath = derived(currentOrg, ($currentOrg) =>
$currentOrg.siteName ? `/org/${$currentOrg.siteName}` : '#' $currentOrg.siteName ? `/org/${$currentOrg.siteName}` : '#'
); );
export const currentOrgDomain = derived(currentOrg, ($currentOrg) => { type OrgPublicOrigin = Pick<AccountOrg, 'customDomain' | 'isCustomDomainVerified' | 'siteName'>;
if (PUBLIC_IS_SELFHOSTED === 'true') return window.location.origin;
const browserOrigin = dev && browser && window.location.origin; /**
* Public origin for an org's tenant site (student LMS, public course pages, login-link handoff).
* Self-hosted uses the current deployment URL. On cloud, verified custom domains win over the
* admin host so `app.classroomio.com` still hands off to the org's `example.com` tenant site.
*/
export function getOrgPublicOrigin(org: OrgPublicOrigin): string {
if (PUBLIC_IS_SELFHOSTED === 'true') {
return browser ? window.location.origin : '';
}
return browserOrigin if (org.customDomain && org.isCustomDomainVerified) {
? browserOrigin return `https://${org.customDomain}`;
: $currentOrg.customDomain && $currentOrg.isCustomDomainVerified }
? `https://${$currentOrg.customDomain}`
: $currentOrg.siteName if (dev && browser) {
? `https://${$currentOrg.siteName}.${TENANT_ROOT_DOMAIN}` return window.location.origin;
: ''; }
});
if (org.siteName) {
return `https://${org.siteName}.${TENANT_ROOT_DOMAIN}`;
}
return browser ? window.location.origin : '';
}
export const currentOrgDomain = derived(currentOrg, ($currentOrg) => getOrgPublicOrigin($currentOrg));
export const isFreePlan = derived(currentOrg, ($currentOrg) => { export const isFreePlan = derived(currentOrg, ($currentOrg) => {
if (!$currentOrg.id || PUBLIC_IS_SELFHOSTED === 'true') return false; if (!$currentOrg.id || PUBLIC_IS_SELFHOSTED === 'true') return false;