MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / AuthGate

Function AuthGate

apps/cloud/src/routes/__root.tsx:192–334  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

190}
191
192function AuthGate() {
193 const auth = useAuth();
194 const location = useLocation();
195 const navigate = useNavigate();
196 const isOnboardingRoute = ONBOARDING_PATHS.has(location.pathname);
197 const isPublicRoute = PUBLIC_PATHS.has(location.pathname);
198 // The org the URL names (the `{-$orgSlug}` segment), if any. `/account/me`
199 // is scoped to it, so `auth.organization` IS this org when the caller is a
200 // member — and `null` when the URL names an org they can't access.
201 const urlOrgSlug = (useParams({ strict: false }) as { orgSlug?: string }).orgSlug;
202 // The same slug derived from the PATHNAME instead of the route params: the
203 // params resolve asynchronously (a fresh load renders once with no orgSlug,
204 // then again with it), and anything keyed on them remounts on that flap.
205 // The pathname is synchronously correct on the very first render, and it is
206 // exactly what the request header derives from (getActiveOrgSlug), so the
207 // registry scope below can never disagree with the header scope.
208 const firstSegment = location.pathname.split("/")[1] ?? "";
209 const pathnameOrgSlug = isValidOrgSlug(firstSegment) ? firstSegment : null;
210
211 // The SSR gate already bounced fresh org-less document requests to
212 // /create-org; this catches the MID-SESSION transitions (org deleted,
213 // membership revoked → /account/me now reports no org). Only for BARE paths:
214 // an org-less result on a slugged URL is a wrong address (404 below), not a
215 // reason to send the user to onboarding.
216 const needsOrgRedirect =
217 auth.status === "authenticated" &&
218 auth.organization == null &&
219 !urlOrgSlug &&
220 !isOnboardingRoute &&
221 !isPublicRoute;
222
223 React.useEffect(() => {
224 if (needsOrgRedirect) {
225 void navigate({ to: "/create-org", replace: true });
226 }
227 }, [needsOrgRedirect, navigate]);
228
229 // The signed-out safety net behind the SSR gate: if a session dies while
230 // the SPA is already loaded (logout elsewhere, expiry), go to /login the
231 // same way a fresh document request would — keeping where they were.
232 const needsLoginRedirect = auth.status === "unauthenticated" && !isPublicRoute;
233 React.useEffect(() => {
234 if (needsLoginRedirect) {
235 window.location.assign(loginPath(`${location.pathname}${location.searchStr}`));
236 }
237 }, [needsLoginRedirect, location.pathname, location.searchStr]);
238
239 if (isPublicRoute) {
240 return <Outlet />;
241 }
242
243 // Every state that isn't "authenticated with an org, on a page that wants
244 // the shell" is a moment between redirects, or the one frame between mount
245 // and the hint cookie seeding (SPA mode reads it in an effect). Neutral
246 // blank — the one placeholder that's correct whatever happens next. The
247 // app-shell skeleton this file used to render here is exactly the
248 // wrong-UI flash the document gate + hint exist to prevent.
249 if (auth.status === "loading" || auth.status === "unauthenticated") {

Callers

nothing calls this directly

Calls 3

useAuthFunction · 0.90
isValidOrgSlugFunction · 0.90
loginPathFunction · 0.90

Tested by

no test coverage detected