@burdenoff/microfe-auth 2026.520.1 → 2026.521.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/auth/AuthRoutes.js +8 -8
  2. package/dist/auth/AuthRoutes.js.map +1 -1
  3. package/dist/auth/components/AuthLayout.js +1 -1
  4. package/dist/auth/components/AuthLayout.js.map +1 -1
  5. package/dist/auth/hooks/useSessionOperations.d.ts.map +1 -1
  6. package/dist/auth/hooks/useSessionOperations.js +4 -1
  7. package/dist/auth/hooks/useSessionOperations.js.map +1 -1
  8. package/dist/auth/hooks/useUserOperations.d.ts.map +1 -1
  9. package/dist/auth/hooks/useUserOperations.js +26 -11
  10. package/dist/auth/hooks/useUserOperations.js.map +1 -1
  11. package/dist/auth/pages/AuditLogPage.d.ts.map +1 -1
  12. package/dist/auth/pages/AuditLogPage.js +49 -48
  13. package/dist/auth/pages/AuditLogPage.js.map +1 -1
  14. package/dist/auth/pages/LoginPage.d.ts.map +1 -1
  15. package/dist/auth/pages/LoginPage.js +3 -2
  16. package/dist/auth/pages/LoginPage.js.map +1 -1
  17. package/dist/auth/pages/PasswordResetPage.js +1 -1
  18. package/dist/auth/pages/PasswordResetPage.js.map +1 -1
  19. package/dist/auth/pages/ReactivatePage.js +1 -1
  20. package/dist/auth/pages/ReactivatePage.js.map +1 -1
  21. package/dist/auth/pages/RegisterPage.js +1 -1
  22. package/dist/auth/pages/RegisterPage.js.map +1 -1
  23. package/dist/auth/pages/SessionsPage.d.ts.map +1 -1
  24. package/dist/auth/pages/SessionsPage.js +26 -23
  25. package/dist/auth/pages/SessionsPage.js.map +1 -1
  26. package/dist/auth/pages/SsoCallbackPage.js +1 -1
  27. package/dist/auth/pages/SsoCallbackPage.js.map +1 -1
  28. package/dist/auth/pages/SsoConfigPage.d.ts.map +1 -1
  29. package/dist/auth/pages/SsoConfigPage.js +214 -190
  30. package/dist/auth/pages/SsoConfigPage.js.map +1 -1
  31. package/dist/auth/pages/SsoLoginPage.js +1 -1
  32. package/dist/auth/pages/SsoLoginPage.js.map +1 -1
  33. package/dist/auth/pages/UserProfilePage.d.ts.map +1 -1
  34. package/dist/auth/pages/UserProfilePage.js +254 -238
  35. package/dist/auth/pages/UserProfilePage.js.map +1 -1
  36. package/dist/auth/pages/UsersPage.d.ts.map +1 -1
  37. package/dist/auth/pages/UsersPage.js +0 -1
  38. package/dist/auth/pages/UsersPage.js.map +1 -1
  39. package/dist/auth/store/authStore.d.ts +20 -0
  40. package/dist/auth/store/authStore.d.ts.map +1 -1
  41. package/dist/auth/store/authStore.js.map +1 -1
  42. package/dist/microfe-auth.css +1 -1
  43. package/dist/translations/en.d.ts +12 -0
  44. package/dist/translations/en.d.ts.map +1 -1
  45. package/package.json +1 -1
  46. package/dist/auth/pages/AppsPage.d.ts +0 -5
  47. package/dist/auth/pages/AppsPage.d.ts.map +0 -1
