@jmruthers/pace-core 0.5.17 → 0.5.18
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/{DataTable-RICY7YDA.js → DataTable-BTXP6MW4.js} +3 -3
- package/dist/{chunk-JZCNOXSG.js → chunk-7QEQCZDV.js} +2 -2
- package/dist/{chunk-F6IHN3DC.js → chunk-J3JWBQSC.js} +8 -8
- package/dist/chunk-J3JWBQSC.js.map +1 -0
- package/dist/{chunk-JPXJGMOO.js → chunk-NU3GLMIQ.js} +2 -2
- package/dist/{chunk-S7KTIIL3.js → chunk-UIBYODOF.js} +13 -6
- package/dist/chunk-UIBYODOF.js.map +1 -0
- package/dist/components.js +3 -3
- package/dist/index.js +4 -4
- package/dist/rbac/index.js +2 -2
- package/dist/utils.js +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +1 -1
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventContextType.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- package/docs/api/interfaces/EventProviderProps.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContextType.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACProviderProps.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +2 -2
- package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +187 -0
- package/docs/troubleshooting/page-permission-guard-diagnostic.js +129 -0
- package/docs/troubleshooting/page-permission-guard-ui-debugging.md +353 -0
- package/package.json +1 -1
- package/src/rbac/components/PagePermissionGuard.tsx +14 -6
- package/src/rbac/hooks/usePermissions.ts +7 -7
- package/dist/chunk-F6IHN3DC.js.map +0 -1
- package/dist/chunk-S7KTIIL3.js.map +0 -1
- /package/dist/{DataTable-RICY7YDA.js.map → DataTable-BTXP6MW4.js.map} +0 -0
- /package/dist/{chunk-JZCNOXSG.js.map → chunk-7QEQCZDV.js.map} +0 -0
- /package/dist/{chunk-JPXJGMOO.js.map → chunk-NU3GLMIQ.js.map} +0 -0
|
@@ -32,8 +32,8 @@ import {
|
|
|
32
32
|
useDataTableContext,
|
|
33
33
|
usePluginRegistry,
|
|
34
34
|
useStateManager
|
|
35
|
-
} from "./chunk-
|
|
36
|
-
import "./chunk-
|
|
35
|
+
} from "./chunk-NU3GLMIQ.js";
|
|
36
|
+
import "./chunk-J3JWBQSC.js";
|
|
37
37
|
import "./chunk-GWSBHC4J.js";
|
|
38
38
|
import "./chunk-7BNPOCLL.js";
|
|
39
39
|
import "./chunk-7UEIZCST.js";
|
|
@@ -96,4 +96,4 @@ export {
|
|
|
96
96
|
usePluginRegistry,
|
|
97
97
|
useStateManager
|
|
98
98
|
};
|
|
99
|
-
//# sourceMappingURL=DataTable-
|
|
99
|
+
//# sourceMappingURL=DataTable-BTXP6MW4.js.map
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
SelectSeparator,
|
|
16
16
|
SelectTrigger,
|
|
17
17
|
SelectValue
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-NU3GLMIQ.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-
|
|
3293
|
+
//# sourceMappingURL=chunk-7QEQCZDV.js.map
|
|
@@ -230,7 +230,7 @@ function usePermissions(userId, scope) {
|
|
|
230
230
|
setIsLoading(false);
|
|
231
231
|
isFetchingRef.current = false;
|
|
232
232
|
}
|
|
233
|
-
}, [userId, scope]);
|
|
233
|
+
}, [userId, scope.organisationId, scope.eventId, scope.appId]);
|
|
234
234
|
return {
|
|
235
235
|
permissions,
|
|
236
236
|
isLoading,
|
|
@@ -267,7 +267,7 @@ function useCan(userId, scope, permission, pageId, useCache = true) {
|
|
|
267
267
|
} finally {
|
|
268
268
|
setIsLoading(false);
|
|
269
269
|
}
|
|
270
|
-
}, [userId, scope, permission, pageId, useCache]);
|
|
270
|
+
}, [userId, scope.organisationId, scope.eventId, scope.appId, permission, pageId, useCache]);
|
|
271
271
|
useEffect2(() => {
|
|
272
272
|
checkPermission();
|
|
273
273
|
}, [checkPermission]);
|
|
@@ -299,7 +299,7 @@ function useAccessLevel(userId, scope) {
|
|
|
299
299
|
} finally {
|
|
300
300
|
setIsLoading(false);
|
|
301
301
|
}
|
|
302
|
-
}, [userId, scope]);
|
|
302
|
+
}, [userId, scope.organisationId, scope.eventId, scope.appId]);
|
|
303
303
|
useEffect2(() => {
|
|
304
304
|
fetchAccessLevel();
|
|
305
305
|
}, [fetchAccessLevel]);
|
|
@@ -335,7 +335,7 @@ function useMultiplePermissions(userId, scope, permissions, useCache = true) {
|
|
|
335
335
|
} finally {
|
|
336
336
|
setIsLoading(false);
|
|
337
337
|
}
|
|
338
|
-
}, [userId, scope, permissions, useCache]);
|
|
338
|
+
}, [userId, scope.organisationId, scope.eventId, scope.appId, permissions, useCache]);
|
|
339
339
|
useEffect2(() => {
|
|
340
340
|
checkPermissions();
|
|
341
341
|
}, [checkPermissions]);
|
|
@@ -374,7 +374,7 @@ function useHasAnyPermission(userId, scope, permissions, useCache = true) {
|
|
|
374
374
|
} finally {
|
|
375
375
|
setIsLoading(false);
|
|
376
376
|
}
|
|
377
|
-
}, [userId, scope, permissions, useCache]);
|
|
377
|
+
}, [userId, scope.organisationId, scope.eventId, scope.appId, permissions, useCache]);
|
|
378
378
|
useEffect2(() => {
|
|
379
379
|
checkAnyPermission();
|
|
380
380
|
}, [checkAnyPermission]);
|
|
@@ -413,7 +413,7 @@ function useHasAllPermissions(userId, scope, permissions, useCache = true) {
|
|
|
413
413
|
} finally {
|
|
414
414
|
setIsLoading(false);
|
|
415
415
|
}
|
|
416
|
-
}, [userId, scope, permissions, useCache]);
|
|
416
|
+
}, [userId, scope.organisationId, scope.eventId, scope.appId, permissions, useCache]);
|
|
417
417
|
useEffect2(() => {
|
|
418
418
|
checkAllPermissions();
|
|
419
419
|
}, [checkAllPermissions]);
|
|
@@ -444,7 +444,7 @@ function useCachedPermissions(userId, scope) {
|
|
|
444
444
|
} finally {
|
|
445
445
|
setIsLoading(false);
|
|
446
446
|
}
|
|
447
|
-
}, [userId, scope]);
|
|
447
|
+
}, [userId, scope.organisationId, scope.eventId, scope.appId]);
|
|
448
448
|
const invalidateCache = useCallback2(() => {
|
|
449
449
|
fetchCachedPermissions();
|
|
450
450
|
}, [fetchCachedPermissions]);
|
|
@@ -470,4 +470,4 @@ export {
|
|
|
470
470
|
useHasAllPermissions,
|
|
471
471
|
useCachedPermissions
|
|
472
472
|
};
|
|
473
|
-
//# sourceMappingURL=chunk-
|
|
473
|
+
//# sourceMappingURL=chunk-J3JWBQSC.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, useRef } 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 const isFetchingRef = useRef(false);\n\n useEffect(() => {\n const fetchPermissions = async () => {\n // Prevent multiple simultaneous fetches\n if (isFetchingRef.current) {\n return;\n }\n\n if (!userId) {\n setPermissions({});\n setIsLoading(false);\n return;\n }\n\n // Don't fetch permissions if scope is invalid (e.g., organisationId is empty)\n // Return empty permissions and loading true for invalid scopes to prevent premature access denied\n if (!scope.organisationId || scope.organisationId.trim() === '') {\n setPermissions({});\n setIsLoading(true);\n setError(null);\n return;\n }\n\n try {\n isFetchingRef.current = true;\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 isFetchingRef.current = false;\n }\n };\n\n fetchPermissions();\n }, [userId, scope.organisationId, scope.eventId, scope.appId]);\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 const refetch = useCallback(async () => {\n // Prevent multiple simultaneous fetches\n if (isFetchingRef.current) {\n return;\n }\n\n if (!userId) {\n setPermissions({});\n setIsLoading(false);\n return;\n }\n\n // Don't fetch permissions if scope is invalid (e.g., organisationId is empty)\n if (!scope.organisationId || scope.organisationId.trim() === '') {\n setPermissions({});\n setIsLoading(true);\n setError(null);\n return;\n }\n\n try {\n isFetchingRef.current = true;\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 isFetchingRef.current = false;\n }\n }, [userId, scope.organisationId, scope.eventId, scope.appId]);\n\n return {\n permissions,\n isLoading,\n error,\n hasPermission,\n hasAnyPermission,\n hasAllPermissions,\n refetch\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 // Return can: false and loading: true for invalid scopes to prevent premature access denied\n if (!scope.organisationId || scope.organisationId.trim() === '') {\n setCan(false);\n setIsLoading(true);\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.organisationId, scope.eventId, scope.appId, 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.organisationId, scope.eventId, scope.appId]);\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.organisationId, scope.eventId, scope.appId, 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.organisationId, scope.eventId, scope.appId, 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.organisationId, scope.eventId, scope.appId, 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.organisationId, scope.eventId, scope.appId]);\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","useEffect","useCallback"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useCan
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-J3JWBQSC.js";
|
|
4
4
|
import {
|
|
5
5
|
useDataTablePerformance
|
|
6
6
|
} from "./chunk-SS3E6QLB.js";
|
|
@@ -5465,4 +5465,4 @@ export {
|
|
|
5465
5465
|
GroupHeader,
|
|
5466
5466
|
EditableRow
|
|
5467
5467
|
};
|
|
5468
|
-
//# sourceMappingURL=chunk-
|
|
5468
|
+
//# sourceMappingURL=chunk-NU3GLMIQ.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useAccessLevel,
|
|
3
3
|
useCan
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-J3JWBQSC.js";
|
|
5
5
|
import {
|
|
6
6
|
OrganisationContextRequiredError,
|
|
7
7
|
RBACCache,
|
|
@@ -290,6 +290,16 @@ function PagePermissionGuard({
|
|
|
290
290
|
const [resolvedScope, setResolvedScope] = useState2(null);
|
|
291
291
|
const supabaseRef = useRef(supabase);
|
|
292
292
|
supabaseRef.current = supabase;
|
|
293
|
+
const stableScope = useMemo2(() => {
|
|
294
|
+
if (!resolvedScope || !resolvedScope.organisationId) {
|
|
295
|
+
return { organisationId: "", appId: "", eventId: void 0 };
|
|
296
|
+
}
|
|
297
|
+
return {
|
|
298
|
+
organisationId: resolvedScope.organisationId,
|
|
299
|
+
appId: resolvedScope.appId,
|
|
300
|
+
eventId: resolvedScope.eventId
|
|
301
|
+
};
|
|
302
|
+
}, [resolvedScope?.organisationId, resolvedScope?.eventId, resolvedScope?.appId]);
|
|
293
303
|
useEffect2(() => {
|
|
294
304
|
const resolveScope = async () => {
|
|
295
305
|
if (scope) {
|
|
@@ -425,12 +435,9 @@ function PagePermissionGuard({
|
|
|
425
435
|
useCache: true
|
|
426
436
|
});
|
|
427
437
|
const shouldCheckPermissions = resolvedScope && resolvedScope.organisationId;
|
|
428
|
-
const scopeForUseCan = useMemo2(() => {
|
|
429
|
-
return shouldCheckPermissions ? resolvedScope : { organisationId: "", appId: "", eventId: void 0 };
|
|
430
|
-
}, [shouldCheckPermissions, resolvedScope]);
|
|
431
438
|
const { can, isLoading: canIsLoading, error: canError } = useCan(
|
|
432
439
|
user?.id || "",
|
|
433
|
-
|
|
440
|
+
stableScope,
|
|
434
441
|
permission,
|
|
435
442
|
effectivePageId,
|
|
436
443
|
true
|
|
@@ -1958,4 +1965,4 @@ export {
|
|
|
1958
1965
|
getPermissionsForRole,
|
|
1959
1966
|
ALL_PERMISSIONS
|
|
1960
1967
|
};
|
|
1961
|
-
//# sourceMappingURL=chunk-
|
|
1968
|
+
//# sourceMappingURL=chunk-UIBYODOF.js.map
|