fix(dashboard): respect URL tenant org for multi-org students (#727)
* fix(dashboard): respect URL tenant org for multi-org students When a student belongs to multiple organizations, setOrgStore was falling back to localStorage or the first /account organization even on tenant sites (subdomain or custom domain). That overwrote the server-resolved org from the URL and sent the wrong cio-org-id on API calls. Pin currentOrg to the URL tenant on org sites, preserve the server org when membership is missing, sync org from /org/[slug] routes, and fix the goToLMS single-org length check. Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * fix(dashboard): update currentOrg when switching tenant sites Address Greptile P1: shouldSetPublicOrg only ran when the site name matched, so navigating from one tenant subdomain to another left the previous org in currentOrg. React to URL tenant changes in an effect and re-pin via setOrgStore when account data is already loaded. Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * fix(dashboard): harden tenant sync when switching org sites - Reset globalStore when leaving a tenant URL - Split org-site seeding from account-backed tenant sync - Add syncTenantOrgFromUrl with deduping and auto-enroll on switch - Stop calling setOrgStore directly from the root layout Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * refactor(dashboard): consolidate org context sync in root layout Address PR review: document why post-setup sync is needed, merge setupApp and syncOrgContext into one effect, resolve /org/[slug] from the root layout via resolveAppOrgParams, and remove duplicate sync from org slug layout. Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com>
This commit is contained in:
co-authored by
Rotimi Best
Cursor Agent
parent
0836d9b5bb
commit
ce0dd376e6
@@ -4,9 +4,11 @@
|
||||
|
||||
import { Snackbar } from '$features/ui';
|
||||
import { appInitApi } from '$features/app/init.svelte';
|
||||
import { resolveAppOrgParams } from '$features/app/resolve-app-org-params';
|
||||
import { setupCloudAnalytics } from '$lib/utils/functions/appSetup';
|
||||
import { globalStore } from '$lib/utils/store/app';
|
||||
import { currentOrg, mergeAccountOrgFromServer } from '$lib/utils/store/org';
|
||||
import { get } from 'svelte/store';
|
||||
import { user } from '$lib/utils/store/user';
|
||||
import { setTheme } from '$lib/utils/functions/theme';
|
||||
import { authClient } from '$lib/utils/services/auth/client';
|
||||
@@ -42,26 +44,52 @@
|
||||
currentSession: data.locals.user
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (data.isOrgSite && data.org) {
|
||||
$globalStore.orgSiteName = data.orgSiteName || '';
|
||||
$globalStore.isOrgSite = true;
|
||||
currentOrg.set(mergeAccountOrgFromServer(data.org));
|
||||
setTheme(data.org.theme || 'blue');
|
||||
$effect(() => {
|
||||
if (!data.isOrgSite || !data.org) {
|
||||
$globalStore.isOrgSite = false;
|
||||
$globalStore.orgSiteName = '';
|
||||
return;
|
||||
}
|
||||
|
||||
$globalStore.orgSiteName = data.orgSiteName || '';
|
||||
$globalStore.isOrgSite = true;
|
||||
|
||||
const existingOrg = get(currentOrg);
|
||||
const shouldSetPublicOrg =
|
||||
!existingOrg.id || existingOrg.siteName !== data.org.siteName || existingOrg.roleId === 0;
|
||||
|
||||
if (shouldSetPublicOrg) {
|
||||
currentOrg.set(mergeAccountOrgFromServer(data.org));
|
||||
}
|
||||
|
||||
setTheme(data.org.theme || 'blue');
|
||||
});
|
||||
|
||||
const session = authClient.useSession();
|
||||
const isSessionReady = $derived(!$session.isPending && !$session.isRefetching && $session.data);
|
||||
const appOrgParams = $derived(resolveAppOrgParams(data, page.url.pathname, page.params.slug));
|
||||
|
||||
/*
|
||||
Auth + org context for the whole dashboard.
|
||||
|
||||
setupApp runs once per session to load /account. After that, org context can
|
||||
still change when a logged-in user navigates to a different tenant subdomain
|
||||
or opens another /org/[slug] on the app host — without another setupApp run.
|
||||
syncOrgContext re-pins currentOrg from the URL + cached account data.
|
||||
*/
|
||||
$effect(() => {
|
||||
if (isSessionReady && !appInitApi.isInitializedAndReady && !appInitApi.loading) {
|
||||
appInitApi.setupApp($session.data as App.Locals, {
|
||||
isOrgSite: data.isOrgSite,
|
||||
orgSiteName: data.orgSiteName,
|
||||
orgId: data.org?.id ?? null
|
||||
});
|
||||
if (!isSessionReady || appInitApi.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!appInitApi.isInitializedAndReady) {
|
||||
appInitApi.setupApp($session.data as App.Locals, appOrgParams);
|
||||
return;
|
||||
}
|
||||
|
||||
void appInitApi.syncOrgContext(appOrgParams);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user