@@ -177,7 +177,7 @@ function B({ basePath: e = "", enableAdminRoutes: c = !0 }) {
177
177
  path: "security",
178
178
  element: /* @__PURE__ */ h(z, { children: /* @__PURE__ */ h(_, {
179
179
  flag: "auth.security",
180
- defaultValue: !1,
180
+ defaultValue: !0,
181
181
  children: /* @__PURE__ */ h(s, {
182
182
  fallback: /* @__PURE__ */ h(I, {}),
183
183
  children: /* @__PURE__ */ h(T, {})
@@ -188,7 +188,7 @@ function B({ basePath: e = "", enableAdminRoutes: c = !0 }) {
188
188
  path: "sessions",
189
189
  element: /* @__PURE__ */ h(z, { children: /* @__PURE__ */ h(_, {
190
190
  flag: "auth.sessions",
191
- defaultValue: !1,
191
+ defaultValue: !0,
192
192
  children: /* @__PURE__ */ h(s, {
193
193
  fallback: /* @__PURE__ */ h(I, {}),
194
194
  children: /* @__PURE__ */ h(E, {})
@@ -199,7 +199,7 @@ function B({ basePath: e = "", enableAdminRoutes: c = !0 }) {
199
199
  path: "mfa",
200
200
  element: /* @__PURE__ */ h(z, { children: /* @__PURE__ */ h(_, {
201
201
  flag: "auth.mfa",
202
- defaultValue: !1,
202
+ defaultValue: !0,
203
203
  children: /* @__PURE__ */ h(s, {
204
204
  fallback: /* @__PURE__ */ h(I, {}),
205
205
  children: /* @__PURE__ */ h(D, {})
@@ -235,7 +235,7 @@ function B({ basePath: e = "", enableAdminRoutes: c = !0 }) {
235
235
  path: "sso",
236
236
  element: c ? /* @__PURE__ */ h(z, { children: /* @__PURE__ */ h(_, {
237
237
  flag: "auth.sso",
238
- defaultValue: !1,
238
+ defaultValue: !0,
239
239
  children: /* @__PURE__ */ h(s, {
240
240
  fallback: /* @__PURE__ */ h(I, {}),
241
241
  children: /* @__PURE__ */ h(k, {})
@@ -251,7 +251,7 @@ function B({ basePath: e = "", enableAdminRoutes: c = !0 }) {
251
251
  flag: "auth.apps",
252
252
  defaultValue: !1,
253
253
  children: /* @__PURE__ */ h(d, {
254
- to: "/devportal/apps/new",
254
+ to: "/devportal/apps",
255
255
  replace: !0
256
256
  })
257
257
  }) })
@@ -260,7 +260,7 @@ function B({ basePath: e = "", enableAdminRoutes: c = !0 }) {
260
260
  path: "users",
261
261
  element: c ? /* @__PURE__ */ h(z, { children: /* @__PURE__ */ h(_, {
262
262
  flag: "auth.users",
263
- defaultValue: !1,
263
+ defaultValue: !0,
264
264
  children: /* @__PURE__ */ h(s, {
265
265
  fallback: /* @__PURE__ */ h(I, {}),
266
266
  children: /* @__PURE__ */ h(N, {})
@@ -274,7 +274,7 @@ function B({ basePath: e = "", enableAdminRoutes: c = !0 }) {
274
274
  path: "users/:id",
275
275
  element: c ? /* @__PURE__ */ h(z, { children: /* @__PURE__ */ h(_, {
276
276
  flag: "auth.users",
277
- defaultValue: !1,
277
+ defaultValue: !0,
278
278
  children: /* @__PURE__ */ h(s, {
279
279
  fallback: /* @__PURE__ */ h(I, {}),
280
280
  children: /* @__PURE__ */ h(P, {})
@@ -288,7 +288,7 @@ function B({ basePath: e = "", enableAdminRoutes: c = !0 }) {
288
288
  path: "profile",
289
289
  element: /* @__PURE__ */ h(z, { children: /* @__PURE__ */ h(_, {
290
290
  flag: "auth.profile",
291
- defaultValue: !1,
291
+ defaultValue: !0,
292
292
  children: /* @__PURE__ */ h(s, {
293
293
  fallback: /* @__PURE__ */ h(I, {}),
294
294
  children: /* @__PURE__ */ h(F, {})
@@ -1 +1 @@
1
- {"version":3,"file":"AuthRoutes.js","names":[],"sources":["../../src/auth/AuthRoutes.tsx"],"sourcesContent":["import { lazy, Suspense, useEffect, useState } from \"react\";\nimport {\n useFeatureFlagDetails,\n FeatureGate,\n} from \"@burdenoff/fe-libs/shared/feature-flags\";\nimport { Navigate, Route, Routes } from \"react-router-dom\";\nimport { useAuthStore } from \"./store/authStore\";\n\n// Eager imports - these are the most commonly accessed routes\nimport { LoginPage } from \"./pages/LoginPage\";\nimport { SessionBridgePage } from \"./pages/SessionBridgePage\";\nimport { SSORelayPage } from \"./pages/SSORelayPage\";\nimport { SSORelayCallbackPage } from \"./pages/SSORelayCallbackPage\";\nimport { SSODepositPage } from \"./pages/SSODepositPage\";\nimport { SSOClearPage } from \"./pages/SSOClearPage\";\n\n// Lazy-loaded pages - loaded on demand when their routes are accessed\nconst RegisterPage = lazy(() =>\n import(\"./pages/RegisterPage\").then((m) => ({ default: m.RegisterPage })),\n);\nconst PasswordResetPage = lazy(() =>\n import(\"./pages/PasswordResetPage\").then((m) => ({\n default: m.PasswordResetPage,\n })),\n);\nconst EmailVerifyPage = lazy(() =>\n import(\"./pages/EmailVerifyPage\").then((m) => ({\n default: m.EmailVerifyPage,\n })),\n);\nconst MfaVerifyPage = lazy(() =>\n import(\"./pages/MfaVerifyPage\").then((m) => ({ default: m.MfaVerifyPage })),\n);\nconst MagicLinkPage = lazy(() =>\n import(\"./pages/MagicLinkPage\").then((m) => ({ default: m.MagicLinkPage })),\n);\nconst ReactivatePage = lazy(() =>\n import(\"./pages/ReactivatePage\").then((m) => ({ default: m.ReactivatePage })),\n);\nconst SecurityPage = lazy(() =>\n import(\"./pages/SecurityPage\").then((m) => ({ default: m.SecurityPage })),\n);\nconst SessionsPage = lazy(() =>\n import(\"./pages/SessionsPage\").then((m) => ({ default: m.SessionsPage })),\n);\nconst MfaSetupPage = lazy(() =>\n import(\"./pages/MfaSetupPage\").then((m) => ({ default: m.MfaSetupPage })),\n);\nconst AuditLogPage = lazy(() =>\n import(\"./pages/AuditLogPage\").then((m) => ({ default: m.AuditLogPage })),\n);\nconst SsoConfigPage = lazy(() =>\n import(\"./pages/SsoConfigPage\").then((m) => ({ default: m.SsoConfigPage })),\n);\nconst SsoLoginPage = lazy(() =>\n import(\"./pages/SsoLoginPage\").then((m) => ({ default: m.SsoLoginPage })),\n);\nconst SsoCallbackPage = lazy(() =>\n import(\"./pages/SsoCallbackPage\").then((m) => ({\n default: m.SsoCallbackPage,\n })),\n);\nconst OAuthCallbackPage = lazy(() =>\n import(\"./pages/OAuthCallbackPage\").then((m) => ({\n default: m.OAuthCallbackPage,\n })),\n);\nconst UsersPage = lazy(() =>\n import(\"./pages/UsersPage\").then((m) => ({ default: m.UsersPage })),\n);\nconst UserDetailsPage = lazy(() =>\n import(\"./pages/UserDetailsPage\").then((m) => ({\n default: m.UserDetailsPage,\n })),\n);\nconst UserProfilePage = lazy(() =>\n import(\"./pages/UserProfilePage\").then((m) => ({\n default: m.UserProfilePage,\n })),\n);\n/**\n * Simple loading fallback for lazy-loaded pages\n */\nfunction PageLoader() {\n return (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent\" />\n </div>\n );\n}\n\nfunction decodeJwtExpiry(token: string): number | null {\n try {\n const payload = JSON.parse(\n atob(token.split(\".\")[1].replace(/-/g, \"+\").replace(/_/g, \"/\")),\n ) as { exp?: number };\n\n return typeof payload.exp === \"number\" ? payload.exp * 1000 : null;\n } catch {\n return null;\n }\n}\n\nfunction getStoredSessionSnapshot(): {\n hasValidSession: boolean;\n expiresAt: number | null;\n} {\n try {\n const activeProfileId = sessionStorage.getItem(\"bf-active-profile\");\n if (!activeProfileId) {\n return { hasValidSession: false, expiresAt: null };\n }\n\n const tokensRaw = localStorage.getItem(`bf-p-${activeProfileId}-tokens`);\n if (!tokensRaw) {\n return { hasValidSession: false, expiresAt: null };\n }\n\n const tokens = JSON.parse(tokensRaw) as {\n accessToken?: string;\n expiresAt?: number;\n };\n\n if (!tokens.accessToken) {\n return { hasValidSession: false, expiresAt: null };\n }\n\n const expiresAt =\n typeof tokens.expiresAt === \"number\"\n ? tokens.expiresAt\n : decodeJwtExpiry(tokens.accessToken);\n\n if (!expiresAt) {\n return { hasValidSession: false, expiresAt: null };\n }\n\n return {\n hasValidSession: expiresAt > Date.now(),\n expiresAt,\n };\n } catch {\n return { hasValidSession: false, expiresAt: null };\n }\n}\n\n/**\n * Protected route wrapper\n */\nfunction ProtectedRoute({ children }: { children: React.ReactNode }) {\n const isAuthenticated = useAuthStore((state) => state.isAuthenticated);\n const clearAuth = useAuthStore((state) => state.clearAuth);\n const [sessionCheckVersion, setSessionCheckVersion] = useState(0);\n const sessionSnapshot = getStoredSessionSnapshot();\n\n useEffect(() => {\n const handleSessionUpdate = () => {\n setSessionCheckVersion((value) => value + 1);\n };\n\n window.addEventListener(\"bf-profile-storage-change\", handleSessionUpdate);\n window.addEventListener(\"storage\", handleSessionUpdate);\n\n return () => {\n window.removeEventListener(\n \"bf-profile-storage-change\",\n handleSessionUpdate,\n );\n window.removeEventListener(\"storage\", handleSessionUpdate);\n };\n }, []);\n\n useEffect(() => {\n if (!sessionSnapshot.expiresAt) return;\n\n const timeoutMs = Math.max(sessionSnapshot.expiresAt - Date.now(), 0) + 50;\n const timer = window.setTimeout(() => {\n setSessionCheckVersion((value) => value + 1);\n }, timeoutMs);\n\n return () => window.clearTimeout(timer);\n }, [sessionSnapshot.expiresAt, sessionCheckVersion]);\n\n useEffect(() => {\n if (isAuthenticated && !sessionSnapshot.hasValidSession) {\n clearAuth();\n }\n }, [clearAuth, isAuthenticated, sessionSnapshot.hasValidSession]);\n\n if (!sessionSnapshot.hasValidSession) {\n return <Navigate to=\"/auth/login\" replace />;\n }\n\n return <>{children}</>;\n}\n\n/**\n * Internal router for the Auth microfrontend.\n * This component handles routing within the microfrontend using React Router v7.\n *\n * When used within a parent route (e.g., <Route path=\"/auth/*\">), all paths are relative:\n * - login → Login page (accessible at /auth/login)\n * - register → Registration page (accessible at /auth/register)\n * - reset-password → Password reset page (accessible at /auth/reset-password)\n * - verify-email → Email verification page (accessible at /auth/verify-email)\n * - mfa-verify → MFA verification page (accessible at /auth/mfa-verify)\n * - magic-link → Magic link authentication page (accessible at /auth/magic-link)\n * - sso/login → SSO login page (accessible at /auth/sso/login)\n * - sso/callback → SSO callback handler (accessible at /auth/sso/callback)\n * - oauth/callback → OAuth callback handler (accessible at /auth/oauth/callback)\n * - security → Security settings (protected, accessible at /auth/security)\n * - sessions → Active sessions (protected, accessible at /auth/sessions)\n * - mfa → MFA setup (protected, accessible at /auth/mfa)\n * - api-keys → API keys management (protected, accessible at /auth/api-keys)\n * - apps → Legacy redirect to Developer Portal app creation\n * - users → Users management (protected, admin only, accessible at /auth/users)\n * - profile → User profile page (protected, accessible at /auth/profile)\n * - audit-log → Security audit log (protected, accessible at /auth/audit-log)\n * - sso → SSO configuration (protected, admin only, accessible at /auth/sso)\n */\nexport function AuthRoutes({\n basePath: _basePath = \"\",\n enableAdminRoutes = true,\n}: {\n basePath?: string;\n enableAdminRoutes?: boolean;\n}) {\n // Note: basePath is kept for backwards compatibility but not used in route paths\n // since React Router v7 uses relative paths when nested inside a parent <Route>\n const auditLogFlag = useFeatureFlagDetails(\"auth.audit-log\");\n const showAuditLog = auditLogFlag?.value === true;\n return (\n <Routes>\n {/* Public routes (no auth required) */}\n {/* LoginPage is eager-loaded as it's the most common entry point */}\n <Route path=\"login\" element={<LoginPage />} />\n <Route\n path=\"register\"\n element={\n <Suspense fallback={<PageLoader />}>\n <RegisterPage />\n </Suspense>\n }\n />\n <Route\n path=\"reset-password\"\n element={\n <Suspense fallback={<PageLoader />}>\n <PasswordResetPage />\n </Suspense>\n }\n />\n <Route\n path=\"verify-email\"\n element={\n <Suspense fallback={<PageLoader />}>\n <EmailVerifyPage />\n </Suspense>\n }\n />\n <Route\n path=\"mfa-verify\"\n element={\n <Suspense fallback={<PageLoader />}>\n <MfaVerifyPage />\n </Suspense>\n }\n />\n <Route\n path=\"magic-link\"\n element={\n <Suspense fallback={<PageLoader />}>\n <MagicLinkPage />\n </Suspense>\n }\n />\n\n {/* SSO routes (public) */}\n <Route\n path=\"sso/login\"\n element={\n <Suspense fallback={<PageLoader />}>\n <SsoLoginPage />\n </Suspense>\n }\n />\n <Route\n path=\"sso/callback\"\n element={\n <Suspense fallback={<PageLoader />}>\n <SsoCallbackPage />\n </Suspense>\n }\n />\n\n {/* OAuth callback route (public) */}\n <Route\n path=\"oauth/callback\"\n element={\n <Suspense fallback={<PageLoader />}>\n <OAuthCallbackPage />\n </Suspense>\n }\n />\n\n {/* Account reactivation (public) */}\n <Route\n path=\"reactivate\"\n element={\n <Suspense fallback={<PageLoader />}>\n <ReactivatePage />\n </Suspense>\n }\n />\n\n {/* Session bridge (public - embedded as hidden iframe by other app shells) */}\n <Route path=\"session-bridge\" element={<SessionBridgePage />} />\n\n {/* Cross-domain SSO relay (reads local tokens, redirects with them to target) */}\n <Route path=\"sso-relay\" element={<SSORelayPage />} />\n\n {/* Cross-domain SSO callback (receives tokens from relay, stores locally) */}\n <Route path=\"sso-callback\" element={<SSORelayCallbackPage />} />\n\n {/* Cross-domain SSO deposit (bridge host receives tokens on top-level\n redirect right after login on a product origin, writes first-party\n localStorage on the bridge origin so other products can discover\n the session). */}\n <Route path=\"sso-deposit\" element={<SSODepositPage />} />\n\n {/* Cross-domain SLO clear (bridge host clears its central session on\n top-level redirect from a product origin's logout). */}\n <Route path=\"sso-clear\" element={<SSOClearPage />} />\n\n {/* Protected routes (auth required) */}\n <Route\n path=\"security\"\n element={\n <ProtectedRoute>\n <FeatureGate flag=\"auth.security\" defaultValue={false}>\n <Suspense fallback={<PageLoader />}>\n <SecurityPage />\n </Suspense>\n </FeatureGate>\n </ProtectedRoute>\n }\n />\n <Route\n path=\"sessions\"\n element={\n <ProtectedRoute>\n <FeatureGate flag=\"auth.sessions\" defaultValue={false}>\n <Suspense fallback={<PageLoader />}>\n <SessionsPage />\n </Suspense>\n </FeatureGate>\n </ProtectedRoute>\n }\n />\n <Route\n path=\"mfa\"\n element={\n <ProtectedRoute>\n <FeatureGate flag=\"auth.mfa\" defaultValue={false}>\n <Suspense fallback={<PageLoader />}>\n <MfaSetupPage />\n </Suspense>\n </FeatureGate>\n </ProtectedRoute>\n }\n />\n <Route\n path=\"api-keys\"\n element={\n <ProtectedRoute>\n <Navigate to=\"/devportal/api-keys\" replace />\n </ProtectedRoute>\n }\n />\n {enableAdminRoutes && showAuditLog && (\n <Route\n path=\"audit-log\"\n element={\n <ProtectedRoute>\n <FeatureGate flag=\"auth.audit-log\" defaultValue={false}>\n <Suspense fallback={<PageLoader />}>\n <AuditLogPage />\n </Suspense>\n </FeatureGate>\n </ProtectedRoute>\n }\n />\n )}\n {!enableAdminRoutes && (\n <Route\n path=\"audit-log\"\n element={<Navigate to=\"/auth/login\" replace />}\n />\n )}\n <Route\n path=\"sso\"\n element={\n enableAdminRoutes ? (\n <ProtectedRoute>\n <FeatureGate flag=\"auth.sso\" defaultValue={false}>\n <Suspense fallback={<PageLoader />}>\n <SsoConfigPage />\n </Suspense>\n </FeatureGate>\n </ProtectedRoute>\n ) : (\n <Navigate to=\"/auth/login\" replace />\n )\n }\n />\n <Route\n path=\"apps\"\n element={\n <ProtectedRoute>\n <FeatureGate flag=\"auth.apps\" defaultValue={false}>\n <Navigate to=\"/devportal/apps/new\" replace />\n </FeatureGate>\n </ProtectedRoute>\n }\n />\n <Route\n path=\"users\"\n element={\n enableAdminRoutes ? (\n <ProtectedRoute>\n <FeatureGate flag=\"auth.users\" defaultValue={false}>\n <Suspense fallback={<PageLoader />}>\n <UsersPage />\n </Suspense>\n </FeatureGate>\n </ProtectedRoute>\n ) : (\n <Navigate to=\"/auth/login\" replace />\n )\n }\n />\n <Route\n path=\"users/:id\"\n element={\n enableAdminRoutes ? (\n <ProtectedRoute>\n <FeatureGate flag=\"auth.users\" defaultValue={false}>\n <Suspense fallback={<PageLoader />}>\n <UserDetailsPage />\n </Suspense>\n </FeatureGate>\n </ProtectedRoute>\n ) : (\n <Navigate to=\"/auth/login\" replace />\n )\n }\n />\n <Route\n path=\"profile\"\n element={\n <ProtectedRoute>\n <FeatureGate flag=\"auth.profile\" defaultValue={false}>\n <Suspense fallback={<PageLoader />}>\n <UserProfilePage />\n </Suspense>\n </FeatureGate>\n </ProtectedRoute>\n }\n />\n <Route\n path=\"delegations\"\n element={\n <ProtectedRoute>\n <Navigate to=\"/devportal/delegations\" replace />\n </ProtectedRoute>\n }\n />\n\n {/* Default redirect - when visiting /auth or /auth/ with no subpath */}\n <Route index element={<Navigate to=\"login\" replace />} />\n </Routes>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AuthRoutes.js","names":[],"sources":["../../src/auth/AuthRoutes.tsx"],"sourcesContent":["import { lazy, Suspense, useEffect, useState } from \"react\";\nimport {\n useFeatureFlagDetails,\n FeatureGate,\n} from \"@burdenoff/fe-libs/shared/feature-flags\";\nimport { Navigate, Route, Routes } from \"react-router-dom\";\nimport { useAuthStore } from \"./store/authStore\";\n\n// Eager imports - these are the most commonly accessed routes\nimport { LoginPage } from \"./pages/LoginPage\";\nimport { SessionBridgePage } from \"./pages/SessionBridgePage\";\nimport { SSORelayPage } from \"./pages/SSORelayPage\";\nimport { SSORelayCallbackPage } from \"./pages/SSORelayCallbackPage\";\nimport { SSODepositPage } from \"./pages/SSODepositPage\";\nimport { SSOClearPage } from \"./pages/SSOClearPage\";\n\n// Lazy-loaded pages - loaded on demand when their routes are accessed\nconst RegisterPage = lazy(() =>\n import(\"./pages/RegisterPage\").then((m) => ({ default: m.RegisterPage })),\n);\nconst PasswordResetPage = lazy(() =>\n import(\"./pages/PasswordResetPage\").then((m) => ({\n default: m.PasswordResetPage,\n })),\n);\nconst EmailVerifyPage = lazy(() =>\n import(\"./pages/EmailVerifyPage\").then((m) => ({\n default: m.EmailVerifyPage,\n })),\n);\nconst MfaVerifyPage = lazy(() =>\n import(\"./pages/MfaVerifyPage\").then((m) => ({ default: m.MfaVerifyPage })),\n);\nconst MagicLinkPage = lazy(() =>\n import(\"./pages/MagicLinkPage\").then((m) => ({ default: m.MagicLinkPage })),\n);\nconst ReactivatePage = lazy(() =>\n import(\"./pages/ReactivatePage\").then((m) => ({ default: m.ReactivatePage })),\n);\nconst SecurityPage = lazy(() =>\n import(\"./pages/SecurityPage\").then((m) => ({ default: m.SecurityPage })),\n);\nconst SessionsPage = lazy(() =>\n import(\"./pages/SessionsPage\").then((m) => ({ default: m.SessionsPage })),\n);\nconst MfaSetupPage = lazy(() =>\n import(\"./pages/MfaSetupPage\").then((m) => ({ default: m.MfaSetupPage })),\n);\nconst AuditLogPage = lazy(() =>\n import(\"./pages/AuditLogPage\").then((m) => ({ default: m.AuditLogPage })),\n);\nconst SsoConfigPage = lazy(() =>\n import(\"./pages/SsoConfigPage\").then((m) => ({ default: m.SsoConfigPage })),\n);\nconst SsoLoginPage = lazy(() =>\n import(\"./pages/SsoLoginPage\").then((m) => ({ default: m.SsoLoginPage })),\n);\nconst SsoCallbackPage = lazy(() =>\n import(\"./pages/SsoCallbackPage\").then((m) => ({\n default: m.SsoCallbackPage,\n })),\n);\nconst OAuthCallbackPage = lazy(() =>\n import(\"./pages/OAuthCallbackPage\").then((m) => ({\n default: m.OAuthCallbackPage,\n })),\n);\nconst UsersPage = lazy(() =>\n import(\"./pages/UsersPage\").then((m) => ({ default: m.UsersPage })),\n);\nconst UserDetailsPage = lazy(() =>\n import(\"./pages/UserDetailsPage\").then((m) => ({\n default: m.UserDetailsPage,\n })),\n);\nconst UserProfilePage = lazy(() =>\n import(\"./pages/UserProfilePage\").then((m) => ({\n default: m.UserProfilePage,\n })),\n);\n/**\n * Simple loading fallback for lazy-loaded pages\n */\nfunction PageLoader() {\n return (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent\" />\n </div>\n );\n}\n\nfunction decodeJwtExpiry(token: string): number | null {\n try {\n const payload = JSON.parse(\n atob(token.split(\".\")[1].replace(/-/g, \"+\").replace(/_/g, \"/\")),\n ) as { exp?: number };\n\n return typeof payload.exp === \"number\" ? payload.exp * 1000 : null;\n } catch {\n return null;\n }\n}\n\nfunction getStoredSessionSnapshot(): {\n hasValidSession: boolean;\n expiresAt: number | null;\n} {\n try {\n const activeProfileId = sessionStorage.getItem(\"bf-active-profile\");\n if (!activeProfileId) {\n return { hasValidSession: false, expiresAt: null };\n }\n\n const tokensRaw = localStorage.getItem(`bf-p-${activeProfileId}-tokens`);\n if (!tokensRaw) {\n return { hasValidSession: false, expiresAt: null };\n }\n\n const tokens = JSON.parse(tokensRaw) as {\n accessToken?: string;\n expiresAt?: number;\n };\n\n if (!tokens.accessToken) {\n return { hasValidSession: false, expiresAt: null };\n }\n\n const expiresAt =\n typeof tokens.expiresAt === \"number\"\n ? tokens.expiresAt\n : decodeJwtExpiry(tokens.accessToken);\n\n if (!expiresAt) {\n return { hasValidSession: false, expiresAt: null };\n }\n\n return {\n hasValidSession: expiresAt > Date.now(),\n expiresAt,\n };\n } catch {\n return { hasValidSession: false, expiresAt: null };\n }\n}\n\n/**\n * Protected route wrapper\n */\nfunction ProtectedRoute({ children }: { children: React.ReactNode }) {\n const isAuthenticated = useAuthStore((state) => state.isAuthenticated);\n const clearAuth = useAuthStore((state) => state.clearAuth);\n const [sessionCheckVersion, setSessionCheckVersion] = useState(0);\n const sessionSnapshot = getStoredSessionSnapshot();\n\n useEffect(() => {\n const handleSessionUpdate = () => {\n setSessionCheckVersion((value) => value + 1);\n };\n\n window.addEventListener(\"bf-profile-storage-change\", handleSessionUpdate);\n window.addEventListener(\"storage\", handleSessionUpdate);\n\n return () => {\n window.removeEventListener(\n \"bf-profile-storage-change\",\n handleSessionUpdate,\n );\n window.removeEventListener(\"storage\", handleSessionUpdate);\n };\n }, []);\n\n useEffect(() => {\n if (!sessionSnapshot.expiresAt) return;\n\n const timeoutMs = Math.max(sessionSnapshot.expiresAt - Date.now(), 0) + 50;\n const timer = window.setTimeout(() => {\n setSessionCheckVersion((value) => value + 1);\n }, timeoutMs);\n\n return () => window.clearTimeout(timer);\n }, [sessionSnapshot.expiresAt, sessionCheckVersion]);\n\n useEffect(() => {\n if (isAuthenticated && !sessionSnapshot.hasValidSession) {\n clearAuth();\n }\n }, [clearAuth, isAuthenticated, sessionSnapshot.hasValidSession]);\n\n if (!sessionSnapshot.hasValidSession) {\n return <Navigate to=\"/auth/login\" replace />;\n }\n\n return <>{children}</>;\n}\n\n/**\n * Internal router for the Auth microfrontend.\n * This component handles routing within the microfrontend using React Router v7.\n *\n * When used within a parent route (e.g., <Route path=\"/auth/*\">), all paths are relative:\n * - login → Login page (accessible at /auth/login)\n * - register → Registration page (accessible at /auth/register)\n * - reset-password → Password reset page (accessible at /auth/reset-password)\n * - verify-email → Email verification page (accessible at /auth/verify-email)\n * - mfa-verify → MFA verification page (accessible at /auth/mfa-verify)\n * - magic-link → Magic link authentication page (accessible at /auth/magic-link)\n * - sso/login → SSO login page (accessible at /auth/sso/login)\n * - sso/callback → SSO callback handler (accessible at /auth/sso/callback)\n * - oauth/callback → OAuth callback handler (accessible at /auth/oauth/callback)\n * - security → Security settings (protected, accessible at /auth/security)\n * - sessions → Active sessions (protected, accessible at /auth/sessions)\n * - mfa → MFA setup (protected, accessible at /auth/mfa)\n * - api-keys → API keys management (protected, accessible at /auth/api-keys)\n * - apps → Legacy redirect to Developer Portal app creation\n * - users → Users management (protected, admin only, accessible at /auth/users)\n * - profile → User profile page (protected, accessible at /auth/profile)\n * - audit-log → Security audit log (protected, accessible at /auth/audit-log)\n * - sso → SSO configuration (protected, admin only, accessible at /auth/sso)\n */\nexport function AuthRoutes({\n basePath: _basePath = \"\",\n enableAdminRoutes = true,\n}: {\n basePath?: string;\n enableAdminRoutes?: boolean;\n}) {\n // Note: basePath is kept for backwards compatibility but not used in route paths\n // since React Router v7 uses relative paths when nested inside a parent <Route>\n const auditLogFlag = useFeatureFlagDetails(\"auth.audit-log\");\n const showAuditLog = auditLogFlag?.value === true;\n return (\n <Routes>\n {/* Public routes (no auth required) */}\n {/* LoginPage is eager-loaded as it's the most common entry point */}\n <Route path=\"login\" element={<LoginPage />} />\n <Route\n path=\"register\"\n element={\n <Suspense fallback={<PageLoader />}>\n <RegisterPage />\n </Suspense>\n }\n />\n <Route\n path=\"reset-password\"\n element={\n <Suspense fallback={<PageLoader />}>\n <PasswordResetPage />\n </Suspense>\n }\n />\n <Route\n path=\"verify-email\"\n element={\n <Suspense fallback={<PageLoader />}>\n <EmailVerifyPage />\n </Suspense>\n }\n />\n <Route\n path=\"mfa-verify\"\n element={\n <Suspense fallback={<PageLoader />}>\n <MfaVerifyPage />\n </Suspense>\n }\n />\n <Route\n path=\"magic-link\"\n element={\n <Suspense fallback={<PageLoader />}>\n <MagicLinkPage />\n </Suspense>\n }\n />\n\n {/* SSO routes (public) */}\n <Route\n path=\"sso/login\"\n element={\n <Suspense fallback={<PageLoader />}>\n <SsoLoginPage />\n </Suspense>\n }\n />\n <Route\n path=\"sso/callback\"\n element={\n <Suspense fallback={<PageLoader />}>\n <SsoCallbackPage />\n </Suspense>\n }\n />\n\n {/* OAuth callback route (public) */}\n <Route\n path=\"oauth/callback\"\n element={\n <Suspense fallback={<PageLoader />}>\n <OAuthCallbackPage />\n </Suspense>\n }\n />\n\n {/* Account reactivation (public) */}\n <Route\n path=\"reactivate\"\n element={\n <Suspense fallback={<PageLoader />}>\n <ReactivatePage />\n </Suspense>\n }\n />\n\n {/* Session bridge (public - embedded as hidden iframe by other app shells) */}\n <Route path=\"session-bridge\" element={<SessionBridgePage />} />\n\n {/* Cross-domain SSO relay (reads local tokens, redirects with them to target) */}\n <Route path=\"sso-relay\" element={<SSORelayPage />} />\n\n {/* Cross-domain SSO callback (receives tokens from relay, stores locally) */}\n <Route path=\"sso-callback\" element={<SSORelayCallbackPage />} />\n\n {/* Cross-domain SSO deposit (bridge host receives tokens on top-level\n redirect right after login on a product origin, writes first-party\n localStorage on the bridge origin so other products can discover\n the session). */}\n <Route path=\"sso-deposit\" element={<SSODepositPage />} />\n\n {/* Cross-domain SLO clear (bridge host clears its central session on\n top-level redirect from a product origin's logout). */}\n <Route path=\"sso-clear\" element={<SSOClearPage />} />\n\n {/* Protected routes (auth required) */}\n <Route\n path=\"security\"\n element={\n <ProtectedRoute>\n <FeatureGate flag=\"auth.security\" defaultValue={true}>\n <Suspense fallback={<PageLoader />}>\n <SecurityPage />\n </Suspense>\n </FeatureGate>\n </ProtectedRoute>\n }\n />\n <Route\n path=\"sessions\"\n element={\n <ProtectedRoute>\n <FeatureGate flag=\"auth.sessions\" defaultValue={true}>\n <Suspense fallback={<PageLoader />}>\n <SessionsPage />\n </Suspense>\n </FeatureGate>\n </ProtectedRoute>\n }\n />\n <Route\n path=\"mfa\"\n element={\n <ProtectedRoute>\n <FeatureGate flag=\"auth.mfa\" defaultValue={true}>\n <Suspense fallback={<PageLoader />}>\n <MfaSetupPage />\n </Suspense>\n </FeatureGate>\n </ProtectedRoute>\n }\n />\n <Route\n path=\"api-keys\"\n element={\n <ProtectedRoute>\n <Navigate to=\"/devportal/api-keys\" replace />\n </ProtectedRoute>\n }\n />\n {enableAdminRoutes && showAuditLog && (\n <Route\n path=\"audit-log\"\n element={\n <ProtectedRoute>\n <FeatureGate flag=\"auth.audit-log\" defaultValue={false}>\n <Suspense fallback={<PageLoader />}>\n <AuditLogPage />\n </Suspense>\n </FeatureGate>\n </ProtectedRoute>\n }\n />\n )}\n {!enableAdminRoutes && (\n <Route\n path=\"audit-log\"\n element={<Navigate to=\"/auth/login\" replace />}\n />\n )}\n <Route\n path=\"sso\"\n element={\n enableAdminRoutes ? (\n <ProtectedRoute>\n <FeatureGate flag=\"auth.sso\" defaultValue={true}>\n <Suspense fallback={<PageLoader />}>\n <SsoConfigPage />\n </Suspense>\n </FeatureGate>\n </ProtectedRoute>\n ) : (\n <Navigate to=\"/auth/login\" replace />\n )\n }\n />\n <Route\n path=\"apps\"\n element={\n <ProtectedRoute>\n <FeatureGate flag=\"auth.apps\" defaultValue={false}>\n <Navigate to=\"/devportal/apps\" replace />\n </FeatureGate>\n </ProtectedRoute>\n }\n />\n <Route\n path=\"users\"\n element={\n enableAdminRoutes ? (\n <ProtectedRoute>\n <FeatureGate flag=\"auth.users\" defaultValue={true}>\n <Suspense fallback={<PageLoader />}>\n <UsersPage />\n </Suspense>\n </FeatureGate>\n </ProtectedRoute>\n ) : (\n <Navigate to=\"/auth/login\" replace />\n )\n }\n />\n <Route\n path=\"users/:id\"\n element={\n enableAdminRoutes ? (\n <ProtectedRoute>\n <FeatureGate flag=\"auth.users\" defaultValue={true}>\n <Suspense fallback={<PageLoader />}>\n <UserDetailsPage />\n </Suspense>\n </FeatureGate>\n </ProtectedRoute>\n ) : (\n <Navigate to=\"/auth/login\" replace />\n )\n }\n />\n <Route\n path=\"profile\"\n element={\n <ProtectedRoute>\n <FeatureGate flag=\"auth.profile\" defaultValue={true}>\n <Suspense fallback={<PageLoader />}>\n <UserProfilePage />\n </Suspense>\n </FeatureGate>\n </ProtectedRoute>\n }\n />\n <Route\n path=\"delegations\"\n element={\n <ProtectedRoute>\n <Navigate to=\"/devportal/delegations\" replace />\n </ProtectedRoute>\n }\n />\n\n {/* Default redirect - when visiting /auth or /auth/ with no subpath */}\n <Route index element={<Navigate to=\"login\" replace />} />\n </Routes>\n );\n}\n"],"mappings":"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"}
@@ -180,7 +180,7 @@ function o({ children: o, title: s, subtitle: c, productName: l, tagline: u }) {
180
180
  })
181
181
  ]
182
182
  })]
183
- }), /* @__PURE__ */ r("div", {
183
+ }), /* @__PURE__ */ r("main", {
184
184
  className: "auth-shell-gradient relative flex flex-1 items-center justify-center bg-[var(--color-bg-canvas)] p-6 sm:p-12",
185
185
  children: [/* @__PURE__ */ n("div", {
186
186
  className: "absolute top-4 right-4 sm:top-6 sm:right-6 z-10",
@@ -1 +1 @@
1
- {"version":3,"file":"AuthLayout.js","names":[],"sources":["../../../src/auth/components/AuthLayout.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { LanguageSwitcher } from \"@burdenoff/fe-libs/chrome\";\nimport type { Language } from \"@burdenoff/fe-libs/chrome\";\nimport {\n useI18n,\n useAppShell,\n} from \"@burdenoff/fe-libs/shared/providers/shell\";\n\ninterface AuthLayoutProps {\n children: ReactNode;\n title: string;\n subtitle: string;\n productName?: string;\n tagline?: string;\n}\n\n/**\n * Supported languages for the auth pages\n */\nconst AUTH_LANGUAGES: Language[] = [\n { code: \"en\", name: \"English\", nativeName: \"English\", flag: \"🇺🇸\" },\n { code: \"ta\", name: \"Tamil\", nativeName: \"தமிழ்\", flag: \"🇮🇳\" },\n { code: \"hi\", name: \"Hindi\", nativeName: \"हिन्दी\", flag: \"🇮🇳\" },\n { code: \"es\", name: \"Spanish\", nativeName: \"Español\", flag: \"🇪🇸\" },\n { code: \"fr\", name: \"French\", nativeName: \"Français\", flag: \"🇫🇷\" },\n];\n\n/**\n * Professional auth layout with split-screen design\n * Left side: Branding with gradient background\n * Right side: Auth form\n */\nexport function AuthLayout({\n children,\n title,\n subtitle,\n productName,\n tagline,\n}: AuthLayoutProps) {\n const shell = useAppShell();\n const displayName = productName || shell.productName || \"Burdenoff\";\n const displayTagline = tagline || shell.tagline || \"Enterprise platform\";\n const { t, locale, setLocale } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n\n const handleLanguageChange = (language: Language) => {\n setLocale(language.code as \"en\" | \"ta\" | \"hi\" | \"es\" | \"fr\");\n };\n\n return (\n <div className=\"min-h-screen flex relative\">\n {/* Left Panel - Branding */}\n <div className=\"auth-brand-panel hidden overflow-hidden lg:flex lg:w-1/2 relative\">\n {/* Decorative Elements */}\n <div className=\"absolute inset-0 overflow-hidden\">\n <div className=\"absolute -top-40 -left-40 w-80 h-80 rounded-full bg-accent-blue/20 blur-3xl\" />\n <div className=\"absolute top-1/2 -right-20 w-96 h-96 rounded-full bg-accent-indigo/20 blur-3xl\" />\n <div className=\"absolute -bottom-40 left-1/4 w-72 h-72 rounded-full bg-accent-purple/20 blur-3xl\" />\n\n {/* Grid Pattern */}\n <div\n className=\"absolute inset-0 opacity-5\"\n style={{\n backgroundImage: `url(\"data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='1'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E\")`,\n }}\n />\n </div>\n\n {/* Content */}\n <div className=\"relative z-10 flex flex-col justify-between p-12 w-full\">\n {/* Logo */}\n <div className=\"flex items-center gap-3\">\n <div className=\"auth-brand-badge flex h-10 w-10 items-center justify-center rounded-xl\">\n <svg\n className=\"w-6 h-6 text-white\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\"\n />\n </svg>\n </div>\n <span className=\"text-xl font-bold text-[var(--color-text-primary)]\">\n {displayName}\n </span>\n </div>\n\n {/* Main Content */}\n <div className=\"max-w-md\">\n <h1 className=\"mb-4 text-4xl font-bold leading-tight text-[var(--color-text-primary)]\">\n {displayTagline}\n </h1>\n <p className=\"auth-brand-copy text-lg leading-relaxed\">\n {tr(\n \"auth.layout.taglineDescription\",\n \"Unify your teams, projects, and workflows in one intelligent workspace. Built for scale with enterprise-grade security, real-time collaboration, and seamless integrations across your entire organization.\",\n )}\n </p>\n\n {/* Features */}\n <div className=\"mt-10 space-y-4\">\n {[\n {\n icon: \"workspace\",\n text: tr(\n \"auth.layout.featureWorkspace\",\n \"Modular workspace architecture\",\n ),\n },\n {\n icon: \"realtime\",\n text: tr(\n \"auth.layout.featureRealtime\",\n \"Real-time collaboration & sync\",\n ),\n },\n {\n icon: \"security\",\n text: tr(\n \"auth.layout.featureSecurity\",\n \"Enterprise-grade security & SSO\",\n ),\n },\n {\n icon: \"scale\",\n text: tr(\n \"auth.layout.featureScale\",\n \"Unlimited scalability & performance\",\n ),\n },\n ].map((feature, i) => (\n <div key={i} className=\"flex items-center gap-3\">\n <div className=\"auth-highlight-chip flex h-8 w-8 items-center justify-center rounded-lg\">\n {feature.icon === \"workspace\" && (\n <svg\n className=\"w-4 h-4 text-accent-blue\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z\"\n />\n </svg>\n )}\n {feature.icon === \"realtime\" && (\n <svg\n className=\"w-4 h-4 text-accent-blue\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z\"\n />\n </svg>\n )}\n {feature.icon === \"security\" && (\n <svg\n className=\"w-4 h-4 text-accent-blue\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"\n />\n </svg>\n )}\n {feature.icon === \"scale\" && (\n <svg\n className=\"w-4 h-4 text-accent-blue\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z\"\n />\n </svg>\n )}\n </div>\n <span className=\"auth-brand-copy text-sm font-medium\">\n {feature.text}\n </span>\n </div>\n ))}\n </div>\n </div>\n\n {/* Footer */}\n <div className=\"auth-brand-copy-muted text-sm\">\n © {new Date().getFullYear()} Burdenoff. All rights reserved.\n </div>\n </div>\n </div>\n\n {/* Right Panel - Form */}\n <div className=\"auth-shell-gradient relative flex flex-1 items-center justify-center bg-[var(--color-bg-canvas)] p-6 sm:p-12\">\n {/* Language Switcher - Top Right */}\n <div className=\"absolute top-4 right-4 sm:top-6 sm:right-6 z-10\">\n <LanguageSwitcher\n languages={AUTH_LANGUAGES}\n currentLanguage={locale}\n onLanguageChange={handleLanguageChange}\n />\n </div>\n <div className=\"w-full max-w-md\">\n {/* Mobile Logo */}\n <div className=\"lg:hidden flex items-center justify-center gap-3 mb-8\">\n <div className=\"auth-brand-badge flex h-10 w-10 items-center justify-center rounded-xl\">\n <svg\n className=\"w-6 h-6 text-white\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\"\n />\n </svg>\n </div>\n <span className=\"text-xl font-bold text-[var(--color-text-primary)]\">\n {displayName}\n </span>\n </div>\n\n {/* Header */}\n <div className=\"text-center lg:text-left mb-8\">\n <h2 className=\"text-2xl sm:text-3xl font-bold text-[var(--color-text-primary)] mb-2\">\n {title}\n </h2>\n <p className=\"text-[var(--color-text-secondary)]\">{subtitle}</p>\n </div>\n\n {/* Form Content */}\n {children}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AuthLayout.js","names":[],"sources":["../../../src/auth/components/AuthLayout.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { LanguageSwitcher } from \"@burdenoff/fe-libs/chrome\";\nimport type { Language } from \"@burdenoff/fe-libs/chrome\";\nimport {\n useI18n,\n useAppShell,\n} from \"@burdenoff/fe-libs/shared/providers/shell\";\n\ninterface AuthLayoutProps {\n children: ReactNode;\n title: string;\n subtitle: string;\n productName?: string;\n tagline?: string;\n}\n\n/**\n * Supported languages for the auth pages\n */\nconst AUTH_LANGUAGES: Language[] = [\n { code: \"en\", name: \"English\", nativeName: \"English\", flag: \"🇺🇸\" },\n { code: \"ta\", name: \"Tamil\", nativeName: \"தமிழ்\", flag: \"🇮🇳\" },\n { code: \"hi\", name: \"Hindi\", nativeName: \"हिन्दी\", flag: \"🇮🇳\" },\n { code: \"es\", name: \"Spanish\", nativeName: \"Español\", flag: \"🇪🇸\" },\n { code: \"fr\", name: \"French\", nativeName: \"Français\", flag: \"🇫🇷\" },\n];\n\n/**\n * Professional auth layout with split-screen design\n * Left side: Branding with gradient background\n * Right side: Auth form\n */\nexport function AuthLayout({\n children,\n title,\n subtitle,\n productName,\n tagline,\n}: AuthLayoutProps) {\n const shell = useAppShell();\n const displayName = productName || shell.productName || \"Burdenoff\";\n const displayTagline = tagline || shell.tagline || \"Enterprise platform\";\n const { t, locale, setLocale } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n\n const handleLanguageChange = (language: Language) => {\n setLocale(language.code as \"en\" | \"ta\" | \"hi\" | \"es\" | \"fr\");\n };\n\n return (\n <div className=\"min-h-screen flex relative\">\n {/* Left Panel - Branding */}\n <div className=\"auth-brand-panel hidden overflow-hidden lg:flex lg:w-1/2 relative\">\n {/* Decorative Elements */}\n <div className=\"absolute inset-0 overflow-hidden\">\n <div className=\"absolute -top-40 -left-40 w-80 h-80 rounded-full bg-accent-blue/20 blur-3xl\" />\n <div className=\"absolute top-1/2 -right-20 w-96 h-96 rounded-full bg-accent-indigo/20 blur-3xl\" />\n <div className=\"absolute -bottom-40 left-1/4 w-72 h-72 rounded-full bg-accent-purple/20 blur-3xl\" />\n\n {/* Grid Pattern */}\n <div\n className=\"absolute inset-0 opacity-5\"\n style={{\n backgroundImage: `url(\"data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='1'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E\")`,\n }}\n />\n </div>\n\n {/* Content */}\n <div className=\"relative z-10 flex flex-col justify-between p-12 w-full\">\n {/* Logo */}\n <div className=\"flex items-center gap-3\">\n <div className=\"auth-brand-badge flex h-10 w-10 items-center justify-center rounded-xl\">\n <svg\n className=\"w-6 h-6 text-white\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\"\n />\n </svg>\n </div>\n <span className=\"text-xl font-bold text-[var(--color-text-primary)]\">\n {displayName}\n </span>\n </div>\n\n {/* Main Content */}\n <div className=\"max-w-md\">\n <h1 className=\"mb-4 text-4xl font-bold leading-tight text-[var(--color-text-primary)]\">\n {displayTagline}\n </h1>\n <p className=\"auth-brand-copy text-lg leading-relaxed\">\n {tr(\n \"auth.layout.taglineDescription\",\n \"Unify your teams, projects, and workflows in one intelligent workspace. Built for scale with enterprise-grade security, real-time collaboration, and seamless integrations across your entire organization.\",\n )}\n </p>\n\n {/* Features */}\n <div className=\"mt-10 space-y-4\">\n {[\n {\n icon: \"workspace\",\n text: tr(\n \"auth.layout.featureWorkspace\",\n \"Modular workspace architecture\",\n ),\n },\n {\n icon: \"realtime\",\n text: tr(\n \"auth.layout.featureRealtime\",\n \"Real-time collaboration & sync\",\n ),\n },\n {\n icon: \"security\",\n text: tr(\n \"auth.layout.featureSecurity\",\n \"Enterprise-grade security & SSO\",\n ),\n },\n {\n icon: \"scale\",\n text: tr(\n \"auth.layout.featureScale\",\n \"Unlimited scalability & performance\",\n ),\n },\n ].map((feature, i) => (\n <div key={i} className=\"flex items-center gap-3\">\n <div className=\"auth-highlight-chip flex h-8 w-8 items-center justify-center rounded-lg\">\n {feature.icon === \"workspace\" && (\n <svg\n className=\"w-4 h-4 text-accent-blue\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z\"\n />\n </svg>\n )}\n {feature.icon === \"realtime\" && (\n <svg\n className=\"w-4 h-4 text-accent-blue\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z\"\n />\n </svg>\n )}\n {feature.icon === \"security\" && (\n <svg\n className=\"w-4 h-4 text-accent-blue\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"\n />\n </svg>\n )}\n {feature.icon === \"scale\" && (\n <svg\n className=\"w-4 h-4 text-accent-blue\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z\"\n />\n </svg>\n )}\n </div>\n <span className=\"auth-brand-copy text-sm font-medium\">\n {feature.text}\n </span>\n </div>\n ))}\n </div>\n </div>\n\n {/* Footer */}\n <div className=\"auth-brand-copy-muted text-sm\">\n © {new Date().getFullYear()} Burdenoff. All rights reserved.\n </div>\n </div>\n </div>\n\n {/* Right Panel - Form */}\n <main className=\"auth-shell-gradient relative flex flex-1 items-center justify-center bg-[var(--color-bg-canvas)] p-6 sm:p-12\">\n {/* Language Switcher - Top Right */}\n <div className=\"absolute top-4 right-4 sm:top-6 sm:right-6 z-10\">\n <LanguageSwitcher\n languages={AUTH_LANGUAGES}\n currentLanguage={locale}\n onLanguageChange={handleLanguageChange}\n />\n </div>\n <div className=\"w-full max-w-md\">\n {/* Mobile Logo */}\n <div className=\"lg:hidden flex items-center justify-center gap-3 mb-8\">\n <div className=\"auth-brand-badge flex h-10 w-10 items-center justify-center rounded-xl\">\n <svg\n className=\"w-6 h-6 text-white\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\"\n />\n </svg>\n </div>\n <span className=\"text-xl font-bold text-[var(--color-text-primary)]\">\n {displayName}\n </span>\n </div>\n\n {/* Header */}\n <div className=\"text-center lg:text-left mb-8\">\n <h2 className=\"text-2xl sm:text-3xl font-bold text-[var(--color-text-primary)] mb-2\">\n {title}\n </h2>\n <p className=\"text-[var(--color-text-secondary)]\">{subtitle}</p>\n </div>\n\n {/* Form Content */}\n {children}\n </div>\n </main>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useSessionOperations.d.ts","sourceRoot":"","sources":["../../../src/auth/hooks/useSessionOperations.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,mBAAmB,EAMpB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAM7E,UAAU,sBAAsB;IAC9B,SAAS,EAAE,uBAAuB,CAAC;CACpC;AAUD,UAAU,2BAA2B;IACnC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,2BAAgC;4BAkEhC,mBAAmB,KACzB,OAAO,CAAC,uBAAuB,CAAC;0BAaR,OAAO;iCAQA,MAAM;;+BASA,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;6BAmB7B,OAAO,CAAC;QAC1C,OAAO,EAAE,OAAO,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;EAsDH"}
1
+ {"version":3,"file":"useSessionOperations.d.ts","sourceRoot":"","sources":["../../../src/auth/hooks/useSessionOperations.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,mBAAmB,EAMpB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAM7E,UAAU,sBAAsB;IAC9B,SAAS,EAAE,uBAAuB,CAAC;CACpC;AAUD,UAAU,2BAA2B;IACnC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,2BAAgC;4BAsEhC,mBAAmB,KACzB,OAAO,CAAC,uBAAuB,CAAC;0BAaR,OAAO;iCAQA,MAAM;;+BASA,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;6BAmB7B,OAAO,CAAC;QAC1C,OAAO,EAAE,OAAO,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;EAsDH"}
@@ -15,7 +15,10 @@ function l(l = {}) {
15
15
  limit: f,
16
16
  offset: p * f
17
17
  } },
18
- context: u.accessToken ? { headers: { authorization: `Bearer ${u.accessToken}` } } : void 0
18
+ context: u.accessToken ? { headers: {
19
+ authorization: `Bearer ${u.accessToken}`,
20
+ "x-workspace-id": ""
21
+ } } : void 0
19
22
  }), [S] = s(r), [C] = s(n), w = async (e) => {
20
23
  try {
21
24
  let { data: t } = await h({ variables: { input: e } });
@@ -1 +1 @@
1
- {"version":3,"file":"useSessionOperations.js","names":[],"sources":["../../../src/auth/hooks/useSessionOperations.ts"],"sourcesContent":["import { useState } from \"react\";\nimport { useQuery, useMutation } from \"@apollo/client/react\";\nimport { useAuthStore } from \"../store/authStore\";\nimport {\n TokenInfoDocument,\n ValidateTokensDocument,\n ActiveSessionsDocument,\n RevokeSessionDocument,\n RevokeAllSessionsDocument,\n} from \"../../generated/global-operations\";\nimport type {\n ActiveSessionsQuery,\n ActiveSessionsQueryVariables,\n RevokeSessionMutation,\n RevokeSessionMutationVariables,\n RevokeAllSessionsMutation,\n RevokeAllSessionsMutationVariables,\n} from \"../../generated/global-operations\";\nimport type { TokenValidationResponse, ValidateTokensInput } from \"../types\";\n\n// =============================================================================\n// GRAPHQL RESPONSE INTERFACES\n// =============================================================================\n\ninterface TokenInfoQueryResponse {\n tokenInfo: TokenValidationResponse;\n}\n\ninterface ValidateTokensMutationResponse {\n validateTokens: TokenValidationResponse;\n}\n\ninterface ValidateTokensMutationVariables {\n input: ValidateTokensInput;\n}\n\ninterface UseSessionOperationsOptions {\n disableTokenInfoQuery?: boolean;\n /** Number of sessions to load per page (default: 10) */\n pageSize?: number;\n}\n\n/**\n * Hook for session/token management operations\n */\nexport function useSessionOperations(\n options: UseSessionOperationsOptions = {},\n) {\n const store = useAuthStore();\n const disableTokenInfoQuery = options.disableTokenInfoQuery ?? false;\n const pageSize = options.pageSize ?? 10;\n\n // Pagination state: page is 0-based for offset calculation\n const [page, setPage] = useState(0);\n\n const [validateTokensMutation] = useMutation<\n ValidateTokensMutationResponse,\n ValidateTokensMutationVariables\n >(ValidateTokensDocument);\n\n const { data, loading, refetch } = useQuery<TokenInfoQueryResponse>(\n TokenInfoDocument,\n {\n skip: disableTokenInfoQuery || !store.isAuthenticated,\n fetchPolicy: \"cache-and-network\",\n pollInterval: 5 * 60 * 1000, // Poll every 5 minutes (was 1 min — too aggressive)\n },\n );\n\n // Active sessions query\n // Pass the access token explicitly in Apollo operation context so the query\n // works both via the shell's MultiGatewayProvider auth link and in standalone mode.\n const {\n data: sessionsData,\n loading: sessionsLoading,\n refetch: refetchSessions,\n } = useQuery<ActiveSessionsQuery, ActiveSessionsQueryVariables>(\n ActiveSessionsDocument,\n {\n skip: !store.isAuthenticated,\n fetchPolicy: \"cache-and-network\",\n variables: {\n pagination: {\n limit: pageSize,\n offset: page * pageSize,\n },\n },\n context: store.accessToken\n ? {\n headers: {\n authorization: `Bearer ${store.accessToken}`,\n },\n }\n : undefined,\n },\n );\n\n // Session mutations\n const [revokeSessionMutation] = useMutation<\n RevokeSessionMutation,\n RevokeSessionMutationVariables\n >(RevokeSessionDocument);\n\n const [revokeAllSessionsMutation] = useMutation<\n RevokeAllSessionsMutation,\n RevokeAllSessionsMutationVariables\n >(RevokeAllSessionsDocument);\n\n /**\n * Validate tokens\n */\n const validateTokens = async (\n input: ValidateTokensInput,\n ): Promise<TokenValidationResponse> => {\n try {\n const { data } = await validateTokensMutation({ variables: { input } });\n return data!.validateTokens;\n } catch (error) {\n console.error(\"Failed to validate tokens:\", error);\n throw error;\n }\n };\n\n /**\n * Check if token is expired\n */\n const isTokenExpired = (): boolean => {\n if (!data?.tokenInfo?.expiresAt) return true;\n return Date.now() / 1000 > data.tokenInfo.expiresAt;\n };\n\n /**\n * Get remaining time until token expires (in seconds)\n */\n const getTokenRemainingTime = (): number => {\n if (!data?.tokenInfo?.expiresAt) return 0;\n const remaining = data.tokenInfo.expiresAt - Date.now() / 1000;\n return Math.max(0, remaining);\n };\n\n /**\n * Revoke a specific session by ID\n */\n const revokeSession = async (sessionId: string): Promise<boolean> => {\n try {\n const { data } = await revokeSessionMutation({\n variables: { sessionId },\n });\n if (data?.revokeSession) {\n // Refetch active sessions to reflect the change\n await refetchSessions();\n }\n return data?.revokeSession ?? false;\n } catch (error) {\n console.error(\"Failed to revoke session:\", error);\n throw error;\n }\n };\n\n /**\n * Revoke all sessions except the current one\n */\n const revokeAllSessions = async (): Promise<{\n success: boolean;\n revokedCount: number;\n }> => {\n try {\n const { data } = await revokeAllSessionsMutation();\n if (data?.revokeAllSessions?.success) {\n // Refetch active sessions to reflect the change\n await refetchSessions();\n }\n return data?.revokeAllSessions ?? { success: false, revokedCount: 0 };\n } catch (error) {\n console.error(\"Failed to revoke all sessions:\", error);\n throw error;\n }\n };\n\n const totalCount = sessionsData?.activeSessions?.totalCount ?? 0;\n const hasMore = sessionsData?.activeSessions?.hasMore ?? false;\n const totalPages = Math.max(1, Math.ceil(totalCount / pageSize));\n\n const goToNextPage = () => {\n if (hasMore) {\n setPage((prev) => prev + 1);\n }\n };\n\n const goToPrevPage = () => {\n if (page > 0) {\n setPage((prev) => prev - 1);\n }\n };\n\n return {\n // Token operations\n validateTokens,\n isTokenExpired,\n getTokenRemainingTime,\n tokenInfo: data?.tokenInfo,\n // Session operations\n revokeSession,\n revokeAllSessions,\n activeSessions: sessionsData?.activeSessions?.sessions ?? [],\n sessionsLoading,\n refetchSessions,\n // Pagination\n page,\n pageSize,\n totalCount,\n totalPages,\n hasMore,\n goToNextPage,\n goToPrevPage,\n // General state\n isLoading: loading || sessionsLoading,\n refetch,\n };\n}\n"],"mappings":";;;;;AA6CA,SAAgB,EACd,IAAuC,EAAE,EACzC;CACA,IAAM,IAAQ,GAAc,EACtB,IAAwB,EAAQ,yBAAyB,IACzD,IAAW,EAAQ,YAAY,IAG/B,CAAC,GAAM,KAAW,EAAS,EAAE,EAE7B,CAAC,KAA0B,EAG/B,EAAuB,EAEnB,EAAE,SAAM,YAAS,eAAY,EACjC,GACA;EACE,MAAM,KAAyB,CAAC,EAAM;EACtC,aAAa;EACb,cAAc,MAAS;EACxB,CACF,EAKK,EACJ,MAAM,GACN,SAAS,GACT,SAAS,MACP,EACF,GACA;EACE,MAAM,CAAC,EAAM;EACb,aAAa;EACb,WAAW,EACT,YAAY;GACV,OAAO;GACP,QAAQ,IAAO;GAChB,EACF;EACD,SAAS,EAAM,cACX,EACE,SAAS,EACP,eAAe,UAAU,EAAM,eAChC,EACF,GACD,KAAA;EACL,CACF,EAGK,CAAC,KAAyB,EAG9B,EAAsB,EAElB,CAAC,KAA6B,EAGlC,EAA0B,EAKtB,IAAiB,OACrB,MACqC;AACrC,MAAI;GACF,IAAM,EAAE,YAAS,MAAM,EAAuB,EAAE,WAAW,EAAE,UAAO,EAAE,CAAC;AACvE,UAAO,EAAM;WACN,GAAO;AAEd,SADA,QAAQ,MAAM,8BAA8B,EAAM,EAC5C;;IAOJ,UACC,GAAM,WAAW,YACf,KAAK,KAAK,GAAG,MAAO,EAAK,UAAU,YADF,IAOpC,UAAsC;AAC1C,MAAI,CAAC,GAAM,WAAW,UAAW,QAAO;EACxC,IAAM,IAAY,EAAK,UAAU,YAAY,KAAK,KAAK,GAAG;AAC1D,SAAO,KAAK,IAAI,GAAG,EAAU;IAMzB,IAAgB,OAAO,MAAwC;AACnE,MAAI;GACF,IAAM,EAAE,YAAS,MAAM,EAAsB,EAC3C,WAAW,EAAE,cAAW,EACzB,CAAC;AAKF,UAJI,GAAM,iBAER,MAAM,GAAiB,EAElB,GAAM,iBAAiB;WACvB,GAAO;AAEd,SADA,QAAQ,MAAM,6BAA6B,EAAM,EAC3C;;IAOJ,IAAoB,YAGpB;AACJ,MAAI;GACF,IAAM,EAAE,YAAS,MAAM,GAA2B;AAKlD,UAJI,GAAM,mBAAmB,WAE3B,MAAM,GAAiB,EAElB,GAAM,qBAAqB;IAAE,SAAS;IAAO,cAAc;IAAG;WAC9D,GAAO;AAEd,SADA,QAAQ,MAAM,kCAAkC,EAAM,EAChD;;IAIJ,IAAa,GAAc,gBAAgB,cAAc,GACzD,IAAU,GAAc,gBAAgB,WAAW,IACnD,IAAa,KAAK,IAAI,GAAG,KAAK,KAAK,IAAa,EAAS,CAAC;AAchE,QAAO;EAEL;EACA;EACA;EACA,WAAW,GAAM;EAEjB;EACA;EACA,gBAAgB,GAAc,gBAAgB,YAAY,EAAE;EAC5D;EACA;EAEA;EACA;EACA;EACA;EACA;EACA,oBA9ByB;AACzB,GAAI,KACF,GAAS,MAAS,IAAO,EAAE;;EA6B7B,oBAzByB;AACzB,GAAI,IAAO,KACT,GAAS,MAAS,IAAO,EAAE;;EAyB7B,WAAW,KAAW;EACtB;EACD"}
1
+ {"version":3,"file":"useSessionOperations.js","names":[],"sources":["../../../src/auth/hooks/useSessionOperations.ts"],"sourcesContent":["import { useState } from \"react\";\nimport { useQuery, useMutation } from \"@apollo/client/react\";\nimport { useAuthStore } from \"../store/authStore\";\nimport {\n TokenInfoDocument,\n ValidateTokensDocument,\n ActiveSessionsDocument,\n RevokeSessionDocument,\n RevokeAllSessionsDocument,\n} from \"../../generated/global-operations\";\nimport type {\n ActiveSessionsQuery,\n ActiveSessionsQueryVariables,\n RevokeSessionMutation,\n RevokeSessionMutationVariables,\n RevokeAllSessionsMutation,\n RevokeAllSessionsMutationVariables,\n} from \"../../generated/global-operations\";\nimport type { TokenValidationResponse, ValidateTokensInput } from \"../types\";\n\n// =============================================================================\n// GRAPHQL RESPONSE INTERFACES\n// =============================================================================\n\ninterface TokenInfoQueryResponse {\n tokenInfo: TokenValidationResponse;\n}\n\ninterface ValidateTokensMutationResponse {\n validateTokens: TokenValidationResponse;\n}\n\ninterface ValidateTokensMutationVariables {\n input: ValidateTokensInput;\n}\n\ninterface UseSessionOperationsOptions {\n disableTokenInfoQuery?: boolean;\n /** Number of sessions to load per page (default: 10) */\n pageSize?: number;\n}\n\n/**\n * Hook for session/token management operations\n */\nexport function useSessionOperations(\n options: UseSessionOperationsOptions = {},\n) {\n const store = useAuthStore();\n const disableTokenInfoQuery = options.disableTokenInfoQuery ?? false;\n const pageSize = options.pageSize ?? 10;\n\n // Pagination state: page is 0-based for offset calculation\n const [page, setPage] = useState(0);\n\n const [validateTokensMutation] = useMutation<\n ValidateTokensMutationResponse,\n ValidateTokensMutationVariables\n >(ValidateTokensDocument);\n\n const { data, loading, refetch } = useQuery<TokenInfoQueryResponse>(\n TokenInfoDocument,\n {\n skip: disableTokenInfoQuery || !store.isAuthenticated,\n fetchPolicy: \"cache-and-network\",\n pollInterval: 5 * 60 * 1000, // Poll every 5 minutes (was 1 min — too aggressive)\n },\n );\n\n // Active sessions query\n // Pass the access token explicitly in Apollo operation context so the query\n // works both via the shell's MultiGatewayProvider auth link and in standalone mode.\n const {\n data: sessionsData,\n loading: sessionsLoading,\n refetch: refetchSessions,\n } = useQuery<ActiveSessionsQuery, ActiveSessionsQueryVariables>(\n ActiveSessionsDocument,\n {\n skip: !store.isAuthenticated,\n fetchPolicy: \"cache-and-network\",\n variables: {\n pagination: {\n limit: pageSize,\n offset: page * pageSize,\n },\n },\n context: store.accessToken\n ? {\n headers: {\n authorization: `Bearer ${store.accessToken}`,\n // activeSessions is a global-layer query scoped to the current user\n // (scopeType: \"self\"). Explicitly clear the workspace-id header so\n // the gateway doesn't attempt workspace scoping for this query.\n \"x-workspace-id\": \"\",\n },\n }\n : undefined,\n },\n );\n\n // Session mutations\n const [revokeSessionMutation] = useMutation<\n RevokeSessionMutation,\n RevokeSessionMutationVariables\n >(RevokeSessionDocument);\n\n const [revokeAllSessionsMutation] = useMutation<\n RevokeAllSessionsMutation,\n RevokeAllSessionsMutationVariables\n >(RevokeAllSessionsDocument);\n\n /**\n * Validate tokens\n */\n const validateTokens = async (\n input: ValidateTokensInput,\n ): Promise<TokenValidationResponse> => {\n try {\n const { data } = await validateTokensMutation({ variables: { input } });\n return data!.validateTokens;\n } catch (error) {\n console.error(\"Failed to validate tokens:\", error);\n throw error;\n }\n };\n\n /**\n * Check if token is expired\n */\n const isTokenExpired = (): boolean => {\n if (!data?.tokenInfo?.expiresAt) return true;\n return Date.now() / 1000 > data.tokenInfo.expiresAt;\n };\n\n /**\n * Get remaining time until token expires (in seconds)\n */\n const getTokenRemainingTime = (): number => {\n if (!data?.tokenInfo?.expiresAt) return 0;\n const remaining = data.tokenInfo.expiresAt - Date.now() / 1000;\n return Math.max(0, remaining);\n };\n\n /**\n * Revoke a specific session by ID\n */\n const revokeSession = async (sessionId: string): Promise<boolean> => {\n try {\n const { data } = await revokeSessionMutation({\n variables: { sessionId },\n });\n if (data?.revokeSession) {\n // Refetch active sessions to reflect the change\n await refetchSessions();\n }\n return data?.revokeSession ?? false;\n } catch (error) {\n console.error(\"Failed to revoke session:\", error);\n throw error;\n }\n };\n\n /**\n * Revoke all sessions except the current one\n */\n const revokeAllSessions = async (): Promise<{\n success: boolean;\n revokedCount: number;\n }> => {\n try {\n const { data } = await revokeAllSessionsMutation();\n if (data?.revokeAllSessions?.success) {\n // Refetch active sessions to reflect the change\n await refetchSessions();\n }\n return data?.revokeAllSessions ?? { success: false, revokedCount: 0 };\n } catch (error) {\n console.error(\"Failed to revoke all sessions:\", error);\n throw error;\n }\n };\n\n const totalCount = sessionsData?.activeSessions?.totalCount ?? 0;\n const hasMore = sessionsData?.activeSessions?.hasMore ?? false;\n const totalPages = Math.max(1, Math.ceil(totalCount / pageSize));\n\n const goToNextPage = () => {\n if (hasMore) {\n setPage((prev) => prev + 1);\n }\n };\n\n const goToPrevPage = () => {\n if (page > 0) {\n setPage((prev) => prev - 1);\n }\n };\n\n return {\n // Token operations\n validateTokens,\n isTokenExpired,\n getTokenRemainingTime,\n tokenInfo: data?.tokenInfo,\n // Session operations\n revokeSession,\n revokeAllSessions,\n activeSessions: sessionsData?.activeSessions?.sessions ?? [],\n sessionsLoading,\n refetchSessions,\n // Pagination\n page,\n pageSize,\n totalCount,\n totalPages,\n hasMore,\n goToNextPage,\n goToPrevPage,\n // General state\n isLoading: loading || sessionsLoading,\n refetch,\n };\n}\n"],"mappings":";;;;;AA6CA,SAAgB,EACd,IAAuC,EAAE,EACzC;CACA,IAAM,IAAQ,GAAc,EACtB,IAAwB,EAAQ,yBAAyB,IACzD,IAAW,EAAQ,YAAY,IAG/B,CAAC,GAAM,KAAW,EAAS,EAAE,EAE7B,CAAC,KAA0B,EAG/B,EAAuB,EAEnB,EAAE,SAAM,YAAS,eAAY,EACjC,GACA;EACE,MAAM,KAAyB,CAAC,EAAM;EACtC,aAAa;EACb,cAAc,MAAS;EACxB,CACF,EAKK,EACJ,MAAM,GACN,SAAS,GACT,SAAS,MACP,EACF,GACA;EACE,MAAM,CAAC,EAAM;EACb,aAAa;EACb,WAAW,EACT,YAAY;GACV,OAAO;GACP,QAAQ,IAAO;GAChB,EACF;EACD,SAAS,EAAM,cACX,EACE,SAAS;GACP,eAAe,UAAU,EAAM;GAI/B,kBAAkB;GACnB,EACF,GACD,KAAA;EACL,CACF,EAGK,CAAC,KAAyB,EAG9B,EAAsB,EAElB,CAAC,KAA6B,EAGlC,EAA0B,EAKtB,IAAiB,OACrB,MACqC;AACrC,MAAI;GACF,IAAM,EAAE,YAAS,MAAM,EAAuB,EAAE,WAAW,EAAE,UAAO,EAAE,CAAC;AACvE,UAAO,EAAM;WACN,GAAO;AAEd,SADA,QAAQ,MAAM,8BAA8B,EAAM,EAC5C;;IAOJ,UACC,GAAM,WAAW,YACf,KAAK,KAAK,GAAG,MAAO,EAAK,UAAU,YADF,IAOpC,UAAsC;AAC1C,MAAI,CAAC,GAAM,WAAW,UAAW,QAAO;EACxC,IAAM,IAAY,EAAK,UAAU,YAAY,KAAK,KAAK,GAAG;AAC1D,SAAO,KAAK,IAAI,GAAG,EAAU;IAMzB,IAAgB,OAAO,MAAwC;AACnE,MAAI;GACF,IAAM,EAAE,YAAS,MAAM,EAAsB,EAC3C,WAAW,EAAE,cAAW,EACzB,CAAC;AAKF,UAJI,GAAM,iBAER,MAAM,GAAiB,EAElB,GAAM,iBAAiB;WACvB,GAAO;AAEd,SADA,QAAQ,MAAM,6BAA6B,EAAM,EAC3C;;IAOJ,IAAoB,YAGpB;AACJ,MAAI;GACF,IAAM,EAAE,YAAS,MAAM,GAA2B;AAKlD,UAJI,GAAM,mBAAmB,WAE3B,MAAM,GAAiB,EAElB,GAAM,qBAAqB;IAAE,SAAS;IAAO,cAAc;IAAG;WAC9D,GAAO;AAEd,SADA,QAAQ,MAAM,kCAAkC,EAAM,EAChD;;IAIJ,IAAa,GAAc,gBAAgB,cAAc,GACzD,IAAU,GAAc,gBAAgB,WAAW,IACnD,IAAa,KAAK,IAAI,GAAG,KAAK,KAAK,IAAa,EAAS,CAAC;AAchE,QAAO;EAEL;EACA;EACA;EACA,WAAW,GAAM;EAEjB;EACA;EACA,gBAAgB,GAAc,gBAAgB,YAAY,EAAE;EAC5D;EACA;EAEA;EACA;EACA;EACA;EACA;EACA,oBA9ByB;AACzB,GAAI,KACF,GAAS,MAAS,IAAO,EAAE;;EA6B7B,oBAzByB;AACzB,GAAI,IAAO,KACT,GAAS,MAAS,IAAO,EAAE;;EAyB7B,WAAW,KAAW;EACtB;EACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"useUserOperations.d.ts","sourceRoot":"","sources":["../../../src/auth/hooks/useUserOperations.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,IAAI,EACJ,cAAc,EACd,eAAe,EACf,eAAe,EACf,gBAAgB,EACjB,MAAM,UAAU,CAAC;AA2DlB,UAAU,sBAAsB;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,oBAAqB,SAAQ,sBAAsB;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,wBAAgB,iBAAiB;kBAqClB,MAAM,KAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;yBAiB7B,eAAe,eACX,eAAe,KAC3B,OAAO,CAAC,cAAc,CAAC;sCAwBZ,sBAAsB,KAAG,OAAO,CAAC,IAAI,CAAC;qBA8BzC,MAAM,SAAS,oBAAoB,KAAG,OAAO,CAAC,IAAI,CAAC;qBAuBnD,MAAM,KAAG,OAAO,CAAC,gBAAgB,CAAC;yBAuBlC,MAAM,KAAG,OAAO,CAAC,gBAAgB,CAAC;;;EAgChD"}
1
+ {"version":3,"file":"useUserOperations.d.ts","sourceRoot":"","sources":["../../../src/auth/hooks/useUserOperations.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,IAAI,EACJ,cAAc,EACd,eAAe,EACf,eAAe,EACf,gBAAgB,EACjB,MAAM,UAAU,CAAC;AA2DlB,UAAU,sBAAsB;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,oBAAqB,SAAQ,sBAAsB;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,wBAAgB,iBAAiB;kBAuClB,MAAM,KAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;yBAsB7B,eAAe,eACX,eAAe,KAC3B,OAAO,CAAC,cAAc,CAAC;sCAyBZ,sBAAsB,KAAG,OAAO,CAAC,IAAI,CAAC;qBAgCzC,MAAM,SAAS,oBAAoB,KAAG,OAAO,CAAC,IAAI,CAAC;qBA0BnD,MAAM,KAAG,OAAO,CAAC,gBAAgB,CAAC;yBA0BlC,MAAM,KAAG,OAAO,CAAC,gBAAgB,CAAC;;;EAiChD"}
@@ -8,7 +8,10 @@ function u() {
8
8
  return {
9
9
  getUser: s(async (e) => {
10
10
  try {
11
- let { data: t } = await m({ variables: { id: e } });
11
+ let { data: t } = await m({
12
+ variables: { id: e },
13
+ context: { headers: { "x-workspace-id": "" } }
14
+ });
12
15
  return t?.user || null;
13
16
  } catch (e) {
14
17
  throw console.error("Failed to get user:", e), e;
@@ -16,10 +19,13 @@ function u() {
16
19
  }, [m]),
17
20
  listUsers: s(async (e, t) => {
18
21
  try {
19
- let { data: n, error: r } = await g({ variables: {
20
- filter: e,
21
- pagination: t
22
- } });
22
+ let { data: n, error: r } = await g({
23
+ variables: {
24
+ filter: e,
25
+ pagination: t
26
+ },
27
+ context: { headers: { "x-workspace-id": "" } }
28
+ });
23
29
  if (r) throw r;
24
30
  return n?.users || {
25
31
  users: [],
@@ -57,10 +63,13 @@ function u() {
57
63
  updateUser: s(async (e, t) => {
58
64
  try {
59
65
  f(!0);
60
- let { data: n } = await y({ variables: {
61
- id: e,
62
- input: t
63
- } });
66
+ let { data: n } = await y({
67
+ variables: {
68
+ id: e,
69
+ input: t
70
+ },
71
+ context: { headers: { "x-workspace-id": "" } }
72
+ });
64
73
  return n.updateUser;
65
74
  } catch (e) {
66
75
  throw console.error("Failed to update user:", e), e;
@@ -71,7 +80,10 @@ function u() {
71
80
  deleteUser: s(async (e) => {
72
81
  try {
73
82
  f(!0);
74
- let { data: t } = await b({ variables: { id: e } });
83
+ let { data: t } = await b({
84
+ variables: { id: e },
85
+ context: { headers: { "x-workspace-id": "" } }
86
+ });
75
87
  return t.deleteUser;
76
88
  } catch (e) {
77
89
  throw console.error("Failed to delete user:", e), e;
@@ -82,7 +94,10 @@ function u() {
82
94
  hardDeleteUser: s(async (e) => {
83
95
  try {
84
96
  f(!0);
85
- let { data: t } = await x({ variables: { id: e } });
97
+ let { data: t } = await x({
98
+ variables: { id: e },
99
+ context: { headers: { "x-workspace-id": "" } }
100
+ });
86
101
  return t.hardDeleteUser;
87
102
  } catch (e) {
88
103
  throw console.error("Failed to hard delete user:", e), e;
@@ -1 +1 @@
1
- {"version":3,"file":"useUserOperations.js","names":[],"sources":["../../../src/auth/hooks/useUserOperations.ts"],"sourcesContent":["import { useMutation, useLazyQuery } from \"@apollo/client/react\";\nimport { useCallback } from \"react\";\nimport { useAuthStore } from \"../store/authStore\";\nimport {\n GetUserDocument,\n ListUsersDocument,\n UpdateCurrentUserProfileDocument,\n UpdateUserDocument,\n DeleteUserDocument,\n HardDeleteUserDocument,\n} from \"../../generated/global-operations\";\nimport type {\n User,\n UserConnection,\n UserFilterInput,\n PaginationInput,\n DeleteUserResult,\n} from \"../types\";\n\n// =============================================================================\n// GRAPHQL RESPONSE TYPES\n// =============================================================================\n\ninterface GetUserQueryVariables {\n id: string;\n}\n\ninterface GetUserQueryResponse {\n user: User | null;\n}\n\ninterface ListUsersQueryVariables {\n filter?: UserFilterInput;\n pagination?: PaginationInput;\n}\n\ninterface ListUsersQueryResponse {\n users: UserConnection;\n}\n\ninterface UpdateCurrentUserProfileVariables {\n input: UpdateUserProfileInput;\n}\n\ninterface UpdateCurrentUserProfileResponse {\n updateCurrentUserProfile: User;\n}\n\ninterface UpdateUserVariables {\n id: string;\n input: AdminUpdateUserInput;\n}\n\ninterface UpdateUserResponse {\n updateUser: User;\n}\n\ninterface DeleteUserVariables {\n id: string;\n}\n\ninterface DeleteUserResponse {\n deleteUser: DeleteUserResult;\n}\n\ninterface HardDeleteUserVariables {\n id: string;\n}\n\ninterface HardDeleteUserResponse {\n hardDeleteUser: DeleteUserResult;\n}\n\n// GraphQL Operations\n\n// Input types for update\ninterface UpdateUserProfileInput {\n avatar?: string;\n username?: string;\n firstName?: string;\n lastName?: string;\n name?: string;\n phoneNumber?: string;\n defaultWorkspaceId?: string;\n language?: string;\n timezone?: string;\n}\n\ninterface AdminUpdateUserInput extends UpdateUserProfileInput {\n role?: string;\n status?: string;\n emailVerified?: boolean;\n}\n\n/**\n * Hook for user management operations\n */\nexport function useUserOperations() {\n const user = useAuthStore((state) => state.user);\n const setUser = useAuthStore((state) => state.setUser);\n const setLoading = useAuthStore((state) => state.setLoading);\n const isLoading = useAuthStore((state) => state.isLoading);\n\n const [getUserQuery, { loading: getUserLoading }] = useLazyQuery<\n GetUserQueryResponse,\n GetUserQueryVariables\n >(GetUserDocument);\n const [listUsersQuery, { loading: listUsersLoading }] = useLazyQuery<\n ListUsersQueryResponse,\n ListUsersQueryVariables\n >(ListUsersDocument, {\n fetchPolicy: \"network-only\",\n });\n const [updateCurrentUserProfileMutation] = useMutation<\n UpdateCurrentUserProfileResponse,\n UpdateCurrentUserProfileVariables\n >(UpdateCurrentUserProfileDocument);\n const [updateUserMutation] = useMutation<\n UpdateUserResponse,\n UpdateUserVariables\n >(UpdateUserDocument);\n const [deleteUserMutation] = useMutation<\n DeleteUserResponse,\n DeleteUserVariables\n >(DeleteUserDocument);\n const [hardDeleteUserMutation] = useMutation<\n HardDeleteUserResponse,\n HardDeleteUserVariables\n >(HardDeleteUserDocument);\n\n /**\n * Get user by ID (admin only)\n */\n const getUser = useCallback(\n async (id: string): Promise<User | null> => {\n try {\n const { data } = await getUserQuery({ variables: { id } });\n return data?.user || null;\n } catch (error) {\n console.error(\"Failed to get user:\", error);\n throw error;\n }\n },\n [getUserQuery],\n );\n\n /**\n * List users with filtering and pagination (admin only)\n */\n const listUsers = useCallback(\n async (\n filter?: UserFilterInput,\n pagination?: PaginationInput,\n ): Promise<UserConnection> => {\n try {\n const { data, error } = await listUsersQuery({\n variables: { filter, pagination },\n });\n\n if (error) throw error;\n return data?.users || { users: [], totalCount: 0, hasMore: false };\n } catch (error) {\n // Ignore abort errors - they happen during component unmount/re-render\n if (error instanceof Error && error.name === \"AbortError\") {\n return { users: [], totalCount: 0, hasMore: false };\n }\n console.error(\"Failed to list users:\", error);\n throw error;\n }\n },\n [listUsersQuery],\n );\n\n /**\n * Update current user's profile\n */\n const updateCurrentUserProfile = useCallback(\n async (input: UpdateUserProfileInput): Promise<User> => {\n try {\n setLoading(true);\n\n const { data } = await updateCurrentUserProfileMutation({\n variables: { input },\n });\n\n const updatedUser = data!.updateCurrentUserProfile;\n\n // Update user in store\n if (user) {\n setUser({ ...user, ...updatedUser });\n }\n\n return updatedUser;\n } catch (error) {\n console.error(\"Failed to update profile:\", error);\n throw error;\n } finally {\n setLoading(false);\n }\n },\n [updateCurrentUserProfileMutation, setLoading, setUser, user],\n );\n\n /**\n * Update user by ID (admin only)\n */\n const updateUser = useCallback(\n async (id: string, input: AdminUpdateUserInput): Promise<User> => {\n try {\n setLoading(true);\n\n const { data } = await updateUserMutation({\n variables: { id, input },\n });\n\n return data!.updateUser;\n } catch (error) {\n console.error(\"Failed to update user:\", error);\n throw error;\n } finally {\n setLoading(false);\n }\n },\n [updateUserMutation, setLoading],\n );\n\n /**\n * Delete user (soft delete, admin only)\n */\n const deleteUser = useCallback(\n async (id: string): Promise<DeleteUserResult> => {\n try {\n setLoading(true);\n\n const { data } = await deleteUserMutation({\n variables: { id },\n });\n\n return data!.deleteUser;\n } catch (error) {\n console.error(\"Failed to delete user:\", error);\n throw error;\n } finally {\n setLoading(false);\n }\n },\n [deleteUserMutation, setLoading],\n );\n\n /**\n * Hard delete user (permanent, super admin only)\n */\n const hardDeleteUser = useCallback(\n async (id: string): Promise<DeleteUserResult> => {\n try {\n setLoading(true);\n\n const { data } = await hardDeleteUserMutation({\n variables: { id },\n });\n\n return data!.hardDeleteUser;\n } catch (error) {\n console.error(\"Failed to hard delete user:\", error);\n throw error;\n } finally {\n setLoading(false);\n }\n },\n [hardDeleteUserMutation, setLoading],\n );\n\n return {\n // Queries\n getUser,\n listUsers,\n // Mutations\n updateCurrentUserProfile,\n updateUser,\n deleteUser,\n hardDeleteUser,\n // State\n currentUser: user,\n isLoading: getUserLoading || listUsersLoading || isLoading,\n };\n}\n"],"mappings":";;;;;AAiGA,SAAgB,IAAoB;CAClC,IAAM,IAAO,GAAc,MAAU,EAAM,KAAK,EAC1C,IAAU,GAAc,MAAU,EAAM,QAAQ,EAChD,IAAa,GAAc,MAAU,EAAM,WAAW,EACtD,IAAY,GAAc,MAAU,EAAM,UAAU,EAEpD,CAAC,GAAc,EAAE,SAAS,OAAoB,EAGlD,EAAgB,EACZ,CAAC,GAAgB,EAAE,SAAS,OAAsB,EAGtD,GAAmB,EACnB,aAAa,gBACd,CAAC,EACI,CAAC,KAAoC,EAGzC,EAAiC,EAC7B,CAAC,KAAsB,EAG3B,EAAmB,EACf,CAAC,KAAsB,EAG3B,EAAmB,EACf,CAAC,KAA0B,EAG/B,EAAuB;AAgJzB,QAAO;EAEL,SA7Ic,EACd,OAAO,MAAqC;AAC1C,OAAI;IACF,IAAM,EAAE,YAAS,MAAM,EAAa,EAAE,WAAW,EAAE,OAAI,EAAE,CAAC;AAC1D,WAAO,GAAM,QAAQ;YACd,GAAO;AAEd,UADA,QAAQ,MAAM,uBAAuB,EAAM,EACrC;;KAGV,CAAC,EAAa,CACf;EAmIC,WA9HgB,EAChB,OACE,GACA,MAC4B;AAC5B,OAAI;IACF,IAAM,EAAE,SAAM,aAAU,MAAM,EAAe,EAC3C,WAAW;KAAE;KAAQ;KAAY,EAClC,CAAC;AAEF,QAAI,EAAO,OAAM;AACjB,WAAO,GAAM,SAAS;KAAE,OAAO,EAAE;KAAE,YAAY;KAAG,SAAS;KAAO;YAC3D,GAAO;AAEd,QAAI,aAAiB,SAAS,EAAM,SAAS,aAC3C,QAAO;KAAE,OAAO,EAAE;KAAE,YAAY;KAAG,SAAS;KAAO;AAGrD,UADA,QAAQ,MAAM,yBAAyB,EAAM,EACvC;;KAGV,CAAC,EAAe,CACjB;EA0GC,0BArG+B,EAC/B,OAAO,MAAiD;AACtD,OAAI;AACF,MAAW,GAAK;IAEhB,IAAM,EAAE,YAAS,MAAM,EAAiC,EACtD,WAAW,EAAE,UAAO,EACrB,CAAC,EAEI,IAAc,EAAM;AAO1B,WAJI,KACF,EAAQ;KAAE,GAAG;KAAM,GAAG;KAAa,CAAC,EAG/B;YACA,GAAO;AAEd,UADA,QAAQ,MAAM,6BAA6B,EAAM,EAC3C;aACE;AACR,MAAW,GAAM;;KAGrB;GAAC;GAAkC;GAAY;GAAS;GAAK,CAC9D;EA6EC,YAxEiB,EACjB,OAAO,GAAY,MAA+C;AAChE,OAAI;AACF,MAAW,GAAK;IAEhB,IAAM,EAAE,YAAS,MAAM,EAAmB,EACxC,WAAW;KAAE;KAAI;KAAO,EACzB,CAAC;AAEF,WAAO,EAAM;YACN,GAAO;AAEd,UADA,QAAQ,MAAM,0BAA0B,EAAM,EACxC;aACE;AACR,MAAW,GAAM;;KAGrB,CAAC,GAAoB,EAAW,CACjC;EAuDC,YAlDiB,EACjB,OAAO,MAA0C;AAC/C,OAAI;AACF,MAAW,GAAK;IAEhB,IAAM,EAAE,YAAS,MAAM,EAAmB,EACxC,WAAW,EAAE,OAAI,EAClB,CAAC;AAEF,WAAO,EAAM;YACN,GAAO;AAEd,UADA,QAAQ,MAAM,0BAA0B,EAAM,EACxC;aACE;AACR,MAAW,GAAM;;KAGrB,CAAC,GAAoB,EAAW,CACjC;EAiCC,gBA5BqB,EACrB,OAAO,MAA0C;AAC/C,OAAI;AACF,MAAW,GAAK;IAEhB,IAAM,EAAE,YAAS,MAAM,EAAuB,EAC5C,WAAW,EAAE,OAAI,EAClB,CAAC;AAEF,WAAO,EAAM;YACN,GAAO;AAEd,UADA,QAAQ,MAAM,+BAA+B,EAAM,EAC7C;aACE;AACR,MAAW,GAAM;;KAGrB,CAAC,GAAwB,EAAW,CACrC;EAYC,aAAa;EACb,WAAW,KAAkB,KAAoB;EAClD"}
1
+ {"version":3,"file":"useUserOperations.js","names":[],"sources":["../../../src/auth/hooks/useUserOperations.ts"],"sourcesContent":["import { useMutation, useLazyQuery } from \"@apollo/client/react\";\nimport { useCallback } from \"react\";\nimport { useAuthStore } from \"../store/authStore\";\nimport {\n GetUserDocument,\n ListUsersDocument,\n UpdateCurrentUserProfileDocument,\n UpdateUserDocument,\n DeleteUserDocument,\n HardDeleteUserDocument,\n} from \"../../generated/global-operations\";\nimport type {\n User,\n UserConnection,\n UserFilterInput,\n PaginationInput,\n DeleteUserResult,\n} from \"../types\";\n\n// =============================================================================\n// GRAPHQL RESPONSE TYPES\n// =============================================================================\n\ninterface GetUserQueryVariables {\n id: string;\n}\n\ninterface GetUserQueryResponse {\n user: User | null;\n}\n\ninterface ListUsersQueryVariables {\n filter?: UserFilterInput;\n pagination?: PaginationInput;\n}\n\ninterface ListUsersQueryResponse {\n users: UserConnection;\n}\n\ninterface UpdateCurrentUserProfileVariables {\n input: UpdateUserProfileInput;\n}\n\ninterface UpdateCurrentUserProfileResponse {\n updateCurrentUserProfile: User;\n}\n\ninterface UpdateUserVariables {\n id: string;\n input: AdminUpdateUserInput;\n}\n\ninterface UpdateUserResponse {\n updateUser: User;\n}\n\ninterface DeleteUserVariables {\n id: string;\n}\n\ninterface DeleteUserResponse {\n deleteUser: DeleteUserResult;\n}\n\ninterface HardDeleteUserVariables {\n id: string;\n}\n\ninterface HardDeleteUserResponse {\n hardDeleteUser: DeleteUserResult;\n}\n\n// GraphQL Operations\n\n// Input types for update\ninterface UpdateUserProfileInput {\n avatar?: string;\n username?: string;\n firstName?: string;\n lastName?: string;\n name?: string;\n phoneNumber?: string;\n defaultWorkspaceId?: string;\n language?: string;\n timezone?: string;\n}\n\ninterface AdminUpdateUserInput extends UpdateUserProfileInput {\n role?: string;\n status?: string;\n emailVerified?: boolean;\n}\n\n/**\n * Hook for user management operations\n */\nexport function useUserOperations() {\n const user = useAuthStore((state) => state.user);\n const setUser = useAuthStore((state) => state.setUser);\n const setLoading = useAuthStore((state) => state.setLoading);\n const isLoading = useAuthStore((state) => state.isLoading);\n\n const [getUserQuery, { loading: getUserLoading }] = useLazyQuery<\n GetUserQueryResponse,\n GetUserQueryVariables\n >(GetUserDocument);\n const [listUsersQuery, { loading: listUsersLoading }] = useLazyQuery<\n ListUsersQueryResponse,\n ListUsersQueryVariables\n >(ListUsersDocument, {\n fetchPolicy: \"network-only\",\n });\n const [updateCurrentUserProfileMutation] = useMutation<\n UpdateCurrentUserProfileResponse,\n UpdateCurrentUserProfileVariables\n >(UpdateCurrentUserProfileDocument);\n const [updateUserMutation] = useMutation<\n UpdateUserResponse,\n UpdateUserVariables\n >(UpdateUserDocument);\n const [deleteUserMutation] = useMutation<\n DeleteUserResponse,\n DeleteUserVariables\n >(DeleteUserDocument);\n const [hardDeleteUserMutation] = useMutation<\n HardDeleteUserResponse,\n HardDeleteUserVariables\n >(HardDeleteUserDocument);\n\n /**\n * Get user by ID (admin only)\n * Uses global-layer context (no x-workspace-id) since user management is\n * a global/tenant operation, not workspace-scoped.\n */\n const getUser = useCallback(\n async (id: string): Promise<User | null> => {\n try {\n const { data } = await getUserQuery({\n variables: { id },\n context: { headers: { \"x-workspace-id\": \"\" } },\n });\n return data?.user || null;\n } catch (error) {\n console.error(\"Failed to get user:\", error);\n throw error;\n }\n },\n [getUserQuery],\n );\n\n /**\n * List users with filtering and pagination (admin only)\n * Uses global-layer context (no x-workspace-id) since user management is\n * a global/tenant operation, not workspace-scoped.\n */\n const listUsers = useCallback(\n async (\n filter?: UserFilterInput,\n pagination?: PaginationInput,\n ): Promise<UserConnection> => {\n try {\n const { data, error } = await listUsersQuery({\n variables: { filter, pagination },\n context: { headers: { \"x-workspace-id\": \"\" } },\n });\n\n if (error) throw error;\n return data?.users || { users: [], totalCount: 0, hasMore: false };\n } catch (error) {\n // Ignore abort errors - they happen during component unmount/re-render\n if (error instanceof Error && error.name === \"AbortError\") {\n return { users: [], totalCount: 0, hasMore: false };\n }\n console.error(\"Failed to list users:\", error);\n throw error;\n }\n },\n [listUsersQuery],\n );\n\n /**\n * Update current user's profile\n */\n const updateCurrentUserProfile = useCallback(\n async (input: UpdateUserProfileInput): Promise<User> => {\n try {\n setLoading(true);\n\n const { data } = await updateCurrentUserProfileMutation({\n variables: { input },\n });\n\n const updatedUser = data!.updateCurrentUserProfile;\n\n // Update user in store\n if (user) {\n setUser({ ...user, ...updatedUser });\n }\n\n return updatedUser;\n } catch (error) {\n console.error(\"Failed to update profile:\", error);\n throw error;\n } finally {\n setLoading(false);\n }\n },\n [updateCurrentUserProfileMutation, setLoading, setUser, user],\n );\n\n /**\n * Update user by ID (admin only)\n * Uses global-layer context (no x-workspace-id) since user management is\n * a global/tenant operation, not workspace-scoped.\n */\n const updateUser = useCallback(\n async (id: string, input: AdminUpdateUserInput): Promise<User> => {\n try {\n setLoading(true);\n\n const { data } = await updateUserMutation({\n variables: { id, input },\n context: { headers: { \"x-workspace-id\": \"\" } },\n });\n\n return data!.updateUser;\n } catch (error) {\n console.error(\"Failed to update user:\", error);\n throw error;\n } finally {\n setLoading(false);\n }\n },\n [updateUserMutation, setLoading],\n );\n\n /**\n * Delete user (soft delete, admin only)\n * Uses global-layer context (no x-workspace-id) since user management is\n * a global/tenant operation, not workspace-scoped.\n */\n const deleteUser = useCallback(\n async (id: string): Promise<DeleteUserResult> => {\n try {\n setLoading(true);\n\n const { data } = await deleteUserMutation({\n variables: { id },\n context: { headers: { \"x-workspace-id\": \"\" } },\n });\n\n return data!.deleteUser;\n } catch (error) {\n console.error(\"Failed to delete user:\", error);\n throw error;\n } finally {\n setLoading(false);\n }\n },\n [deleteUserMutation, setLoading],\n );\n\n /**\n * Hard delete user (permanent, super admin only)\n * Uses global-layer context (no x-workspace-id) since user management is\n * a global/tenant operation, not workspace-scoped.\n */\n const hardDeleteUser = useCallback(\n async (id: string): Promise<DeleteUserResult> => {\n try {\n setLoading(true);\n\n const { data } = await hardDeleteUserMutation({\n variables: { id },\n context: { headers: { \"x-workspace-id\": \"\" } },\n });\n\n return data!.hardDeleteUser;\n } catch (error) {\n console.error(\"Failed to hard delete user:\", error);\n throw error;\n } finally {\n setLoading(false);\n }\n },\n [hardDeleteUserMutation, setLoading],\n );\n\n return {\n // Queries\n getUser,\n listUsers,\n // Mutations\n updateCurrentUserProfile,\n updateUser,\n deleteUser,\n hardDeleteUser,\n // State\n currentUser: user,\n isLoading: getUserLoading || listUsersLoading || isLoading,\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"AuditLogPage.d.ts","sourceRoot":"","sources":["../../../src/auth/pages/AuditLogPage.tsx"],"names":[],"mappings":"AAaA;;;;;;;;;GASG;AACH,wBAAgB,YAAY,4CA2Q3B"}
1
+ {"version":3,"file":"AuditLogPage.d.ts","sourceRoot":"","sources":["../../../src/auth/pages/AuditLogPage.tsx"],"names":[],"mappings":"AAcA;;;;;;;;;GASG;AACH,wBAAgB,YAAY,4CA4Q3B"}