@jmruthers/pace-core 0.5.7 → 0.5.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +15 -0
  3. package/dist/{DataTable-MZKEENPY.js → DataTable-4TQ6VBHW.js} +3 -3
  4. package/dist/{chunk-2VSQSO5Z.js → chunk-CTV3NKPM.js} +2 -2
  5. package/dist/{chunk-QVYBYGT2.js → chunk-OCM3I4GY.js} +6 -1
  6. package/dist/chunk-OCM3I4GY.js.map +1 -0
  7. package/dist/{chunk-Y2LJQ7QE.js → chunk-PCFG6WRC.js} +2 -2
  8. package/dist/{chunk-5SIXIV7R.js → chunk-SM6KCLW5.js} +4 -4
  9. package/dist/chunk-SM6KCLW5.js.map +1 -0
  10. package/dist/components.js +3 -3
  11. package/dist/index.js +4 -4
  12. package/dist/rbac/index.js +2 -2
  13. package/dist/utils.js +1 -1
  14. package/docs/api/README.md +15 -0
  15. package/docs/api/classes/ErrorBoundary.md +1 -1
  16. package/docs/api/classes/InvalidScopeError.md +1 -1
  17. package/docs/api/classes/MissingUserContextError.md +1 -1
  18. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  19. package/docs/api/classes/PermissionDeniedError.md +1 -1
  20. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  21. package/docs/api/classes/RBACAuditManager.md +1 -1
  22. package/docs/api/classes/RBACCache.md +1 -1
  23. package/docs/api/classes/RBACEngine.md +1 -1
  24. package/docs/api/classes/RBACError.md +1 -1
  25. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  26. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  27. package/docs/api/interfaces/AggregateConfig.md +1 -1
  28. package/docs/api/interfaces/ButtonProps.md +1 -1
  29. package/docs/api/interfaces/CardProps.md +1 -1
  30. package/docs/api/interfaces/ColorPalette.md +1 -1
  31. package/docs/api/interfaces/ColorShade.md +1 -1
  32. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  33. package/docs/api/interfaces/DataTableAction.md +1 -1
  34. package/docs/api/interfaces/DataTableColumn.md +1 -1
  35. package/docs/api/interfaces/DataTableProps.md +1 -1
  36. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  37. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  38. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  39. package/docs/api/interfaces/EventContextType.md +1 -1
  40. package/docs/api/interfaces/EventLogoProps.md +1 -1
  41. package/docs/api/interfaces/EventProviderProps.md +1 -1
  42. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  43. package/docs/api/interfaces/FileUploadProps.md +1 -1
  44. package/docs/api/interfaces/FooterProps.md +1 -1
  45. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  46. package/docs/api/interfaces/InputProps.md +1 -1
  47. package/docs/api/interfaces/LabelProps.md +1 -1
  48. package/docs/api/interfaces/LoginFormProps.md +1 -1
  49. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  50. package/docs/api/interfaces/NavigationContextType.md +1 -1
  51. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  52. package/docs/api/interfaces/NavigationItem.md +1 -1
  53. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  54. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  55. package/docs/api/interfaces/Organisation.md +1 -1
  56. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  57. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  58. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  59. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  60. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  61. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  62. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  63. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  64. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  65. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  66. package/docs/api/interfaces/PaletteData.md +1 -1
  67. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  68. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  69. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  70. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  71. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  72. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  73. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  74. package/docs/api/interfaces/RBACConfig.md +1 -1
  75. package/docs/api/interfaces/RBACContextType.md +1 -1
  76. package/docs/api/interfaces/RBACLogger.md +1 -1
  77. package/docs/api/interfaces/RBACProviderProps.md +1 -1
  78. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  79. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  80. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  81. package/docs/api/interfaces/RouteConfig.md +1 -1
  82. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  83. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  84. package/docs/api/interfaces/StorageConfig.md +1 -1
  85. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  86. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  87. package/docs/api/interfaces/StorageListOptions.md +1 -1
  88. package/docs/api/interfaces/StorageListResult.md +1 -1
  89. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  90. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  91. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  92. package/docs/api/interfaces/StyleImport.md +1 -1
  93. package/docs/api/interfaces/ToastActionElement.md +1 -1
  94. package/docs/api/interfaces/ToastProps.md +1 -1
  95. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  96. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  97. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  98. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  99. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  100. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  101. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  102. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  103. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  104. package/docs/api/interfaces/UserEventAccess.md +1 -1
  105. package/docs/api/interfaces/UserMenuProps.md +1 -1
  106. package/docs/api/interfaces/UserProfile.md +1 -1
  107. package/docs/api/modules.md +7 -7
  108. package/package.json +1 -1
  109. package/src/rbac/components/PagePermissionGuard.tsx +2 -2
  110. package/src/rbac/hooks/useCan.test.ts +4 -10
  111. package/src/rbac/hooks/usePermissions.ts +8 -0
  112. package/dist/chunk-5SIXIV7R.js.map +0 -1
  113. package/dist/chunk-QVYBYGT2.js.map +0 -1
  114. /package/dist/{DataTable-MZKEENPY.js.map → DataTable-4TQ6VBHW.js.map} +0 -0
  115. /package/dist/{chunk-2VSQSO5Z.js.map → chunk-CTV3NKPM.js.map} +0 -0
  116. /package/dist/{chunk-Y2LJQ7QE.js.map → chunk-PCFG6WRC.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -24,6 +24,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
24
24
  - **Data Reference Stability**: Improved data reference stability to prevent unnecessary re-renders
25
25
  - **Memory Optimization**: Added safeguards against infinite loops with render counting and data comparison
26
26
  - **Performance**: Optimized table configuration memoization to prevent unnecessary re-creation
27
+ - **RBAC Race Condition**: Fixed "Access Denied" errors for users with valid permissions caused by race condition in permission checking
28
+ - **Permission Loading State**: Improved loading state handling during scope resolution to prevent premature access denied errors
27
29
 
28
30
  ### Improved
29
31
  - **Data Processing Documentation**: Added comprehensive best practices for data processing with DataTable
package/README.md CHANGED
@@ -221,6 +221,21 @@ export default defineConfig({
221
221
  }
222
222
  ```
223
223
 
224
+ ### Issue: "Access Denied" errors with valid permissions
225
+
226
+ **Problem**: Users with valid permissions see "Access Denied" when loading pages with DataTable components.
227
+
228
+ **Root Cause**: Race condition in permission checking - `useCan` hook was being called with invalid scopes before scope resolution completed.
229
+
230
+ **Solution**: Fixed in v0.5.7+ - the `useCan` hook now properly handles invalid scopes and shows loading state until valid scope is available.
231
+
232
+ **What was fixed**:
233
+ - `useCan` hook skips API calls when `organisationId` is empty
234
+ - `PagePermissionGuard` shows loading state during scope resolution
235
+ - Eliminates race condition between scope resolution and permission checking
236
+
237
+ **No action needed** - this is automatically fixed in v0.5.7+
238
+
224
239
  ## Features
225
240
 
226
241
  - 🎨 **Complete Design System** - Colors, typography, spacing, shadows
@@ -32,8 +32,8 @@ import {
32
32
  useDataTableContext,
33
33
  usePluginRegistry,
34
34
  useStateManager
35
- } from "./chunk-2VSQSO5Z.js";
36
- import "./chunk-QVYBYGT2.js";
35
+ } from "./chunk-CTV3NKPM.js";
36
+ import "./chunk-OCM3I4GY.js";
37
37
  import "./chunk-GWSBHC4J.js";
38
38
  import "./chunk-7BNPOCLL.js";
39
39
  import "./chunk-HXX35Q2M.js";
@@ -96,4 +96,4 @@ export {
96
96
  usePluginRegistry,
97
97
  useStateManager
98
98
  };
99
- //# sourceMappingURL=DataTable-MZKEENPY.js.map
99
+ //# sourceMappingURL=DataTable-4TQ6VBHW.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  useCan
3
- } from "./chunk-QVYBYGT2.js";
3
+ } from "./chunk-OCM3I4GY.js";
4
4
  import {
5
5
  useDataTablePerformance
6
6
  } from "./chunk-SS3E6QLB.js";
@@ -5463,4 +5463,4 @@ export {
5463
5463
  GroupHeader,
5464
5464
  EditableRow
5465
5465
  };
5466
- //# sourceMappingURL=chunk-2VSQSO5Z.js.map
5466
+ //# sourceMappingURL=chunk-CTV3NKPM.js.map
@@ -211,6 +211,11 @@ function useCan(userId, scope, permission, pageId, useCache = true) {
211
211
  setIsLoading(false);
212
212
  return;
213
213
  }
214
+ if (!scope.organisationId) {
215
+ setCan(false);
216
+ setIsLoading(true);
217
+ return;
218
+ }
214
219
  try {
215
220
  setIsLoading(true);
216
221
  setError(null);
@@ -425,4 +430,4 @@ export {
425
430
  useHasAllPermissions,
426
431
  useCachedPermissions
427
432
  };
428
- //# sourceMappingURL=chunk-QVYBYGT2.js.map
433
+ //# sourceMappingURL=chunk-OCM3I4GY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/rbac/hooks/useRBAC.ts","../src/rbac/hooks/usePermissions.ts"],"sourcesContent":["/**\n * @file RBAC Hook\n * @package @jmruthers/pace-core\n * @module RBAC/Hooks\n * @since 0.3.0\n *\n * A React hook that provides access to the new RBAC (Role-Based Access Control) system.\n * This hook integrates with the database to provide real-time role and permission information.\n *\n * Features:\n * - Real-time role detection (global, organisation, event-app)\n * - Permission checking with database validation\n * - Hierarchical permission resolution\n * - Loading states and error handling\n * - Type-safe permission operations\n * - Automatic context detection\n *\n * @example\n * ```tsx\n * import { useRBAC } from '@jmruthers/pace-core/rbac';\n * \n * function MyComponent() {\n * const {\n * globalRole,\n * organisationRole,\n * eventAppRole,\n * hasPermission,\n * isSuperAdmin,\n * isLoading,\n * error\n * } = useRBAC();\n * \n * if (isLoading) return <div>Loading permissions...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return (\n * <div>\n * {isSuperAdmin && <AdminPanel />}\n * {hasPermission('read', 'dashboard') && <Dashboard />}\n * {hasPermission('create', 'events') && <CreateEventButton />}\n * </div>\n * );\n * }\n * ```\n *\n * @accessibility\n * - No direct accessibility concerns (hook)\n * - Enables accessible permission-based UI rendering\n * - Supports screen reader friendly conditional content\n *\n * @security\n * - Database-backed permission validation\n * - Hierarchical permission resolution\n * - Organisation context enforcement\n * - Real-time permission updates\n *\n * @performance\n * - Optimized with useMemo and useCallback\n * - Permission caching\n * - Minimal re-renders\n * - Lazy loading of permissions\n *\n * @dependencies\n * - React 18+ - Hooks and effects\n * - @supabase/supabase-js - Database integration\n * - RBAC types - Type definitions\n */\n\nimport { useState, useEffect, useCallback, useMemo } from 'react';\nimport { useUnifiedAuth } from '../../providers/UnifiedAuthProvider';\nimport { useOrganisations } from '../../providers/OrganisationProvider';\nimport { useEvents } from '../../providers/EventProvider';\nimport type { \n UserRBACContext, \n GlobalRole, \n OrganisationRole, \n EventAppRole, \n Operation,\n RBACPermission \n} from '../types';\n\nexport function useRBAC(pageId?: string): UserRBACContext {\n const { user, session, supabase, appName } = useUnifiedAuth();\n const { selectedOrganisation } = useOrganisations();\n \n // Try to get events context, but don't fail if not available\n let selectedEvent = null;\n try {\n const eventsContext = useEvents();\n selectedEvent = eventsContext.selectedEvent;\n } catch (error) {\n // EventProvider not available, continue without event context\n console.debug('useRBAC: EventProvider not available, continuing without event context');\n }\n \n // State\n const [globalRole, setGlobalRole] = useState<GlobalRole | null>(null);\n const [organisationRole, setOrganisationRole] = useState<OrganisationRole | null>(null);\n const [eventAppRole, setEventAppRole] = useState<EventAppRole | null>(null);\n const [permissions, setPermissions] = useState<RBACPermission[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Load RBAC context\n const loadRBACContext = useCallback(async () => {\n if (!user || !session || !supabase || !appName) {\n console.log('[useRBAC] Missing required dependencies, clearing RBAC state');\n setGlobalRole(null);\n setOrganisationRole(null);\n setEventAppRole(null);\n setPermissions([]);\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n // First resolve app name to app_id\n const { data: appData, error: appError } = await supabase\n .from('rbac_apps')\n .select('id')\n .eq('name', appName)\n .eq('is_active', true)\n .single();\n\n if (appError || !appData) {\n console.warn('App not found or inactive:', appName);\n setIsLoading(false);\n return;\n }\n\n const { data, error: rpcError } = await supabase.rpc('get_rbac_permissions', {\n p_user_id: user.id,\n p_app_id: appData.id,\n p_event_id: selectedEvent?.event_id || null,\n p_organisation_id: selectedOrganisation?.id || null,\n p_page_id: pageId || null\n });\n\n if (rpcError) {\n throw new Error(`Failed to load RBAC permissions: ${rpcError.message}`);\n }\n\n if (data) {\n // Extract roles from permissions based on permission_type\n const globalPerms = data.filter((p: RBACPermission) => p.permission_type === 'all_permissions');\n const orgPerms = data.filter((p: RBACPermission) => p.permission_type === 'organisation_access');\n const eventPerms = data.filter((p: RBACPermission) => p.permission_type === 'event_app_access');\n\n // Set roles (take the highest permission for each type)\n setGlobalRole(globalPerms.length > 0 ? 'super_admin' : null);\n setOrganisationRole(orgPerms.length > 0 ? orgPerms[0].role_name as OrganisationRole : null);\n setEventAppRole(eventPerms.length > 0 ? eventPerms[0].role_name as EventAppRole : null);\n setPermissions(data);\n } else {\n setPermissions([]);\n }\n } catch (err) {\n console.error('RBAC Context Loading Error:', err);\n setError(err instanceof Error ? err : new Error('Unknown error loading RBAC context'));\n setPermissions([]);\n } finally {\n setIsLoading(false);\n }\n }, [user?.id, session, supabase, appName, selectedEvent?.event_id, selectedOrganisation?.id, pageId]);\n\n // Permission checking function\n const hasPermission = useCallback(async (operation: Operation, targetPageId?: string): Promise<boolean> => {\n if (!user || !session || !supabase || !appName) return false;\n\n // Super admin has all permissions\n if (globalRole === 'super_admin') {\n return true;\n }\n\n try {\n // First resolve app name to app_id\n const { data: appData, error: appError } = await supabase\n .from('rbac_apps')\n .select('id')\n .eq('name', appName)\n .eq('is_active', true)\n .single();\n\n if (appError || !appData) {\n console.warn('App not found or inactive:', appName);\n return false;\n }\n\n const { data, error } = await supabase.rpc('check_page_permission', {\n p_user_id: user.id,\n p_app_id: appData.id,\n p_page_id: targetPageId || pageId || 'default',\n p_operation: operation,\n p_event_id: selectedEvent?.event_id,\n p_organisation_id: selectedOrganisation?.id\n });\n\n if (error) {\n console.error('Permission check failed:', error);\n return false;\n }\n\n return data === true;\n } catch (err) {\n console.error('Permission check error:', err);\n return false;\n }\n }, [user, supabase, appName, selectedEvent, selectedOrganisation, pageId, globalRole]);\n\n // Simple permission check for global roles (synchronous)\n const hasGlobalPermission = useCallback((permission: string): boolean => {\n // Super admin has all permissions\n if (globalRole === 'super_admin') {\n return true;\n }\n \n // Check specific global roles\n if (permission === 'super_admin') {\n return globalRole === 'super_admin';\n }\n \n if (permission === 'org_admin') {\n return organisationRole === 'org_admin' || globalRole === 'super_admin';\n }\n \n return false;\n }, [globalRole, organisationRole]);\n\n // Computed properties\n const isSuperAdmin = useMemo(() => globalRole === 'super_admin', [globalRole]);\n const isOrgAdmin = useMemo(() => organisationRole === 'org_admin', [organisationRole]);\n const isEventAdmin = useMemo(() => eventAppRole === 'event_admin', [eventAppRole]);\n const canManageOrganisation = useMemo(() => \n isSuperAdmin || isOrgAdmin, [isSuperAdmin, isOrgAdmin]\n );\n const canManageEvent = useMemo(() => \n isSuperAdmin || isEventAdmin, [isSuperAdmin, isEventAdmin]\n );\n\n // Load context when dependencies change\n useEffect(() => {\n loadRBACContext();\n }, [loadRBACContext]);\n\n return {\n user, // Add user to the returned context\n globalRole,\n organisationRole,\n eventAppRole,\n hasPermission,\n hasGlobalPermission,\n isSuperAdmin,\n isOrgAdmin,\n isEventAdmin,\n canManageOrganisation,\n canManageEvent,\n isLoading,\n error\n };\n}\n","/**\n * @file RBAC Permission Hooks\n * @package @jmruthers/pace-core\n * @module RBAC/Hooks\n * @since 1.0.0\n * \n * This module provides React hooks for RBAC functionality.\n */\n\nimport { useState, useEffect, useCallback, useMemo } from 'react';\nimport { \n UUID, \n Scope, \n Permission, \n PermissionMap\n} from '../types';\nimport { AccessLevel as AccessLevelType } from '../types';\nimport { \n getAccessLevel, \n getPermissionMap, \n isPermitted,\n isPermittedCached \n} from '../api';\n\n/**\n * Hook to get user's permissions in a scope\n * \n * @param userId - User ID\n * @param scope - Scope for permission checking\n * @returns Permission state and methods\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { permissions, isLoading, error } = usePermissions(userId, scope);\n * \n * if (isLoading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return (\n * <div>\n * {permissions['read:users'] && <UserList />}\n * {permissions['create:users'] && <CreateUserButton />}\n * </div>\n * );\n * }\n * ```\n */\nexport function usePermissions(userId: UUID, scope: Scope) {\n const [permissions, setPermissions] = useState<PermissionMap>({});\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetchPermissions = useCallback(async () => {\n if (!userId) {\n setPermissions({});\n setIsLoading(false);\n return;\n }\n\n try {\n setIsLoading(true);\n setError(null);\n \n const permissionMap = await getPermissionMap({ userId, scope });\n setPermissions(permissionMap);\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to fetch permissions'));\n } finally {\n setIsLoading(false);\n }\n }, [userId, scope]);\n\n useEffect(() => {\n fetchPermissions();\n }, [fetchPermissions]);\n\n const hasPermission = useCallback((permission: Permission): boolean => {\n return !!permissions[permission];\n }, [permissions]);\n\n const hasAnyPermission = useCallback((permissionList: Permission[]): boolean => {\n return permissionList.some(p => !!permissions[p]);\n }, [permissions]);\n\n const hasAllPermissions = useCallback((permissionList: Permission[]): boolean => {\n return permissionList.every(p => !!permissions[p]);\n }, [permissions]);\n\n return {\n permissions,\n isLoading,\n error,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n refetch: fetchPermissions\n };\n}\n\n/**\n * Hook to check if user can perform an action\n * \n * @param userId - User ID\n * @param scope - Scope for permission checking\n * @param permission - Permission to check\n * @param pageId - Optional page ID\n * @param useCache - Whether to use cached results\n * @returns Permission check state and methods\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { can, isLoading, error } = useCan(userId, scope, 'read:users');\n * \n * if (isLoading) return <div>Checking permission...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return can ? <UserList /> : <div>Access denied</div>;\n * }\n * ```\n */\nexport function useCan(\n userId: UUID, \n scope: Scope, \n permission: Permission, \n pageId?: UUID,\n useCache: boolean = true\n) {\n const [can, setCan] = useState<boolean>(false);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const checkPermission = useCallback(async () => {\n if (!userId) {\n setCan(false);\n setIsLoading(false);\n return;\n }\n\n // Don't check permissions if scope is invalid (e.g., organisationId is empty)\n // Instead of returning can: false, keep loading state to prevent premature access denied\n if (!scope.organisationId) {\n setCan(false);\n setIsLoading(true); // Keep loading state instead of false\n return;\n }\n\n try {\n setIsLoading(true);\n setError(null);\n \n const result = useCache \n ? await isPermittedCached({ userId, scope, permission, pageId })\n : await isPermitted({ userId, scope, permission, pageId });\n \n setCan(result);\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to check permission'));\n setCan(false);\n } finally {\n setIsLoading(false);\n }\n }, [userId, scope, permission, pageId, useCache]);\n\n useEffect(() => {\n checkPermission();\n }, [checkPermission]);\n\n return {\n can,\n isLoading,\n error,\n refetch: checkPermission\n };\n}\n\n/**\n * Hook to get user's access level in a scope\n * \n * @param userId - User ID\n * @param scope - Scope for access level checking\n * @returns Access level state and methods\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { accessLevel, isLoading, error } = useAccessLevel(userId, scope);\n * \n * if (isLoading) return <div>Loading access level...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return (\n * <div>\n * Access Level: {accessLevel}\n * {accessLevel >= AccessLevel.ADMIN && <AdminPanel />}\n * </div>\n * );\n * }\n * ```\n */\nexport function useAccessLevel(userId: UUID, scope: Scope): {\n accessLevel: AccessLevelType;\n isLoading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n} {\n const [accessLevel, setAccessLevel] = useState<AccessLevelType>('viewer');\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetchAccessLevel = useCallback(async () => {\n if (!userId) {\n setAccessLevel('viewer');\n setIsLoading(false);\n return;\n }\n\n try {\n setIsLoading(true);\n setError(null);\n \n const level = await getAccessLevel({ userId, scope });\n setAccessLevel(level);\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to fetch access level'));\n setAccessLevel('viewer');\n } finally {\n setIsLoading(false);\n }\n }, [userId, scope]);\n\n useEffect(() => {\n fetchAccessLevel();\n }, [fetchAccessLevel]);\n\n return {\n accessLevel,\n isLoading,\n error,\n refetch: fetchAccessLevel\n };\n}\n\n/**\n * Hook to check multiple permissions at once\n * \n * @param userId - User ID\n * @param scope - Scope for permission checking\n * @param permissions - Array of permissions to check\n * @param useCache - Whether to use cached results\n * @returns Multiple permission check results\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { results, isLoading, error } = useMultiplePermissions(\n * userId, \n * scope, \n * ['read:users', 'create:users', 'update:users']\n * );\n * \n * if (isLoading) return <div>Checking permissions...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return (\n * <div>\n * {results['read:users'] && <UserList />}\n * {results['create:users'] && <CreateUserButton />}\n * {results['update:users'] && <EditUserButton />}\n * </div>\n * );\n * }\n * ```\n */\nexport function useMultiplePermissions(\n userId: UUID, \n scope: Scope, \n permissions: Permission[],\n useCache: boolean = true\n): {\n results: Record<Permission, boolean>;\n isLoading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n} {\n const [results, setResults] = useState<Record<Permission, boolean>>({} as Record<Permission, boolean>);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const checkPermissions = useCallback(async () => {\n if (!userId || permissions.length === 0) {\n setResults({} as Record<Permission, boolean>);\n setIsLoading(false);\n return;\n }\n\n try {\n setIsLoading(true);\n setError(null);\n \n const permissionResults: Record<Permission, boolean> = {} as Record<Permission, boolean>;\n \n // Check each permission\n for (const permission of permissions) {\n const result = useCache \n ? await isPermittedCached({ userId, scope, permission })\n : await isPermitted({ userId, scope, permission });\n permissionResults[permission] = result;\n }\n \n setResults(permissionResults);\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to check permissions'));\n setResults({} as Record<Permission, boolean>);\n } finally {\n setIsLoading(false);\n }\n }, [userId, scope, permissions, useCache]);\n\n useEffect(() => {\n checkPermissions();\n }, [checkPermissions]);\n\n return {\n results,\n isLoading,\n error,\n refetch: checkPermissions\n };\n}\n\n/**\n * Hook to check if user has any of the specified permissions\n * \n * @param userId - User ID\n * @param scope - Scope for permission checking\n * @param permissions - Array of permissions to check\n * @param useCache - Whether to use cached results\n * @returns Whether user has any of the permissions\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { hasAny, isLoading, error } = useHasAnyPermission(\n * userId, \n * scope, \n * ['read:users', 'create:users']\n * );\n * \n * if (isLoading) return <div>Checking permissions...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return hasAny ? <UserManagementPanel /> : <div>No user permissions</div>;\n * }\n * ```\n */\nexport function useHasAnyPermission(\n userId: UUID, \n scope: Scope, \n permissions: Permission[],\n useCache: boolean = true\n): {\n hasAny: boolean;\n isLoading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n} {\n const [hasAny, setHasAny] = useState<boolean>(false);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const checkAnyPermission = useCallback(async () => {\n if (!userId || permissions.length === 0) {\n setHasAny(false);\n setIsLoading(false);\n return;\n }\n\n try {\n setIsLoading(true);\n setError(null);\n \n let hasAnyPermission = false;\n \n for (const permission of permissions) {\n const result = useCache \n ? await isPermittedCached({ userId, scope, permission })\n : await isPermitted({ userId, scope, permission });\n \n if (result) {\n hasAnyPermission = true;\n break;\n }\n }\n \n setHasAny(hasAnyPermission);\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to check permissions'));\n setHasAny(false);\n } finally {\n setIsLoading(false);\n }\n }, [userId, scope, permissions, useCache]);\n\n useEffect(() => {\n checkAnyPermission();\n }, [checkAnyPermission]);\n\n return {\n hasAny,\n isLoading,\n error,\n refetch: checkAnyPermission\n };\n}\n\n/**\n * Hook to check if user has all of the specified permissions\n * \n * @param userId - User ID\n * @param scope - Scope for permission checking\n * @param permissions - Array of permissions to check\n * @param useCache - Whether to use cached results\n * @returns Whether user has all of the permissions\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { hasAll, isLoading, error } = useHasAllPermissions(\n * userId, \n * scope, \n * ['read:users', 'create:users', 'update:users']\n * );\n * \n * if (isLoading) return <div>Checking permissions...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return hasAll ? <FullUserManagementPanel /> : <div>Insufficient permissions</div>;\n * }\n * ```\n */\nexport function useHasAllPermissions(\n userId: UUID, \n scope: Scope, \n permissions: Permission[],\n useCache: boolean = true\n): {\n hasAll: boolean;\n isLoading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n} {\n const [hasAll, setHasAll] = useState<boolean>(false);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const checkAllPermissions = useCallback(async () => {\n if (!userId || permissions.length === 0) {\n setHasAll(false);\n setIsLoading(false);\n return;\n }\n\n try {\n setIsLoading(true);\n setError(null);\n \n let hasAllPermissions = true;\n \n for (const permission of permissions) {\n const result = useCache \n ? await isPermittedCached({ userId, scope, permission })\n : await isPermitted({ userId, scope, permission });\n \n if (!result) {\n hasAllPermissions = false;\n break;\n }\n }\n \n setHasAll(hasAllPermissions);\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to check permissions'));\n setHasAll(false);\n } finally {\n setIsLoading(false);\n }\n }, [userId, scope, permissions, useCache]);\n\n useEffect(() => {\n checkAllPermissions();\n }, [checkAllPermissions]);\n\n return {\n hasAll,\n isLoading,\n error,\n refetch: checkAllPermissions\n };\n}\n\n/**\n * Hook to get cached permissions with TTL management\n * \n * @param userId - User ID\n * @param scope - Scope for permission checking\n * @returns Cached permission state and methods\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { permissions, isLoading, error, invalidateCache } = useCachedPermissions(userId, scope);\n * \n * if (isLoading) return <div>Loading cached permissions...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * \n * return (\n * <div>\n * {permissions['read:users'] && <UserList />}\n * <button onClick={invalidateCache}>Refresh Permissions</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useCachedPermissions(userId: UUID, scope: Scope): {\n permissions: PermissionMap;\n isLoading: boolean;\n error: Error | null;\n invalidateCache: () => void;\n refetch: () => Promise<void>;\n} {\n const [permissions, setPermissions] = useState<PermissionMap>({});\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const fetchCachedPermissions = useCallback(async () => {\n if (!userId) {\n setPermissions({});\n setIsLoading(false);\n return;\n }\n\n try {\n setIsLoading(true);\n setError(null);\n \n const permissionMap = await getPermissionMap({ userId, scope });\n setPermissions(permissionMap);\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to fetch cached permissions'));\n } finally {\n setIsLoading(false);\n }\n }, [userId, scope]);\n\n const invalidateCache = useCallback(() => {\n // This would typically invalidate the cache in the actual implementation\n // For now, we'll just refetch\n fetchCachedPermissions();\n }, [fetchCachedPermissions]);\n\n useEffect(() => {\n fetchCachedPermissions();\n }, [fetchCachedPermissions]);\n\n return {\n permissions,\n isLoading,\n error,\n invalidateCache,\n refetch: fetchCachedPermissions\n };\n}\n"],"mappings":"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","names":["error","useState","useEffect","useCallback","useState","useCallback","useEffect"]}
@@ -15,7 +15,7 @@ import {
15
15
  SelectSeparator,
16
16
  SelectTrigger,
17
17
  SelectValue
18
- } from "./chunk-2VSQSO5Z.js";
18
+ } from "./chunk-CTV3NKPM.js";
19
19
  import {
20
20
  isPermitted
21
21
  } from "./chunk-GWSBHC4J.js";
@@ -3290,4 +3290,4 @@ export {
3290
3290
  PublicPageDiagnostic,
3291
3291
  PublicPageContextChecker
3292
3292
  };
3293
- //# sourceMappingURL=chunk-Y2LJQ7QE.js.map
3293
+ //# sourceMappingURL=chunk-PCFG6WRC.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  useAccessLevel,
3
3
  useCan
4
- } from "./chunk-QVYBYGT2.js";
4
+ } from "./chunk-OCM3I4GY.js";
5
5
  import {
6
6
  OrganisationContextRequiredError,
7
7
  RBACCache,
@@ -413,7 +413,7 @@ function PagePermissionGuard({
413
413
  console.log("[PagePermissionGuard] selectedEventId:", selectedEventId);
414
414
  console.log("[PagePermissionGuard] About to call useCan with:", {
415
415
  userId: user?.id || "",
416
- scope: resolvedScope || { organisationId: "", appId: "", eventId: selectedEventId || void 0 },
416
+ scope: resolvedScope,
417
417
  permission,
418
418
  pageId: effectivePageId,
419
419
  useCache: true
@@ -471,7 +471,7 @@ function PagePermissionGuard({
471
471
  });
472
472
  }
473
473
  }, [strictMode, hasChecked, isLoading, can, pageName, operation, user?.id, resolvedScope]);
474
- if (isLoading || !resolvedScope || !hasChecked) {
474
+ if (isLoading || !resolvedScope) {
475
475
  return /* @__PURE__ */ jsx2(Fragment, { children: loading });
476
476
  }
477
477
  if (checkError) {
@@ -1922,4 +1922,4 @@ export {
1922
1922
  getPermissionsForRole,
1923
1923
  ALL_PERMISSIONS
1924
1924
  };
1925
- //# sourceMappingURL=chunk-5SIXIV7R.js.map
1925
+ //# sourceMappingURL=chunk-SM6KCLW5.js.map