fix(dashboard): redirect students on app domain to org LMS (#675)

* fix(dashboard): redirect students on app domain to org LMS

When a student logs in on app.classroomio.com, send them to their org
tenant domain with a full page reload instead of staying on /lms at the
app host. Org sites and self-hosted installs keep the existing behavior.

Students who explicitly open /onboarding while already belonging to an
org are no longer redirected away, so they can still create their own
academy with the same email.

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

* refactor(dashboard): use getOrgPublicUrl instead of duplicate helper

Main added getOrgPublicOrigin for tenant URLs; extend it with
getOrgPublicUrl for path-based redirects and drop the parallel
getOrgSiteUrl helper from org utils.

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

---------
This commit is contained in:
Rotimi Best
2026-06-21 17:42:02 +01:00
committed by GitHub
co-authored by Rotimi Best
parent 5320f1eb44
commit 3547901de6
2 changed files with 37 additions and 3 deletions
@@ -1,5 +1,5 @@
import { BaseApi, classroomio } from '$lib/utils/services/api';
import { currentOrg, mergeAccountOrgFromServer, orgs } from '$lib/utils/store/org';
import { currentOrg, getOrgPublicUrl, mergeAccountOrgFromServer, orgs } from '$lib/utils/store/org';
import { defaultProfileState, defaultUserState, profile, user } from '$lib/utils/store/user';
import type { AccountResponse } from './types';
@@ -201,12 +201,26 @@ class AppInitApi extends BaseApi {
if (!shouldRedirectOnAuth(page.url.pathname)) return;
// Students with existing org memberships who open /onboarding may intend to create their own academy.
if (path.includes('/onboarding') && isStudent && userHasOrganizations) {
return;
}
const shouldGoToLMS = isCloud ? isOrgSite || !!isStudent : !!isStudent;
console.log('redirecting to', shouldGoToLMS ? 'lms' : 'org');
return shouldGoToLMS ? this.goToLMS() : this.goToOrg();
return shouldGoToLMS ? this.goToLMS(isOrgSite) : this.goToOrg();
}
goToLMS() {
goToLMS(isOrgSite: boolean) {
const isCloud = PUBLIC_IS_SELFHOSTED !== 'true';
const isStudent = get(isOrgStudent);
const selectedOrg = get(currentOrg);
if (isCloud && !isOrgSite && isStudent && selectedOrg.siteName) {
window.location.href = getOrgPublicUrl(selectedOrg, '/lms');
return;
}
goto(resolve('/lms', {}));
}
+20
View File
@@ -104,6 +104,26 @@ export function getOrgPublicOrigin(org: OrgPublicOrigin): string {
return browser ? window.location.origin : '';
}
/** Absolute URL on an org's public tenant site (e.g. `/lms`, `/course/{slug}`). Client-only. */
export function getOrgPublicUrl(org: OrgPublicOrigin, pathname = '/'): string {
if (!browser) {
return pathname;
}
const origin = getOrgPublicOrigin(org);
if (!origin) {
return pathname;
}
const url = new URL(pathname, origin);
if (window.location.host.includes('localhost') && org.siteName) {
url.searchParams.set('org', org.siteName);
}
return url.toString();
}
export const currentOrgDomain = derived(currentOrg, ($currentOrg) => getOrgPublicOrigin($currentOrg));
export const isFreePlan = derived(currentOrg, ($currentOrg) => {