exguard-client 1.0.4 โ 1.0.6
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.
- package/dist/index.cjs +9 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +9 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -182,11 +182,13 @@ var useUserAccess = (options = {}) => {
|
|
|
182
182
|
const [isLoading, setIsLoading] = React.useState(true);
|
|
183
183
|
const [error, setError] = React.useState(null);
|
|
184
184
|
const realtimeContext = React.use(ExGuardRealtimeContext);
|
|
185
|
-
const fetchUserAccess = React.useCallback(async () => {
|
|
185
|
+
const fetchUserAccess = React.useCallback(async (silent = false) => {
|
|
186
186
|
if (!enabled) return;
|
|
187
187
|
try {
|
|
188
|
-
console.log(
|
|
189
|
-
|
|
188
|
+
console.log(`[useUserAccess] \u{1F504} Fetching user access data... ${silent ? "(silent)" : ""}`);
|
|
189
|
+
if (!silent) {
|
|
190
|
+
setIsLoading(true);
|
|
191
|
+
}
|
|
190
192
|
setError(null);
|
|
191
193
|
const data = await getUserAccess();
|
|
192
194
|
setUserAccess(data);
|
|
@@ -201,7 +203,9 @@ var useUserAccess = (options = {}) => {
|
|
|
201
203
|
setError(errorObj);
|
|
202
204
|
console.error("[useUserAccess] \u274C Failed to fetch user access:", errorObj);
|
|
203
205
|
} finally {
|
|
204
|
-
|
|
206
|
+
if (!silent) {
|
|
207
|
+
setIsLoading(false);
|
|
208
|
+
}
|
|
205
209
|
}
|
|
206
210
|
}, [enabled]);
|
|
207
211
|
React.useEffect(() => {
|
|
@@ -210,7 +214,7 @@ var useUserAccess = (options = {}) => {
|
|
|
210
214
|
return;
|
|
211
215
|
}
|
|
212
216
|
console.log("[useUserAccess] \u{1F4E1} Registering RBAC refresh callback");
|
|
213
|
-
const unsubscribe = realtimeContext.registerRbacRefreshCallback(fetchUserAccess);
|
|
217
|
+
const unsubscribe = realtimeContext.registerRbacRefreshCallback(() => fetchUserAccess(true));
|
|
214
218
|
console.log("[useUserAccess] \u2705 RBAC refresh callback registered");
|
|
215
219
|
return () => {
|
|
216
220
|
console.log("[useUserAccess] \u{1F507} Unregistering RBAC refresh callback");
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config/exguard-config.ts","../src/config/realtime-rbac-config.ts","../src/api/exguard-api.ts","../src/providers/exguard-realtime-context.ts","../src/hooks/use-user-access.ts","../src/components/ui/spinner.tsx","../src/components/ui/button.tsx","../src/components/ui/card.tsx","../src/components/permission-guard.tsx","../src/lib/realtime-client.ts","../src/hooks/use-realtime.ts","../src/providers/use-exguard-realtime.ts","../src/hooks/use-exguard-rbac.ts","../src/utils/exguard-realtime-utils.ts","../src/providers/exguard-realtime-provider.tsx","../src/providers/use-exguard-realtime-subscription.ts"],"names":["axios","createContext","useState","use","useCallback","useEffect","jsx","Navigate","jsxs","Lock","ShieldAlert","ArrowLeft","Outlet","io","useRef","React","unsubscribers"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * ExGuard API Configuration\r\n * Configuration for ExGuard backend API\r\n */\r\n\r\nexport interface ExGuardConfig {\r\n apiUrl: string;\r\n withCredentials?: boolean;\r\n}\r\n\r\n/**\r\n * Default ExGuard API configuration\r\n * Note: apiUrl should be provided by the consuming application\r\n */\r\nexport const DEFAULT_EXGUARD_CONFIG: ExGuardConfig = {\r\n apiUrl: '',\r\n withCredentials: true,\r\n};\r\n\r\n/**\r\n * Get ExGuard API URL from environment or provided config\r\n * For Vite apps: import.meta.env.VITE_GUARD_APP_URL\r\n * For Next.js: process.env.NEXT_PUBLIC_GUARD_APP_URL\r\n * Or provide via setExGuardConfig()\r\n */\r\nlet configuredApiUrl: string = '';\r\n\r\nexport const setExGuardConfig = (config: Partial<ExGuardConfig>): void => {\r\n if (config.apiUrl) {\r\n configuredApiUrl = config.apiUrl;\r\n }\r\n};\r\n\r\nexport const getExGuardApiUrl = (): string => {\r\n if (configuredApiUrl) {\r\n return configuredApiUrl;\r\n }\r\n \r\n // Try to get from global environment\r\n if (typeof window !== 'undefined') {\r\n // Check for injected env vars\r\n if ((window as any).__EXGUARD_API_URL__) {\r\n return (window as any).__EXGUARD_API_URL__;\r\n }\r\n }\r\n \r\n // Fallback to localhost for development\r\n return 'http://localhost:3000';\r\n};\r\n\r\n/**\r\n * Storage keys for ExGuard\r\n */\r\nexport const EXGUARD_STORAGE_KEYS = {\r\n ACCESS_TOKEN: 'access_token',\r\n ID_TOKEN: 'id_token',\r\n REFRESH_TOKEN: 'refresh_token',\r\n} as const;\r\n","/**\n * ExGuard Realtime RBAC Configuration\n *\n * This file contains all configuration for realtime RBAC events\n * specific to ExGuard module (users, roles, permissions management)\n */\n\n/**\n * Channels to subscribe to for ExGuard RBAC\n */\nexport const EXGUARD_RBAC_CHANNELS = {\n ROLES: 'roles',\n PERMISSIONS: 'permissions',\n RBAC: 'rbac',\n} as const;\n\n/**\n * Event types for ExGuard RBAC realtime updates\n */\nexport const EXGUARD_RBAC_EVENTS = {\n // Role events\n ROLE_CREATED: 'role:created',\n ROLE_UPDATED: 'role:updated',\n ROLE_DELETED: 'role:deleted',\n\n // Permission events\n PERMISSION_CREATED: 'permission:created',\n PERMISSION_UPDATED: 'permission:updated',\n PERMISSION_DELETED: 'permission:deleted',\n\n // Role-Permission events\n ROLE_PERMISSION_ASSIGNED: 'role-permission:assigned',\n ROLE_PERMISSION_REMOVED: 'role-permission:removed',\n\n // User RBAC events\n USER_ROLES_UPDATED: 'user:roles-updated',\n USER_PERMISSIONS_CHANGED: 'user:permissions-changed',\n USER_ACCESS_CHANGED: 'user:access-changed',\n RBAC_USER_ASSIGNED_TO_GROUP: 'rbac:user-assigned-to-group',\n RBAC_USER_REMOVED_FROM_GROUP: 'rbac:user-removed-from-group',\n RBAC_PERMISSIONS_UPDATED: 'rbac:permissions-updated',\n\n // User status events\n USER_ONLINE: 'user:online',\n USER_OFFLINE: 'user:offline',\n\n // Group events\n GROUP_UPDATED: 'group:updated',\n} as const;\n\n/**\n * Reconnection delay after RBAC updates (in milliseconds)\n * This ensures backend has fully processed the update before refetching data\n */\nexport const RBAC_RECONNECT_DELAY = 300;\n\n/**\n * Configuration for automatic reconnection after specific events\n */\nexport const RBAC_AUTO_RECONNECT_EVENTS = [\n EXGUARD_RBAC_EVENTS.ROLE_UPDATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_UPDATED,\n EXGUARD_RBAC_EVENTS.USER_ACCESS_CHANGED,\n] as const;\n\n/**\n * Events that should trigger user data refresh\n */\nexport const USER_REFRESH_EVENTS = [\n EXGUARD_RBAC_EVENTS.USER_ROLES_UPDATED,\n EXGUARD_RBAC_EVENTS.USER_PERMISSIONS_CHANGED,\n EXGUARD_RBAC_EVENTS.USER_ACCESS_CHANGED,\n EXGUARD_RBAC_EVENTS.RBAC_USER_ASSIGNED_TO_GROUP,\n EXGUARD_RBAC_EVENTS.RBAC_USER_REMOVED_FROM_GROUP,\n EXGUARD_RBAC_EVENTS.RBAC_PERMISSIONS_UPDATED,\n] as const;\n\n/**\n * Events that should trigger role data refresh\n */\nexport const ROLE_REFRESH_EVENTS = [\n EXGUARD_RBAC_EVENTS.ROLE_CREATED,\n EXGUARD_RBAC_EVENTS.ROLE_UPDATED,\n EXGUARD_RBAC_EVENTS.ROLE_DELETED,\n EXGUARD_RBAC_EVENTS.ROLE_PERMISSION_ASSIGNED,\n] as const;\n\n/**\n * Events that should trigger permission data refresh\n */\nexport const PERMISSION_REFRESH_EVENTS = [\n EXGUARD_RBAC_EVENTS.PERMISSION_CREATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_UPDATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_DELETED,\n] as const;\n","import axios, { type AxiosError } from 'axios';\nimport type { VerifyTokenResponse, UserAccessData, AuthApiResponse } from '../types/exguard-types';\nimport { getExGuardApiUrl, EXGUARD_STORAGE_KEYS } from '../config/exguard-config';\n\n// Create a separate axios instance for Guard API endpoints\n// Note: baseURL is set dynamically in the interceptor to support runtime configuration\nconst guardApiClient = axios.create({\n withCredentials: true,\n headers: {\n 'Content-Type': 'application/json',\n },\n});\n\n// Add interceptor to dynamically set baseURL and include access token\nguardApiClient.interceptors.request.use(\n (config) => {\n // Set baseURL dynamically from config (supports runtime configuration)\n config.baseURL = getExGuardApiUrl();\n \n const token = window.localStorage.getItem(EXGUARD_STORAGE_KEYS.ACCESS_TOKEN);\n if (token) {\n config.headers.Authorization = `Bearer ${token}`;\n }\n return config;\n },\n (error: unknown) => Promise.reject(error instanceof Error ? error : new Error(String(error))),\n);\n\n/**\n * Verify ID token with ExGuard backend\n */\nexport async function verifyToken(): Promise<VerifyTokenResponse> {\n try {\n const idToken = window.localStorage.getItem(EXGUARD_STORAGE_KEYS.ID_TOKEN);\n const response = await guardApiClient.post<\n AuthApiResponse<{\n user?: {\n id: string;\n username: string;\n email: string;\n givenName: string;\n familyName: string;\n };\n }>\n >('/guard/verify-token', {\n id_token: idToken,\n });\n\n if (response.data.success && response.data.data) {\n console.log('Token verification response:', response.data.data);\n\n // Map backend response to frontend format\n const backendData = response.data.data;\n const mappedResponse: VerifyTokenResponse = {\n valid: true,\n user: backendData.user\n ? {\n userId: backendData.user.id,\n username: backendData.user.username,\n email: backendData.user.email,\n givenName: backendData.user.givenName,\n familyName: backendData.user.familyName,\n }\n : undefined,\n };\n\n console.log('Mapped user data:', mappedResponse.user);\n return mappedResponse;\n }\n\n throw new Error(response.data.message ?? 'Token verification failed');\n } catch (error) {\n const axiosError = error as AxiosError<AuthApiResponse<never>>;\n\n if (axiosError.response?.data) {\n const errorData = axiosError.response.data;\n const errorMessage = errorData.message ?? 'Token verification failed';\n throw new Error(errorMessage);\n }\n\n throw error;\n }\n}\n\n/**\n * Get user access data including roles, permissions, modules, and field offices\n */\nexport async function getUserAccess(): Promise<UserAccessData> {\n try {\n const response = await guardApiClient.get<AuthApiResponse<UserAccessData>>('/guard/me');\n\n if (response.data.success && response.data.data) {\n console.log('User Access Data:', response.data.data);\n console.log('User Details:', response.data.data.user);\n console.log('User Roles:', response.data.data.roles);\n console.log('User Groups:', response.data.data.groups);\n console.log('User Modules:', response.data.data.modules);\n console.log('User Field Offices:', response.data.data.fieldOffices);\n return response.data.data;\n }\n\n throw new Error(response.data.message ?? 'Failed to get user access data');\n } catch (error) {\n const axiosError = error as AxiosError<AuthApiResponse<never>>;\n\n if (axiosError.response?.data) {\n const errorData = axiosError.response.data;\n const errorMessage = errorData.message ?? 'Failed to get user access data';\n throw new Error(errorMessage);\n }\n\n throw error;\n }\n}\n","/**\n * ExGuard Realtime Context\n *\n * Context for managing realtime RBAC connections and state\n */\n\nimport { createContext } from 'react';\n\nexport interface ExGuardRealtimeContextType {\n isConnected: boolean;\n connect: (token: string, userId: string) => Promise<void>;\n disconnect: () => void;\n reconnect: () => Promise<void>;\n refreshRbac: () => Promise<void>;\n registerRbacRefreshCallback: (callback: () => Promise<void>) => () => void;\n}\n\nexport const ExGuardRealtimeContext = createContext<ExGuardRealtimeContextType | undefined>(undefined);\n","import { useEffect, useState, useCallback, use } from 'react';\r\nimport { getUserAccess } from '../api/exguard-api';\r\nimport type { UserAccessData, ModulePermissions } from '../types/exguard-types';\r\nimport { ExGuardRealtimeContext } from '../providers/exguard-realtime-context';\r\n\r\ninterface UseUserAccessOptions {\r\n enabled?: boolean;\r\n refetchInterval?: number;\r\n}\r\n\r\n/**\r\n * Custom hook to fetch and manage user access data with RBAC\r\n * Includes caching and periodic refetching for real-time RBAC\r\n */\r\nexport const useUserAccess = (options: UseUserAccessOptions = {}) => {\r\n const { enabled = true, refetchInterval = 0 } = options;\r\n const [userAccess, setUserAccess] = useState<UserAccessData | null>(null);\r\n const [isLoading, setIsLoading] = useState(true);\r\n const [error, setError] = useState<Error | null>(null);\r\n const realtimeContext = use(ExGuardRealtimeContext);\r\n\r\n const fetchUserAccess = useCallback(async (): Promise<void> => {\r\n if (!enabled) return;\r\n\r\n try {\r\n console.log('[useUserAccess] ๐ Fetching user access data...');\r\n setIsLoading(true);\r\n setError(null);\r\n const data = await getUserAccess();\r\n setUserAccess(data);\r\n console.log('[useUserAccess] โ
User access refreshed successfully', {\r\n userId: data.user.id,\r\n username: data.user.username,\r\n modulesCount: data.modules.length,\r\n modules: data.modules.map((m) => m.key),\r\n });\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error('Failed to fetch user access');\r\n setError(errorObj);\r\n console.error('[useUserAccess] โ Failed to fetch user access:', errorObj);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [enabled]);\r\n\r\n // Register for real-time RBAC updates from the realtime provider\r\n useEffect(() => {\r\n if (!realtimeContext) {\r\n console.warn('[useUserAccess] โ ๏ธ RealtimeContext not available');\r\n return;\r\n }\r\n\r\n console.log('[useUserAccess] ๐ก Registering RBAC refresh callback');\r\n const unsubscribe = realtimeContext.registerRbacRefreshCallback(fetchUserAccess);\r\n console.log('[useUserAccess] โ
RBAC refresh callback registered');\r\n\r\n return () => {\r\n console.log('[useUserAccess] ๐ Unregistering RBAC refresh callback');\r\n unsubscribe();\r\n };\r\n }, [realtimeContext, fetchUserAccess]);\r\n\r\n useEffect(() => {\r\n void fetchUserAccess();\r\n\r\n if (refetchInterval > 0) {\r\n const interval = setInterval(() => {\r\n void fetchUserAccess();\r\n }, refetchInterval);\r\n\r\n return () => {\r\n clearInterval(interval);\r\n };\r\n }\r\n }, [fetchUserAccess, refetchInterval]);\r\n\r\n const hasModuleAccess = useCallback(\r\n (moduleKey: string): boolean => {\r\n if (!userAccess) return false;\r\n const module = userAccess.modules.find((m: ModulePermissions) => m.key.toLowerCase() === moduleKey.toLowerCase());\r\n return !!module && module.permissions.length > 0;\r\n },\r\n [userAccess],\r\n );\r\n\r\n const getModulePermissions = useCallback(\r\n (moduleKey: string): string[] => {\r\n if (!userAccess) return [];\r\n const module = userAccess.modules.find((m: ModulePermissions) => m.key.toLowerCase() === moduleKey.toLowerCase());\r\n return module?.permissions ?? [];\r\n },\r\n [userAccess],\r\n );\r\n\r\n const hasPermission = useCallback(\r\n (moduleKey: string, permission: string): boolean => {\r\n const permissions = getModulePermissions(moduleKey);\r\n return permissions.includes(permission);\r\n },\r\n [getModulePermissions],\r\n );\r\n\r\n return {\r\n userAccess,\r\n isLoading,\r\n error,\r\n hasModuleAccess,\r\n getModulePermissions,\r\n hasPermission,\r\n refetch: fetchUserAccess,\r\n };\r\n};\r\n","import React from 'react';\r\n\r\ninterface SpinnerProps {\r\n className?: string;\r\n}\r\n\r\nexport function Spinner({ className = '' }: SpinnerProps) {\r\n return (\r\n <div\r\n className={`animate-spin rounded-full border-4 border-solid border-current border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite] ${className}`}\r\n role=\"status\"\r\n >\r\n <span className=\"!absolute !-m-px !h-px !w-px !overflow-hidden !whitespace-nowrap !border-0 !p-0 ![clip:rect(0,0,0,0)]\">\r\n Loading...\r\n </span>\r\n </div>\r\n );\r\n}\r\n","import React from 'react';\r\n\r\ninterface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\r\n variant?: 'default' | 'outline' | 'destructive' | 'ghost' | 'link';\r\n size?: 'default' | 'sm' | 'lg' | 'icon';\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport function Button({\r\n className = '',\r\n variant = 'default',\r\n size = 'default',\r\n children,\r\n ...props\r\n}: ButtonProps) {\r\n const baseStyles =\r\n 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50';\r\n\r\n const variantStyles = {\r\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\r\n outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',\r\n destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',\r\n ghost: 'hover:bg-accent hover:text-accent-foreground',\r\n link: 'text-primary underline-offset-4 hover:underline',\r\n };\r\n\r\n const sizeStyles = {\r\n default: 'h-10 px-4 py-2',\r\n sm: 'h-9 rounded-md px-3',\r\n lg: 'h-11 rounded-md px-8',\r\n icon: 'h-10 w-10',\r\n };\r\n\r\n return (\r\n <button\r\n className={`${baseStyles} ${variantStyles[variant]} ${sizeStyles[size]} ${className}`}\r\n {...props}\r\n >\r\n {children}\r\n </button>\r\n );\r\n}\r\n","import React from 'react';\r\n\r\ninterface CardProps extends React.HTMLAttributes<HTMLDivElement> {\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport function Card({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <div\r\n className={`rounded-lg border bg-card text-card-foreground shadow-sm ${className}`}\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nexport function CardHeader({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <div className={`flex flex-col space-y-1.5 p-6 ${className}`} {...props}>\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nexport function CardTitle({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <h3 className={`text-2xl font-semibold leading-none tracking-tight ${className}`} {...props}>\r\n {children}\r\n </h3>\r\n );\r\n}\r\n\r\nexport function CardDescription({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <p className={`text-sm text-muted-foreground ${className}`} {...props}>\r\n {children}\r\n </p>\r\n );\r\n}\r\n\r\nexport function CardContent({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <div className={`p-6 pt-0 ${className}`} {...props}>\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nexport function CardFooter({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <div className={`flex items-center p-6 pt-0 ${className}`} {...props}>\r\n {children}\r\n </div>\r\n );\r\n}\r\n","import { Navigate, Outlet } from 'react-router';\r\nimport { useUserAccess } from '../hooks/use-user-access';\r\nimport { Spinner } from './ui/spinner';\r\nimport { Button } from './ui/button';\r\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from './ui/card';\r\nimport { ArrowLeft, ShieldAlert, Lock } from 'lucide-react';\r\n\r\ninterface PermissionGuardProps {\r\n module: string;\r\n permission?: string;\r\n requireModule?: boolean;\r\n requirePermission?: boolean;\r\n fallbackPath?: string;\r\n}\r\n\r\n/**\r\n * PermissionGuard component that checks if user has required module access and/or permissions\r\n *\r\n * @param module - The module key (e.g., 'EXID', 'EXFLOW', 'TEV')\r\n * @param permission - Optional specific permission to check (e.g., 'profile:create', 'profile:update')\r\n * @param requireModule - Whether to require module access (default: true)\r\n * @param requirePermission - Whether to require the specific permission (default: true if permission is provided)\r\n * @param fallbackPath - Path to redirect to if access is denied (default: show error page)\r\n */\r\nexport function PermissionGuard({\r\n module,\r\n permission,\r\n requireModule = true,\r\n requirePermission = true,\r\n fallbackPath,\r\n}: PermissionGuardProps) {\r\n const { isLoading, hasModuleAccess, hasPermission } = useUserAccess();\r\n\r\n // Show loading spinner while checking permissions\r\n if (isLoading) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px]\">\r\n <Spinner className=\"size-8\" />\r\n </div>\r\n );\r\n }\r\n\r\n // Check module access\r\n const hasModule = hasModuleAccess(module);\r\n const moduleCheckFailed = requireModule && !hasModule;\r\n\r\n // Check specific permission if provided\r\n const hasSpecificPermission = permission ? hasPermission(module, permission) : true;\r\n const permissionCheckFailed = permission && requirePermission && !hasSpecificPermission;\r\n\r\n // Determine if access should be denied\r\n const accessDenied = moduleCheckFailed || permissionCheckFailed;\r\n\r\n // Redirect to fallback path if provided\r\n if (accessDenied && fallbackPath) {\r\n return <Navigate to={fallbackPath} replace />;\r\n }\r\n\r\n // Show access denied message\r\n if (accessDenied) {\r\n const denialReason = moduleCheckFailed\r\n ? {\r\n title: 'Module Access Required',\r\n description: `Access to the ${module} module is required to view this page`,\r\n detail: `Your current account permissions do not include access to the ${module} module. This module may be restricted to specific roles or user groups.`,\r\n }\r\n : {\r\n title: 'Permission Required',\r\n description: `The permission \"${permission ?? 'unknown'}\" is needed to access this resource`,\r\n detail: `Your account has access to the ${module} module but lacks the specific permission required for this action. This permission may need to be assigned to your role or user group.`,\r\n };\r\n\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[calc(100vh-4rem)] p-6\">\r\n <Card className=\"w-full max-w-lg\">\r\n <CardHeader className=\"text-center pb-4\">\r\n <div className=\"mx-auto mb-4 flex size-16 items-center justify-center rounded-full bg-destructive/10\">\r\n {moduleCheckFailed ? (\r\n <Lock className=\"size-8 text-destructive\" />\r\n ) : (\r\n <ShieldAlert className=\"size-8 text-destructive\" />\r\n )}\r\n </div>\r\n <CardTitle className=\"text-2xl\">{denialReason.title}</CardTitle>\r\n <CardDescription className=\"text-base\">{denialReason.description}</CardDescription>\r\n </CardHeader>\r\n <CardContent className=\"space-y-4\">\r\n <div className=\"rounded-lg bg-muted p-4\">\r\n <p className=\"text-sm text-muted-foreground\">{denialReason.detail}</p>\r\n </div>\r\n <div className=\"flex flex-col gap-2 sm:flex-row sm:justify-center\">\r\n <Button\r\n variant=\"outline\"\r\n onClick={() => {\r\n window.history.back();\r\n }}\r\n className=\"w-full sm:w-auto\"\r\n >\r\n <ArrowLeft className=\"mr-2 size-4\" />\r\n Go Back\r\n </Button>\r\n <Button\r\n variant=\"default\"\r\n onClick={() => {\r\n window.location.href = '/';\r\n }}\r\n className=\"w-full sm:w-auto\"\r\n >\r\n Return to Dashboard\r\n </Button>\r\n </div>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n );\r\n }\r\n\r\n // User has required access, render child routes\r\n return <Outlet />;\r\n}\r\n","import { io, type Socket } from 'socket.io-client';\nimport type { RealtimeEventPayload, RealtimeEventType, RealtimeEventHandler } from './realtime.types';\nimport { getExGuardApiUrl } from '../config/exguard-config';\n\nclass RealtimeClient {\n private socket: Socket | null = null;\n private listeners = new Map<string, Set<RealtimeEventHandler>>();\n private isConnected = false;\n private debug = true; // Enable/disable debug logging\n private connectionPromise: Promise<void> | null = null;\n\n constructor() {\n this.log('๐ข RealtimeClient initialized');\n }\n \n private getApiUrl(): string {\n return getExGuardApiUrl();\n }\n\n private log(message: string, data?: unknown) {\n if (this.debug) {\n console.log(`[RealtimeClient] ${message}`, data);\n }\n }\n\n private logError(message: string, error?: unknown) {\n console.error(`[RealtimeClient] ${message}`, error);\n }\n\n private logWarn(message: string, data?: unknown) {\n console.warn(`[RealtimeClient] ${message}`, data);\n }\n\n /**\n * Connect to the realtime server\n */\n connect(token: string, userId: string): Promise<void> {\n // Validate inputs\n if (!token) {\n this.logError('โ Cannot connect - token is missing or empty');\n return Promise.reject(new Error('Missing authentication token'));\n }\n\n if (!userId) {\n this.logError('โ Cannot connect - userId is missing or empty');\n return Promise.reject(new Error('Missing userId'));\n }\n\n // Return existing connection promise if already connecting\n if (this.connectionPromise) {\n this.log('โณ Connection already in progress, returning existing promise');\n return this.connectionPromise;\n }\n\n this.connectionPromise = new Promise((resolve, reject) => {\n try {\n const apiUrl = this.getApiUrl();\n this.log('๐ Attempting to connect...', { apiUrl, userId, hasToken: !!token });\n\n if (this.socket?.connected) {\n this.log('โ
Already connected');\n this.connectionPromise = null;\n resolve();\n return;\n }\n\n const socketUrl = `${apiUrl}/realtime`;\n this.log('๐ Creating Socket.IO connection', {\n url: socketUrl,\n transports: ['websocket', 'polling'],\n userId,\n });\n\n this.socket = io(socketUrl, {\n auth: {\n token,\n userId,\n },\n transports: ['websocket', 'polling'],\n reconnection: true,\n reconnectionDelay: 1000,\n reconnectionDelayMax: 5000,\n reconnectionAttempts: 5,\n });\n\n this.socket.on('connect', () => {\n this.isConnected = true;\n this.log('โ
Connected to realtime server', {\n socketId: this.socket?.id,\n userId,\n });\n this.connectionPromise = null;\n resolve();\n });\n\n this.socket.on('disconnect', (reason: string) => {\n this.isConnected = false;\n this.log('โ Disconnected from realtime server', { reason });\n });\n\n this.socket.on('connect_error', (error: unknown) => {\n this.logError('โ Connection error (check token and backend)', error);\n this.connectionPromise = null;\n const errorMessage = error instanceof Error ? error.message : String(error);\n reject(new Error(`Connection error: ${errorMessage}`));\n });\n\n this.socket.on('error', (error: unknown) => {\n this.logError('โ Realtime error', error);\n this.connectionPromise = null;\n const errorMessage = error instanceof Error ? error.message : String(error);\n reject(new Error(`Socket.IO error: ${errorMessage}`));\n });\n\n this.socket.on('reconnect_attempt', () => {\n this.log('๐ Attempting to reconnect...');\n });\n\n this.socket.on('reconnect', () => {\n this.isConnected = true;\n this.log('๐ Reconnected to realtime server', {\n socketId: this.socket?.id,\n });\n });\n\n this.socket.on('reconnect_failed', () => {\n this.logError('โ Reconnection failed after maximum attempts');\n this.connectionPromise = null;\n reject(new Error('Reconnection failed'));\n });\n\n // Listen to all realtime events\n this.socket.onAny((eventName: string, payload: unknown) => {\n // Debug: log raw event for troubleshooting\n this.log(`๐จ Raw event received`, {\n eventName,\n payloadType: typeof payload,\n payload,\n });\n\n // Normalize payload - backend sends event name separately from payload\n const payloadObj =\n typeof payload === 'object' && payload !== null ? (payload as Record<string, unknown>) : {};\n\n // CRITICAL FIX: Use eventName as the primary event type (e.g., 'user:access-changed')\n // Socket.IO sends the event name as the first parameter, not nested in payload.type\n const eventType = eventName;\n\n const normalizedPayload: RealtimeEventPayload = {\n type: eventType as RealtimeEventType,\n timestamp:\n 'timestamp' in payloadObj\n ? typeof payloadObj.timestamp === 'number'\n ? payloadObj.timestamp\n : new Date(payloadObj.timestamp as string).getTime()\n : Date.now(),\n data: 'data' in payloadObj ? payloadObj.data : payload,\n };\n\n this.log(`๐จ Event processed: ${eventType}`, {\n type: normalizedPayload.type,\n timestamp: normalizedPayload.timestamp,\n dataKeys:\n typeof normalizedPayload.data === 'object' && normalizedPayload.data !== null\n ? Object.keys(normalizedPayload.data as Record<string, unknown>)\n : 'N/A',\n });\n this.handleEvent(eventType as RealtimeEventType, normalizedPayload);\n });\n } catch (error) {\n this.logError('Failed to initialize connection', error);\n const errorMessage = error instanceof Error ? error.message : String(error);\n reject(new Error(`Connection initialization failed: ${errorMessage}`));\n }\n });\n\n return this.connectionPromise;\n }\n\n /**\n * Disconnect from the realtime server\n */\n disconnect(): void {\n this.log('๐ Disconnecting from realtime server...');\n if (this.socket) {\n this.socket.disconnect();\n this.socket = null;\n this.isConnected = false;\n this.log('โ
Disconnected');\n }\n }\n\n /**\n * Check if connected\n */\n getIsConnected(): boolean {\n return this.isConnected && this.socket?.connected === true;\n }\n\n /**\n * Wait for connection to be ready (with timeout)\n */\n async waitForConnection(timeoutMs = 30000): Promise<void> {\n const startTime = Date.now();\n\n while (Date.now() - startTime < timeoutMs) {\n if (this.getIsConnected()) {\n this.log('โ
Connection ready');\n return;\n }\n\n // Wait 100ms before checking again\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n this.logError('โ Timeout waiting for connection', { timeoutMs, elapsed: Date.now() - startTime });\n throw new Error('Connection timeout - failed to establish WebSocket connection');\n }\n\n /**\n * Subscribe to a specific event type\n */\n subscribe<T extends RealtimeEventPayload = RealtimeEventPayload>(\n eventType: RealtimeEventType,\n handler: RealtimeEventHandler<T>,\n ): () => void {\n if (!this.listeners.has(eventType)) {\n this.listeners.set(eventType, new Set());\n }\n\n this.listeners.get(eventType)?.add(handler as RealtimeEventHandler);\n const listenerCount = this.listeners.get(eventType)?.size ?? 0;\n this.log(`๐ Subscribed to event: ${eventType}`, { totalListeners: listenerCount });\n\n // Return unsubscribe function\n return () => {\n const handlers = this.listeners.get(eventType);\n if (handlers) {\n handlers.delete(handler as RealtimeEventHandler);\n this.log(`๐ Unsubscribed from event: ${eventType}`, {\n remainingListeners: handlers.size,\n });\n }\n };\n }\n\n /**\n * Unsubscribe from an event\n */\n unsubscribe(eventType: RealtimeEventType, handler: RealtimeEventHandler): void {\n const handlers = this.listeners.get(eventType);\n if (handlers) {\n handlers.delete(handler);\n this.log(`๐ Unsubscribed from event: ${eventType}`, {\n remainingListeners: handlers.size,\n });\n }\n }\n /**\n * Send a subscription message to the server with connection wait\n */\n async subscribeToChannel(channel: 'roles' | 'permissions' | 'rbac'): Promise<void> {\n try {\n this.log(`๐ก Subscribing to channel: ${channel}`);\n\n // Wait for connection to be ready\n await this.waitForConnection(15000);\n\n // Now emit subscribe\n this.log(`๐ก Emitting subscribe event for channel: ${channel}`);\n this.socket?.emit(`subscribe:${channel}`);\n this.log(`โ
Subscribed to channel: ${channel}`);\n } catch (error) {\n this.logError(`โ Failed to subscribe to channel \"${channel}\"`, error);\n throw error;\n }\n }\n\n /**\n * Send an unsubscription message to the server\n */\n unsubscribeFromChannel(channel: 'roles' | 'permissions' | 'rbac'): void {\n if (!this.socket?.connected) {\n this.logWarn(`Cannot unsubscribe from channel \"${channel}\" - socket not connected`);\n return;\n }\n\n this.log(`๐ก Unsubscribing from channel: ${channel}`);\n this.socket.emit(`unsubscribe:${channel}`);\n }\n\n /**\n * Handle incoming events\n */\n private handleEvent(eventType: RealtimeEventType, payload: RealtimeEventPayload): void {\n // Call specific event handlers\n const handlers = this.listeners.get(eventType);\n if (handlers && handlers.size > 0) {\n this.log(`๐ Triggering ${String(handlers.size)} handler(s) for event: ${eventType}`);\n handlers.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n this.logError(`Error in event handler for ${eventType}`, error);\n }\n });\n }\n\n // Call wildcard handlers if any\n const wildcardHandlers = this.listeners.get('*' as RealtimeEventType);\n if (wildcardHandlers && wildcardHandlers.size > 0) {\n this.log(`๐ Triggering ${String(wildcardHandlers.size)} wildcard handler(s)`);\n wildcardHandlers.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n this.logError('Error in wildcard event handler', error);\n }\n });\n }\n }\n\n /**\n * Get all connected listeners count\n */\n getListenerCount(eventType?: RealtimeEventType): number {\n if (eventType) {\n return this.listeners.get(eventType)?.size ?? 0;\n }\n let total = 0;\n this.listeners.forEach((handlers) => {\n total += handlers.size;\n });\n return total;\n }\n\n /**\n * Enable or disable debug logging\n */\n setDebug(enabled: boolean): void {\n this.debug = enabled;\n this.log(`Debug logging ${enabled ? 'enabled' : 'disabled'}`);\n }\n\n /**\n * Get connection status summary\n */\n getStatus() {\n const status = {\n isConnected: this.getIsConnected(),\n socketId: this.socket?.id ?? 'N/A',\n apiUrl: this.getApiUrl(),\n totalListeners: this.getListenerCount(),\n listeners: Array.from(this.listeners.entries()).map(([event, handlers]) => ({\n event,\n count: handlers.size,\n })),\n };\n this.log('๐ Connection Status', status);\n return status;\n }\n}\n\n// Create singleton instance\nexport const realtimeClient = new RealtimeClient();\n\n// Expose debug methods on window for console access\nif (typeof window !== 'undefined') {\n const w = window as unknown as Record<string, unknown>;\n w.__realtimeClient = {\n client: realtimeClient,\n connect: (token: string, userId: string) => realtimeClient.connect(token, userId),\n disconnect: () => {\n realtimeClient.disconnect();\n },\n isConnected: () => realtimeClient.getIsConnected(),\n setDebug: (enabled: boolean) => {\n realtimeClient.setDebug(enabled);\n },\n status: () => realtimeClient.getStatus(),\n getListenerCount: (eventType?: RealtimeEventType) => realtimeClient.getListenerCount(eventType),\n };\n console.log('๐ฏ RealtimeClient debug tools available at: window.__realtimeClient');\n}\n\nexport type { RealtimeClient };\n","/**\n * Shared Realtime Hooks\n *\n * Basic hooks for realtime functionality that wraps the realtime-client\n */\n\nimport { useEffect, useRef, useState } from 'react';\nimport { realtimeClient } from '../lib/realtime-client';\nimport type { RealtimeEventType, RealtimeEventPayload, RealtimeEventHandler } from '../lib/realtime.types';\n\n/**\n * Hook to subscribe to realtime RBAC events\n * Automatically handles subscription/unsubscription lifecycle\n */\nexport function useRealtimeRbac<T extends RealtimeEventPayload = RealtimeEventPayload>(\n eventType: RealtimeEventType,\n handler: RealtimeEventHandler<T>,\n) {\n const handlerRef = useRef(handler);\n\n useEffect(() => {\n handlerRef.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const unsubscribe = realtimeClient.subscribe<T>(eventType, (payload) => {\n handlerRef.current(payload);\n });\n\n return () => {\n unsubscribe();\n };\n }, [eventType]);\n}\n\n/**\n * Hook to manage channel subscriptions\n */\nexport function useRealtimeSubscription(channel: 'roles' | 'permissions' | 'rbac') {\n useEffect(() => {\n let isMounted = true;\n\n // Subscribe asynchronously\n realtimeClient.subscribeToChannel(channel).catch((error: unknown) => {\n if (isMounted) {\n console.error(`Failed to subscribe to channel \"${channel}\":`, error);\n }\n });\n\n return () => {\n isMounted = false;\n realtimeClient.unsubscribeFromChannel(channel);\n };\n }, [channel]);\n}\n\n/**\n * Hook to listen to multiple event types\n */\nexport function useRealtimeMultiple(\n events: {\n type: RealtimeEventType;\n handler: RealtimeEventHandler;\n }[],\n) {\n useEffect(() => {\n const unsubscribers = events.map(({ type, handler }) => realtimeClient.subscribe(type, handler));\n\n return () => {\n unsubscribers.forEach((unsub) => {\n unsub();\n });\n };\n }, [events]);\n}\n\n/**\n * Hook to listen to all realtime events\n */\nexport function useRealtimeAll(handler: RealtimeEventHandler) {\n const handlerRef = useRef(handler);\n\n useEffect(() => {\n handlerRef.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const unsubscribe = realtimeClient.subscribe('*' as RealtimeEventType, (payload) => {\n handlerRef.current(payload);\n });\n\n return () => {\n unsubscribe();\n };\n }, []);\n}\n\n/**\n * Hook to get the connection status\n */\nexport function useRealtimeStatus() {\n const [isConnected, setIsConnected] = useState(realtimeClient.getIsConnected());\n\n useEffect(() => {\n const checkConnection = () => {\n setIsConnected(realtimeClient.getIsConnected());\n };\n\n const interval = setInterval(checkConnection, 1000);\n\n return () => {\n clearInterval(interval);\n };\n }, []);\n\n return { isConnected };\n}\n","/**\n * Hook to use ExGuard Realtime Context\n */\n\nimport { use } from 'react';\nimport { ExGuardRealtimeContext, type ExGuardRealtimeContextType } from './exguard-realtime-context';\n\n/**\n * Hook to access ExGuard realtime context\n * Must be used within ExGuardRealtimeProvider\n */\nexport function useExGuardRealtime(): ExGuardRealtimeContextType {\n const context = use(ExGuardRealtimeContext);\n if (!context) {\n throw new Error('useExGuardRealtime must be used within a ExGuardRealtimeProvider');\n }\n return context;\n}\n","/**\n * ExGuard Realtime RBAC Hooks\n *\n * Custom hooks for handling ExGuard-specific realtime RBAC events\n */\n\nimport { useCallback } from 'react';\nimport { useRealtimeRbac, useRealtimeSubscription } from './use-realtime';\nimport { useExGuardRealtime } from '../providers/use-exguard-realtime';\nimport { EXGUARD_RBAC_CHANNELS, EXGUARD_RBAC_EVENTS, RBAC_RECONNECT_DELAY } from '../config/realtime-rbac-config';\nimport type { RealtimeEventPayload } from '../lib/realtime.types';\n\n/**\n * Hook to subscribe to all ExGuard RBAC channels\n */\nexport function useExGuardRbacChannels() {\n useRealtimeSubscription(EXGUARD_RBAC_CHANNELS.RBAC);\n useRealtimeSubscription(EXGUARD_RBAC_CHANNELS.ROLES);\n useRealtimeSubscription(EXGUARD_RBAC_CHANNELS.PERMISSIONS);\n}\n\n/**\n * Hook to handle role updates with automatic reconnection\n */\nexport function useRoleUpdateHandler(onUpdate: () => Promise<void>, fetchUserAccess?: () => Promise<void>) {\n const { reconnect } = useExGuardRealtime();\n\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.ROLE_UPDATED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ Role updated:', (payload.data as { id?: string })?.id ?? payload.data);\n\n try {\n console.log('[ExGuard] ๐ Reconnecting after role update...');\n await reconnect();\n console.log('[ExGuard] โ
Reconnected successfully');\n\n // Delay to ensure backend has processed\n await new Promise((resolve) => setTimeout(resolve, RBAC_RECONNECT_DELAY));\n\n // Refresh data\n const promises = [onUpdate()];\n if (fetchUserAccess) {\n promises.push(fetchUserAccess());\n }\n await Promise.all(promises);\n\n console.log('[ExGuard] โ
Data refreshed after role update');\n } catch (error) {\n console.error('[ExGuard] โ Error handling role update:', error);\n }\n })();\n },\n [reconnect, onUpdate, fetchUserAccess],\n ),\n );\n}\n\n/**\n * Hook to handle user RBAC updates (role assignments, permissions, etc.)\n */\nexport function useUserRbacUpdateHandler(onUpdate: () => Promise<void>) {\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.USER_ROLES_UPDATED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ User roles updated:', payload.data);\n await onUpdate();\n console.log('[ExGuard] โ
User data refreshed');\n })();\n },\n [onUpdate],\n ),\n );\n}\n\n/**\n * Hook to handle permission updates\n */\nexport function usePermissionUpdateHandler(onUpdate: () => Promise<void>) {\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.PERMISSION_UPDATED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ Permission updated:', payload.data);\n await onUpdate();\n console.log('[ExGuard] โ
Permission data refreshed');\n })();\n },\n [onUpdate],\n ),\n );\n}\n\n/**\n * Hook to handle group updates\n */\nexport function useGroupUpdateHandler(onUpdate: () => Promise<void>) {\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.GROUP_UPDATED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ Group updated:', payload.data);\n await onUpdate();\n console.log('[ExGuard] โ
Group data refreshed');\n })();\n },\n [onUpdate],\n ),\n );\n}\n\n/**\n * Hook to handle user access changes (personal notifications)\n * This is for individual user notifications received via user:{cognitoSubId} room\n */\nexport function useUserAccessChangeHandler(onAccessChange: () => Promise<void>) {\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.USER_ACCESS_CHANGED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ฏ Your access has changed:', payload.data);\n await onAccessChange();\n console.log('[ExGuard] โ
User access refreshed');\n })();\n },\n [onAccessChange],\n ),\n );\n}\n","/**\n * ExGuard Realtime Utilities\n *\n * Utility functions for ExGuard realtime functionality\n */\n\nimport { getUserAccess } from '../api/exguard-api';\n\n/**\n * Get current user's Cognito Sub ID from backend\n * This is used for websocket room identification (user:{cognitoSubId})\n */\nexport async function getCurrentUserId(): Promise<string | null> {\n try {\n const userAccess = await getUserAccess();\n console.log('[ExGuardRealtimeUtils] ๐ก Fetched user access:', {\n id: userAccess.user.id,\n cognitoSubId: userAccess.user.cognitoSubId,\n email: userAccess.user.email,\n });\n // CRITICAL: Use cognitoSubId for websocket room targeting, not database UUID\n return userAccess.user.cognitoSubId;\n } catch (error) {\n console.error('[ExGuardRealtimeUtils] Failed to fetch user:', error);\n return null;\n }\n}\n","/**\n * ExGuard Realtime Provider\n *\n * Provider for managing realtime RBAC connections and events\n */\n\nimport React, { useEffect, useRef, type ReactNode } from 'react';\nimport { realtimeClient } from '../lib/realtime-client';\nimport { ExGuardRealtimeContext, type ExGuardRealtimeContextType } from './exguard-realtime-context';\nimport { getCurrentUserId } from '../utils/exguard-realtime-utils';\nimport type { UserRbacEventPayload } from '../lib/realtime.types';\n\ninterface ExGuardRealtimeProviderProps {\n children: ReactNode;\n}\n\nexport function ExGuardRealtimeProvider({ children }: ExGuardRealtimeProviderProps) {\n const [isConnected, setIsConnected] = React.useState(false);\n const connectionAttempted = useRef(false);\n const rbacRefreshCallbacks = useRef<Set<() => Promise<void>>>(new Set());\n const currentUserRef = useRef<{ token: string; userId: string } | null>(null);\n const currentUserIdRef = useRef<string | null>(null);\n\n // Register callback to refresh user access\n const registerRbacRefreshCallback = (callback: () => Promise<void>) => {\n rbacRefreshCallbacks.current.add(callback);\n return () => {\n rbacRefreshCallbacks.current.delete(callback);\n };\n };\n\n // Trigger refresh for all registered callbacks\n const triggerRbacRefresh = async (): Promise<void> => {\n console.log('[ExGuardRealtimeProvider] ๐ Triggering RBAC refresh for all listeners', {\n callbackCount: rbacRefreshCallbacks.current.size,\n });\n\n if (rbacRefreshCallbacks.current.size === 0) {\n console.warn('[ExGuardRealtimeProvider] โ ๏ธ No RBAC refresh callbacks registered!');\n return;\n }\n\n const refreshPromises = Array.from(rbacRefreshCallbacks.current).map((cb, index) => {\n console.log(\n `[ExGuardRealtimeProvider] ๐ Executing callback ${String(index + 1)}/${String(rbacRefreshCallbacks.current.size)}`,\n );\n return cb().catch((err: unknown) => {\n console.error(`[ExGuardRealtimeProvider] โ Error during RBAC refresh callback ${String(index + 1)}:`, err);\n });\n });\n\n await Promise.all(refreshPromises);\n console.log('[ExGuardRealtimeProvider] โ
All RBAC refresh callbacks completed');\n };\n\n // Manual reconnect function\n const handleReconnect = async (): Promise<void> => {\n if (!currentUserRef.current) {\n console.warn('[ExGuardRealtimeProvider] โ ๏ธ No user credentials available for reconnect');\n return;\n }\n const { token, userId } = currentUserRef.current;\n console.log('[ExGuardRealtimeProvider] ๐ Manual reconnect requested for', { userId });\n await handleConnect(token, userId);\n };\n\n // Manual RBAC refresh function\n const handleRefreshRbac = async (): Promise<void> => {\n console.log('[ExGuardRealtimeProvider] ๐ Manual RBAC refresh requested');\n await triggerRbacRefresh();\n };\n\n useEffect(() => {\n const accessToken = localStorage.getItem('access_token');\n\n console.log('[ExGuardRealtimeProvider] ๐ Checking credentials on mount:', {\n hasAccessToken: Boolean(accessToken),\n tokenLength: accessToken?.length,\n });\n\n if (!accessToken) {\n console.warn('[ExGuardRealtimeProvider] โ ๏ธ No access token found in localStorage');\n return;\n }\n\n if (connectionAttempted.current) {\n return;\n }\n\n connectionAttempted.current = true;\n\n // Fetch user info from backend\n const initializeConnection = async (): Promise<void> => {\n try {\n const userId = await getCurrentUserId();\n\n if (!userId) {\n console.error('[ExGuardRealtimeProvider] โ Failed to get userId from backend');\n return;\n }\n\n console.log('[ExGuardRealtimeProvider] ๐ Initiating realtime connection', {\n userId,\n });\n\n currentUserRef.current = { token: accessToken, userId };\n currentUserIdRef.current = userId;\n await realtimeClient.connect(accessToken, userId);\n console.log('[ExGuardRealtimeProvider] โ
Auto-connection successful');\n setIsConnected(true);\n\n // INDIVIDUAL user event listener - NO GLOBAL LISTENERS\n console.log('[ExGuardRealtimeProvider] ๐ง Setting up INDIVIDUAL user notification listener');\n\n // Listen ONLY for THIS USER's access changes (sent to user:{userId} room)\n realtimeClient.subscribe('user:access-changed', (payload: UserRbacEventPayload): void => {\n const { userId: eventUserId, roleId, action } = payload.data;\n console.log('[ExGuardRealtimeProvider] ๐ฏ INDIVIDUAL: Your access has been changed!', {\n eventUserId,\n roleId,\n action,\n currentUserId: currentUserIdRef.current,\n });\n\n // No need to check userId - if this event reached our room (user:{cognitoSubId}),\n // it's definitely for us. Backend ensures correct room targeting.\n console.log('[ExGuardRealtimeProvider] โ
Event received in our personal room! Refreshing access...');\n console.log(\n `[ExGuardRealtimeProvider] ๐ข Triggering RBAC refresh for ${String(rbacRefreshCallbacks.current.size)} registered callbacks`,\n );\n void triggerRbacRefresh();\n });\n\n console.log('[ExGuardRealtimeProvider] โ
Individual user event listener registered');\n } catch (error: unknown) {\n console.error('[ExGuardRealtimeProvider] โ Failed to establish realtime connection:');\n const errorMessage = error instanceof Error ? error.message : String(error);\n const tokenStr = accessToken ? accessToken.substring(0, 20) + '...' : '';\n console.error('[ExGuardRealtimeProvider] Error details:', {\n message: errorMessage,\n token: tokenStr,\n });\n setIsConnected(false);\n }\n };\n\n void initializeConnection();\n\n // Monitor connection status\n let lastConnectedState = realtimeClient.getIsConnected();\n const interval = setInterval(() => {\n const currentConnectedState = realtimeClient.getIsConnected();\n if (currentConnectedState !== lastConnectedState) {\n console.log('[ExGuardRealtimeProvider] ๐ Connection status changed:', {\n from: lastConnectedState,\n to: currentConnectedState,\n });\n lastConnectedState = currentConnectedState;\n setIsConnected(currentConnectedState);\n }\n }, 1000);\n\n return () => {\n clearInterval(interval);\n };\n }, []);\n\n const handleConnect = async (token: string, userId: string) => {\n try {\n console.log('[ExGuardRealtimeProvider] ๐ Manual connection requested', { userId });\n currentUserRef.current = { token, userId };\n await realtimeClient.connect(token, userId);\n setIsConnected(true);\n console.log('[ExGuardRealtimeProvider] โ
Manual connection successful');\n } catch (error: unknown) {\n console.error('[ExGuardRealtimeProvider] โ Failed to connect to realtime:', error);\n setIsConnected(false);\n throw error;\n }\n };\n\n const handleDisconnect = () => {\n console.log('[ExGuardRealtimeProvider] ๐ Disconnection requested');\n realtimeClient.disconnect();\n setIsConnected(false);\n };\n\n const value: ExGuardRealtimeContextType = {\n isConnected,\n connect: handleConnect,\n disconnect: handleDisconnect,\n reconnect: handleReconnect,\n refreshRbac: handleRefreshRbac,\n registerRbacRefreshCallback,\n };\n\n return <ExGuardRealtimeContext value={value}>{children}</ExGuardRealtimeContext>;\n}\n","/**\n * ExGuard Realtime Subscription Hook\n *\n * Hook to subscribe to realtime channels and handle RBAC events\n */\n\nimport { useEffect } from 'react';\nimport { useExGuardRealtime } from './use-exguard-realtime';\nimport { realtimeClient } from '../lib/realtime-client';\nimport { EXGUARD_RBAC_EVENTS, EXGUARD_RBAC_CHANNELS } from '../config/realtime-rbac-config';\nimport type { RealtimeEventType } from '../lib/realtime.types';\n\ninterface UseExGuardRealtimeSubscriptionOptions {\n /** Event types to subscribe to. If not provided, subscribes to all RBAC events */\n events?: RealtimeEventType[];\n /** Whether to auto-subscribe on mount */\n autoSubscribe?: boolean;\n}\n\n/**\n * Hook to subscribe to ExGuard realtime channel and handle RBAC updates\n * @param channel - Channel name ('rbac', 'roles', 'permissions')\n * @param options - Subscription options\n */\nexport function useExGuardRealtimeSubscription(\n channel: keyof typeof EXGUARD_RBAC_CHANNELS = 'RBAC',\n options: UseExGuardRealtimeSubscriptionOptions = {},\n): void {\n const { registerRbacRefreshCallback } = useExGuardRealtime();\n const { autoSubscribe = true, events } = options;\n const channelName = EXGUARD_RBAC_CHANNELS[channel];\n\n useEffect(() => {\n if (!autoSubscribe) {\n return;\n }\n\n console.log(`[useExGuardRealtimeSubscription] ๐ก Subscribing to channel: ${channelName}`);\n\n // Subscribe to channel on server\n void realtimeClient.subscribeToChannel(channelName);\n\n // If specific events provided, subscribe to them\n if (events && events.length > 0) {\n const unsubscribers: (() => void)[] = [];\n\n events.forEach((eventType) => {\n const unsubscribe = realtimeClient.subscribe(eventType, (): void => {\n console.log(`[useExGuardRealtimeSubscription] ๐ Received event: ${eventType}`);\n });\n unsubscribers.push(unsubscribe);\n });\n\n return () => {\n console.log(`[useExGuardRealtimeSubscription] ๐งน Cleaning up subscriptions for channel: ${channelName}`);\n unsubscribers.forEach((unsubscribe) => {\n unsubscribe();\n });\n realtimeClient.unsubscribeFromChannel(channelName);\n };\n }\n\n // Default: subscribe to all RBAC events\n const defaultRbacEvents: RealtimeEventType[] = [\n EXGUARD_RBAC_EVENTS.ROLE_CREATED,\n EXGUARD_RBAC_EVENTS.ROLE_UPDATED,\n EXGUARD_RBAC_EVENTS.ROLE_DELETED,\n EXGUARD_RBAC_EVENTS.PERMISSION_CREATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_UPDATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_DELETED,\n EXGUARD_RBAC_EVENTS.ROLE_PERMISSION_ASSIGNED,\n EXGUARD_RBAC_EVENTS.ROLE_PERMISSION_REMOVED,\n EXGUARD_RBAC_EVENTS.USER_ONLINE,\n EXGUARD_RBAC_EVENTS.GROUP_UPDATED,\n ];\n\n const unsubscribers: (() => void)[] = [];\n\n defaultRbacEvents.forEach((eventType) => {\n const unsubscribe = realtimeClient.subscribe(eventType, (): void => {\n console.log(`[useExGuardRealtimeSubscription] ๐ Received event: ${eventType}`);\n });\n unsubscribers.push(unsubscribe);\n });\n\n // Register callback to trigger RBAC refresh\n const unregisterCallback = registerRbacRefreshCallback(() => {\n console.log(`[useExGuardRealtimeSubscription] ๐ RBAC refresh triggered for channel: ${channelName}`);\n return Promise.resolve();\n });\n\n return () => {\n console.log(`[useExGuardRealtimeSubscription] ๐งน Cleaning up subscriptions for channel: ${channelName}`);\n unsubscribers.forEach((unsubscribe) => {\n unsubscribe();\n });\n unregisterCallback();\n realtimeClient.unsubscribeFromChannel(channelName);\n };\n }, [channelName, autoSubscribe, events, registerRbacRefreshCallback]);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/config/exguard-config.ts","../src/config/realtime-rbac-config.ts","../src/api/exguard-api.ts","../src/providers/exguard-realtime-context.ts","../src/hooks/use-user-access.ts","../src/components/ui/spinner.tsx","../src/components/ui/button.tsx","../src/components/ui/card.tsx","../src/components/permission-guard.tsx","../src/lib/realtime-client.ts","../src/hooks/use-realtime.ts","../src/providers/use-exguard-realtime.ts","../src/hooks/use-exguard-rbac.ts","../src/utils/exguard-realtime-utils.ts","../src/providers/exguard-realtime-provider.tsx","../src/providers/use-exguard-realtime-subscription.ts"],"names":["axios","createContext","useState","use","useCallback","useEffect","jsx","Navigate","jsxs","Lock","ShieldAlert","ArrowLeft","Outlet","io","useRef","React","unsubscribers"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * ExGuard API Configuration\r\n * Configuration for ExGuard backend API\r\n */\r\n\r\nexport interface ExGuardConfig {\r\n apiUrl: string;\r\n withCredentials?: boolean;\r\n}\r\n\r\n/**\r\n * Default ExGuard API configuration\r\n * Note: apiUrl should be provided by the consuming application\r\n */\r\nexport const DEFAULT_EXGUARD_CONFIG: ExGuardConfig = {\r\n apiUrl: '',\r\n withCredentials: true,\r\n};\r\n\r\n/**\r\n * Get ExGuard API URL from environment or provided config\r\n * For Vite apps: import.meta.env.VITE_GUARD_APP_URL\r\n * For Next.js: process.env.NEXT_PUBLIC_GUARD_APP_URL\r\n * Or provide via setExGuardConfig()\r\n */\r\nlet configuredApiUrl: string = '';\r\n\r\nexport const setExGuardConfig = (config: Partial<ExGuardConfig>): void => {\r\n if (config.apiUrl) {\r\n configuredApiUrl = config.apiUrl;\r\n }\r\n};\r\n\r\nexport const getExGuardApiUrl = (): string => {\r\n if (configuredApiUrl) {\r\n return configuredApiUrl;\r\n }\r\n \r\n // Try to get from global environment\r\n if (typeof window !== 'undefined') {\r\n // Check for injected env vars\r\n if ((window as any).__EXGUARD_API_URL__) {\r\n return (window as any).__EXGUARD_API_URL__;\r\n }\r\n }\r\n \r\n // Fallback to localhost for development\r\n return 'http://localhost:3000';\r\n};\r\n\r\n/**\r\n * Storage keys for ExGuard\r\n */\r\nexport const EXGUARD_STORAGE_KEYS = {\r\n ACCESS_TOKEN: 'access_token',\r\n ID_TOKEN: 'id_token',\r\n REFRESH_TOKEN: 'refresh_token',\r\n} as const;\r\n","/**\n * ExGuard Realtime RBAC Configuration\n *\n * This file contains all configuration for realtime RBAC events\n * specific to ExGuard module (users, roles, permissions management)\n */\n\n/**\n * Channels to subscribe to for ExGuard RBAC\n */\nexport const EXGUARD_RBAC_CHANNELS = {\n ROLES: 'roles',\n PERMISSIONS: 'permissions',\n RBAC: 'rbac',\n} as const;\n\n/**\n * Event types for ExGuard RBAC realtime updates\n */\nexport const EXGUARD_RBAC_EVENTS = {\n // Role events\n ROLE_CREATED: 'role:created',\n ROLE_UPDATED: 'role:updated',\n ROLE_DELETED: 'role:deleted',\n\n // Permission events\n PERMISSION_CREATED: 'permission:created',\n PERMISSION_UPDATED: 'permission:updated',\n PERMISSION_DELETED: 'permission:deleted',\n\n // Role-Permission events\n ROLE_PERMISSION_ASSIGNED: 'role-permission:assigned',\n ROLE_PERMISSION_REMOVED: 'role-permission:removed',\n\n // User RBAC events\n USER_ROLES_UPDATED: 'user:roles-updated',\n USER_PERMISSIONS_CHANGED: 'user:permissions-changed',\n USER_ACCESS_CHANGED: 'user:access-changed',\n RBAC_USER_ASSIGNED_TO_GROUP: 'rbac:user-assigned-to-group',\n RBAC_USER_REMOVED_FROM_GROUP: 'rbac:user-removed-from-group',\n RBAC_PERMISSIONS_UPDATED: 'rbac:permissions-updated',\n\n // User status events\n USER_ONLINE: 'user:online',\n USER_OFFLINE: 'user:offline',\n\n // Group events\n GROUP_UPDATED: 'group:updated',\n} as const;\n\n/**\n * Reconnection delay after RBAC updates (in milliseconds)\n * This ensures backend has fully processed the update before refetching data\n */\nexport const RBAC_RECONNECT_DELAY = 300;\n\n/**\n * Configuration for automatic reconnection after specific events\n */\nexport const RBAC_AUTO_RECONNECT_EVENTS = [\n EXGUARD_RBAC_EVENTS.ROLE_UPDATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_UPDATED,\n EXGUARD_RBAC_EVENTS.USER_ACCESS_CHANGED,\n] as const;\n\n/**\n * Events that should trigger user data refresh\n */\nexport const USER_REFRESH_EVENTS = [\n EXGUARD_RBAC_EVENTS.USER_ROLES_UPDATED,\n EXGUARD_RBAC_EVENTS.USER_PERMISSIONS_CHANGED,\n EXGUARD_RBAC_EVENTS.USER_ACCESS_CHANGED,\n EXGUARD_RBAC_EVENTS.RBAC_USER_ASSIGNED_TO_GROUP,\n EXGUARD_RBAC_EVENTS.RBAC_USER_REMOVED_FROM_GROUP,\n EXGUARD_RBAC_EVENTS.RBAC_PERMISSIONS_UPDATED,\n] as const;\n\n/**\n * Events that should trigger role data refresh\n */\nexport const ROLE_REFRESH_EVENTS = [\n EXGUARD_RBAC_EVENTS.ROLE_CREATED,\n EXGUARD_RBAC_EVENTS.ROLE_UPDATED,\n EXGUARD_RBAC_EVENTS.ROLE_DELETED,\n EXGUARD_RBAC_EVENTS.ROLE_PERMISSION_ASSIGNED,\n] as const;\n\n/**\n * Events that should trigger permission data refresh\n */\nexport const PERMISSION_REFRESH_EVENTS = [\n EXGUARD_RBAC_EVENTS.PERMISSION_CREATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_UPDATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_DELETED,\n] as const;\n","import axios, { type AxiosError } from 'axios';\nimport type { VerifyTokenResponse, UserAccessData, AuthApiResponse } from '../types/exguard-types';\nimport { getExGuardApiUrl, EXGUARD_STORAGE_KEYS } from '../config/exguard-config';\n\n// Create a separate axios instance for Guard API endpoints\n// Note: baseURL is set dynamically in the interceptor to support runtime configuration\nconst guardApiClient = axios.create({\n withCredentials: true,\n headers: {\n 'Content-Type': 'application/json',\n },\n});\n\n// Add interceptor to dynamically set baseURL and include access token\nguardApiClient.interceptors.request.use(\n (config) => {\n // Set baseURL dynamically from config (supports runtime configuration)\n config.baseURL = getExGuardApiUrl();\n \n const token = window.localStorage.getItem(EXGUARD_STORAGE_KEYS.ACCESS_TOKEN);\n if (token) {\n config.headers.Authorization = `Bearer ${token}`;\n }\n return config;\n },\n (error: unknown) => Promise.reject(error instanceof Error ? error : new Error(String(error))),\n);\n\n/**\n * Verify ID token with ExGuard backend\n */\nexport async function verifyToken(): Promise<VerifyTokenResponse> {\n try {\n const idToken = window.localStorage.getItem(EXGUARD_STORAGE_KEYS.ID_TOKEN);\n const response = await guardApiClient.post<\n AuthApiResponse<{\n user?: {\n id: string;\n username: string;\n email: string;\n givenName: string;\n familyName: string;\n };\n }>\n >('/guard/verify-token', {\n id_token: idToken,\n });\n\n if (response.data.success && response.data.data) {\n console.log('Token verification response:', response.data.data);\n\n // Map backend response to frontend format\n const backendData = response.data.data;\n const mappedResponse: VerifyTokenResponse = {\n valid: true,\n user: backendData.user\n ? {\n userId: backendData.user.id,\n username: backendData.user.username,\n email: backendData.user.email,\n givenName: backendData.user.givenName,\n familyName: backendData.user.familyName,\n }\n : undefined,\n };\n\n console.log('Mapped user data:', mappedResponse.user);\n return mappedResponse;\n }\n\n throw new Error(response.data.message ?? 'Token verification failed');\n } catch (error) {\n const axiosError = error as AxiosError<AuthApiResponse<never>>;\n\n if (axiosError.response?.data) {\n const errorData = axiosError.response.data;\n const errorMessage = errorData.message ?? 'Token verification failed';\n throw new Error(errorMessage);\n }\n\n throw error;\n }\n}\n\n/**\n * Get user access data including roles, permissions, modules, and field offices\n */\nexport async function getUserAccess(): Promise<UserAccessData> {\n try {\n const response = await guardApiClient.get<AuthApiResponse<UserAccessData>>('/guard/me');\n\n if (response.data.success && response.data.data) {\n console.log('User Access Data:', response.data.data);\n console.log('User Details:', response.data.data.user);\n console.log('User Roles:', response.data.data.roles);\n console.log('User Groups:', response.data.data.groups);\n console.log('User Modules:', response.data.data.modules);\n console.log('User Field Offices:', response.data.data.fieldOffices);\n return response.data.data;\n }\n\n throw new Error(response.data.message ?? 'Failed to get user access data');\n } catch (error) {\n const axiosError = error as AxiosError<AuthApiResponse<never>>;\n\n if (axiosError.response?.data) {\n const errorData = axiosError.response.data;\n const errorMessage = errorData.message ?? 'Failed to get user access data';\n throw new Error(errorMessage);\n }\n\n throw error;\n }\n}\n","/**\n * ExGuard Realtime Context\n *\n * Context for managing realtime RBAC connections and state\n */\n\nimport { createContext } from 'react';\n\nexport interface ExGuardRealtimeContextType {\n isConnected: boolean;\n connect: (token: string, userId: string) => Promise<void>;\n disconnect: () => void;\n reconnect: () => Promise<void>;\n refreshRbac: () => Promise<void>;\n registerRbacRefreshCallback: (callback: () => Promise<void>) => () => void;\n}\n\nexport const ExGuardRealtimeContext = createContext<ExGuardRealtimeContextType | undefined>(undefined);\n","import { useEffect, useState, useCallback, use } from 'react';\r\nimport { getUserAccess } from '../api/exguard-api';\r\nimport type { UserAccessData, ModulePermissions } from '../types/exguard-types';\r\nimport { ExGuardRealtimeContext } from '../providers/exguard-realtime-context';\r\n\r\ninterface UseUserAccessOptions {\r\n enabled?: boolean;\r\n refetchInterval?: number;\r\n}\r\n\r\n/**\r\n * Custom hook to fetch and manage user access data with RBAC\r\n * Includes caching and periodic refetching for real-time RBAC\r\n */\r\nexport const useUserAccess = (options: UseUserAccessOptions = {}) => {\r\n const { enabled = true, refetchInterval = 0 } = options;\r\n const [userAccess, setUserAccess] = useState<UserAccessData | null>(null);\r\n const [isLoading, setIsLoading] = useState(true);\r\n const [error, setError] = useState<Error | null>(null);\r\n const realtimeContext = use(ExGuardRealtimeContext);\r\n\r\n const fetchUserAccess = useCallback(async (silent = false): Promise<void> => {\r\n if (!enabled) return;\r\n\r\n try {\r\n console.log(`[useUserAccess] ๐ Fetching user access data... ${silent ? '(silent)' : ''}`);\r\n // Only set loading state if not silent refresh\r\n if (!silent) {\r\n setIsLoading(true);\r\n }\r\n setError(null);\r\n const data = await getUserAccess();\r\n setUserAccess(data);\r\n console.log('[useUserAccess] โ
User access refreshed successfully', {\r\n userId: data.user.id,\r\n username: data.user.username,\r\n modulesCount: data.modules.length,\r\n modules: data.modules.map((m) => m.key),\r\n });\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error('Failed to fetch user access');\r\n setError(errorObj);\r\n console.error('[useUserAccess] โ Failed to fetch user access:', errorObj);\r\n } finally {\r\n // Only clear loading state if not silent refresh\r\n if (!silent) {\r\n setIsLoading(false);\r\n }\r\n }\r\n }, [enabled]);\r\n\r\n // Register for real-time RBAC updates from the realtime provider\r\n useEffect(() => {\r\n if (!realtimeContext) {\r\n console.warn('[useUserAccess] โ ๏ธ RealtimeContext not available');\r\n return;\r\n }\r\n\r\n console.log('[useUserAccess] ๐ก Registering RBAC refresh callback');\r\n // Use silent refresh for realtime updates to prevent UI disruption\r\n const unsubscribe = realtimeContext.registerRbacRefreshCallback(() => fetchUserAccess(true));\r\n console.log('[useUserAccess] โ
RBAC refresh callback registered');\r\n\r\n return () => {\r\n console.log('[useUserAccess] ๐ Unregistering RBAC refresh callback');\r\n unsubscribe();\r\n };\r\n }, [realtimeContext, fetchUserAccess]);\r\n\r\n useEffect(() => {\r\n void fetchUserAccess();\r\n\r\n if (refetchInterval > 0) {\r\n const interval = setInterval(() => {\r\n void fetchUserAccess();\r\n }, refetchInterval);\r\n\r\n return () => {\r\n clearInterval(interval);\r\n };\r\n }\r\n }, [fetchUserAccess, refetchInterval]);\r\n\r\n const hasModuleAccess = useCallback(\r\n (moduleKey: string): boolean => {\r\n if (!userAccess) return false;\r\n const module = userAccess.modules.find((m: ModulePermissions) => m.key.toLowerCase() === moduleKey.toLowerCase());\r\n return !!module && module.permissions.length > 0;\r\n },\r\n [userAccess],\r\n );\r\n\r\n const getModulePermissions = useCallback(\r\n (moduleKey: string): string[] => {\r\n if (!userAccess) return [];\r\n const module = userAccess.modules.find((m: ModulePermissions) => m.key.toLowerCase() === moduleKey.toLowerCase());\r\n return module?.permissions ?? [];\r\n },\r\n [userAccess],\r\n );\r\n\r\n const hasPermission = useCallback(\r\n (moduleKey: string, permission: string): boolean => {\r\n const permissions = getModulePermissions(moduleKey);\r\n return permissions.includes(permission);\r\n },\r\n [getModulePermissions],\r\n );\r\n\r\n return {\r\n userAccess,\r\n isLoading,\r\n error,\r\n hasModuleAccess,\r\n getModulePermissions,\r\n hasPermission,\r\n refetch: fetchUserAccess,\r\n };\r\n};\r\n","import React from 'react';\r\n\r\ninterface SpinnerProps {\r\n className?: string;\r\n}\r\n\r\nexport function Spinner({ className = '' }: SpinnerProps) {\r\n return (\r\n <div\r\n className={`animate-spin rounded-full border-4 border-solid border-current border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite] ${className}`}\r\n role=\"status\"\r\n >\r\n <span className=\"!absolute !-m-px !h-px !w-px !overflow-hidden !whitespace-nowrap !border-0 !p-0 ![clip:rect(0,0,0,0)]\">\r\n Loading...\r\n </span>\r\n </div>\r\n );\r\n}\r\n","import React from 'react';\r\n\r\ninterface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\r\n variant?: 'default' | 'outline' | 'destructive' | 'ghost' | 'link';\r\n size?: 'default' | 'sm' | 'lg' | 'icon';\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport function Button({\r\n className = '',\r\n variant = 'default',\r\n size = 'default',\r\n children,\r\n ...props\r\n}: ButtonProps) {\r\n const baseStyles =\r\n 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50';\r\n\r\n const variantStyles = {\r\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\r\n outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',\r\n destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',\r\n ghost: 'hover:bg-accent hover:text-accent-foreground',\r\n link: 'text-primary underline-offset-4 hover:underline',\r\n };\r\n\r\n const sizeStyles = {\r\n default: 'h-10 px-4 py-2',\r\n sm: 'h-9 rounded-md px-3',\r\n lg: 'h-11 rounded-md px-8',\r\n icon: 'h-10 w-10',\r\n };\r\n\r\n return (\r\n <button\r\n className={`${baseStyles} ${variantStyles[variant]} ${sizeStyles[size]} ${className}`}\r\n {...props}\r\n >\r\n {children}\r\n </button>\r\n );\r\n}\r\n","import React from 'react';\r\n\r\ninterface CardProps extends React.HTMLAttributes<HTMLDivElement> {\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport function Card({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <div\r\n className={`rounded-lg border bg-card text-card-foreground shadow-sm ${className}`}\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nexport function CardHeader({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <div className={`flex flex-col space-y-1.5 p-6 ${className}`} {...props}>\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nexport function CardTitle({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <h3 className={`text-2xl font-semibold leading-none tracking-tight ${className}`} {...props}>\r\n {children}\r\n </h3>\r\n );\r\n}\r\n\r\nexport function CardDescription({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <p className={`text-sm text-muted-foreground ${className}`} {...props}>\r\n {children}\r\n </p>\r\n );\r\n}\r\n\r\nexport function CardContent({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <div className={`p-6 pt-0 ${className}`} {...props}>\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nexport function CardFooter({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <div className={`flex items-center p-6 pt-0 ${className}`} {...props}>\r\n {children}\r\n </div>\r\n );\r\n}\r\n","import { Navigate, Outlet } from 'react-router';\r\nimport { useUserAccess } from '../hooks/use-user-access';\r\nimport { Spinner } from './ui/spinner';\r\nimport { Button } from './ui/button';\r\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from './ui/card';\r\nimport { ArrowLeft, ShieldAlert, Lock } from 'lucide-react';\r\n\r\ninterface PermissionGuardProps {\r\n module: string;\r\n permission?: string;\r\n requireModule?: boolean;\r\n requirePermission?: boolean;\r\n fallbackPath?: string;\r\n}\r\n\r\n/**\r\n * PermissionGuard component that checks if user has required module access and/or permissions\r\n *\r\n * @param module - The module key (e.g., 'EXID', 'EXFLOW', 'TEV')\r\n * @param permission - Optional specific permission to check (e.g., 'profile:create', 'profile:update')\r\n * @param requireModule - Whether to require module access (default: true)\r\n * @param requirePermission - Whether to require the specific permission (default: true if permission is provided)\r\n * @param fallbackPath - Path to redirect to if access is denied (default: show error page)\r\n */\r\nexport function PermissionGuard({\r\n module,\r\n permission,\r\n requireModule = true,\r\n requirePermission = true,\r\n fallbackPath,\r\n}: PermissionGuardProps) {\r\n const { isLoading, hasModuleAccess, hasPermission } = useUserAccess();\r\n\r\n // Show loading spinner while checking permissions\r\n if (isLoading) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px]\">\r\n <Spinner className=\"size-8\" />\r\n </div>\r\n );\r\n }\r\n\r\n // Check module access\r\n const hasModule = hasModuleAccess(module);\r\n const moduleCheckFailed = requireModule && !hasModule;\r\n\r\n // Check specific permission if provided\r\n const hasSpecificPermission = permission ? hasPermission(module, permission) : true;\r\n const permissionCheckFailed = permission && requirePermission && !hasSpecificPermission;\r\n\r\n // Determine if access should be denied\r\n const accessDenied = moduleCheckFailed || permissionCheckFailed;\r\n\r\n // Redirect to fallback path if provided\r\n if (accessDenied && fallbackPath) {\r\n return <Navigate to={fallbackPath} replace />;\r\n }\r\n\r\n // Show access denied message\r\n if (accessDenied) {\r\n const denialReason = moduleCheckFailed\r\n ? {\r\n title: 'Module Access Required',\r\n description: `Access to the ${module} module is required to view this page`,\r\n detail: `Your current account permissions do not include access to the ${module} module. This module may be restricted to specific roles or user groups.`,\r\n }\r\n : {\r\n title: 'Permission Required',\r\n description: `The permission \"${permission ?? 'unknown'}\" is needed to access this resource`,\r\n detail: `Your account has access to the ${module} module but lacks the specific permission required for this action. This permission may need to be assigned to your role or user group.`,\r\n };\r\n\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[calc(100vh-4rem)] p-6\">\r\n <Card className=\"w-full max-w-lg\">\r\n <CardHeader className=\"text-center pb-4\">\r\n <div className=\"mx-auto mb-4 flex size-16 items-center justify-center rounded-full bg-destructive/10\">\r\n {moduleCheckFailed ? (\r\n <Lock className=\"size-8 text-destructive\" />\r\n ) : (\r\n <ShieldAlert className=\"size-8 text-destructive\" />\r\n )}\r\n </div>\r\n <CardTitle className=\"text-2xl\">{denialReason.title}</CardTitle>\r\n <CardDescription className=\"text-base\">{denialReason.description}</CardDescription>\r\n </CardHeader>\r\n <CardContent className=\"space-y-4\">\r\n <div className=\"rounded-lg bg-muted p-4\">\r\n <p className=\"text-sm text-muted-foreground\">{denialReason.detail}</p>\r\n </div>\r\n <div className=\"flex flex-col gap-2 sm:flex-row sm:justify-center\">\r\n <Button\r\n variant=\"outline\"\r\n onClick={() => {\r\n window.history.back();\r\n }}\r\n className=\"w-full sm:w-auto\"\r\n >\r\n <ArrowLeft className=\"mr-2 size-4\" />\r\n Go Back\r\n </Button>\r\n <Button\r\n variant=\"default\"\r\n onClick={() => {\r\n window.location.href = '/';\r\n }}\r\n className=\"w-full sm:w-auto\"\r\n >\r\n Return to Dashboard\r\n </Button>\r\n </div>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n );\r\n }\r\n\r\n // User has required access, render child routes\r\n return <Outlet />;\r\n}\r\n","import { io, type Socket } from 'socket.io-client';\nimport type { RealtimeEventPayload, RealtimeEventType, RealtimeEventHandler } from './realtime.types';\nimport { getExGuardApiUrl } from '../config/exguard-config';\n\nclass RealtimeClient {\n private socket: Socket | null = null;\n private listeners = new Map<string, Set<RealtimeEventHandler>>();\n private isConnected = false;\n private debug = true; // Enable/disable debug logging\n private connectionPromise: Promise<void> | null = null;\n\n constructor() {\n this.log('๐ข RealtimeClient initialized');\n }\n \n private getApiUrl(): string {\n return getExGuardApiUrl();\n }\n\n private log(message: string, data?: unknown) {\n if (this.debug) {\n console.log(`[RealtimeClient] ${message}`, data);\n }\n }\n\n private logError(message: string, error?: unknown) {\n console.error(`[RealtimeClient] ${message}`, error);\n }\n\n private logWarn(message: string, data?: unknown) {\n console.warn(`[RealtimeClient] ${message}`, data);\n }\n\n /**\n * Connect to the realtime server\n */\n connect(token: string, userId: string): Promise<void> {\n // Validate inputs\n if (!token) {\n this.logError('โ Cannot connect - token is missing or empty');\n return Promise.reject(new Error('Missing authentication token'));\n }\n\n if (!userId) {\n this.logError('โ Cannot connect - userId is missing or empty');\n return Promise.reject(new Error('Missing userId'));\n }\n\n // Return existing connection promise if already connecting\n if (this.connectionPromise) {\n this.log('โณ Connection already in progress, returning existing promise');\n return this.connectionPromise;\n }\n\n this.connectionPromise = new Promise((resolve, reject) => {\n try {\n const apiUrl = this.getApiUrl();\n this.log('๐ Attempting to connect...', { apiUrl, userId, hasToken: !!token });\n\n if (this.socket?.connected) {\n this.log('โ
Already connected');\n this.connectionPromise = null;\n resolve();\n return;\n }\n\n const socketUrl = `${apiUrl}/realtime`;\n this.log('๐ Creating Socket.IO connection', {\n url: socketUrl,\n transports: ['websocket', 'polling'],\n userId,\n });\n\n this.socket = io(socketUrl, {\n auth: {\n token,\n userId,\n },\n transports: ['websocket', 'polling'],\n reconnection: true,\n reconnectionDelay: 1000,\n reconnectionDelayMax: 5000,\n reconnectionAttempts: 5,\n });\n\n this.socket.on('connect', () => {\n this.isConnected = true;\n this.log('โ
Connected to realtime server', {\n socketId: this.socket?.id,\n userId,\n });\n this.connectionPromise = null;\n resolve();\n });\n\n this.socket.on('disconnect', (reason: string) => {\n this.isConnected = false;\n this.log('โ Disconnected from realtime server', { reason });\n });\n\n this.socket.on('connect_error', (error: unknown) => {\n this.logError('โ Connection error (check token and backend)', error);\n this.connectionPromise = null;\n const errorMessage = error instanceof Error ? error.message : String(error);\n reject(new Error(`Connection error: ${errorMessage}`));\n });\n\n this.socket.on('error', (error: unknown) => {\n this.logError('โ Realtime error', error);\n this.connectionPromise = null;\n const errorMessage = error instanceof Error ? error.message : String(error);\n reject(new Error(`Socket.IO error: ${errorMessage}`));\n });\n\n this.socket.on('reconnect_attempt', () => {\n this.log('๐ Attempting to reconnect...');\n });\n\n this.socket.on('reconnect', () => {\n this.isConnected = true;\n this.log('๐ Reconnected to realtime server', {\n socketId: this.socket?.id,\n });\n });\n\n this.socket.on('reconnect_failed', () => {\n this.logError('โ Reconnection failed after maximum attempts');\n this.connectionPromise = null;\n reject(new Error('Reconnection failed'));\n });\n\n // Listen to all realtime events\n this.socket.onAny((eventName: string, payload: unknown) => {\n // Debug: log raw event for troubleshooting\n this.log(`๐จ Raw event received`, {\n eventName,\n payloadType: typeof payload,\n payload,\n });\n\n // Normalize payload - backend sends event name separately from payload\n const payloadObj =\n typeof payload === 'object' && payload !== null ? (payload as Record<string, unknown>) : {};\n\n // CRITICAL FIX: Use eventName as the primary event type (e.g., 'user:access-changed')\n // Socket.IO sends the event name as the first parameter, not nested in payload.type\n const eventType = eventName;\n\n const normalizedPayload: RealtimeEventPayload = {\n type: eventType as RealtimeEventType,\n timestamp:\n 'timestamp' in payloadObj\n ? typeof payloadObj.timestamp === 'number'\n ? payloadObj.timestamp\n : new Date(payloadObj.timestamp as string).getTime()\n : Date.now(),\n data: 'data' in payloadObj ? payloadObj.data : payload,\n };\n\n this.log(`๐จ Event processed: ${eventType}`, {\n type: normalizedPayload.type,\n timestamp: normalizedPayload.timestamp,\n dataKeys:\n typeof normalizedPayload.data === 'object' && normalizedPayload.data !== null\n ? Object.keys(normalizedPayload.data as Record<string, unknown>)\n : 'N/A',\n });\n this.handleEvent(eventType as RealtimeEventType, normalizedPayload);\n });\n } catch (error) {\n this.logError('Failed to initialize connection', error);\n const errorMessage = error instanceof Error ? error.message : String(error);\n reject(new Error(`Connection initialization failed: ${errorMessage}`));\n }\n });\n\n return this.connectionPromise;\n }\n\n /**\n * Disconnect from the realtime server\n */\n disconnect(): void {\n this.log('๐ Disconnecting from realtime server...');\n if (this.socket) {\n this.socket.disconnect();\n this.socket = null;\n this.isConnected = false;\n this.log('โ
Disconnected');\n }\n }\n\n /**\n * Check if connected\n */\n getIsConnected(): boolean {\n return this.isConnected && this.socket?.connected === true;\n }\n\n /**\n * Wait for connection to be ready (with timeout)\n */\n async waitForConnection(timeoutMs = 30000): Promise<void> {\n const startTime = Date.now();\n\n while (Date.now() - startTime < timeoutMs) {\n if (this.getIsConnected()) {\n this.log('โ
Connection ready');\n return;\n }\n\n // Wait 100ms before checking again\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n this.logError('โ Timeout waiting for connection', { timeoutMs, elapsed: Date.now() - startTime });\n throw new Error('Connection timeout - failed to establish WebSocket connection');\n }\n\n /**\n * Subscribe to a specific event type\n */\n subscribe<T extends RealtimeEventPayload = RealtimeEventPayload>(\n eventType: RealtimeEventType,\n handler: RealtimeEventHandler<T>,\n ): () => void {\n if (!this.listeners.has(eventType)) {\n this.listeners.set(eventType, new Set());\n }\n\n this.listeners.get(eventType)?.add(handler as RealtimeEventHandler);\n const listenerCount = this.listeners.get(eventType)?.size ?? 0;\n this.log(`๐ Subscribed to event: ${eventType}`, { totalListeners: listenerCount });\n\n // Return unsubscribe function\n return () => {\n const handlers = this.listeners.get(eventType);\n if (handlers) {\n handlers.delete(handler as RealtimeEventHandler);\n this.log(`๐ Unsubscribed from event: ${eventType}`, {\n remainingListeners: handlers.size,\n });\n }\n };\n }\n\n /**\n * Unsubscribe from an event\n */\n unsubscribe(eventType: RealtimeEventType, handler: RealtimeEventHandler): void {\n const handlers = this.listeners.get(eventType);\n if (handlers) {\n handlers.delete(handler);\n this.log(`๐ Unsubscribed from event: ${eventType}`, {\n remainingListeners: handlers.size,\n });\n }\n }\n /**\n * Send a subscription message to the server with connection wait\n */\n async subscribeToChannel(channel: 'roles' | 'permissions' | 'rbac'): Promise<void> {\n try {\n this.log(`๐ก Subscribing to channel: ${channel}`);\n\n // Wait for connection to be ready\n await this.waitForConnection(15000);\n\n // Now emit subscribe\n this.log(`๐ก Emitting subscribe event for channel: ${channel}`);\n this.socket?.emit(`subscribe:${channel}`);\n this.log(`โ
Subscribed to channel: ${channel}`);\n } catch (error) {\n this.logError(`โ Failed to subscribe to channel \"${channel}\"`, error);\n throw error;\n }\n }\n\n /**\n * Send an unsubscription message to the server\n */\n unsubscribeFromChannel(channel: 'roles' | 'permissions' | 'rbac'): void {\n if (!this.socket?.connected) {\n this.logWarn(`Cannot unsubscribe from channel \"${channel}\" - socket not connected`);\n return;\n }\n\n this.log(`๐ก Unsubscribing from channel: ${channel}`);\n this.socket.emit(`unsubscribe:${channel}`);\n }\n\n /**\n * Handle incoming events\n */\n private handleEvent(eventType: RealtimeEventType, payload: RealtimeEventPayload): void {\n // Call specific event handlers\n const handlers = this.listeners.get(eventType);\n if (handlers && handlers.size > 0) {\n this.log(`๐ Triggering ${String(handlers.size)} handler(s) for event: ${eventType}`);\n handlers.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n this.logError(`Error in event handler for ${eventType}`, error);\n }\n });\n }\n\n // Call wildcard handlers if any\n const wildcardHandlers = this.listeners.get('*' as RealtimeEventType);\n if (wildcardHandlers && wildcardHandlers.size > 0) {\n this.log(`๐ Triggering ${String(wildcardHandlers.size)} wildcard handler(s)`);\n wildcardHandlers.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n this.logError('Error in wildcard event handler', error);\n }\n });\n }\n }\n\n /**\n * Get all connected listeners count\n */\n getListenerCount(eventType?: RealtimeEventType): number {\n if (eventType) {\n return this.listeners.get(eventType)?.size ?? 0;\n }\n let total = 0;\n this.listeners.forEach((handlers) => {\n total += handlers.size;\n });\n return total;\n }\n\n /**\n * Enable or disable debug logging\n */\n setDebug(enabled: boolean): void {\n this.debug = enabled;\n this.log(`Debug logging ${enabled ? 'enabled' : 'disabled'}`);\n }\n\n /**\n * Get connection status summary\n */\n getStatus() {\n const status = {\n isConnected: this.getIsConnected(),\n socketId: this.socket?.id ?? 'N/A',\n apiUrl: this.getApiUrl(),\n totalListeners: this.getListenerCount(),\n listeners: Array.from(this.listeners.entries()).map(([event, handlers]) => ({\n event,\n count: handlers.size,\n })),\n };\n this.log('๐ Connection Status', status);\n return status;\n }\n}\n\n// Create singleton instance\nexport const realtimeClient = new RealtimeClient();\n\n// Expose debug methods on window for console access\nif (typeof window !== 'undefined') {\n const w = window as unknown as Record<string, unknown>;\n w.__realtimeClient = {\n client: realtimeClient,\n connect: (token: string, userId: string) => realtimeClient.connect(token, userId),\n disconnect: () => {\n realtimeClient.disconnect();\n },\n isConnected: () => realtimeClient.getIsConnected(),\n setDebug: (enabled: boolean) => {\n realtimeClient.setDebug(enabled);\n },\n status: () => realtimeClient.getStatus(),\n getListenerCount: (eventType?: RealtimeEventType) => realtimeClient.getListenerCount(eventType),\n };\n console.log('๐ฏ RealtimeClient debug tools available at: window.__realtimeClient');\n}\n\nexport type { RealtimeClient };\n","/**\n * Shared Realtime Hooks\n *\n * Basic hooks for realtime functionality that wraps the realtime-client\n */\n\nimport { useEffect, useRef, useState } from 'react';\nimport { realtimeClient } from '../lib/realtime-client';\nimport type { RealtimeEventType, RealtimeEventPayload, RealtimeEventHandler } from '../lib/realtime.types';\n\n/**\n * Hook to subscribe to realtime RBAC events\n * Automatically handles subscription/unsubscription lifecycle\n */\nexport function useRealtimeRbac<T extends RealtimeEventPayload = RealtimeEventPayload>(\n eventType: RealtimeEventType,\n handler: RealtimeEventHandler<T>,\n) {\n const handlerRef = useRef(handler);\n\n useEffect(() => {\n handlerRef.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const unsubscribe = realtimeClient.subscribe<T>(eventType, (payload) => {\n handlerRef.current(payload);\n });\n\n return () => {\n unsubscribe();\n };\n }, [eventType]);\n}\n\n/**\n * Hook to manage channel subscriptions\n */\nexport function useRealtimeSubscription(channel: 'roles' | 'permissions' | 'rbac') {\n useEffect(() => {\n let isMounted = true;\n\n // Subscribe asynchronously\n realtimeClient.subscribeToChannel(channel).catch((error: unknown) => {\n if (isMounted) {\n console.error(`Failed to subscribe to channel \"${channel}\":`, error);\n }\n });\n\n return () => {\n isMounted = false;\n realtimeClient.unsubscribeFromChannel(channel);\n };\n }, [channel]);\n}\n\n/**\n * Hook to listen to multiple event types\n */\nexport function useRealtimeMultiple(\n events: {\n type: RealtimeEventType;\n handler: RealtimeEventHandler;\n }[],\n) {\n useEffect(() => {\n const unsubscribers = events.map(({ type, handler }) => realtimeClient.subscribe(type, handler));\n\n return () => {\n unsubscribers.forEach((unsub) => {\n unsub();\n });\n };\n }, [events]);\n}\n\n/**\n * Hook to listen to all realtime events\n */\nexport function useRealtimeAll(handler: RealtimeEventHandler) {\n const handlerRef = useRef(handler);\n\n useEffect(() => {\n handlerRef.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const unsubscribe = realtimeClient.subscribe('*' as RealtimeEventType, (payload) => {\n handlerRef.current(payload);\n });\n\n return () => {\n unsubscribe();\n };\n }, []);\n}\n\n/**\n * Hook to get the connection status\n */\nexport function useRealtimeStatus() {\n const [isConnected, setIsConnected] = useState(realtimeClient.getIsConnected());\n\n useEffect(() => {\n const checkConnection = () => {\n setIsConnected(realtimeClient.getIsConnected());\n };\n\n const interval = setInterval(checkConnection, 1000);\n\n return () => {\n clearInterval(interval);\n };\n }, []);\n\n return { isConnected };\n}\n","/**\n * Hook to use ExGuard Realtime Context\n */\n\nimport { use } from 'react';\nimport { ExGuardRealtimeContext, type ExGuardRealtimeContextType } from './exguard-realtime-context';\n\n/**\n * Hook to access ExGuard realtime context\n * Must be used within ExGuardRealtimeProvider\n */\nexport function useExGuardRealtime(): ExGuardRealtimeContextType {\n const context = use(ExGuardRealtimeContext);\n if (!context) {\n throw new Error('useExGuardRealtime must be used within a ExGuardRealtimeProvider');\n }\n return context;\n}\n","/**\n * ExGuard Realtime RBAC Hooks\n *\n * Custom hooks for handling ExGuard-specific realtime RBAC events\n */\n\nimport { useCallback } from 'react';\nimport { useRealtimeRbac, useRealtimeSubscription } from './use-realtime';\nimport { useExGuardRealtime } from '../providers/use-exguard-realtime';\nimport { EXGUARD_RBAC_CHANNELS, EXGUARD_RBAC_EVENTS, RBAC_RECONNECT_DELAY } from '../config/realtime-rbac-config';\nimport type { RealtimeEventPayload } from '../lib/realtime.types';\n\n/**\n * Hook to subscribe to all ExGuard RBAC channels\n */\nexport function useExGuardRbacChannels() {\n useRealtimeSubscription(EXGUARD_RBAC_CHANNELS.RBAC);\n useRealtimeSubscription(EXGUARD_RBAC_CHANNELS.ROLES);\n useRealtimeSubscription(EXGUARD_RBAC_CHANNELS.PERMISSIONS);\n}\n\n/**\n * Hook to handle role updates with automatic reconnection\n */\nexport function useRoleUpdateHandler(onUpdate: () => Promise<void>, fetchUserAccess?: () => Promise<void>) {\n const { reconnect } = useExGuardRealtime();\n\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.ROLE_UPDATED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ Role updated:', (payload.data as { id?: string })?.id ?? payload.data);\n\n try {\n console.log('[ExGuard] ๐ Reconnecting after role update...');\n await reconnect();\n console.log('[ExGuard] โ
Reconnected successfully');\n\n // Delay to ensure backend has processed\n await new Promise((resolve) => setTimeout(resolve, RBAC_RECONNECT_DELAY));\n\n // Refresh data\n const promises = [onUpdate()];\n if (fetchUserAccess) {\n promises.push(fetchUserAccess());\n }\n await Promise.all(promises);\n\n console.log('[ExGuard] โ
Data refreshed after role update');\n } catch (error) {\n console.error('[ExGuard] โ Error handling role update:', error);\n }\n })();\n },\n [reconnect, onUpdate, fetchUserAccess],\n ),\n );\n}\n\n/**\n * Hook to handle user RBAC updates (role assignments, permissions, etc.)\n */\nexport function useUserRbacUpdateHandler(onUpdate: () => Promise<void>) {\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.USER_ROLES_UPDATED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ User roles updated:', payload.data);\n await onUpdate();\n console.log('[ExGuard] โ
User data refreshed');\n })();\n },\n [onUpdate],\n ),\n );\n}\n\n/**\n * Hook to handle permission updates\n */\nexport function usePermissionUpdateHandler(onUpdate: () => Promise<void>) {\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.PERMISSION_UPDATED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ Permission updated:', payload.data);\n await onUpdate();\n console.log('[ExGuard] โ
Permission data refreshed');\n })();\n },\n [onUpdate],\n ),\n );\n}\n\n/**\n * Hook to handle group updates\n */\nexport function useGroupUpdateHandler(onUpdate: () => Promise<void>) {\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.GROUP_UPDATED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ Group updated:', payload.data);\n await onUpdate();\n console.log('[ExGuard] โ
Group data refreshed');\n })();\n },\n [onUpdate],\n ),\n );\n}\n\n/**\n * Hook to handle user access changes (personal notifications)\n * This is for individual user notifications received via user:{cognitoSubId} room\n */\nexport function useUserAccessChangeHandler(onAccessChange: () => Promise<void>) {\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.USER_ACCESS_CHANGED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ฏ Your access has changed:', payload.data);\n await onAccessChange();\n console.log('[ExGuard] โ
User access refreshed');\n })();\n },\n [onAccessChange],\n ),\n );\n}\n","/**\n * ExGuard Realtime Utilities\n *\n * Utility functions for ExGuard realtime functionality\n */\n\nimport { getUserAccess } from '../api/exguard-api';\n\n/**\n * Get current user's Cognito Sub ID from backend\n * This is used for websocket room identification (user:{cognitoSubId})\n */\nexport async function getCurrentUserId(): Promise<string | null> {\n try {\n const userAccess = await getUserAccess();\n console.log('[ExGuardRealtimeUtils] ๐ก Fetched user access:', {\n id: userAccess.user.id,\n cognitoSubId: userAccess.user.cognitoSubId,\n email: userAccess.user.email,\n });\n // CRITICAL: Use cognitoSubId for websocket room targeting, not database UUID\n return userAccess.user.cognitoSubId;\n } catch (error) {\n console.error('[ExGuardRealtimeUtils] Failed to fetch user:', error);\n return null;\n }\n}\n","/**\n * ExGuard Realtime Provider\n *\n * Provider for managing realtime RBAC connections and events\n */\n\nimport React, { useEffect, useRef, type ReactNode } from 'react';\nimport { realtimeClient } from '../lib/realtime-client';\nimport { ExGuardRealtimeContext, type ExGuardRealtimeContextType } from './exguard-realtime-context';\nimport { getCurrentUserId } from '../utils/exguard-realtime-utils';\nimport type { UserRbacEventPayload } from '../lib/realtime.types';\n\ninterface ExGuardRealtimeProviderProps {\n children: ReactNode;\n}\n\nexport function ExGuardRealtimeProvider({ children }: ExGuardRealtimeProviderProps) {\n const [isConnected, setIsConnected] = React.useState(false);\n const connectionAttempted = useRef(false);\n const rbacRefreshCallbacks = useRef<Set<() => Promise<void>>>(new Set());\n const currentUserRef = useRef<{ token: string; userId: string } | null>(null);\n const currentUserIdRef = useRef<string | null>(null);\n\n // Register callback to refresh user access\n const registerRbacRefreshCallback = (callback: () => Promise<void>) => {\n rbacRefreshCallbacks.current.add(callback);\n return () => {\n rbacRefreshCallbacks.current.delete(callback);\n };\n };\n\n // Trigger refresh for all registered callbacks\n const triggerRbacRefresh = async (): Promise<void> => {\n console.log('[ExGuardRealtimeProvider] ๐ Triggering RBAC refresh for all listeners', {\n callbackCount: rbacRefreshCallbacks.current.size,\n });\n\n if (rbacRefreshCallbacks.current.size === 0) {\n console.warn('[ExGuardRealtimeProvider] โ ๏ธ No RBAC refresh callbacks registered!');\n return;\n }\n\n const refreshPromises = Array.from(rbacRefreshCallbacks.current).map((cb, index) => {\n console.log(\n `[ExGuardRealtimeProvider] ๐ Executing callback ${String(index + 1)}/${String(rbacRefreshCallbacks.current.size)}`,\n );\n return cb().catch((err: unknown) => {\n console.error(`[ExGuardRealtimeProvider] โ Error during RBAC refresh callback ${String(index + 1)}:`, err);\n });\n });\n\n await Promise.all(refreshPromises);\n console.log('[ExGuardRealtimeProvider] โ
All RBAC refresh callbacks completed');\n };\n\n // Manual reconnect function\n const handleReconnect = async (): Promise<void> => {\n if (!currentUserRef.current) {\n console.warn('[ExGuardRealtimeProvider] โ ๏ธ No user credentials available for reconnect');\n return;\n }\n const { token, userId } = currentUserRef.current;\n console.log('[ExGuardRealtimeProvider] ๐ Manual reconnect requested for', { userId });\n await handleConnect(token, userId);\n };\n\n // Manual RBAC refresh function\n const handleRefreshRbac = async (): Promise<void> => {\n console.log('[ExGuardRealtimeProvider] ๐ Manual RBAC refresh requested');\n await triggerRbacRefresh();\n };\n\n useEffect(() => {\n const accessToken = localStorage.getItem('access_token');\n\n console.log('[ExGuardRealtimeProvider] ๐ Checking credentials on mount:', {\n hasAccessToken: Boolean(accessToken),\n tokenLength: accessToken?.length,\n });\n\n if (!accessToken) {\n console.warn('[ExGuardRealtimeProvider] โ ๏ธ No access token found in localStorage');\n return;\n }\n\n if (connectionAttempted.current) {\n return;\n }\n\n connectionAttempted.current = true;\n\n // Fetch user info from backend\n const initializeConnection = async (): Promise<void> => {\n try {\n const userId = await getCurrentUserId();\n\n if (!userId) {\n console.error('[ExGuardRealtimeProvider] โ Failed to get userId from backend');\n return;\n }\n\n console.log('[ExGuardRealtimeProvider] ๐ Initiating realtime connection', {\n userId,\n });\n\n currentUserRef.current = { token: accessToken, userId };\n currentUserIdRef.current = userId;\n await realtimeClient.connect(accessToken, userId);\n console.log('[ExGuardRealtimeProvider] โ
Auto-connection successful');\n setIsConnected(true);\n\n // INDIVIDUAL user event listener - NO GLOBAL LISTENERS\n console.log('[ExGuardRealtimeProvider] ๐ง Setting up INDIVIDUAL user notification listener');\n\n // Listen ONLY for THIS USER's access changes (sent to user:{userId} room)\n realtimeClient.subscribe('user:access-changed', (payload: UserRbacEventPayload): void => {\n const { userId: eventUserId, roleId, action } = payload.data;\n console.log('[ExGuardRealtimeProvider] ๐ฏ INDIVIDUAL: Your access has been changed!', {\n eventUserId,\n roleId,\n action,\n currentUserId: currentUserIdRef.current,\n });\n\n // No need to check userId - if this event reached our room (user:{cognitoSubId}),\n // it's definitely for us. Backend ensures correct room targeting.\n console.log('[ExGuardRealtimeProvider] โ
Event received in our personal room! Refreshing access...');\n console.log(\n `[ExGuardRealtimeProvider] ๐ข Triggering RBAC refresh for ${String(rbacRefreshCallbacks.current.size)} registered callbacks`,\n );\n void triggerRbacRefresh();\n });\n\n console.log('[ExGuardRealtimeProvider] โ
Individual user event listener registered');\n } catch (error: unknown) {\n console.error('[ExGuardRealtimeProvider] โ Failed to establish realtime connection:');\n const errorMessage = error instanceof Error ? error.message : String(error);\n const tokenStr = accessToken ? accessToken.substring(0, 20) + '...' : '';\n console.error('[ExGuardRealtimeProvider] Error details:', {\n message: errorMessage,\n token: tokenStr,\n });\n setIsConnected(false);\n }\n };\n\n void initializeConnection();\n\n // Monitor connection status\n let lastConnectedState = realtimeClient.getIsConnected();\n const interval = setInterval(() => {\n const currentConnectedState = realtimeClient.getIsConnected();\n if (currentConnectedState !== lastConnectedState) {\n console.log('[ExGuardRealtimeProvider] ๐ Connection status changed:', {\n from: lastConnectedState,\n to: currentConnectedState,\n });\n lastConnectedState = currentConnectedState;\n setIsConnected(currentConnectedState);\n }\n }, 1000);\n\n return () => {\n clearInterval(interval);\n };\n }, []);\n\n const handleConnect = async (token: string, userId: string) => {\n try {\n console.log('[ExGuardRealtimeProvider] ๐ Manual connection requested', { userId });\n currentUserRef.current = { token, userId };\n await realtimeClient.connect(token, userId);\n setIsConnected(true);\n console.log('[ExGuardRealtimeProvider] โ
Manual connection successful');\n } catch (error: unknown) {\n console.error('[ExGuardRealtimeProvider] โ Failed to connect to realtime:', error);\n setIsConnected(false);\n throw error;\n }\n };\n\n const handleDisconnect = () => {\n console.log('[ExGuardRealtimeProvider] ๐ Disconnection requested');\n realtimeClient.disconnect();\n setIsConnected(false);\n };\n\n const value: ExGuardRealtimeContextType = {\n isConnected,\n connect: handleConnect,\n disconnect: handleDisconnect,\n reconnect: handleReconnect,\n refreshRbac: handleRefreshRbac,\n registerRbacRefreshCallback,\n };\n\n return <ExGuardRealtimeContext value={value}>{children}</ExGuardRealtimeContext>;\n}\n","/**\n * ExGuard Realtime Subscription Hook\n *\n * Hook to subscribe to realtime channels and handle RBAC events\n */\n\nimport { useEffect } from 'react';\nimport { useExGuardRealtime } from './use-exguard-realtime';\nimport { realtimeClient } from '../lib/realtime-client';\nimport { EXGUARD_RBAC_EVENTS, EXGUARD_RBAC_CHANNELS } from '../config/realtime-rbac-config';\nimport type { RealtimeEventType } from '../lib/realtime.types';\n\ninterface UseExGuardRealtimeSubscriptionOptions {\n /** Event types to subscribe to. If not provided, subscribes to all RBAC events */\n events?: RealtimeEventType[];\n /** Whether to auto-subscribe on mount */\n autoSubscribe?: boolean;\n}\n\n/**\n * Hook to subscribe to ExGuard realtime channel and handle RBAC updates\n * @param channel - Channel name ('rbac', 'roles', 'permissions')\n * @param options - Subscription options\n */\nexport function useExGuardRealtimeSubscription(\n channel: keyof typeof EXGUARD_RBAC_CHANNELS = 'RBAC',\n options: UseExGuardRealtimeSubscriptionOptions = {},\n): void {\n const { registerRbacRefreshCallback } = useExGuardRealtime();\n const { autoSubscribe = true, events } = options;\n const channelName = EXGUARD_RBAC_CHANNELS[channel];\n\n useEffect(() => {\n if (!autoSubscribe) {\n return;\n }\n\n console.log(`[useExGuardRealtimeSubscription] ๐ก Subscribing to channel: ${channelName}`);\n\n // Subscribe to channel on server\n void realtimeClient.subscribeToChannel(channelName);\n\n // If specific events provided, subscribe to them\n if (events && events.length > 0) {\n const unsubscribers: (() => void)[] = [];\n\n events.forEach((eventType) => {\n const unsubscribe = realtimeClient.subscribe(eventType, (): void => {\n console.log(`[useExGuardRealtimeSubscription] ๐ Received event: ${eventType}`);\n });\n unsubscribers.push(unsubscribe);\n });\n\n return () => {\n console.log(`[useExGuardRealtimeSubscription] ๐งน Cleaning up subscriptions for channel: ${channelName}`);\n unsubscribers.forEach((unsubscribe) => {\n unsubscribe();\n });\n realtimeClient.unsubscribeFromChannel(channelName);\n };\n }\n\n // Default: subscribe to all RBAC events\n const defaultRbacEvents: RealtimeEventType[] = [\n EXGUARD_RBAC_EVENTS.ROLE_CREATED,\n EXGUARD_RBAC_EVENTS.ROLE_UPDATED,\n EXGUARD_RBAC_EVENTS.ROLE_DELETED,\n EXGUARD_RBAC_EVENTS.PERMISSION_CREATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_UPDATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_DELETED,\n EXGUARD_RBAC_EVENTS.ROLE_PERMISSION_ASSIGNED,\n EXGUARD_RBAC_EVENTS.ROLE_PERMISSION_REMOVED,\n EXGUARD_RBAC_EVENTS.USER_ONLINE,\n EXGUARD_RBAC_EVENTS.GROUP_UPDATED,\n ];\n\n const unsubscribers: (() => void)[] = [];\n\n defaultRbacEvents.forEach((eventType) => {\n const unsubscribe = realtimeClient.subscribe(eventType, (): void => {\n console.log(`[useExGuardRealtimeSubscription] ๐ Received event: ${eventType}`);\n });\n unsubscribers.push(unsubscribe);\n });\n\n // Register callback to trigger RBAC refresh\n const unregisterCallback = registerRbacRefreshCallback(() => {\n console.log(`[useExGuardRealtimeSubscription] ๐ RBAC refresh triggered for channel: ${channelName}`);\n return Promise.resolve();\n });\n\n return () => {\n console.log(`[useExGuardRealtimeSubscription] ๐งน Cleaning up subscriptions for channel: ${channelName}`);\n unsubscribers.forEach((unsubscribe) => {\n unsubscribe();\n });\n unregisterCallback();\n realtimeClient.unsubscribeFromChannel(channelName);\n };\n }, [channelName, autoSubscribe, events, registerRbacRefreshCallback]);\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -271,7 +271,7 @@ declare const useUserAccess: (options?: UseUserAccessOptions) => {
|
|
|
271
271
|
hasModuleAccess: (moduleKey: string) => boolean;
|
|
272
272
|
getModulePermissions: (moduleKey: string) => string[];
|
|
273
273
|
hasPermission: (moduleKey: string, permission: string) => boolean;
|
|
274
|
-
refetch: () => Promise<void>;
|
|
274
|
+
refetch: (silent?: boolean) => Promise<void>;
|
|
275
275
|
};
|
|
276
276
|
|
|
277
277
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -271,7 +271,7 @@ declare const useUserAccess: (options?: UseUserAccessOptions) => {
|
|
|
271
271
|
hasModuleAccess: (moduleKey: string) => boolean;
|
|
272
272
|
getModulePermissions: (moduleKey: string) => string[];
|
|
273
273
|
hasPermission: (moduleKey: string, permission: string) => boolean;
|
|
274
|
-
refetch: () => Promise<void>;
|
|
274
|
+
refetch: (silent?: boolean) => Promise<void>;
|
|
275
275
|
};
|
|
276
276
|
|
|
277
277
|
/**
|
package/dist/index.js
CHANGED
|
@@ -175,11 +175,13 @@ var useUserAccess = (options = {}) => {
|
|
|
175
175
|
const [isLoading, setIsLoading] = useState(true);
|
|
176
176
|
const [error, setError] = useState(null);
|
|
177
177
|
const realtimeContext = use(ExGuardRealtimeContext);
|
|
178
|
-
const fetchUserAccess = useCallback(async () => {
|
|
178
|
+
const fetchUserAccess = useCallback(async (silent = false) => {
|
|
179
179
|
if (!enabled) return;
|
|
180
180
|
try {
|
|
181
|
-
console.log(
|
|
182
|
-
|
|
181
|
+
console.log(`[useUserAccess] \u{1F504} Fetching user access data... ${silent ? "(silent)" : ""}`);
|
|
182
|
+
if (!silent) {
|
|
183
|
+
setIsLoading(true);
|
|
184
|
+
}
|
|
183
185
|
setError(null);
|
|
184
186
|
const data = await getUserAccess();
|
|
185
187
|
setUserAccess(data);
|
|
@@ -194,7 +196,9 @@ var useUserAccess = (options = {}) => {
|
|
|
194
196
|
setError(errorObj);
|
|
195
197
|
console.error("[useUserAccess] \u274C Failed to fetch user access:", errorObj);
|
|
196
198
|
} finally {
|
|
197
|
-
|
|
199
|
+
if (!silent) {
|
|
200
|
+
setIsLoading(false);
|
|
201
|
+
}
|
|
198
202
|
}
|
|
199
203
|
}, [enabled]);
|
|
200
204
|
useEffect(() => {
|
|
@@ -203,7 +207,7 @@ var useUserAccess = (options = {}) => {
|
|
|
203
207
|
return;
|
|
204
208
|
}
|
|
205
209
|
console.log("[useUserAccess] \u{1F4E1} Registering RBAC refresh callback");
|
|
206
|
-
const unsubscribe = realtimeContext.registerRbacRefreshCallback(fetchUserAccess);
|
|
210
|
+
const unsubscribe = realtimeContext.registerRbacRefreshCallback(() => fetchUserAccess(true));
|
|
207
211
|
console.log("[useUserAccess] \u2705 RBAC refresh callback registered");
|
|
208
212
|
return () => {
|
|
209
213
|
console.log("[useUserAccess] \u{1F507} Unregistering RBAC refresh callback");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config/exguard-config.ts","../src/config/realtime-rbac-config.ts","../src/api/exguard-api.ts","../src/providers/exguard-realtime-context.ts","../src/hooks/use-user-access.ts","../src/components/ui/spinner.tsx","../src/components/ui/button.tsx","../src/components/ui/card.tsx","../src/components/permission-guard.tsx","../src/lib/realtime-client.ts","../src/hooks/use-realtime.ts","../src/providers/use-exguard-realtime.ts","../src/hooks/use-exguard-rbac.ts","../src/utils/exguard-realtime-utils.ts","../src/providers/exguard-realtime-provider.tsx","../src/providers/use-exguard-realtime-subscription.ts"],"names":["jsx","useEffect","use","useRef","unsubscribers"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * ExGuard API Configuration\r\n * Configuration for ExGuard backend API\r\n */\r\n\r\nexport interface ExGuardConfig {\r\n apiUrl: string;\r\n withCredentials?: boolean;\r\n}\r\n\r\n/**\r\n * Default ExGuard API configuration\r\n * Note: apiUrl should be provided by the consuming application\r\n */\r\nexport const DEFAULT_EXGUARD_CONFIG: ExGuardConfig = {\r\n apiUrl: '',\r\n withCredentials: true,\r\n};\r\n\r\n/**\r\n * Get ExGuard API URL from environment or provided config\r\n * For Vite apps: import.meta.env.VITE_GUARD_APP_URL\r\n * For Next.js: process.env.NEXT_PUBLIC_GUARD_APP_URL\r\n * Or provide via setExGuardConfig()\r\n */\r\nlet configuredApiUrl: string = '';\r\n\r\nexport const setExGuardConfig = (config: Partial<ExGuardConfig>): void => {\r\n if (config.apiUrl) {\r\n configuredApiUrl = config.apiUrl;\r\n }\r\n};\r\n\r\nexport const getExGuardApiUrl = (): string => {\r\n if (configuredApiUrl) {\r\n return configuredApiUrl;\r\n }\r\n \r\n // Try to get from global environment\r\n if (typeof window !== 'undefined') {\r\n // Check for injected env vars\r\n if ((window as any).__EXGUARD_API_URL__) {\r\n return (window as any).__EXGUARD_API_URL__;\r\n }\r\n }\r\n \r\n // Fallback to localhost for development\r\n return 'http://localhost:3000';\r\n};\r\n\r\n/**\r\n * Storage keys for ExGuard\r\n */\r\nexport const EXGUARD_STORAGE_KEYS = {\r\n ACCESS_TOKEN: 'access_token',\r\n ID_TOKEN: 'id_token',\r\n REFRESH_TOKEN: 'refresh_token',\r\n} as const;\r\n","/**\n * ExGuard Realtime RBAC Configuration\n *\n * This file contains all configuration for realtime RBAC events\n * specific to ExGuard module (users, roles, permissions management)\n */\n\n/**\n * Channels to subscribe to for ExGuard RBAC\n */\nexport const EXGUARD_RBAC_CHANNELS = {\n ROLES: 'roles',\n PERMISSIONS: 'permissions',\n RBAC: 'rbac',\n} as const;\n\n/**\n * Event types for ExGuard RBAC realtime updates\n */\nexport const EXGUARD_RBAC_EVENTS = {\n // Role events\n ROLE_CREATED: 'role:created',\n ROLE_UPDATED: 'role:updated',\n ROLE_DELETED: 'role:deleted',\n\n // Permission events\n PERMISSION_CREATED: 'permission:created',\n PERMISSION_UPDATED: 'permission:updated',\n PERMISSION_DELETED: 'permission:deleted',\n\n // Role-Permission events\n ROLE_PERMISSION_ASSIGNED: 'role-permission:assigned',\n ROLE_PERMISSION_REMOVED: 'role-permission:removed',\n\n // User RBAC events\n USER_ROLES_UPDATED: 'user:roles-updated',\n USER_PERMISSIONS_CHANGED: 'user:permissions-changed',\n USER_ACCESS_CHANGED: 'user:access-changed',\n RBAC_USER_ASSIGNED_TO_GROUP: 'rbac:user-assigned-to-group',\n RBAC_USER_REMOVED_FROM_GROUP: 'rbac:user-removed-from-group',\n RBAC_PERMISSIONS_UPDATED: 'rbac:permissions-updated',\n\n // User status events\n USER_ONLINE: 'user:online',\n USER_OFFLINE: 'user:offline',\n\n // Group events\n GROUP_UPDATED: 'group:updated',\n} as const;\n\n/**\n * Reconnection delay after RBAC updates (in milliseconds)\n * This ensures backend has fully processed the update before refetching data\n */\nexport const RBAC_RECONNECT_DELAY = 300;\n\n/**\n * Configuration for automatic reconnection after specific events\n */\nexport const RBAC_AUTO_RECONNECT_EVENTS = [\n EXGUARD_RBAC_EVENTS.ROLE_UPDATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_UPDATED,\n EXGUARD_RBAC_EVENTS.USER_ACCESS_CHANGED,\n] as const;\n\n/**\n * Events that should trigger user data refresh\n */\nexport const USER_REFRESH_EVENTS = [\n EXGUARD_RBAC_EVENTS.USER_ROLES_UPDATED,\n EXGUARD_RBAC_EVENTS.USER_PERMISSIONS_CHANGED,\n EXGUARD_RBAC_EVENTS.USER_ACCESS_CHANGED,\n EXGUARD_RBAC_EVENTS.RBAC_USER_ASSIGNED_TO_GROUP,\n EXGUARD_RBAC_EVENTS.RBAC_USER_REMOVED_FROM_GROUP,\n EXGUARD_RBAC_EVENTS.RBAC_PERMISSIONS_UPDATED,\n] as const;\n\n/**\n * Events that should trigger role data refresh\n */\nexport const ROLE_REFRESH_EVENTS = [\n EXGUARD_RBAC_EVENTS.ROLE_CREATED,\n EXGUARD_RBAC_EVENTS.ROLE_UPDATED,\n EXGUARD_RBAC_EVENTS.ROLE_DELETED,\n EXGUARD_RBAC_EVENTS.ROLE_PERMISSION_ASSIGNED,\n] as const;\n\n/**\n * Events that should trigger permission data refresh\n */\nexport const PERMISSION_REFRESH_EVENTS = [\n EXGUARD_RBAC_EVENTS.PERMISSION_CREATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_UPDATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_DELETED,\n] as const;\n","import axios, { type AxiosError } from 'axios';\nimport type { VerifyTokenResponse, UserAccessData, AuthApiResponse } from '../types/exguard-types';\nimport { getExGuardApiUrl, EXGUARD_STORAGE_KEYS } from '../config/exguard-config';\n\n// Create a separate axios instance for Guard API endpoints\n// Note: baseURL is set dynamically in the interceptor to support runtime configuration\nconst guardApiClient = axios.create({\n withCredentials: true,\n headers: {\n 'Content-Type': 'application/json',\n },\n});\n\n// Add interceptor to dynamically set baseURL and include access token\nguardApiClient.interceptors.request.use(\n (config) => {\n // Set baseURL dynamically from config (supports runtime configuration)\n config.baseURL = getExGuardApiUrl();\n \n const token = window.localStorage.getItem(EXGUARD_STORAGE_KEYS.ACCESS_TOKEN);\n if (token) {\n config.headers.Authorization = `Bearer ${token}`;\n }\n return config;\n },\n (error: unknown) => Promise.reject(error instanceof Error ? error : new Error(String(error))),\n);\n\n/**\n * Verify ID token with ExGuard backend\n */\nexport async function verifyToken(): Promise<VerifyTokenResponse> {\n try {\n const idToken = window.localStorage.getItem(EXGUARD_STORAGE_KEYS.ID_TOKEN);\n const response = await guardApiClient.post<\n AuthApiResponse<{\n user?: {\n id: string;\n username: string;\n email: string;\n givenName: string;\n familyName: string;\n };\n }>\n >('/guard/verify-token', {\n id_token: idToken,\n });\n\n if (response.data.success && response.data.data) {\n console.log('Token verification response:', response.data.data);\n\n // Map backend response to frontend format\n const backendData = response.data.data;\n const mappedResponse: VerifyTokenResponse = {\n valid: true,\n user: backendData.user\n ? {\n userId: backendData.user.id,\n username: backendData.user.username,\n email: backendData.user.email,\n givenName: backendData.user.givenName,\n familyName: backendData.user.familyName,\n }\n : undefined,\n };\n\n console.log('Mapped user data:', mappedResponse.user);\n return mappedResponse;\n }\n\n throw new Error(response.data.message ?? 'Token verification failed');\n } catch (error) {\n const axiosError = error as AxiosError<AuthApiResponse<never>>;\n\n if (axiosError.response?.data) {\n const errorData = axiosError.response.data;\n const errorMessage = errorData.message ?? 'Token verification failed';\n throw new Error(errorMessage);\n }\n\n throw error;\n }\n}\n\n/**\n * Get user access data including roles, permissions, modules, and field offices\n */\nexport async function getUserAccess(): Promise<UserAccessData> {\n try {\n const response = await guardApiClient.get<AuthApiResponse<UserAccessData>>('/guard/me');\n\n if (response.data.success && response.data.data) {\n console.log('User Access Data:', response.data.data);\n console.log('User Details:', response.data.data.user);\n console.log('User Roles:', response.data.data.roles);\n console.log('User Groups:', response.data.data.groups);\n console.log('User Modules:', response.data.data.modules);\n console.log('User Field Offices:', response.data.data.fieldOffices);\n return response.data.data;\n }\n\n throw new Error(response.data.message ?? 'Failed to get user access data');\n } catch (error) {\n const axiosError = error as AxiosError<AuthApiResponse<never>>;\n\n if (axiosError.response?.data) {\n const errorData = axiosError.response.data;\n const errorMessage = errorData.message ?? 'Failed to get user access data';\n throw new Error(errorMessage);\n }\n\n throw error;\n }\n}\n","/**\n * ExGuard Realtime Context\n *\n * Context for managing realtime RBAC connections and state\n */\n\nimport { createContext } from 'react';\n\nexport interface ExGuardRealtimeContextType {\n isConnected: boolean;\n connect: (token: string, userId: string) => Promise<void>;\n disconnect: () => void;\n reconnect: () => Promise<void>;\n refreshRbac: () => Promise<void>;\n registerRbacRefreshCallback: (callback: () => Promise<void>) => () => void;\n}\n\nexport const ExGuardRealtimeContext = createContext<ExGuardRealtimeContextType | undefined>(undefined);\n","import { useEffect, useState, useCallback, use } from 'react';\r\nimport { getUserAccess } from '../api/exguard-api';\r\nimport type { UserAccessData, ModulePermissions } from '../types/exguard-types';\r\nimport { ExGuardRealtimeContext } from '../providers/exguard-realtime-context';\r\n\r\ninterface UseUserAccessOptions {\r\n enabled?: boolean;\r\n refetchInterval?: number;\r\n}\r\n\r\n/**\r\n * Custom hook to fetch and manage user access data with RBAC\r\n * Includes caching and periodic refetching for real-time RBAC\r\n */\r\nexport const useUserAccess = (options: UseUserAccessOptions = {}) => {\r\n const { enabled = true, refetchInterval = 0 } = options;\r\n const [userAccess, setUserAccess] = useState<UserAccessData | null>(null);\r\n const [isLoading, setIsLoading] = useState(true);\r\n const [error, setError] = useState<Error | null>(null);\r\n const realtimeContext = use(ExGuardRealtimeContext);\r\n\r\n const fetchUserAccess = useCallback(async (): Promise<void> => {\r\n if (!enabled) return;\r\n\r\n try {\r\n console.log('[useUserAccess] ๐ Fetching user access data...');\r\n setIsLoading(true);\r\n setError(null);\r\n const data = await getUserAccess();\r\n setUserAccess(data);\r\n console.log('[useUserAccess] โ
User access refreshed successfully', {\r\n userId: data.user.id,\r\n username: data.user.username,\r\n modulesCount: data.modules.length,\r\n modules: data.modules.map((m) => m.key),\r\n });\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error('Failed to fetch user access');\r\n setError(errorObj);\r\n console.error('[useUserAccess] โ Failed to fetch user access:', errorObj);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [enabled]);\r\n\r\n // Register for real-time RBAC updates from the realtime provider\r\n useEffect(() => {\r\n if (!realtimeContext) {\r\n console.warn('[useUserAccess] โ ๏ธ RealtimeContext not available');\r\n return;\r\n }\r\n\r\n console.log('[useUserAccess] ๐ก Registering RBAC refresh callback');\r\n const unsubscribe = realtimeContext.registerRbacRefreshCallback(fetchUserAccess);\r\n console.log('[useUserAccess] โ
RBAC refresh callback registered');\r\n\r\n return () => {\r\n console.log('[useUserAccess] ๐ Unregistering RBAC refresh callback');\r\n unsubscribe();\r\n };\r\n }, [realtimeContext, fetchUserAccess]);\r\n\r\n useEffect(() => {\r\n void fetchUserAccess();\r\n\r\n if (refetchInterval > 0) {\r\n const interval = setInterval(() => {\r\n void fetchUserAccess();\r\n }, refetchInterval);\r\n\r\n return () => {\r\n clearInterval(interval);\r\n };\r\n }\r\n }, [fetchUserAccess, refetchInterval]);\r\n\r\n const hasModuleAccess = useCallback(\r\n (moduleKey: string): boolean => {\r\n if (!userAccess) return false;\r\n const module = userAccess.modules.find((m: ModulePermissions) => m.key.toLowerCase() === moduleKey.toLowerCase());\r\n return !!module && module.permissions.length > 0;\r\n },\r\n [userAccess],\r\n );\r\n\r\n const getModulePermissions = useCallback(\r\n (moduleKey: string): string[] => {\r\n if (!userAccess) return [];\r\n const module = userAccess.modules.find((m: ModulePermissions) => m.key.toLowerCase() === moduleKey.toLowerCase());\r\n return module?.permissions ?? [];\r\n },\r\n [userAccess],\r\n );\r\n\r\n const hasPermission = useCallback(\r\n (moduleKey: string, permission: string): boolean => {\r\n const permissions = getModulePermissions(moduleKey);\r\n return permissions.includes(permission);\r\n },\r\n [getModulePermissions],\r\n );\r\n\r\n return {\r\n userAccess,\r\n isLoading,\r\n error,\r\n hasModuleAccess,\r\n getModulePermissions,\r\n hasPermission,\r\n refetch: fetchUserAccess,\r\n };\r\n};\r\n","import React from 'react';\r\n\r\ninterface SpinnerProps {\r\n className?: string;\r\n}\r\n\r\nexport function Spinner({ className = '' }: SpinnerProps) {\r\n return (\r\n <div\r\n className={`animate-spin rounded-full border-4 border-solid border-current border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite] ${className}`}\r\n role=\"status\"\r\n >\r\n <span className=\"!absolute !-m-px !h-px !w-px !overflow-hidden !whitespace-nowrap !border-0 !p-0 ![clip:rect(0,0,0,0)]\">\r\n Loading...\r\n </span>\r\n </div>\r\n );\r\n}\r\n","import React from 'react';\r\n\r\ninterface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\r\n variant?: 'default' | 'outline' | 'destructive' | 'ghost' | 'link';\r\n size?: 'default' | 'sm' | 'lg' | 'icon';\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport function Button({\r\n className = '',\r\n variant = 'default',\r\n size = 'default',\r\n children,\r\n ...props\r\n}: ButtonProps) {\r\n const baseStyles =\r\n 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50';\r\n\r\n const variantStyles = {\r\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\r\n outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',\r\n destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',\r\n ghost: 'hover:bg-accent hover:text-accent-foreground',\r\n link: 'text-primary underline-offset-4 hover:underline',\r\n };\r\n\r\n const sizeStyles = {\r\n default: 'h-10 px-4 py-2',\r\n sm: 'h-9 rounded-md px-3',\r\n lg: 'h-11 rounded-md px-8',\r\n icon: 'h-10 w-10',\r\n };\r\n\r\n return (\r\n <button\r\n className={`${baseStyles} ${variantStyles[variant]} ${sizeStyles[size]} ${className}`}\r\n {...props}\r\n >\r\n {children}\r\n </button>\r\n );\r\n}\r\n","import React from 'react';\r\n\r\ninterface CardProps extends React.HTMLAttributes<HTMLDivElement> {\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport function Card({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <div\r\n className={`rounded-lg border bg-card text-card-foreground shadow-sm ${className}`}\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nexport function CardHeader({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <div className={`flex flex-col space-y-1.5 p-6 ${className}`} {...props}>\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nexport function CardTitle({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <h3 className={`text-2xl font-semibold leading-none tracking-tight ${className}`} {...props}>\r\n {children}\r\n </h3>\r\n );\r\n}\r\n\r\nexport function CardDescription({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <p className={`text-sm text-muted-foreground ${className}`} {...props}>\r\n {children}\r\n </p>\r\n );\r\n}\r\n\r\nexport function CardContent({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <div className={`p-6 pt-0 ${className}`} {...props}>\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nexport function CardFooter({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <div className={`flex items-center p-6 pt-0 ${className}`} {...props}>\r\n {children}\r\n </div>\r\n );\r\n}\r\n","import { Navigate, Outlet } from 'react-router';\r\nimport { useUserAccess } from '../hooks/use-user-access';\r\nimport { Spinner } from './ui/spinner';\r\nimport { Button } from './ui/button';\r\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from './ui/card';\r\nimport { ArrowLeft, ShieldAlert, Lock } from 'lucide-react';\r\n\r\ninterface PermissionGuardProps {\r\n module: string;\r\n permission?: string;\r\n requireModule?: boolean;\r\n requirePermission?: boolean;\r\n fallbackPath?: string;\r\n}\r\n\r\n/**\r\n * PermissionGuard component that checks if user has required module access and/or permissions\r\n *\r\n * @param module - The module key (e.g., 'EXID', 'EXFLOW', 'TEV')\r\n * @param permission - Optional specific permission to check (e.g., 'profile:create', 'profile:update')\r\n * @param requireModule - Whether to require module access (default: true)\r\n * @param requirePermission - Whether to require the specific permission (default: true if permission is provided)\r\n * @param fallbackPath - Path to redirect to if access is denied (default: show error page)\r\n */\r\nexport function PermissionGuard({\r\n module,\r\n permission,\r\n requireModule = true,\r\n requirePermission = true,\r\n fallbackPath,\r\n}: PermissionGuardProps) {\r\n const { isLoading, hasModuleAccess, hasPermission } = useUserAccess();\r\n\r\n // Show loading spinner while checking permissions\r\n if (isLoading) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px]\">\r\n <Spinner className=\"size-8\" />\r\n </div>\r\n );\r\n }\r\n\r\n // Check module access\r\n const hasModule = hasModuleAccess(module);\r\n const moduleCheckFailed = requireModule && !hasModule;\r\n\r\n // Check specific permission if provided\r\n const hasSpecificPermission = permission ? hasPermission(module, permission) : true;\r\n const permissionCheckFailed = permission && requirePermission && !hasSpecificPermission;\r\n\r\n // Determine if access should be denied\r\n const accessDenied = moduleCheckFailed || permissionCheckFailed;\r\n\r\n // Redirect to fallback path if provided\r\n if (accessDenied && fallbackPath) {\r\n return <Navigate to={fallbackPath} replace />;\r\n }\r\n\r\n // Show access denied message\r\n if (accessDenied) {\r\n const denialReason = moduleCheckFailed\r\n ? {\r\n title: 'Module Access Required',\r\n description: `Access to the ${module} module is required to view this page`,\r\n detail: `Your current account permissions do not include access to the ${module} module. This module may be restricted to specific roles or user groups.`,\r\n }\r\n : {\r\n title: 'Permission Required',\r\n description: `The permission \"${permission ?? 'unknown'}\" is needed to access this resource`,\r\n detail: `Your account has access to the ${module} module but lacks the specific permission required for this action. This permission may need to be assigned to your role or user group.`,\r\n };\r\n\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[calc(100vh-4rem)] p-6\">\r\n <Card className=\"w-full max-w-lg\">\r\n <CardHeader className=\"text-center pb-4\">\r\n <div className=\"mx-auto mb-4 flex size-16 items-center justify-center rounded-full bg-destructive/10\">\r\n {moduleCheckFailed ? (\r\n <Lock className=\"size-8 text-destructive\" />\r\n ) : (\r\n <ShieldAlert className=\"size-8 text-destructive\" />\r\n )}\r\n </div>\r\n <CardTitle className=\"text-2xl\">{denialReason.title}</CardTitle>\r\n <CardDescription className=\"text-base\">{denialReason.description}</CardDescription>\r\n </CardHeader>\r\n <CardContent className=\"space-y-4\">\r\n <div className=\"rounded-lg bg-muted p-4\">\r\n <p className=\"text-sm text-muted-foreground\">{denialReason.detail}</p>\r\n </div>\r\n <div className=\"flex flex-col gap-2 sm:flex-row sm:justify-center\">\r\n <Button\r\n variant=\"outline\"\r\n onClick={() => {\r\n window.history.back();\r\n }}\r\n className=\"w-full sm:w-auto\"\r\n >\r\n <ArrowLeft className=\"mr-2 size-4\" />\r\n Go Back\r\n </Button>\r\n <Button\r\n variant=\"default\"\r\n onClick={() => {\r\n window.location.href = '/';\r\n }}\r\n className=\"w-full sm:w-auto\"\r\n >\r\n Return to Dashboard\r\n </Button>\r\n </div>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n );\r\n }\r\n\r\n // User has required access, render child routes\r\n return <Outlet />;\r\n}\r\n","import { io, type Socket } from 'socket.io-client';\nimport type { RealtimeEventPayload, RealtimeEventType, RealtimeEventHandler } from './realtime.types';\nimport { getExGuardApiUrl } from '../config/exguard-config';\n\nclass RealtimeClient {\n private socket: Socket | null = null;\n private listeners = new Map<string, Set<RealtimeEventHandler>>();\n private isConnected = false;\n private debug = true; // Enable/disable debug logging\n private connectionPromise: Promise<void> | null = null;\n\n constructor() {\n this.log('๐ข RealtimeClient initialized');\n }\n \n private getApiUrl(): string {\n return getExGuardApiUrl();\n }\n\n private log(message: string, data?: unknown) {\n if (this.debug) {\n console.log(`[RealtimeClient] ${message}`, data);\n }\n }\n\n private logError(message: string, error?: unknown) {\n console.error(`[RealtimeClient] ${message}`, error);\n }\n\n private logWarn(message: string, data?: unknown) {\n console.warn(`[RealtimeClient] ${message}`, data);\n }\n\n /**\n * Connect to the realtime server\n */\n connect(token: string, userId: string): Promise<void> {\n // Validate inputs\n if (!token) {\n this.logError('โ Cannot connect - token is missing or empty');\n return Promise.reject(new Error('Missing authentication token'));\n }\n\n if (!userId) {\n this.logError('โ Cannot connect - userId is missing or empty');\n return Promise.reject(new Error('Missing userId'));\n }\n\n // Return existing connection promise if already connecting\n if (this.connectionPromise) {\n this.log('โณ Connection already in progress, returning existing promise');\n return this.connectionPromise;\n }\n\n this.connectionPromise = new Promise((resolve, reject) => {\n try {\n const apiUrl = this.getApiUrl();\n this.log('๐ Attempting to connect...', { apiUrl, userId, hasToken: !!token });\n\n if (this.socket?.connected) {\n this.log('โ
Already connected');\n this.connectionPromise = null;\n resolve();\n return;\n }\n\n const socketUrl = `${apiUrl}/realtime`;\n this.log('๐ Creating Socket.IO connection', {\n url: socketUrl,\n transports: ['websocket', 'polling'],\n userId,\n });\n\n this.socket = io(socketUrl, {\n auth: {\n token,\n userId,\n },\n transports: ['websocket', 'polling'],\n reconnection: true,\n reconnectionDelay: 1000,\n reconnectionDelayMax: 5000,\n reconnectionAttempts: 5,\n });\n\n this.socket.on('connect', () => {\n this.isConnected = true;\n this.log('โ
Connected to realtime server', {\n socketId: this.socket?.id,\n userId,\n });\n this.connectionPromise = null;\n resolve();\n });\n\n this.socket.on('disconnect', (reason: string) => {\n this.isConnected = false;\n this.log('โ Disconnected from realtime server', { reason });\n });\n\n this.socket.on('connect_error', (error: unknown) => {\n this.logError('โ Connection error (check token and backend)', error);\n this.connectionPromise = null;\n const errorMessage = error instanceof Error ? error.message : String(error);\n reject(new Error(`Connection error: ${errorMessage}`));\n });\n\n this.socket.on('error', (error: unknown) => {\n this.logError('โ Realtime error', error);\n this.connectionPromise = null;\n const errorMessage = error instanceof Error ? error.message : String(error);\n reject(new Error(`Socket.IO error: ${errorMessage}`));\n });\n\n this.socket.on('reconnect_attempt', () => {\n this.log('๐ Attempting to reconnect...');\n });\n\n this.socket.on('reconnect', () => {\n this.isConnected = true;\n this.log('๐ Reconnected to realtime server', {\n socketId: this.socket?.id,\n });\n });\n\n this.socket.on('reconnect_failed', () => {\n this.logError('โ Reconnection failed after maximum attempts');\n this.connectionPromise = null;\n reject(new Error('Reconnection failed'));\n });\n\n // Listen to all realtime events\n this.socket.onAny((eventName: string, payload: unknown) => {\n // Debug: log raw event for troubleshooting\n this.log(`๐จ Raw event received`, {\n eventName,\n payloadType: typeof payload,\n payload,\n });\n\n // Normalize payload - backend sends event name separately from payload\n const payloadObj =\n typeof payload === 'object' && payload !== null ? (payload as Record<string, unknown>) : {};\n\n // CRITICAL FIX: Use eventName as the primary event type (e.g., 'user:access-changed')\n // Socket.IO sends the event name as the first parameter, not nested in payload.type\n const eventType = eventName;\n\n const normalizedPayload: RealtimeEventPayload = {\n type: eventType as RealtimeEventType,\n timestamp:\n 'timestamp' in payloadObj\n ? typeof payloadObj.timestamp === 'number'\n ? payloadObj.timestamp\n : new Date(payloadObj.timestamp as string).getTime()\n : Date.now(),\n data: 'data' in payloadObj ? payloadObj.data : payload,\n };\n\n this.log(`๐จ Event processed: ${eventType}`, {\n type: normalizedPayload.type,\n timestamp: normalizedPayload.timestamp,\n dataKeys:\n typeof normalizedPayload.data === 'object' && normalizedPayload.data !== null\n ? Object.keys(normalizedPayload.data as Record<string, unknown>)\n : 'N/A',\n });\n this.handleEvent(eventType as RealtimeEventType, normalizedPayload);\n });\n } catch (error) {\n this.logError('Failed to initialize connection', error);\n const errorMessage = error instanceof Error ? error.message : String(error);\n reject(new Error(`Connection initialization failed: ${errorMessage}`));\n }\n });\n\n return this.connectionPromise;\n }\n\n /**\n * Disconnect from the realtime server\n */\n disconnect(): void {\n this.log('๐ Disconnecting from realtime server...');\n if (this.socket) {\n this.socket.disconnect();\n this.socket = null;\n this.isConnected = false;\n this.log('โ
Disconnected');\n }\n }\n\n /**\n * Check if connected\n */\n getIsConnected(): boolean {\n return this.isConnected && this.socket?.connected === true;\n }\n\n /**\n * Wait for connection to be ready (with timeout)\n */\n async waitForConnection(timeoutMs = 30000): Promise<void> {\n const startTime = Date.now();\n\n while (Date.now() - startTime < timeoutMs) {\n if (this.getIsConnected()) {\n this.log('โ
Connection ready');\n return;\n }\n\n // Wait 100ms before checking again\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n this.logError('โ Timeout waiting for connection', { timeoutMs, elapsed: Date.now() - startTime });\n throw new Error('Connection timeout - failed to establish WebSocket connection');\n }\n\n /**\n * Subscribe to a specific event type\n */\n subscribe<T extends RealtimeEventPayload = RealtimeEventPayload>(\n eventType: RealtimeEventType,\n handler: RealtimeEventHandler<T>,\n ): () => void {\n if (!this.listeners.has(eventType)) {\n this.listeners.set(eventType, new Set());\n }\n\n this.listeners.get(eventType)?.add(handler as RealtimeEventHandler);\n const listenerCount = this.listeners.get(eventType)?.size ?? 0;\n this.log(`๐ Subscribed to event: ${eventType}`, { totalListeners: listenerCount });\n\n // Return unsubscribe function\n return () => {\n const handlers = this.listeners.get(eventType);\n if (handlers) {\n handlers.delete(handler as RealtimeEventHandler);\n this.log(`๐ Unsubscribed from event: ${eventType}`, {\n remainingListeners: handlers.size,\n });\n }\n };\n }\n\n /**\n * Unsubscribe from an event\n */\n unsubscribe(eventType: RealtimeEventType, handler: RealtimeEventHandler): void {\n const handlers = this.listeners.get(eventType);\n if (handlers) {\n handlers.delete(handler);\n this.log(`๐ Unsubscribed from event: ${eventType}`, {\n remainingListeners: handlers.size,\n });\n }\n }\n /**\n * Send a subscription message to the server with connection wait\n */\n async subscribeToChannel(channel: 'roles' | 'permissions' | 'rbac'): Promise<void> {\n try {\n this.log(`๐ก Subscribing to channel: ${channel}`);\n\n // Wait for connection to be ready\n await this.waitForConnection(15000);\n\n // Now emit subscribe\n this.log(`๐ก Emitting subscribe event for channel: ${channel}`);\n this.socket?.emit(`subscribe:${channel}`);\n this.log(`โ
Subscribed to channel: ${channel}`);\n } catch (error) {\n this.logError(`โ Failed to subscribe to channel \"${channel}\"`, error);\n throw error;\n }\n }\n\n /**\n * Send an unsubscription message to the server\n */\n unsubscribeFromChannel(channel: 'roles' | 'permissions' | 'rbac'): void {\n if (!this.socket?.connected) {\n this.logWarn(`Cannot unsubscribe from channel \"${channel}\" - socket not connected`);\n return;\n }\n\n this.log(`๐ก Unsubscribing from channel: ${channel}`);\n this.socket.emit(`unsubscribe:${channel}`);\n }\n\n /**\n * Handle incoming events\n */\n private handleEvent(eventType: RealtimeEventType, payload: RealtimeEventPayload): void {\n // Call specific event handlers\n const handlers = this.listeners.get(eventType);\n if (handlers && handlers.size > 0) {\n this.log(`๐ Triggering ${String(handlers.size)} handler(s) for event: ${eventType}`);\n handlers.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n this.logError(`Error in event handler for ${eventType}`, error);\n }\n });\n }\n\n // Call wildcard handlers if any\n const wildcardHandlers = this.listeners.get('*' as RealtimeEventType);\n if (wildcardHandlers && wildcardHandlers.size > 0) {\n this.log(`๐ Triggering ${String(wildcardHandlers.size)} wildcard handler(s)`);\n wildcardHandlers.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n this.logError('Error in wildcard event handler', error);\n }\n });\n }\n }\n\n /**\n * Get all connected listeners count\n */\n getListenerCount(eventType?: RealtimeEventType): number {\n if (eventType) {\n return this.listeners.get(eventType)?.size ?? 0;\n }\n let total = 0;\n this.listeners.forEach((handlers) => {\n total += handlers.size;\n });\n return total;\n }\n\n /**\n * Enable or disable debug logging\n */\n setDebug(enabled: boolean): void {\n this.debug = enabled;\n this.log(`Debug logging ${enabled ? 'enabled' : 'disabled'}`);\n }\n\n /**\n * Get connection status summary\n */\n getStatus() {\n const status = {\n isConnected: this.getIsConnected(),\n socketId: this.socket?.id ?? 'N/A',\n apiUrl: this.getApiUrl(),\n totalListeners: this.getListenerCount(),\n listeners: Array.from(this.listeners.entries()).map(([event, handlers]) => ({\n event,\n count: handlers.size,\n })),\n };\n this.log('๐ Connection Status', status);\n return status;\n }\n}\n\n// Create singleton instance\nexport const realtimeClient = new RealtimeClient();\n\n// Expose debug methods on window for console access\nif (typeof window !== 'undefined') {\n const w = window as unknown as Record<string, unknown>;\n w.__realtimeClient = {\n client: realtimeClient,\n connect: (token: string, userId: string) => realtimeClient.connect(token, userId),\n disconnect: () => {\n realtimeClient.disconnect();\n },\n isConnected: () => realtimeClient.getIsConnected(),\n setDebug: (enabled: boolean) => {\n realtimeClient.setDebug(enabled);\n },\n status: () => realtimeClient.getStatus(),\n getListenerCount: (eventType?: RealtimeEventType) => realtimeClient.getListenerCount(eventType),\n };\n console.log('๐ฏ RealtimeClient debug tools available at: window.__realtimeClient');\n}\n\nexport type { RealtimeClient };\n","/**\n * Shared Realtime Hooks\n *\n * Basic hooks for realtime functionality that wraps the realtime-client\n */\n\nimport { useEffect, useRef, useState } from 'react';\nimport { realtimeClient } from '../lib/realtime-client';\nimport type { RealtimeEventType, RealtimeEventPayload, RealtimeEventHandler } from '../lib/realtime.types';\n\n/**\n * Hook to subscribe to realtime RBAC events\n * Automatically handles subscription/unsubscription lifecycle\n */\nexport function useRealtimeRbac<T extends RealtimeEventPayload = RealtimeEventPayload>(\n eventType: RealtimeEventType,\n handler: RealtimeEventHandler<T>,\n) {\n const handlerRef = useRef(handler);\n\n useEffect(() => {\n handlerRef.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const unsubscribe = realtimeClient.subscribe<T>(eventType, (payload) => {\n handlerRef.current(payload);\n });\n\n return () => {\n unsubscribe();\n };\n }, [eventType]);\n}\n\n/**\n * Hook to manage channel subscriptions\n */\nexport function useRealtimeSubscription(channel: 'roles' | 'permissions' | 'rbac') {\n useEffect(() => {\n let isMounted = true;\n\n // Subscribe asynchronously\n realtimeClient.subscribeToChannel(channel).catch((error: unknown) => {\n if (isMounted) {\n console.error(`Failed to subscribe to channel \"${channel}\":`, error);\n }\n });\n\n return () => {\n isMounted = false;\n realtimeClient.unsubscribeFromChannel(channel);\n };\n }, [channel]);\n}\n\n/**\n * Hook to listen to multiple event types\n */\nexport function useRealtimeMultiple(\n events: {\n type: RealtimeEventType;\n handler: RealtimeEventHandler;\n }[],\n) {\n useEffect(() => {\n const unsubscribers = events.map(({ type, handler }) => realtimeClient.subscribe(type, handler));\n\n return () => {\n unsubscribers.forEach((unsub) => {\n unsub();\n });\n };\n }, [events]);\n}\n\n/**\n * Hook to listen to all realtime events\n */\nexport function useRealtimeAll(handler: RealtimeEventHandler) {\n const handlerRef = useRef(handler);\n\n useEffect(() => {\n handlerRef.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const unsubscribe = realtimeClient.subscribe('*' as RealtimeEventType, (payload) => {\n handlerRef.current(payload);\n });\n\n return () => {\n unsubscribe();\n };\n }, []);\n}\n\n/**\n * Hook to get the connection status\n */\nexport function useRealtimeStatus() {\n const [isConnected, setIsConnected] = useState(realtimeClient.getIsConnected());\n\n useEffect(() => {\n const checkConnection = () => {\n setIsConnected(realtimeClient.getIsConnected());\n };\n\n const interval = setInterval(checkConnection, 1000);\n\n return () => {\n clearInterval(interval);\n };\n }, []);\n\n return { isConnected };\n}\n","/**\n * Hook to use ExGuard Realtime Context\n */\n\nimport { use } from 'react';\nimport { ExGuardRealtimeContext, type ExGuardRealtimeContextType } from './exguard-realtime-context';\n\n/**\n * Hook to access ExGuard realtime context\n * Must be used within ExGuardRealtimeProvider\n */\nexport function useExGuardRealtime(): ExGuardRealtimeContextType {\n const context = use(ExGuardRealtimeContext);\n if (!context) {\n throw new Error('useExGuardRealtime must be used within a ExGuardRealtimeProvider');\n }\n return context;\n}\n","/**\n * ExGuard Realtime RBAC Hooks\n *\n * Custom hooks for handling ExGuard-specific realtime RBAC events\n */\n\nimport { useCallback } from 'react';\nimport { useRealtimeRbac, useRealtimeSubscription } from './use-realtime';\nimport { useExGuardRealtime } from '../providers/use-exguard-realtime';\nimport { EXGUARD_RBAC_CHANNELS, EXGUARD_RBAC_EVENTS, RBAC_RECONNECT_DELAY } from '../config/realtime-rbac-config';\nimport type { RealtimeEventPayload } from '../lib/realtime.types';\n\n/**\n * Hook to subscribe to all ExGuard RBAC channels\n */\nexport function useExGuardRbacChannels() {\n useRealtimeSubscription(EXGUARD_RBAC_CHANNELS.RBAC);\n useRealtimeSubscription(EXGUARD_RBAC_CHANNELS.ROLES);\n useRealtimeSubscription(EXGUARD_RBAC_CHANNELS.PERMISSIONS);\n}\n\n/**\n * Hook to handle role updates with automatic reconnection\n */\nexport function useRoleUpdateHandler(onUpdate: () => Promise<void>, fetchUserAccess?: () => Promise<void>) {\n const { reconnect } = useExGuardRealtime();\n\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.ROLE_UPDATED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ Role updated:', (payload.data as { id?: string })?.id ?? payload.data);\n\n try {\n console.log('[ExGuard] ๐ Reconnecting after role update...');\n await reconnect();\n console.log('[ExGuard] โ
Reconnected successfully');\n\n // Delay to ensure backend has processed\n await new Promise((resolve) => setTimeout(resolve, RBAC_RECONNECT_DELAY));\n\n // Refresh data\n const promises = [onUpdate()];\n if (fetchUserAccess) {\n promises.push(fetchUserAccess());\n }\n await Promise.all(promises);\n\n console.log('[ExGuard] โ
Data refreshed after role update');\n } catch (error) {\n console.error('[ExGuard] โ Error handling role update:', error);\n }\n })();\n },\n [reconnect, onUpdate, fetchUserAccess],\n ),\n );\n}\n\n/**\n * Hook to handle user RBAC updates (role assignments, permissions, etc.)\n */\nexport function useUserRbacUpdateHandler(onUpdate: () => Promise<void>) {\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.USER_ROLES_UPDATED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ User roles updated:', payload.data);\n await onUpdate();\n console.log('[ExGuard] โ
User data refreshed');\n })();\n },\n [onUpdate],\n ),\n );\n}\n\n/**\n * Hook to handle permission updates\n */\nexport function usePermissionUpdateHandler(onUpdate: () => Promise<void>) {\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.PERMISSION_UPDATED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ Permission updated:', payload.data);\n await onUpdate();\n console.log('[ExGuard] โ
Permission data refreshed');\n })();\n },\n [onUpdate],\n ),\n );\n}\n\n/**\n * Hook to handle group updates\n */\nexport function useGroupUpdateHandler(onUpdate: () => Promise<void>) {\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.GROUP_UPDATED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ Group updated:', payload.data);\n await onUpdate();\n console.log('[ExGuard] โ
Group data refreshed');\n })();\n },\n [onUpdate],\n ),\n );\n}\n\n/**\n * Hook to handle user access changes (personal notifications)\n * This is for individual user notifications received via user:{cognitoSubId} room\n */\nexport function useUserAccessChangeHandler(onAccessChange: () => Promise<void>) {\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.USER_ACCESS_CHANGED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ฏ Your access has changed:', payload.data);\n await onAccessChange();\n console.log('[ExGuard] โ
User access refreshed');\n })();\n },\n [onAccessChange],\n ),\n );\n}\n","/**\n * ExGuard Realtime Utilities\n *\n * Utility functions for ExGuard realtime functionality\n */\n\nimport { getUserAccess } from '../api/exguard-api';\n\n/**\n * Get current user's Cognito Sub ID from backend\n * This is used for websocket room identification (user:{cognitoSubId})\n */\nexport async function getCurrentUserId(): Promise<string | null> {\n try {\n const userAccess = await getUserAccess();\n console.log('[ExGuardRealtimeUtils] ๐ก Fetched user access:', {\n id: userAccess.user.id,\n cognitoSubId: userAccess.user.cognitoSubId,\n email: userAccess.user.email,\n });\n // CRITICAL: Use cognitoSubId for websocket room targeting, not database UUID\n return userAccess.user.cognitoSubId;\n } catch (error) {\n console.error('[ExGuardRealtimeUtils] Failed to fetch user:', error);\n return null;\n }\n}\n","/**\n * ExGuard Realtime Provider\n *\n * Provider for managing realtime RBAC connections and events\n */\n\nimport React, { useEffect, useRef, type ReactNode } from 'react';\nimport { realtimeClient } from '../lib/realtime-client';\nimport { ExGuardRealtimeContext, type ExGuardRealtimeContextType } from './exguard-realtime-context';\nimport { getCurrentUserId } from '../utils/exguard-realtime-utils';\nimport type { UserRbacEventPayload } from '../lib/realtime.types';\n\ninterface ExGuardRealtimeProviderProps {\n children: ReactNode;\n}\n\nexport function ExGuardRealtimeProvider({ children }: ExGuardRealtimeProviderProps) {\n const [isConnected, setIsConnected] = React.useState(false);\n const connectionAttempted = useRef(false);\n const rbacRefreshCallbacks = useRef<Set<() => Promise<void>>>(new Set());\n const currentUserRef = useRef<{ token: string; userId: string } | null>(null);\n const currentUserIdRef = useRef<string | null>(null);\n\n // Register callback to refresh user access\n const registerRbacRefreshCallback = (callback: () => Promise<void>) => {\n rbacRefreshCallbacks.current.add(callback);\n return () => {\n rbacRefreshCallbacks.current.delete(callback);\n };\n };\n\n // Trigger refresh for all registered callbacks\n const triggerRbacRefresh = async (): Promise<void> => {\n console.log('[ExGuardRealtimeProvider] ๐ Triggering RBAC refresh for all listeners', {\n callbackCount: rbacRefreshCallbacks.current.size,\n });\n\n if (rbacRefreshCallbacks.current.size === 0) {\n console.warn('[ExGuardRealtimeProvider] โ ๏ธ No RBAC refresh callbacks registered!');\n return;\n }\n\n const refreshPromises = Array.from(rbacRefreshCallbacks.current).map((cb, index) => {\n console.log(\n `[ExGuardRealtimeProvider] ๐ Executing callback ${String(index + 1)}/${String(rbacRefreshCallbacks.current.size)}`,\n );\n return cb().catch((err: unknown) => {\n console.error(`[ExGuardRealtimeProvider] โ Error during RBAC refresh callback ${String(index + 1)}:`, err);\n });\n });\n\n await Promise.all(refreshPromises);\n console.log('[ExGuardRealtimeProvider] โ
All RBAC refresh callbacks completed');\n };\n\n // Manual reconnect function\n const handleReconnect = async (): Promise<void> => {\n if (!currentUserRef.current) {\n console.warn('[ExGuardRealtimeProvider] โ ๏ธ No user credentials available for reconnect');\n return;\n }\n const { token, userId } = currentUserRef.current;\n console.log('[ExGuardRealtimeProvider] ๐ Manual reconnect requested for', { userId });\n await handleConnect(token, userId);\n };\n\n // Manual RBAC refresh function\n const handleRefreshRbac = async (): Promise<void> => {\n console.log('[ExGuardRealtimeProvider] ๐ Manual RBAC refresh requested');\n await triggerRbacRefresh();\n };\n\n useEffect(() => {\n const accessToken = localStorage.getItem('access_token');\n\n console.log('[ExGuardRealtimeProvider] ๐ Checking credentials on mount:', {\n hasAccessToken: Boolean(accessToken),\n tokenLength: accessToken?.length,\n });\n\n if (!accessToken) {\n console.warn('[ExGuardRealtimeProvider] โ ๏ธ No access token found in localStorage');\n return;\n }\n\n if (connectionAttempted.current) {\n return;\n }\n\n connectionAttempted.current = true;\n\n // Fetch user info from backend\n const initializeConnection = async (): Promise<void> => {\n try {\n const userId = await getCurrentUserId();\n\n if (!userId) {\n console.error('[ExGuardRealtimeProvider] โ Failed to get userId from backend');\n return;\n }\n\n console.log('[ExGuardRealtimeProvider] ๐ Initiating realtime connection', {\n userId,\n });\n\n currentUserRef.current = { token: accessToken, userId };\n currentUserIdRef.current = userId;\n await realtimeClient.connect(accessToken, userId);\n console.log('[ExGuardRealtimeProvider] โ
Auto-connection successful');\n setIsConnected(true);\n\n // INDIVIDUAL user event listener - NO GLOBAL LISTENERS\n console.log('[ExGuardRealtimeProvider] ๐ง Setting up INDIVIDUAL user notification listener');\n\n // Listen ONLY for THIS USER's access changes (sent to user:{userId} room)\n realtimeClient.subscribe('user:access-changed', (payload: UserRbacEventPayload): void => {\n const { userId: eventUserId, roleId, action } = payload.data;\n console.log('[ExGuardRealtimeProvider] ๐ฏ INDIVIDUAL: Your access has been changed!', {\n eventUserId,\n roleId,\n action,\n currentUserId: currentUserIdRef.current,\n });\n\n // No need to check userId - if this event reached our room (user:{cognitoSubId}),\n // it's definitely for us. Backend ensures correct room targeting.\n console.log('[ExGuardRealtimeProvider] โ
Event received in our personal room! Refreshing access...');\n console.log(\n `[ExGuardRealtimeProvider] ๐ข Triggering RBAC refresh for ${String(rbacRefreshCallbacks.current.size)} registered callbacks`,\n );\n void triggerRbacRefresh();\n });\n\n console.log('[ExGuardRealtimeProvider] โ
Individual user event listener registered');\n } catch (error: unknown) {\n console.error('[ExGuardRealtimeProvider] โ Failed to establish realtime connection:');\n const errorMessage = error instanceof Error ? error.message : String(error);\n const tokenStr = accessToken ? accessToken.substring(0, 20) + '...' : '';\n console.error('[ExGuardRealtimeProvider] Error details:', {\n message: errorMessage,\n token: tokenStr,\n });\n setIsConnected(false);\n }\n };\n\n void initializeConnection();\n\n // Monitor connection status\n let lastConnectedState = realtimeClient.getIsConnected();\n const interval = setInterval(() => {\n const currentConnectedState = realtimeClient.getIsConnected();\n if (currentConnectedState !== lastConnectedState) {\n console.log('[ExGuardRealtimeProvider] ๐ Connection status changed:', {\n from: lastConnectedState,\n to: currentConnectedState,\n });\n lastConnectedState = currentConnectedState;\n setIsConnected(currentConnectedState);\n }\n }, 1000);\n\n return () => {\n clearInterval(interval);\n };\n }, []);\n\n const handleConnect = async (token: string, userId: string) => {\n try {\n console.log('[ExGuardRealtimeProvider] ๐ Manual connection requested', { userId });\n currentUserRef.current = { token, userId };\n await realtimeClient.connect(token, userId);\n setIsConnected(true);\n console.log('[ExGuardRealtimeProvider] โ
Manual connection successful');\n } catch (error: unknown) {\n console.error('[ExGuardRealtimeProvider] โ Failed to connect to realtime:', error);\n setIsConnected(false);\n throw error;\n }\n };\n\n const handleDisconnect = () => {\n console.log('[ExGuardRealtimeProvider] ๐ Disconnection requested');\n realtimeClient.disconnect();\n setIsConnected(false);\n };\n\n const value: ExGuardRealtimeContextType = {\n isConnected,\n connect: handleConnect,\n disconnect: handleDisconnect,\n reconnect: handleReconnect,\n refreshRbac: handleRefreshRbac,\n registerRbacRefreshCallback,\n };\n\n return <ExGuardRealtimeContext value={value}>{children}</ExGuardRealtimeContext>;\n}\n","/**\n * ExGuard Realtime Subscription Hook\n *\n * Hook to subscribe to realtime channels and handle RBAC events\n */\n\nimport { useEffect } from 'react';\nimport { useExGuardRealtime } from './use-exguard-realtime';\nimport { realtimeClient } from '../lib/realtime-client';\nimport { EXGUARD_RBAC_EVENTS, EXGUARD_RBAC_CHANNELS } from '../config/realtime-rbac-config';\nimport type { RealtimeEventType } from '../lib/realtime.types';\n\ninterface UseExGuardRealtimeSubscriptionOptions {\n /** Event types to subscribe to. If not provided, subscribes to all RBAC events */\n events?: RealtimeEventType[];\n /** Whether to auto-subscribe on mount */\n autoSubscribe?: boolean;\n}\n\n/**\n * Hook to subscribe to ExGuard realtime channel and handle RBAC updates\n * @param channel - Channel name ('rbac', 'roles', 'permissions')\n * @param options - Subscription options\n */\nexport function useExGuardRealtimeSubscription(\n channel: keyof typeof EXGUARD_RBAC_CHANNELS = 'RBAC',\n options: UseExGuardRealtimeSubscriptionOptions = {},\n): void {\n const { registerRbacRefreshCallback } = useExGuardRealtime();\n const { autoSubscribe = true, events } = options;\n const channelName = EXGUARD_RBAC_CHANNELS[channel];\n\n useEffect(() => {\n if (!autoSubscribe) {\n return;\n }\n\n console.log(`[useExGuardRealtimeSubscription] ๐ก Subscribing to channel: ${channelName}`);\n\n // Subscribe to channel on server\n void realtimeClient.subscribeToChannel(channelName);\n\n // If specific events provided, subscribe to them\n if (events && events.length > 0) {\n const unsubscribers: (() => void)[] = [];\n\n events.forEach((eventType) => {\n const unsubscribe = realtimeClient.subscribe(eventType, (): void => {\n console.log(`[useExGuardRealtimeSubscription] ๐ Received event: ${eventType}`);\n });\n unsubscribers.push(unsubscribe);\n });\n\n return () => {\n console.log(`[useExGuardRealtimeSubscription] ๐งน Cleaning up subscriptions for channel: ${channelName}`);\n unsubscribers.forEach((unsubscribe) => {\n unsubscribe();\n });\n realtimeClient.unsubscribeFromChannel(channelName);\n };\n }\n\n // Default: subscribe to all RBAC events\n const defaultRbacEvents: RealtimeEventType[] = [\n EXGUARD_RBAC_EVENTS.ROLE_CREATED,\n EXGUARD_RBAC_EVENTS.ROLE_UPDATED,\n EXGUARD_RBAC_EVENTS.ROLE_DELETED,\n EXGUARD_RBAC_EVENTS.PERMISSION_CREATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_UPDATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_DELETED,\n EXGUARD_RBAC_EVENTS.ROLE_PERMISSION_ASSIGNED,\n EXGUARD_RBAC_EVENTS.ROLE_PERMISSION_REMOVED,\n EXGUARD_RBAC_EVENTS.USER_ONLINE,\n EXGUARD_RBAC_EVENTS.GROUP_UPDATED,\n ];\n\n const unsubscribers: (() => void)[] = [];\n\n defaultRbacEvents.forEach((eventType) => {\n const unsubscribe = realtimeClient.subscribe(eventType, (): void => {\n console.log(`[useExGuardRealtimeSubscription] ๐ Received event: ${eventType}`);\n });\n unsubscribers.push(unsubscribe);\n });\n\n // Register callback to trigger RBAC refresh\n const unregisterCallback = registerRbacRefreshCallback(() => {\n console.log(`[useExGuardRealtimeSubscription] ๐ RBAC refresh triggered for channel: ${channelName}`);\n return Promise.resolve();\n });\n\n return () => {\n console.log(`[useExGuardRealtimeSubscription] ๐งน Cleaning up subscriptions for channel: ${channelName}`);\n unsubscribers.forEach((unsubscribe) => {\n unsubscribe();\n });\n unregisterCallback();\n realtimeClient.unsubscribeFromChannel(channelName);\n };\n }, [channelName, autoSubscribe, events, registerRbacRefreshCallback]);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/config/exguard-config.ts","../src/config/realtime-rbac-config.ts","../src/api/exguard-api.ts","../src/providers/exguard-realtime-context.ts","../src/hooks/use-user-access.ts","../src/components/ui/spinner.tsx","../src/components/ui/button.tsx","../src/components/ui/card.tsx","../src/components/permission-guard.tsx","../src/lib/realtime-client.ts","../src/hooks/use-realtime.ts","../src/providers/use-exguard-realtime.ts","../src/hooks/use-exguard-rbac.ts","../src/utils/exguard-realtime-utils.ts","../src/providers/exguard-realtime-provider.tsx","../src/providers/use-exguard-realtime-subscription.ts"],"names":["jsx","useEffect","use","useRef","unsubscribers"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * ExGuard API Configuration\r\n * Configuration for ExGuard backend API\r\n */\r\n\r\nexport interface ExGuardConfig {\r\n apiUrl: string;\r\n withCredentials?: boolean;\r\n}\r\n\r\n/**\r\n * Default ExGuard API configuration\r\n * Note: apiUrl should be provided by the consuming application\r\n */\r\nexport const DEFAULT_EXGUARD_CONFIG: ExGuardConfig = {\r\n apiUrl: '',\r\n withCredentials: true,\r\n};\r\n\r\n/**\r\n * Get ExGuard API URL from environment or provided config\r\n * For Vite apps: import.meta.env.VITE_GUARD_APP_URL\r\n * For Next.js: process.env.NEXT_PUBLIC_GUARD_APP_URL\r\n * Or provide via setExGuardConfig()\r\n */\r\nlet configuredApiUrl: string = '';\r\n\r\nexport const setExGuardConfig = (config: Partial<ExGuardConfig>): void => {\r\n if (config.apiUrl) {\r\n configuredApiUrl = config.apiUrl;\r\n }\r\n};\r\n\r\nexport const getExGuardApiUrl = (): string => {\r\n if (configuredApiUrl) {\r\n return configuredApiUrl;\r\n }\r\n \r\n // Try to get from global environment\r\n if (typeof window !== 'undefined') {\r\n // Check for injected env vars\r\n if ((window as any).__EXGUARD_API_URL__) {\r\n return (window as any).__EXGUARD_API_URL__;\r\n }\r\n }\r\n \r\n // Fallback to localhost for development\r\n return 'http://localhost:3000';\r\n};\r\n\r\n/**\r\n * Storage keys for ExGuard\r\n */\r\nexport const EXGUARD_STORAGE_KEYS = {\r\n ACCESS_TOKEN: 'access_token',\r\n ID_TOKEN: 'id_token',\r\n REFRESH_TOKEN: 'refresh_token',\r\n} as const;\r\n","/**\n * ExGuard Realtime RBAC Configuration\n *\n * This file contains all configuration for realtime RBAC events\n * specific to ExGuard module (users, roles, permissions management)\n */\n\n/**\n * Channels to subscribe to for ExGuard RBAC\n */\nexport const EXGUARD_RBAC_CHANNELS = {\n ROLES: 'roles',\n PERMISSIONS: 'permissions',\n RBAC: 'rbac',\n} as const;\n\n/**\n * Event types for ExGuard RBAC realtime updates\n */\nexport const EXGUARD_RBAC_EVENTS = {\n // Role events\n ROLE_CREATED: 'role:created',\n ROLE_UPDATED: 'role:updated',\n ROLE_DELETED: 'role:deleted',\n\n // Permission events\n PERMISSION_CREATED: 'permission:created',\n PERMISSION_UPDATED: 'permission:updated',\n PERMISSION_DELETED: 'permission:deleted',\n\n // Role-Permission events\n ROLE_PERMISSION_ASSIGNED: 'role-permission:assigned',\n ROLE_PERMISSION_REMOVED: 'role-permission:removed',\n\n // User RBAC events\n USER_ROLES_UPDATED: 'user:roles-updated',\n USER_PERMISSIONS_CHANGED: 'user:permissions-changed',\n USER_ACCESS_CHANGED: 'user:access-changed',\n RBAC_USER_ASSIGNED_TO_GROUP: 'rbac:user-assigned-to-group',\n RBAC_USER_REMOVED_FROM_GROUP: 'rbac:user-removed-from-group',\n RBAC_PERMISSIONS_UPDATED: 'rbac:permissions-updated',\n\n // User status events\n USER_ONLINE: 'user:online',\n USER_OFFLINE: 'user:offline',\n\n // Group events\n GROUP_UPDATED: 'group:updated',\n} as const;\n\n/**\n * Reconnection delay after RBAC updates (in milliseconds)\n * This ensures backend has fully processed the update before refetching data\n */\nexport const RBAC_RECONNECT_DELAY = 300;\n\n/**\n * Configuration for automatic reconnection after specific events\n */\nexport const RBAC_AUTO_RECONNECT_EVENTS = [\n EXGUARD_RBAC_EVENTS.ROLE_UPDATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_UPDATED,\n EXGUARD_RBAC_EVENTS.USER_ACCESS_CHANGED,\n] as const;\n\n/**\n * Events that should trigger user data refresh\n */\nexport const USER_REFRESH_EVENTS = [\n EXGUARD_RBAC_EVENTS.USER_ROLES_UPDATED,\n EXGUARD_RBAC_EVENTS.USER_PERMISSIONS_CHANGED,\n EXGUARD_RBAC_EVENTS.USER_ACCESS_CHANGED,\n EXGUARD_RBAC_EVENTS.RBAC_USER_ASSIGNED_TO_GROUP,\n EXGUARD_RBAC_EVENTS.RBAC_USER_REMOVED_FROM_GROUP,\n EXGUARD_RBAC_EVENTS.RBAC_PERMISSIONS_UPDATED,\n] as const;\n\n/**\n * Events that should trigger role data refresh\n */\nexport const ROLE_REFRESH_EVENTS = [\n EXGUARD_RBAC_EVENTS.ROLE_CREATED,\n EXGUARD_RBAC_EVENTS.ROLE_UPDATED,\n EXGUARD_RBAC_EVENTS.ROLE_DELETED,\n EXGUARD_RBAC_EVENTS.ROLE_PERMISSION_ASSIGNED,\n] as const;\n\n/**\n * Events that should trigger permission data refresh\n */\nexport const PERMISSION_REFRESH_EVENTS = [\n EXGUARD_RBAC_EVENTS.PERMISSION_CREATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_UPDATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_DELETED,\n] as const;\n","import axios, { type AxiosError } from 'axios';\nimport type { VerifyTokenResponse, UserAccessData, AuthApiResponse } from '../types/exguard-types';\nimport { getExGuardApiUrl, EXGUARD_STORAGE_KEYS } from '../config/exguard-config';\n\n// Create a separate axios instance for Guard API endpoints\n// Note: baseURL is set dynamically in the interceptor to support runtime configuration\nconst guardApiClient = axios.create({\n withCredentials: true,\n headers: {\n 'Content-Type': 'application/json',\n },\n});\n\n// Add interceptor to dynamically set baseURL and include access token\nguardApiClient.interceptors.request.use(\n (config) => {\n // Set baseURL dynamically from config (supports runtime configuration)\n config.baseURL = getExGuardApiUrl();\n \n const token = window.localStorage.getItem(EXGUARD_STORAGE_KEYS.ACCESS_TOKEN);\n if (token) {\n config.headers.Authorization = `Bearer ${token}`;\n }\n return config;\n },\n (error: unknown) => Promise.reject(error instanceof Error ? error : new Error(String(error))),\n);\n\n/**\n * Verify ID token with ExGuard backend\n */\nexport async function verifyToken(): Promise<VerifyTokenResponse> {\n try {\n const idToken = window.localStorage.getItem(EXGUARD_STORAGE_KEYS.ID_TOKEN);\n const response = await guardApiClient.post<\n AuthApiResponse<{\n user?: {\n id: string;\n username: string;\n email: string;\n givenName: string;\n familyName: string;\n };\n }>\n >('/guard/verify-token', {\n id_token: idToken,\n });\n\n if (response.data.success && response.data.data) {\n console.log('Token verification response:', response.data.data);\n\n // Map backend response to frontend format\n const backendData = response.data.data;\n const mappedResponse: VerifyTokenResponse = {\n valid: true,\n user: backendData.user\n ? {\n userId: backendData.user.id,\n username: backendData.user.username,\n email: backendData.user.email,\n givenName: backendData.user.givenName,\n familyName: backendData.user.familyName,\n }\n : undefined,\n };\n\n console.log('Mapped user data:', mappedResponse.user);\n return mappedResponse;\n }\n\n throw new Error(response.data.message ?? 'Token verification failed');\n } catch (error) {\n const axiosError = error as AxiosError<AuthApiResponse<never>>;\n\n if (axiosError.response?.data) {\n const errorData = axiosError.response.data;\n const errorMessage = errorData.message ?? 'Token verification failed';\n throw new Error(errorMessage);\n }\n\n throw error;\n }\n}\n\n/**\n * Get user access data including roles, permissions, modules, and field offices\n */\nexport async function getUserAccess(): Promise<UserAccessData> {\n try {\n const response = await guardApiClient.get<AuthApiResponse<UserAccessData>>('/guard/me');\n\n if (response.data.success && response.data.data) {\n console.log('User Access Data:', response.data.data);\n console.log('User Details:', response.data.data.user);\n console.log('User Roles:', response.data.data.roles);\n console.log('User Groups:', response.data.data.groups);\n console.log('User Modules:', response.data.data.modules);\n console.log('User Field Offices:', response.data.data.fieldOffices);\n return response.data.data;\n }\n\n throw new Error(response.data.message ?? 'Failed to get user access data');\n } catch (error) {\n const axiosError = error as AxiosError<AuthApiResponse<never>>;\n\n if (axiosError.response?.data) {\n const errorData = axiosError.response.data;\n const errorMessage = errorData.message ?? 'Failed to get user access data';\n throw new Error(errorMessage);\n }\n\n throw error;\n }\n}\n","/**\n * ExGuard Realtime Context\n *\n * Context for managing realtime RBAC connections and state\n */\n\nimport { createContext } from 'react';\n\nexport interface ExGuardRealtimeContextType {\n isConnected: boolean;\n connect: (token: string, userId: string) => Promise<void>;\n disconnect: () => void;\n reconnect: () => Promise<void>;\n refreshRbac: () => Promise<void>;\n registerRbacRefreshCallback: (callback: () => Promise<void>) => () => void;\n}\n\nexport const ExGuardRealtimeContext = createContext<ExGuardRealtimeContextType | undefined>(undefined);\n","import { useEffect, useState, useCallback, use } from 'react';\r\nimport { getUserAccess } from '../api/exguard-api';\r\nimport type { UserAccessData, ModulePermissions } from '../types/exguard-types';\r\nimport { ExGuardRealtimeContext } from '../providers/exguard-realtime-context';\r\n\r\ninterface UseUserAccessOptions {\r\n enabled?: boolean;\r\n refetchInterval?: number;\r\n}\r\n\r\n/**\r\n * Custom hook to fetch and manage user access data with RBAC\r\n * Includes caching and periodic refetching for real-time RBAC\r\n */\r\nexport const useUserAccess = (options: UseUserAccessOptions = {}) => {\r\n const { enabled = true, refetchInterval = 0 } = options;\r\n const [userAccess, setUserAccess] = useState<UserAccessData | null>(null);\r\n const [isLoading, setIsLoading] = useState(true);\r\n const [error, setError] = useState<Error | null>(null);\r\n const realtimeContext = use(ExGuardRealtimeContext);\r\n\r\n const fetchUserAccess = useCallback(async (silent = false): Promise<void> => {\r\n if (!enabled) return;\r\n\r\n try {\r\n console.log(`[useUserAccess] ๐ Fetching user access data... ${silent ? '(silent)' : ''}`);\r\n // Only set loading state if not silent refresh\r\n if (!silent) {\r\n setIsLoading(true);\r\n }\r\n setError(null);\r\n const data = await getUserAccess();\r\n setUserAccess(data);\r\n console.log('[useUserAccess] โ
User access refreshed successfully', {\r\n userId: data.user.id,\r\n username: data.user.username,\r\n modulesCount: data.modules.length,\r\n modules: data.modules.map((m) => m.key),\r\n });\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error('Failed to fetch user access');\r\n setError(errorObj);\r\n console.error('[useUserAccess] โ Failed to fetch user access:', errorObj);\r\n } finally {\r\n // Only clear loading state if not silent refresh\r\n if (!silent) {\r\n setIsLoading(false);\r\n }\r\n }\r\n }, [enabled]);\r\n\r\n // Register for real-time RBAC updates from the realtime provider\r\n useEffect(() => {\r\n if (!realtimeContext) {\r\n console.warn('[useUserAccess] โ ๏ธ RealtimeContext not available');\r\n return;\r\n }\r\n\r\n console.log('[useUserAccess] ๐ก Registering RBAC refresh callback');\r\n // Use silent refresh for realtime updates to prevent UI disruption\r\n const unsubscribe = realtimeContext.registerRbacRefreshCallback(() => fetchUserAccess(true));\r\n console.log('[useUserAccess] โ
RBAC refresh callback registered');\r\n\r\n return () => {\r\n console.log('[useUserAccess] ๐ Unregistering RBAC refresh callback');\r\n unsubscribe();\r\n };\r\n }, [realtimeContext, fetchUserAccess]);\r\n\r\n useEffect(() => {\r\n void fetchUserAccess();\r\n\r\n if (refetchInterval > 0) {\r\n const interval = setInterval(() => {\r\n void fetchUserAccess();\r\n }, refetchInterval);\r\n\r\n return () => {\r\n clearInterval(interval);\r\n };\r\n }\r\n }, [fetchUserAccess, refetchInterval]);\r\n\r\n const hasModuleAccess = useCallback(\r\n (moduleKey: string): boolean => {\r\n if (!userAccess) return false;\r\n const module = userAccess.modules.find((m: ModulePermissions) => m.key.toLowerCase() === moduleKey.toLowerCase());\r\n return !!module && module.permissions.length > 0;\r\n },\r\n [userAccess],\r\n );\r\n\r\n const getModulePermissions = useCallback(\r\n (moduleKey: string): string[] => {\r\n if (!userAccess) return [];\r\n const module = userAccess.modules.find((m: ModulePermissions) => m.key.toLowerCase() === moduleKey.toLowerCase());\r\n return module?.permissions ?? [];\r\n },\r\n [userAccess],\r\n );\r\n\r\n const hasPermission = useCallback(\r\n (moduleKey: string, permission: string): boolean => {\r\n const permissions = getModulePermissions(moduleKey);\r\n return permissions.includes(permission);\r\n },\r\n [getModulePermissions],\r\n );\r\n\r\n return {\r\n userAccess,\r\n isLoading,\r\n error,\r\n hasModuleAccess,\r\n getModulePermissions,\r\n hasPermission,\r\n refetch: fetchUserAccess,\r\n };\r\n};\r\n","import React from 'react';\r\n\r\ninterface SpinnerProps {\r\n className?: string;\r\n}\r\n\r\nexport function Spinner({ className = '' }: SpinnerProps) {\r\n return (\r\n <div\r\n className={`animate-spin rounded-full border-4 border-solid border-current border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite] ${className}`}\r\n role=\"status\"\r\n >\r\n <span className=\"!absolute !-m-px !h-px !w-px !overflow-hidden !whitespace-nowrap !border-0 !p-0 ![clip:rect(0,0,0,0)]\">\r\n Loading...\r\n </span>\r\n </div>\r\n );\r\n}\r\n","import React from 'react';\r\n\r\ninterface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\r\n variant?: 'default' | 'outline' | 'destructive' | 'ghost' | 'link';\r\n size?: 'default' | 'sm' | 'lg' | 'icon';\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport function Button({\r\n className = '',\r\n variant = 'default',\r\n size = 'default',\r\n children,\r\n ...props\r\n}: ButtonProps) {\r\n const baseStyles =\r\n 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50';\r\n\r\n const variantStyles = {\r\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\r\n outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',\r\n destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',\r\n ghost: 'hover:bg-accent hover:text-accent-foreground',\r\n link: 'text-primary underline-offset-4 hover:underline',\r\n };\r\n\r\n const sizeStyles = {\r\n default: 'h-10 px-4 py-2',\r\n sm: 'h-9 rounded-md px-3',\r\n lg: 'h-11 rounded-md px-8',\r\n icon: 'h-10 w-10',\r\n };\r\n\r\n return (\r\n <button\r\n className={`${baseStyles} ${variantStyles[variant]} ${sizeStyles[size]} ${className}`}\r\n {...props}\r\n >\r\n {children}\r\n </button>\r\n );\r\n}\r\n","import React from 'react';\r\n\r\ninterface CardProps extends React.HTMLAttributes<HTMLDivElement> {\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport function Card({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <div\r\n className={`rounded-lg border bg-card text-card-foreground shadow-sm ${className}`}\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nexport function CardHeader({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <div className={`flex flex-col space-y-1.5 p-6 ${className}`} {...props}>\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nexport function CardTitle({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <h3 className={`text-2xl font-semibold leading-none tracking-tight ${className}`} {...props}>\r\n {children}\r\n </h3>\r\n );\r\n}\r\n\r\nexport function CardDescription({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <p className={`text-sm text-muted-foreground ${className}`} {...props}>\r\n {children}\r\n </p>\r\n );\r\n}\r\n\r\nexport function CardContent({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <div className={`p-6 pt-0 ${className}`} {...props}>\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nexport function CardFooter({ className = '', children, ...props }: CardProps) {\r\n return (\r\n <div className={`flex items-center p-6 pt-0 ${className}`} {...props}>\r\n {children}\r\n </div>\r\n );\r\n}\r\n","import { Navigate, Outlet } from 'react-router';\r\nimport { useUserAccess } from '../hooks/use-user-access';\r\nimport { Spinner } from './ui/spinner';\r\nimport { Button } from './ui/button';\r\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from './ui/card';\r\nimport { ArrowLeft, ShieldAlert, Lock } from 'lucide-react';\r\n\r\ninterface PermissionGuardProps {\r\n module: string;\r\n permission?: string;\r\n requireModule?: boolean;\r\n requirePermission?: boolean;\r\n fallbackPath?: string;\r\n}\r\n\r\n/**\r\n * PermissionGuard component that checks if user has required module access and/or permissions\r\n *\r\n * @param module - The module key (e.g., 'EXID', 'EXFLOW', 'TEV')\r\n * @param permission - Optional specific permission to check (e.g., 'profile:create', 'profile:update')\r\n * @param requireModule - Whether to require module access (default: true)\r\n * @param requirePermission - Whether to require the specific permission (default: true if permission is provided)\r\n * @param fallbackPath - Path to redirect to if access is denied (default: show error page)\r\n */\r\nexport function PermissionGuard({\r\n module,\r\n permission,\r\n requireModule = true,\r\n requirePermission = true,\r\n fallbackPath,\r\n}: PermissionGuardProps) {\r\n const { isLoading, hasModuleAccess, hasPermission } = useUserAccess();\r\n\r\n // Show loading spinner while checking permissions\r\n if (isLoading) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px]\">\r\n <Spinner className=\"size-8\" />\r\n </div>\r\n );\r\n }\r\n\r\n // Check module access\r\n const hasModule = hasModuleAccess(module);\r\n const moduleCheckFailed = requireModule && !hasModule;\r\n\r\n // Check specific permission if provided\r\n const hasSpecificPermission = permission ? hasPermission(module, permission) : true;\r\n const permissionCheckFailed = permission && requirePermission && !hasSpecificPermission;\r\n\r\n // Determine if access should be denied\r\n const accessDenied = moduleCheckFailed || permissionCheckFailed;\r\n\r\n // Redirect to fallback path if provided\r\n if (accessDenied && fallbackPath) {\r\n return <Navigate to={fallbackPath} replace />;\r\n }\r\n\r\n // Show access denied message\r\n if (accessDenied) {\r\n const denialReason = moduleCheckFailed\r\n ? {\r\n title: 'Module Access Required',\r\n description: `Access to the ${module} module is required to view this page`,\r\n detail: `Your current account permissions do not include access to the ${module} module. This module may be restricted to specific roles or user groups.`,\r\n }\r\n : {\r\n title: 'Permission Required',\r\n description: `The permission \"${permission ?? 'unknown'}\" is needed to access this resource`,\r\n detail: `Your account has access to the ${module} module but lacks the specific permission required for this action. This permission may need to be assigned to your role or user group.`,\r\n };\r\n\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[calc(100vh-4rem)] p-6\">\r\n <Card className=\"w-full max-w-lg\">\r\n <CardHeader className=\"text-center pb-4\">\r\n <div className=\"mx-auto mb-4 flex size-16 items-center justify-center rounded-full bg-destructive/10\">\r\n {moduleCheckFailed ? (\r\n <Lock className=\"size-8 text-destructive\" />\r\n ) : (\r\n <ShieldAlert className=\"size-8 text-destructive\" />\r\n )}\r\n </div>\r\n <CardTitle className=\"text-2xl\">{denialReason.title}</CardTitle>\r\n <CardDescription className=\"text-base\">{denialReason.description}</CardDescription>\r\n </CardHeader>\r\n <CardContent className=\"space-y-4\">\r\n <div className=\"rounded-lg bg-muted p-4\">\r\n <p className=\"text-sm text-muted-foreground\">{denialReason.detail}</p>\r\n </div>\r\n <div className=\"flex flex-col gap-2 sm:flex-row sm:justify-center\">\r\n <Button\r\n variant=\"outline\"\r\n onClick={() => {\r\n window.history.back();\r\n }}\r\n className=\"w-full sm:w-auto\"\r\n >\r\n <ArrowLeft className=\"mr-2 size-4\" />\r\n Go Back\r\n </Button>\r\n <Button\r\n variant=\"default\"\r\n onClick={() => {\r\n window.location.href = '/';\r\n }}\r\n className=\"w-full sm:w-auto\"\r\n >\r\n Return to Dashboard\r\n </Button>\r\n </div>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n );\r\n }\r\n\r\n // User has required access, render child routes\r\n return <Outlet />;\r\n}\r\n","import { io, type Socket } from 'socket.io-client';\nimport type { RealtimeEventPayload, RealtimeEventType, RealtimeEventHandler } from './realtime.types';\nimport { getExGuardApiUrl } from '../config/exguard-config';\n\nclass RealtimeClient {\n private socket: Socket | null = null;\n private listeners = new Map<string, Set<RealtimeEventHandler>>();\n private isConnected = false;\n private debug = true; // Enable/disable debug logging\n private connectionPromise: Promise<void> | null = null;\n\n constructor() {\n this.log('๐ข RealtimeClient initialized');\n }\n \n private getApiUrl(): string {\n return getExGuardApiUrl();\n }\n\n private log(message: string, data?: unknown) {\n if (this.debug) {\n console.log(`[RealtimeClient] ${message}`, data);\n }\n }\n\n private logError(message: string, error?: unknown) {\n console.error(`[RealtimeClient] ${message}`, error);\n }\n\n private logWarn(message: string, data?: unknown) {\n console.warn(`[RealtimeClient] ${message}`, data);\n }\n\n /**\n * Connect to the realtime server\n */\n connect(token: string, userId: string): Promise<void> {\n // Validate inputs\n if (!token) {\n this.logError('โ Cannot connect - token is missing or empty');\n return Promise.reject(new Error('Missing authentication token'));\n }\n\n if (!userId) {\n this.logError('โ Cannot connect - userId is missing or empty');\n return Promise.reject(new Error('Missing userId'));\n }\n\n // Return existing connection promise if already connecting\n if (this.connectionPromise) {\n this.log('โณ Connection already in progress, returning existing promise');\n return this.connectionPromise;\n }\n\n this.connectionPromise = new Promise((resolve, reject) => {\n try {\n const apiUrl = this.getApiUrl();\n this.log('๐ Attempting to connect...', { apiUrl, userId, hasToken: !!token });\n\n if (this.socket?.connected) {\n this.log('โ
Already connected');\n this.connectionPromise = null;\n resolve();\n return;\n }\n\n const socketUrl = `${apiUrl}/realtime`;\n this.log('๐ Creating Socket.IO connection', {\n url: socketUrl,\n transports: ['websocket', 'polling'],\n userId,\n });\n\n this.socket = io(socketUrl, {\n auth: {\n token,\n userId,\n },\n transports: ['websocket', 'polling'],\n reconnection: true,\n reconnectionDelay: 1000,\n reconnectionDelayMax: 5000,\n reconnectionAttempts: 5,\n });\n\n this.socket.on('connect', () => {\n this.isConnected = true;\n this.log('โ
Connected to realtime server', {\n socketId: this.socket?.id,\n userId,\n });\n this.connectionPromise = null;\n resolve();\n });\n\n this.socket.on('disconnect', (reason: string) => {\n this.isConnected = false;\n this.log('โ Disconnected from realtime server', { reason });\n });\n\n this.socket.on('connect_error', (error: unknown) => {\n this.logError('โ Connection error (check token and backend)', error);\n this.connectionPromise = null;\n const errorMessage = error instanceof Error ? error.message : String(error);\n reject(new Error(`Connection error: ${errorMessage}`));\n });\n\n this.socket.on('error', (error: unknown) => {\n this.logError('โ Realtime error', error);\n this.connectionPromise = null;\n const errorMessage = error instanceof Error ? error.message : String(error);\n reject(new Error(`Socket.IO error: ${errorMessage}`));\n });\n\n this.socket.on('reconnect_attempt', () => {\n this.log('๐ Attempting to reconnect...');\n });\n\n this.socket.on('reconnect', () => {\n this.isConnected = true;\n this.log('๐ Reconnected to realtime server', {\n socketId: this.socket?.id,\n });\n });\n\n this.socket.on('reconnect_failed', () => {\n this.logError('โ Reconnection failed after maximum attempts');\n this.connectionPromise = null;\n reject(new Error('Reconnection failed'));\n });\n\n // Listen to all realtime events\n this.socket.onAny((eventName: string, payload: unknown) => {\n // Debug: log raw event for troubleshooting\n this.log(`๐จ Raw event received`, {\n eventName,\n payloadType: typeof payload,\n payload,\n });\n\n // Normalize payload - backend sends event name separately from payload\n const payloadObj =\n typeof payload === 'object' && payload !== null ? (payload as Record<string, unknown>) : {};\n\n // CRITICAL FIX: Use eventName as the primary event type (e.g., 'user:access-changed')\n // Socket.IO sends the event name as the first parameter, not nested in payload.type\n const eventType = eventName;\n\n const normalizedPayload: RealtimeEventPayload = {\n type: eventType as RealtimeEventType,\n timestamp:\n 'timestamp' in payloadObj\n ? typeof payloadObj.timestamp === 'number'\n ? payloadObj.timestamp\n : new Date(payloadObj.timestamp as string).getTime()\n : Date.now(),\n data: 'data' in payloadObj ? payloadObj.data : payload,\n };\n\n this.log(`๐จ Event processed: ${eventType}`, {\n type: normalizedPayload.type,\n timestamp: normalizedPayload.timestamp,\n dataKeys:\n typeof normalizedPayload.data === 'object' && normalizedPayload.data !== null\n ? Object.keys(normalizedPayload.data as Record<string, unknown>)\n : 'N/A',\n });\n this.handleEvent(eventType as RealtimeEventType, normalizedPayload);\n });\n } catch (error) {\n this.logError('Failed to initialize connection', error);\n const errorMessage = error instanceof Error ? error.message : String(error);\n reject(new Error(`Connection initialization failed: ${errorMessage}`));\n }\n });\n\n return this.connectionPromise;\n }\n\n /**\n * Disconnect from the realtime server\n */\n disconnect(): void {\n this.log('๐ Disconnecting from realtime server...');\n if (this.socket) {\n this.socket.disconnect();\n this.socket = null;\n this.isConnected = false;\n this.log('โ
Disconnected');\n }\n }\n\n /**\n * Check if connected\n */\n getIsConnected(): boolean {\n return this.isConnected && this.socket?.connected === true;\n }\n\n /**\n * Wait for connection to be ready (with timeout)\n */\n async waitForConnection(timeoutMs = 30000): Promise<void> {\n const startTime = Date.now();\n\n while (Date.now() - startTime < timeoutMs) {\n if (this.getIsConnected()) {\n this.log('โ
Connection ready');\n return;\n }\n\n // Wait 100ms before checking again\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n this.logError('โ Timeout waiting for connection', { timeoutMs, elapsed: Date.now() - startTime });\n throw new Error('Connection timeout - failed to establish WebSocket connection');\n }\n\n /**\n * Subscribe to a specific event type\n */\n subscribe<T extends RealtimeEventPayload = RealtimeEventPayload>(\n eventType: RealtimeEventType,\n handler: RealtimeEventHandler<T>,\n ): () => void {\n if (!this.listeners.has(eventType)) {\n this.listeners.set(eventType, new Set());\n }\n\n this.listeners.get(eventType)?.add(handler as RealtimeEventHandler);\n const listenerCount = this.listeners.get(eventType)?.size ?? 0;\n this.log(`๐ Subscribed to event: ${eventType}`, { totalListeners: listenerCount });\n\n // Return unsubscribe function\n return () => {\n const handlers = this.listeners.get(eventType);\n if (handlers) {\n handlers.delete(handler as RealtimeEventHandler);\n this.log(`๐ Unsubscribed from event: ${eventType}`, {\n remainingListeners: handlers.size,\n });\n }\n };\n }\n\n /**\n * Unsubscribe from an event\n */\n unsubscribe(eventType: RealtimeEventType, handler: RealtimeEventHandler): void {\n const handlers = this.listeners.get(eventType);\n if (handlers) {\n handlers.delete(handler);\n this.log(`๐ Unsubscribed from event: ${eventType}`, {\n remainingListeners: handlers.size,\n });\n }\n }\n /**\n * Send a subscription message to the server with connection wait\n */\n async subscribeToChannel(channel: 'roles' | 'permissions' | 'rbac'): Promise<void> {\n try {\n this.log(`๐ก Subscribing to channel: ${channel}`);\n\n // Wait for connection to be ready\n await this.waitForConnection(15000);\n\n // Now emit subscribe\n this.log(`๐ก Emitting subscribe event for channel: ${channel}`);\n this.socket?.emit(`subscribe:${channel}`);\n this.log(`โ
Subscribed to channel: ${channel}`);\n } catch (error) {\n this.logError(`โ Failed to subscribe to channel \"${channel}\"`, error);\n throw error;\n }\n }\n\n /**\n * Send an unsubscription message to the server\n */\n unsubscribeFromChannel(channel: 'roles' | 'permissions' | 'rbac'): void {\n if (!this.socket?.connected) {\n this.logWarn(`Cannot unsubscribe from channel \"${channel}\" - socket not connected`);\n return;\n }\n\n this.log(`๐ก Unsubscribing from channel: ${channel}`);\n this.socket.emit(`unsubscribe:${channel}`);\n }\n\n /**\n * Handle incoming events\n */\n private handleEvent(eventType: RealtimeEventType, payload: RealtimeEventPayload): void {\n // Call specific event handlers\n const handlers = this.listeners.get(eventType);\n if (handlers && handlers.size > 0) {\n this.log(`๐ Triggering ${String(handlers.size)} handler(s) for event: ${eventType}`);\n handlers.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n this.logError(`Error in event handler for ${eventType}`, error);\n }\n });\n }\n\n // Call wildcard handlers if any\n const wildcardHandlers = this.listeners.get('*' as RealtimeEventType);\n if (wildcardHandlers && wildcardHandlers.size > 0) {\n this.log(`๐ Triggering ${String(wildcardHandlers.size)} wildcard handler(s)`);\n wildcardHandlers.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n this.logError('Error in wildcard event handler', error);\n }\n });\n }\n }\n\n /**\n * Get all connected listeners count\n */\n getListenerCount(eventType?: RealtimeEventType): number {\n if (eventType) {\n return this.listeners.get(eventType)?.size ?? 0;\n }\n let total = 0;\n this.listeners.forEach((handlers) => {\n total += handlers.size;\n });\n return total;\n }\n\n /**\n * Enable or disable debug logging\n */\n setDebug(enabled: boolean): void {\n this.debug = enabled;\n this.log(`Debug logging ${enabled ? 'enabled' : 'disabled'}`);\n }\n\n /**\n * Get connection status summary\n */\n getStatus() {\n const status = {\n isConnected: this.getIsConnected(),\n socketId: this.socket?.id ?? 'N/A',\n apiUrl: this.getApiUrl(),\n totalListeners: this.getListenerCount(),\n listeners: Array.from(this.listeners.entries()).map(([event, handlers]) => ({\n event,\n count: handlers.size,\n })),\n };\n this.log('๐ Connection Status', status);\n return status;\n }\n}\n\n// Create singleton instance\nexport const realtimeClient = new RealtimeClient();\n\n// Expose debug methods on window for console access\nif (typeof window !== 'undefined') {\n const w = window as unknown as Record<string, unknown>;\n w.__realtimeClient = {\n client: realtimeClient,\n connect: (token: string, userId: string) => realtimeClient.connect(token, userId),\n disconnect: () => {\n realtimeClient.disconnect();\n },\n isConnected: () => realtimeClient.getIsConnected(),\n setDebug: (enabled: boolean) => {\n realtimeClient.setDebug(enabled);\n },\n status: () => realtimeClient.getStatus(),\n getListenerCount: (eventType?: RealtimeEventType) => realtimeClient.getListenerCount(eventType),\n };\n console.log('๐ฏ RealtimeClient debug tools available at: window.__realtimeClient');\n}\n\nexport type { RealtimeClient };\n","/**\n * Shared Realtime Hooks\n *\n * Basic hooks for realtime functionality that wraps the realtime-client\n */\n\nimport { useEffect, useRef, useState } from 'react';\nimport { realtimeClient } from '../lib/realtime-client';\nimport type { RealtimeEventType, RealtimeEventPayload, RealtimeEventHandler } from '../lib/realtime.types';\n\n/**\n * Hook to subscribe to realtime RBAC events\n * Automatically handles subscription/unsubscription lifecycle\n */\nexport function useRealtimeRbac<T extends RealtimeEventPayload = RealtimeEventPayload>(\n eventType: RealtimeEventType,\n handler: RealtimeEventHandler<T>,\n) {\n const handlerRef = useRef(handler);\n\n useEffect(() => {\n handlerRef.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const unsubscribe = realtimeClient.subscribe<T>(eventType, (payload) => {\n handlerRef.current(payload);\n });\n\n return () => {\n unsubscribe();\n };\n }, [eventType]);\n}\n\n/**\n * Hook to manage channel subscriptions\n */\nexport function useRealtimeSubscription(channel: 'roles' | 'permissions' | 'rbac') {\n useEffect(() => {\n let isMounted = true;\n\n // Subscribe asynchronously\n realtimeClient.subscribeToChannel(channel).catch((error: unknown) => {\n if (isMounted) {\n console.error(`Failed to subscribe to channel \"${channel}\":`, error);\n }\n });\n\n return () => {\n isMounted = false;\n realtimeClient.unsubscribeFromChannel(channel);\n };\n }, [channel]);\n}\n\n/**\n * Hook to listen to multiple event types\n */\nexport function useRealtimeMultiple(\n events: {\n type: RealtimeEventType;\n handler: RealtimeEventHandler;\n }[],\n) {\n useEffect(() => {\n const unsubscribers = events.map(({ type, handler }) => realtimeClient.subscribe(type, handler));\n\n return () => {\n unsubscribers.forEach((unsub) => {\n unsub();\n });\n };\n }, [events]);\n}\n\n/**\n * Hook to listen to all realtime events\n */\nexport function useRealtimeAll(handler: RealtimeEventHandler) {\n const handlerRef = useRef(handler);\n\n useEffect(() => {\n handlerRef.current = handler;\n }, [handler]);\n\n useEffect(() => {\n const unsubscribe = realtimeClient.subscribe('*' as RealtimeEventType, (payload) => {\n handlerRef.current(payload);\n });\n\n return () => {\n unsubscribe();\n };\n }, []);\n}\n\n/**\n * Hook to get the connection status\n */\nexport function useRealtimeStatus() {\n const [isConnected, setIsConnected] = useState(realtimeClient.getIsConnected());\n\n useEffect(() => {\n const checkConnection = () => {\n setIsConnected(realtimeClient.getIsConnected());\n };\n\n const interval = setInterval(checkConnection, 1000);\n\n return () => {\n clearInterval(interval);\n };\n }, []);\n\n return { isConnected };\n}\n","/**\n * Hook to use ExGuard Realtime Context\n */\n\nimport { use } from 'react';\nimport { ExGuardRealtimeContext, type ExGuardRealtimeContextType } from './exguard-realtime-context';\n\n/**\n * Hook to access ExGuard realtime context\n * Must be used within ExGuardRealtimeProvider\n */\nexport function useExGuardRealtime(): ExGuardRealtimeContextType {\n const context = use(ExGuardRealtimeContext);\n if (!context) {\n throw new Error('useExGuardRealtime must be used within a ExGuardRealtimeProvider');\n }\n return context;\n}\n","/**\n * ExGuard Realtime RBAC Hooks\n *\n * Custom hooks for handling ExGuard-specific realtime RBAC events\n */\n\nimport { useCallback } from 'react';\nimport { useRealtimeRbac, useRealtimeSubscription } from './use-realtime';\nimport { useExGuardRealtime } from '../providers/use-exguard-realtime';\nimport { EXGUARD_RBAC_CHANNELS, EXGUARD_RBAC_EVENTS, RBAC_RECONNECT_DELAY } from '../config/realtime-rbac-config';\nimport type { RealtimeEventPayload } from '../lib/realtime.types';\n\n/**\n * Hook to subscribe to all ExGuard RBAC channels\n */\nexport function useExGuardRbacChannels() {\n useRealtimeSubscription(EXGUARD_RBAC_CHANNELS.RBAC);\n useRealtimeSubscription(EXGUARD_RBAC_CHANNELS.ROLES);\n useRealtimeSubscription(EXGUARD_RBAC_CHANNELS.PERMISSIONS);\n}\n\n/**\n * Hook to handle role updates with automatic reconnection\n */\nexport function useRoleUpdateHandler(onUpdate: () => Promise<void>, fetchUserAccess?: () => Promise<void>) {\n const { reconnect } = useExGuardRealtime();\n\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.ROLE_UPDATED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ Role updated:', (payload.data as { id?: string })?.id ?? payload.data);\n\n try {\n console.log('[ExGuard] ๐ Reconnecting after role update...');\n await reconnect();\n console.log('[ExGuard] โ
Reconnected successfully');\n\n // Delay to ensure backend has processed\n await new Promise((resolve) => setTimeout(resolve, RBAC_RECONNECT_DELAY));\n\n // Refresh data\n const promises = [onUpdate()];\n if (fetchUserAccess) {\n promises.push(fetchUserAccess());\n }\n await Promise.all(promises);\n\n console.log('[ExGuard] โ
Data refreshed after role update');\n } catch (error) {\n console.error('[ExGuard] โ Error handling role update:', error);\n }\n })();\n },\n [reconnect, onUpdate, fetchUserAccess],\n ),\n );\n}\n\n/**\n * Hook to handle user RBAC updates (role assignments, permissions, etc.)\n */\nexport function useUserRbacUpdateHandler(onUpdate: () => Promise<void>) {\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.USER_ROLES_UPDATED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ User roles updated:', payload.data);\n await onUpdate();\n console.log('[ExGuard] โ
User data refreshed');\n })();\n },\n [onUpdate],\n ),\n );\n}\n\n/**\n * Hook to handle permission updates\n */\nexport function usePermissionUpdateHandler(onUpdate: () => Promise<void>) {\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.PERMISSION_UPDATED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ Permission updated:', payload.data);\n await onUpdate();\n console.log('[ExGuard] โ
Permission data refreshed');\n })();\n },\n [onUpdate],\n ),\n );\n}\n\n/**\n * Hook to handle group updates\n */\nexport function useGroupUpdateHandler(onUpdate: () => Promise<void>) {\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.GROUP_UPDATED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ Group updated:', payload.data);\n await onUpdate();\n console.log('[ExGuard] โ
Group data refreshed');\n })();\n },\n [onUpdate],\n ),\n );\n}\n\n/**\n * Hook to handle user access changes (personal notifications)\n * This is for individual user notifications received via user:{cognitoSubId} room\n */\nexport function useUserAccessChangeHandler(onAccessChange: () => Promise<void>) {\n return useRealtimeRbac(\n EXGUARD_RBAC_EVENTS.USER_ACCESS_CHANGED,\n useCallback(\n (payload: RealtimeEventPayload) => {\n void (async () => {\n console.log('[ExGuard] ๐ฏ Your access has changed:', payload.data);\n await onAccessChange();\n console.log('[ExGuard] โ
User access refreshed');\n })();\n },\n [onAccessChange],\n ),\n );\n}\n","/**\n * ExGuard Realtime Utilities\n *\n * Utility functions for ExGuard realtime functionality\n */\n\nimport { getUserAccess } from '../api/exguard-api';\n\n/**\n * Get current user's Cognito Sub ID from backend\n * This is used for websocket room identification (user:{cognitoSubId})\n */\nexport async function getCurrentUserId(): Promise<string | null> {\n try {\n const userAccess = await getUserAccess();\n console.log('[ExGuardRealtimeUtils] ๐ก Fetched user access:', {\n id: userAccess.user.id,\n cognitoSubId: userAccess.user.cognitoSubId,\n email: userAccess.user.email,\n });\n // CRITICAL: Use cognitoSubId for websocket room targeting, not database UUID\n return userAccess.user.cognitoSubId;\n } catch (error) {\n console.error('[ExGuardRealtimeUtils] Failed to fetch user:', error);\n return null;\n }\n}\n","/**\n * ExGuard Realtime Provider\n *\n * Provider for managing realtime RBAC connections and events\n */\n\nimport React, { useEffect, useRef, type ReactNode } from 'react';\nimport { realtimeClient } from '../lib/realtime-client';\nimport { ExGuardRealtimeContext, type ExGuardRealtimeContextType } from './exguard-realtime-context';\nimport { getCurrentUserId } from '../utils/exguard-realtime-utils';\nimport type { UserRbacEventPayload } from '../lib/realtime.types';\n\ninterface ExGuardRealtimeProviderProps {\n children: ReactNode;\n}\n\nexport function ExGuardRealtimeProvider({ children }: ExGuardRealtimeProviderProps) {\n const [isConnected, setIsConnected] = React.useState(false);\n const connectionAttempted = useRef(false);\n const rbacRefreshCallbacks = useRef<Set<() => Promise<void>>>(new Set());\n const currentUserRef = useRef<{ token: string; userId: string } | null>(null);\n const currentUserIdRef = useRef<string | null>(null);\n\n // Register callback to refresh user access\n const registerRbacRefreshCallback = (callback: () => Promise<void>) => {\n rbacRefreshCallbacks.current.add(callback);\n return () => {\n rbacRefreshCallbacks.current.delete(callback);\n };\n };\n\n // Trigger refresh for all registered callbacks\n const triggerRbacRefresh = async (): Promise<void> => {\n console.log('[ExGuardRealtimeProvider] ๐ Triggering RBAC refresh for all listeners', {\n callbackCount: rbacRefreshCallbacks.current.size,\n });\n\n if (rbacRefreshCallbacks.current.size === 0) {\n console.warn('[ExGuardRealtimeProvider] โ ๏ธ No RBAC refresh callbacks registered!');\n return;\n }\n\n const refreshPromises = Array.from(rbacRefreshCallbacks.current).map((cb, index) => {\n console.log(\n `[ExGuardRealtimeProvider] ๐ Executing callback ${String(index + 1)}/${String(rbacRefreshCallbacks.current.size)}`,\n );\n return cb().catch((err: unknown) => {\n console.error(`[ExGuardRealtimeProvider] โ Error during RBAC refresh callback ${String(index + 1)}:`, err);\n });\n });\n\n await Promise.all(refreshPromises);\n console.log('[ExGuardRealtimeProvider] โ
All RBAC refresh callbacks completed');\n };\n\n // Manual reconnect function\n const handleReconnect = async (): Promise<void> => {\n if (!currentUserRef.current) {\n console.warn('[ExGuardRealtimeProvider] โ ๏ธ No user credentials available for reconnect');\n return;\n }\n const { token, userId } = currentUserRef.current;\n console.log('[ExGuardRealtimeProvider] ๐ Manual reconnect requested for', { userId });\n await handleConnect(token, userId);\n };\n\n // Manual RBAC refresh function\n const handleRefreshRbac = async (): Promise<void> => {\n console.log('[ExGuardRealtimeProvider] ๐ Manual RBAC refresh requested');\n await triggerRbacRefresh();\n };\n\n useEffect(() => {\n const accessToken = localStorage.getItem('access_token');\n\n console.log('[ExGuardRealtimeProvider] ๐ Checking credentials on mount:', {\n hasAccessToken: Boolean(accessToken),\n tokenLength: accessToken?.length,\n });\n\n if (!accessToken) {\n console.warn('[ExGuardRealtimeProvider] โ ๏ธ No access token found in localStorage');\n return;\n }\n\n if (connectionAttempted.current) {\n return;\n }\n\n connectionAttempted.current = true;\n\n // Fetch user info from backend\n const initializeConnection = async (): Promise<void> => {\n try {\n const userId = await getCurrentUserId();\n\n if (!userId) {\n console.error('[ExGuardRealtimeProvider] โ Failed to get userId from backend');\n return;\n }\n\n console.log('[ExGuardRealtimeProvider] ๐ Initiating realtime connection', {\n userId,\n });\n\n currentUserRef.current = { token: accessToken, userId };\n currentUserIdRef.current = userId;\n await realtimeClient.connect(accessToken, userId);\n console.log('[ExGuardRealtimeProvider] โ
Auto-connection successful');\n setIsConnected(true);\n\n // INDIVIDUAL user event listener - NO GLOBAL LISTENERS\n console.log('[ExGuardRealtimeProvider] ๐ง Setting up INDIVIDUAL user notification listener');\n\n // Listen ONLY for THIS USER's access changes (sent to user:{userId} room)\n realtimeClient.subscribe('user:access-changed', (payload: UserRbacEventPayload): void => {\n const { userId: eventUserId, roleId, action } = payload.data;\n console.log('[ExGuardRealtimeProvider] ๐ฏ INDIVIDUAL: Your access has been changed!', {\n eventUserId,\n roleId,\n action,\n currentUserId: currentUserIdRef.current,\n });\n\n // No need to check userId - if this event reached our room (user:{cognitoSubId}),\n // it's definitely for us. Backend ensures correct room targeting.\n console.log('[ExGuardRealtimeProvider] โ
Event received in our personal room! Refreshing access...');\n console.log(\n `[ExGuardRealtimeProvider] ๐ข Triggering RBAC refresh for ${String(rbacRefreshCallbacks.current.size)} registered callbacks`,\n );\n void triggerRbacRefresh();\n });\n\n console.log('[ExGuardRealtimeProvider] โ
Individual user event listener registered');\n } catch (error: unknown) {\n console.error('[ExGuardRealtimeProvider] โ Failed to establish realtime connection:');\n const errorMessage = error instanceof Error ? error.message : String(error);\n const tokenStr = accessToken ? accessToken.substring(0, 20) + '...' : '';\n console.error('[ExGuardRealtimeProvider] Error details:', {\n message: errorMessage,\n token: tokenStr,\n });\n setIsConnected(false);\n }\n };\n\n void initializeConnection();\n\n // Monitor connection status\n let lastConnectedState = realtimeClient.getIsConnected();\n const interval = setInterval(() => {\n const currentConnectedState = realtimeClient.getIsConnected();\n if (currentConnectedState !== lastConnectedState) {\n console.log('[ExGuardRealtimeProvider] ๐ Connection status changed:', {\n from: lastConnectedState,\n to: currentConnectedState,\n });\n lastConnectedState = currentConnectedState;\n setIsConnected(currentConnectedState);\n }\n }, 1000);\n\n return () => {\n clearInterval(interval);\n };\n }, []);\n\n const handleConnect = async (token: string, userId: string) => {\n try {\n console.log('[ExGuardRealtimeProvider] ๐ Manual connection requested', { userId });\n currentUserRef.current = { token, userId };\n await realtimeClient.connect(token, userId);\n setIsConnected(true);\n console.log('[ExGuardRealtimeProvider] โ
Manual connection successful');\n } catch (error: unknown) {\n console.error('[ExGuardRealtimeProvider] โ Failed to connect to realtime:', error);\n setIsConnected(false);\n throw error;\n }\n };\n\n const handleDisconnect = () => {\n console.log('[ExGuardRealtimeProvider] ๐ Disconnection requested');\n realtimeClient.disconnect();\n setIsConnected(false);\n };\n\n const value: ExGuardRealtimeContextType = {\n isConnected,\n connect: handleConnect,\n disconnect: handleDisconnect,\n reconnect: handleReconnect,\n refreshRbac: handleRefreshRbac,\n registerRbacRefreshCallback,\n };\n\n return <ExGuardRealtimeContext value={value}>{children}</ExGuardRealtimeContext>;\n}\n","/**\n * ExGuard Realtime Subscription Hook\n *\n * Hook to subscribe to realtime channels and handle RBAC events\n */\n\nimport { useEffect } from 'react';\nimport { useExGuardRealtime } from './use-exguard-realtime';\nimport { realtimeClient } from '../lib/realtime-client';\nimport { EXGUARD_RBAC_EVENTS, EXGUARD_RBAC_CHANNELS } from '../config/realtime-rbac-config';\nimport type { RealtimeEventType } from '../lib/realtime.types';\n\ninterface UseExGuardRealtimeSubscriptionOptions {\n /** Event types to subscribe to. If not provided, subscribes to all RBAC events */\n events?: RealtimeEventType[];\n /** Whether to auto-subscribe on mount */\n autoSubscribe?: boolean;\n}\n\n/**\n * Hook to subscribe to ExGuard realtime channel and handle RBAC updates\n * @param channel - Channel name ('rbac', 'roles', 'permissions')\n * @param options - Subscription options\n */\nexport function useExGuardRealtimeSubscription(\n channel: keyof typeof EXGUARD_RBAC_CHANNELS = 'RBAC',\n options: UseExGuardRealtimeSubscriptionOptions = {},\n): void {\n const { registerRbacRefreshCallback } = useExGuardRealtime();\n const { autoSubscribe = true, events } = options;\n const channelName = EXGUARD_RBAC_CHANNELS[channel];\n\n useEffect(() => {\n if (!autoSubscribe) {\n return;\n }\n\n console.log(`[useExGuardRealtimeSubscription] ๐ก Subscribing to channel: ${channelName}`);\n\n // Subscribe to channel on server\n void realtimeClient.subscribeToChannel(channelName);\n\n // If specific events provided, subscribe to them\n if (events && events.length > 0) {\n const unsubscribers: (() => void)[] = [];\n\n events.forEach((eventType) => {\n const unsubscribe = realtimeClient.subscribe(eventType, (): void => {\n console.log(`[useExGuardRealtimeSubscription] ๐ Received event: ${eventType}`);\n });\n unsubscribers.push(unsubscribe);\n });\n\n return () => {\n console.log(`[useExGuardRealtimeSubscription] ๐งน Cleaning up subscriptions for channel: ${channelName}`);\n unsubscribers.forEach((unsubscribe) => {\n unsubscribe();\n });\n realtimeClient.unsubscribeFromChannel(channelName);\n };\n }\n\n // Default: subscribe to all RBAC events\n const defaultRbacEvents: RealtimeEventType[] = [\n EXGUARD_RBAC_EVENTS.ROLE_CREATED,\n EXGUARD_RBAC_EVENTS.ROLE_UPDATED,\n EXGUARD_RBAC_EVENTS.ROLE_DELETED,\n EXGUARD_RBAC_EVENTS.PERMISSION_CREATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_UPDATED,\n EXGUARD_RBAC_EVENTS.PERMISSION_DELETED,\n EXGUARD_RBAC_EVENTS.ROLE_PERMISSION_ASSIGNED,\n EXGUARD_RBAC_EVENTS.ROLE_PERMISSION_REMOVED,\n EXGUARD_RBAC_EVENTS.USER_ONLINE,\n EXGUARD_RBAC_EVENTS.GROUP_UPDATED,\n ];\n\n const unsubscribers: (() => void)[] = [];\n\n defaultRbacEvents.forEach((eventType) => {\n const unsubscribe = realtimeClient.subscribe(eventType, (): void => {\n console.log(`[useExGuardRealtimeSubscription] ๐ Received event: ${eventType}`);\n });\n unsubscribers.push(unsubscribe);\n });\n\n // Register callback to trigger RBAC refresh\n const unregisterCallback = registerRbacRefreshCallback(() => {\n console.log(`[useExGuardRealtimeSubscription] ๐ RBAC refresh triggered for channel: ${channelName}`);\n return Promise.resolve();\n });\n\n return () => {\n console.log(`[useExGuardRealtimeSubscription] ๐งน Cleaning up subscriptions for channel: ${channelName}`);\n unsubscribers.forEach((unsubscribe) => {\n unsubscribe();\n });\n unregisterCallback();\n realtimeClient.unsubscribeFromChannel(channelName);\n };\n }, [channelName, autoSubscribe, events, registerRbacRefreshCallback]);\n}\n"]}
|