everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
1 lines • 3.83 kB
Source Map (JSON)
{"version":3,"file":"auth-guards.cjs","names":["sessionQueryOptions","redirect","pluginHref","pluginPath","sessionQueryKey"],"sources":["../../src/ui/auth-guards.ts"],"sourcesContent":["/**\n * The auth redirect policy — the single owner of the guard pair that decides\n * every session-driven redirect in the composed tree. The login route\n * (`_public/login` in the auth plugin ui) and the authenticated mounts read\n * through this module so both sides of the ping-pong loop live in one place,\n * tested as a pair.\n */\n\nimport type { QueryClient } from \"@tanstack/react-query\";\nimport { redirect } from \"@tanstack/react-router\";\nimport type { AuthClient, SessionData } from \"./auth\";\nimport { sessionQueryKey, sessionQueryOptions } from \"./auth\";\nimport { pluginHref, pluginPath } from \"./plugin-path\";\n\nexport interface AuthContext {\n isAuthenticated: boolean;\n user: SessionData[\"user\"] | null;\n session: SessionData[\"session\"] | null;\n activeOrganizationId: string | null;\n isAnonymous: boolean;\n isAdmin: boolean;\n isBanned: boolean;\n}\n\ninterface AuthGuardContext {\n queryClient: QueryClient;\n authClient: AuthClient;\n}\n\nexport interface AuthGuardArgs {\n context: AuthGuardContext;\n location: { href: string };\n}\n\nasync function ensureSession(context: AuthGuardContext): Promise<SessionData | null> {\n const { queryClient, authClient } = context;\n return queryClient.query(sessionQueryOptions(authClient));\n}\n\nfunction buildAuthContext(session: SessionData | null | undefined): AuthContext {\n return {\n isAuthenticated: !!session?.user,\n user: session?.user ?? null,\n session: session?.session ?? null,\n activeOrganizationId: session?.session?.activeOrganizationId ?? null,\n isAnonymous: session?.user?.isAnonymous ?? false,\n isAdmin: session?.user?.role === \"admin\",\n isBanned: session?.user?.banned ?? false,\n };\n}\n\nexport async function requireSession({ context, location }: AuthGuardArgs) {\n const session = await ensureSession(context);\n if (!session?.user) {\n throw redirect({ href: pluginHref(\"/login\", { redirect: location.href }) });\n }\n if (session.user.banned) {\n throw redirect({ href: pluginPath(\"/login#banned\") });\n }\n return { auth: buildAuthContext(session), session };\n}\n\nexport async function requireAdmin(args: AuthGuardArgs) {\n const result = await requireSession(args);\n if (result.session.user?.role !== \"admin\") {\n throw redirect({ to: \"/dashboard\" });\n }\n return result;\n}\n\n/**\n * Clears private and public query data on sign-out while leaving an explicit\n * signed-out session entry — the cache must remember \"signed out\" so a late\n * router-context session cannot resurrect stale authed state.\n */\nexport async function clearAuthenticatedQueries(queryClient: QueryClient) {\n await queryClient.cancelQueries();\n queryClient.clear();\n queryClient.setQueryData(sessionQueryKey, null);\n}\n"],"mappings":";;;;;AAkCA,eAAe,cAAc,SAAwD;CACnF,MAAM,EAAE,aAAa,eAAe;CACpC,OAAO,YAAY,MAAMA,oCAAoB,UAAU,CAAC;AAC1D;AAEA,SAAS,iBAAiB,SAAsD;CAC9E,OAAO;EACL,iBAAiB,CAAC,CAAC,SAAS;EAC5B,MAAM,SAAS,QAAQ;EACvB,SAAS,SAAS,WAAW;EAC7B,sBAAsB,SAAS,SAAS,wBAAwB;EAChE,aAAa,SAAS,MAAM,eAAe;EAC3C,SAAS,SAAS,MAAM,SAAS;EACjC,UAAU,SAAS,MAAM,UAAU;CACrC;AACF;AAEA,eAAsB,eAAe,EAAE,SAAS,YAA2B;CACzE,MAAM,UAAU,MAAM,cAAc,OAAO;CAC3C,IAAI,CAAC,SAAS,MACZ,UAAMC,iCAAS,EAAE,MAAMC,+BAAW,UAAU,EAAE,UAAU,SAAS,KAAK,CAAC,EAAE,CAAC;CAE5E,IAAI,QAAQ,KAAK,QACf,UAAMD,iCAAS,EAAE,MAAME,+BAAW,eAAe,EAAE,CAAC;CAEtD,OAAO;EAAE,MAAM,iBAAiB,OAAO;EAAG;CAAQ;AACpD;AAEA,eAAsB,aAAa,MAAqB;CACtD,MAAM,SAAS,MAAM,eAAe,IAAI;CACxC,IAAI,OAAO,QAAQ,MAAM,SAAS,SAChC,UAAMF,iCAAS,EAAE,IAAI,aAAa,CAAC;CAErC,OAAO;AACT;;;;;;AAOA,eAAsB,0BAA0B,aAA0B;CACxE,MAAM,YAAY,cAAc;CAChC,YAAY,MAAM;CAClB,YAAY,aAAaG,iCAAiB,IAAI;AAChD"}