Skip to content

Commit 9130b33

Browse files
os-zhuangclaude
andauthored
fix(console): route org-less users into guided org creation on multi-org (#2004)
RequireOrganization previously treated an empty organizations list as single-tenant and rendered through to /home — so on a multi-org (cloud) deployment a brand-new, org-less user landed on a dead home with no org/env. Now, when the runtime config has multiOrgEnabled !== false and the user has no orgs, redirect to /organizations (the 'Create your first organization' screen). Single-tenant self-host (multiOrgEnabled === false) still renders through. Pairs with cloud's guided-org-creation (signup no longer auto-provisions an org). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent eb682d1 commit 9130b33

1 file changed

Lines changed: 18 additions & 2 deletions

File tree

packages/app-shell/src/console/ConsoleShell.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* apps/console/src/App.tsx for one with custom system routes + CreateApp.
1111
*/
1212

13-
import { Suspense, useEffect, useRef, type ReactNode } from 'react';
13+
import { Suspense, useEffect, useRef, useState, type ReactNode } from 'react';
1414
import { Navigate, useLocation } from 'react-router-dom';
1515
import { AuthGuard, useAuth } from '@object-ui/auth';
1616
import { useObjectTranslation } from '@object-ui/i18n';
@@ -175,11 +175,27 @@ function UserStateBridge() {
175175
* deployments (empty organizations list) render through.
176176
*/
177177
export function RequireOrganization({ children }: { children: ReactNode }) {
178-
const { activeOrganization, organizations, isOrganizationsLoading } = useAuth();
178+
const { activeOrganization, organizations, isOrganizationsLoading, getAuthConfig } = useAuth();
179+
// Multi-org (cloud) deployments route a brand-new, org-less user into the
180+
// guided "Create your workspace" flow; single-tenant self-host renders through.
181+
const [multiOrgEnabled, setMultiOrgEnabled] = useState<boolean | null>(null);
182+
useEffect(() => {
183+
let cancelled = false;
184+
getAuthConfig()
185+
.then((cfg: any) => { if (!cancelled) setMultiOrgEnabled(cfg?.features?.multiOrgEnabled !== false); })
186+
.catch(() => { if (!cancelled) setMultiOrgEnabled(false); });
187+
return () => { cancelled = true; };
188+
}, [getAuthConfig]);
179189
if (isOrganizationsLoading) return <LoadingFallback />;
180190
const orgList = organizations ?? [];
181191
const orgFeatureEnabled = orgList.length > 0 || !!activeOrganization;
182192
if (orgFeatureEnabled && !activeOrganization) return <Navigate to="/organizations" replace />;
193+
// No org at all: on multi-org, send them to /organizations (the create
194+
// screen); wait for the flag so we don't flash /home then redirect.
195+
if (orgList.length === 0 && !activeOrganization) {
196+
if (multiOrgEnabled === null) return <LoadingFallback />;
197+
if (multiOrgEnabled) return <Navigate to="/organizations" replace />;
198+
}
183199
return <>{children}</>;
184200
}
185201

0 commit comments

Comments
 (0)