@jmruthers/pace-core 0.5.193 → 0.6.2
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/CHANGELOG.md +62 -0
- package/README.md +7 -1
- package/cursor-rules/00-pace-core-compliance.mdc +299 -0
- package/cursor-rules/01-standards-compliance.mdc +244 -0
- package/cursor-rules/02-project-structure.mdc +200 -0
- package/cursor-rules/03-solid-principles.mdc +222 -0
- package/cursor-rules/04-testing-standards.mdc +268 -0
- package/cursor-rules/05-bug-reports-and-features.mdc +246 -0
- package/cursor-rules/06-code-quality.mdc +309 -0
- package/cursor-rules/07-tech-stack-compliance.mdc +214 -0
- package/cursor-rules/08-markup-quality.mdc +452 -0
- package/cursor-rules/CHANGELOG.md +119 -0
- package/cursor-rules/README.md +192 -0
- package/dist/{AuthService-DjnJHDtC.d.ts → AuthService-BPvc3Ka0.d.ts} +54 -0
- package/dist/{DataTable-Be6dH_dR.d.ts → DataTable-BMRU8a1j.d.ts} +34 -2
- package/dist/{DataTable-5FU7IESH.js → DataTable-TPTKCX4D.js} +10 -9
- package/dist/{PublicPageProvider-C0Sm_e5k.d.ts → PublicPageProvider-DC6kCaqf.d.ts} +385 -261
- package/dist/{UnifiedAuthProvider-RGJTDE2C.js → UnifiedAuthProvider-CH6Z342H.js} +3 -3
- package/dist/{UnifiedAuthProvider-185Ih4dj.d.ts → UnifiedAuthProvider-CVcTjx-d.d.ts} +29 -0
- package/dist/{api-N774RPUA.js → api-MVVQZLJI.js} +2 -2
- package/dist/{chunk-KNC55RTG.js → chunk-24UVZUZG.js} +90 -54
- package/dist/chunk-24UVZUZG.js.map +1 -0
- package/dist/{chunk-HWIIPPNI.js → chunk-2UOI2FG5.js} +20 -20
- package/dist/chunk-2UOI2FG5.js.map +1 -0
- package/dist/{chunk-E3SPN4VZ 5.js → chunk-3XC4CPTD.js} +4345 -3986
- package/dist/chunk-3XC4CPTD.js.map +1 -0
- package/dist/{chunk-7EQTDTTJ.js → chunk-6J4GEEJR.js} +172 -45
- package/dist/chunk-6J4GEEJR.js.map +1 -0
- package/dist/{chunk-6C4YBBJM 5.js → chunk-6SOIHG6Z.js} +1 -1
- package/dist/chunk-6SOIHG6Z.js.map +1 -0
- package/dist/{chunk-7FLMSG37.js → chunk-EHMR7VYL.js} +25 -25
- package/dist/chunk-EHMR7VYL.js.map +1 -0
- package/dist/{chunk-I7PSE6JW.js → chunk-F2IMUDXZ.js} +2 -75
- package/dist/chunk-F2IMUDXZ.js.map +1 -0
- package/dist/{chunk-QWWZ5CAQ.js → chunk-FFQEQTNW.js} +7 -9
- package/dist/chunk-FFQEQTNW.js.map +1 -0
- package/dist/chunk-FMUCXFII.js +76 -0
- package/dist/chunk-FMUCXFII.js.map +1 -0
- package/dist/{chunk-HW3OVDUF.js → chunk-J36DSWQK.js} +1 -1
- package/dist/{chunk-HW3OVDUF.js.map → chunk-J36DSWQK.js.map} +1 -1
- package/dist/{chunk-SQGMNID3.js → chunk-L4OXEN46.js} +4 -5
- package/dist/chunk-L4OXEN46.js.map +1 -0
- package/dist/{chunk-R77UEZ4E 3.js → chunk-M43Y4SSO.js} +1 -1
- package/dist/chunk-M43Y4SSO.js.map +1 -0
- package/dist/{chunk-IIELH4DL.js → chunk-MMZ7JXPU.js} +60 -223
- package/dist/chunk-MMZ7JXPU.js.map +1 -0
- package/dist/{chunk-NOAYCWCX 5.js → chunk-NECFR5MM.js} +394 -312
- package/dist/chunk-NECFR5MM.js.map +1 -0
- package/dist/{chunk-BC4IJKSL.js → chunk-SFZUDBL5.js} +40 -4
- package/dist/chunk-SFZUDBL5.js.map +1 -0
- package/dist/{chunk-XNXXZ43G.js → chunk-XWQCNGTQ.js} +748 -364
- package/dist/chunk-XWQCNGTQ.js.map +1 -0
- package/dist/components.d.ts +6 -6
- package/dist/components.js +15 -12
- package/dist/components.js.map +1 -1
- package/dist/{functions-D_kgHktt.d.ts → functions-DHebl8-F.d.ts} +1 -1
- package/dist/hooks.d.ts +59 -126
- package/dist/hooks.js +19 -28
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +63 -16
- package/dist/index.js +23 -24
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +21 -3
- package/dist/providers.js +2 -2
- package/dist/rbac/index.d.ts +146 -115
- package/dist/rbac/index.js +8 -11
- package/dist/theming/runtime.d.ts +1 -13
- package/dist/theming/runtime.js +1 -1
- package/dist/{timezone-_pgH8qrY.d.ts → timezone-CHhWg6b4.d.ts} +3 -10
- package/dist/{types-UU913iLA.d.ts → types-BeoeWV5I.d.ts} +8 -0
- package/dist/{types-CEpcvwwF.d.ts → types-CkbwOr4Y.d.ts} +6 -0
- package/dist/types.d.ts +2 -2
- package/dist/{usePublicRouteParams-TZe0gy-4.d.ts → usePublicRouteParams-1oMokgLF.d.ts} +34 -4
- package/dist/{useToast-C8gR5ir4.d.ts → useToast-AyaT-x7p.d.ts} +2 -2
- package/dist/utils.d.ts +4 -5
- package/dist/utils.js +15 -15
- package/dist/utils.js.map +1 -1
- package/docs/api/README.md +7 -1
- package/docs/api/classes/ColumnFactory.md +8 -8
- package/docs/api/classes/InvalidScopeError.md +4 -4
- package/docs/api/classes/Logger.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +4 -4
- package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
- package/docs/api/classes/PermissionDeniedError.md +4 -4
- 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 +4 -4
- package/docs/api/classes/RBACNotInitializedError.md +4 -4
- package/docs/api/classes/SecureSupabaseClient.md +18 -15
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/enums/LogLevel.md +1 -1
- package/docs/api/enums/RBACErrorCode.md +1 -1
- package/docs/api/enums/RPCFunction.md +1 -1
- package/docs/api/interfaces/AddressFieldProps.md +1 -1
- package/docs/api/interfaces/AddressFieldRef.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +4 -4
- package/docs/api/interfaces/AutocompleteOptions.md +1 -1
- package/docs/api/interfaces/AvatarProps.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +9 -2
- package/docs/api/interfaces/ButtonProps.md +7 -4
- package/docs/api/interfaces/CalendarProps.md +8 -5
- package/docs/api/interfaces/CardProps.md +8 -5
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/ComplianceResult.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +9 -9
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +24 -21
- package/docs/api/interfaces/DataTableColumn.md +31 -31
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
- package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
- package/docs/api/interfaces/DatabaseIssue.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +5 -5
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/ErrorBoundaryProps.md +147 -0
- package/docs/api/interfaces/ErrorBoundaryProviderProps.md +36 -0
- package/docs/api/interfaces/ErrorBoundaryState.md +75 -0
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +8 -8
- package/docs/api/interfaces/FileDisplayProps.md +1 -1
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +26 -23
- package/docs/api/interfaces/FooterProps.md +10 -8
- package/docs/api/interfaces/FormFieldProps.md +10 -10
- package/docs/api/interfaces/FormProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +7 -4
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoggerConfig.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +14 -11
- 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 +11 -11
- package/docs/api/interfaces/NavigationMenuProps.md +15 -15
- 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 +30 -27
- package/docs/api/interfaces/PaceLoginPageProps.md +6 -4
- 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/ParsedAddress.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProgressProps.md +1 -1
- package/docs/api/interfaces/ProtectedRouteProps.md +7 -26
- package/docs/api/interfaces/PublicPageFooterProps.md +9 -9
- package/docs/api/interfaces/PublicPageHeaderProps.md +10 -10
- package/docs/api/interfaces/PublicPageLayoutProps.md +7 -20
- package/docs/api/interfaces/QuickFix.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
- package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
- package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContext.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
- package/docs/api/interfaces/RBACResult.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
- package/docs/api/interfaces/RBACRolesListParams.md +1 -1
- package/docs/api/interfaces/RBACRolesListResult.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
- package/docs/api/interfaces/ResourcePermissions.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +9 -9
- package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +3 -3
- package/docs/api/interfaces/SetupIssue.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/SwitchProps.md +1 -1
- package/docs/api/interfaces/TabsContentProps.md +1 -1
- package/docs/api/interfaces/TabsListProps.md +1 -1
- package/docs/api/interfaces/TabsProps.md +1 -1
- package/docs/api/interfaces/TabsTriggerProps.md +3 -3
- package/docs/api/interfaces/TextareaProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +4 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +58 -55
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +15 -13
- package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
- package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +11 -9
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +6 -6
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +9 -6
- package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
- package/docs/api/interfaces/UsePublicEventReturn.md +8 -5
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +12 -9
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +10 -7
- package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +14 -11
- package/docs/api/interfaces/UserMenuProps.md +8 -6
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +575 -634
- package/docs/architecture/database-schema-requirements.md +161 -0
- package/docs/core-concepts/rbac-system.md +3 -3
- package/docs/documentation-index.md +2 -4
- package/docs/getting-started/cursor-rules.md +263 -0
- package/docs/getting-started/installation-guide.md +6 -1
- package/docs/getting-started/quick-start.md +6 -1
- package/docs/migration/DOCUMENTATION_STRUCTURE.md +441 -0
- package/docs/migration/MIGRATION_GUIDE.md +6 -28
- package/docs/migration/README.md +52 -6
- package/docs/migration/V0.5.190_TO_V0.6.1_MIGRATION.md +1153 -0
- package/docs/migration/V0.6.0_REACT_19_MIGRATION.md +227 -0
- package/docs/migration/database-changes-december-2025.md +3 -3
- package/docs/rbac/event-based-apps.md +1 -1
- package/docs/rbac/getting-started.md +1 -1
- package/docs/rbac/quick-start.md +1 -1
- package/docs/standards/README.md +40 -0
- package/docs/troubleshooting/migration.md +4 -4
- package/examples/PublicPages/PublicEventPage.tsx +1 -1
- package/package.json +12 -6
- package/scripts/audit/core/checks/accessibility.cjs +197 -0
- package/scripts/audit/core/checks/api-usage.cjs +191 -0
- package/scripts/audit/core/checks/bundle.cjs +142 -0
- package/scripts/{check-pace-core-compliance.cjs → audit/core/checks/compliance.cjs} +737 -691
- package/scripts/audit/core/checks/config.cjs +54 -0
- package/scripts/audit/core/checks/coverage.cjs +84 -0
- package/scripts/audit/core/checks/dependencies.cjs +454 -0
- package/scripts/audit/core/checks/documentation.cjs +203 -0
- package/scripts/audit/core/checks/environment.cjs +128 -0
- package/scripts/audit/core/checks/error-handling.cjs +299 -0
- package/scripts/audit/core/checks/forms.cjs +172 -0
- package/scripts/audit/core/checks/heuristics.cjs +68 -0
- package/scripts/audit/core/checks/hooks.cjs +334 -0
- package/scripts/audit/core/checks/imports.cjs +244 -0
- package/scripts/audit/core/checks/performance.cjs +325 -0
- package/scripts/audit/core/checks/routes.cjs +117 -0
- package/scripts/audit/core/checks/state.cjs +130 -0
- package/scripts/audit/core/checks/structure.cjs +65 -0
- package/scripts/audit/core/checks/style.cjs +584 -0
- package/scripts/audit/core/checks/testing.cjs +122 -0
- package/scripts/audit/core/checks/typescript.cjs +61 -0
- package/scripts/audit/core/scanner.cjs +199 -0
- package/scripts/audit/core/utils.cjs +137 -0
- package/scripts/audit/index.cjs +223 -0
- package/scripts/audit/reporters/console.cjs +151 -0
- package/scripts/audit/reporters/json.cjs +54 -0
- package/scripts/audit/reporters/markdown.cjs +124 -0
- package/scripts/audit-consuming-app.cjs +86 -0
- package/scripts/build-docs/build-decision.js +240 -0
- package/scripts/build-docs/cache-utils.js +105 -0
- package/scripts/build-docs/content-normalization.js +150 -0
- package/scripts/build-docs/file-utils.js +105 -0
- package/scripts/build-docs/git-utils.js +86 -0
- package/scripts/build-docs/hash-utils.js +116 -0
- package/scripts/build-docs/typedoc-runner.js +220 -0
- package/scripts/build-docs-incremental.js +77 -913
- package/scripts/install-cursor-rules.cjs +236 -0
- package/scripts/utils/command-runner.js +16 -11
- package/scripts/validate-formats.js +61 -56
- package/scripts/validate-master.js +74 -69
- package/scripts/validate-pre-publish.js +70 -65
- package/src/__tests__/helpers/test-providers.tsx +1 -1
- package/src/__tests__/helpers/test-utils.tsx +1 -1
- package/src/__tests__/hooks/usePermissions.test.ts +2 -2
- package/src/components/Alert/Alert.test.tsx +12 -18
- package/src/components/Alert/Alert.tsx +5 -7
- package/src/components/Avatar/Avatar.test.tsx +4 -4
- package/src/components/Badge/Badge.tsx +16 -4
- package/src/components/Button/Button.tsx +27 -4
- package/src/components/Calendar/Calendar.tsx +9 -3
- package/src/components/Card/Card.tsx +4 -0
- package/src/components/Checkbox/Checkbox.test.tsx +12 -12
- package/src/components/Checkbox/Checkbox.tsx +2 -2
- package/src/components/DataTable/DataTable.test.tsx +57 -93
- package/src/components/DataTable/DataTable.tsx +40 -6
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +5 -6
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +29 -7
- package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +12 -12
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +2 -3
- package/src/components/DataTable/components/AccessDeniedPage.tsx +17 -26
- package/src/components/DataTable/components/ActionButtons.tsx +10 -7
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
- package/src/components/DataTable/components/ColumnFilter.tsx +10 -0
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +12 -0
- package/src/components/DataTable/components/DataTableBody.tsx +8 -0
- package/src/components/DataTable/components/DataTableCore.tsx +200 -561
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +11 -0
- package/src/components/DataTable/components/DataTableLayout.tsx +559 -0
- package/src/components/DataTable/components/DataTableModals.tsx +9 -1
- package/src/components/DataTable/components/DataTableToolbar.tsx +8 -0
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +12 -0
- package/src/components/DataTable/components/EditFields.tsx +307 -0
- package/src/components/DataTable/components/EditableRow.tsx +9 -1
- package/src/components/DataTable/components/EmptyState.tsx +10 -0
- package/src/components/DataTable/components/FilterRow.tsx +12 -0
- package/src/components/DataTable/components/GroupHeader.tsx +12 -0
- package/src/components/DataTable/components/GroupingDropdown.tsx +12 -0
- package/src/components/DataTable/components/ImportModal.tsx +7 -0
- package/src/components/DataTable/components/LoadingState.tsx +6 -0
- package/src/components/DataTable/components/PaginationControls.tsx +16 -1
- package/src/components/DataTable/components/RowComponent.tsx +391 -0
- package/src/components/DataTable/components/UnifiedTableBody.tsx +62 -852
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +16 -4
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +4 -2
- package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +23 -23
- package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +11 -11
- package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +36 -36
- package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +27 -27
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +39 -39
- package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +33 -33
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +29 -29
- package/src/components/DataTable/components/cellValueUtils.ts +40 -0
- package/src/components/DataTable/components/hooks/useImportModalFocus.ts +53 -0
- package/src/components/DataTable/components/hooks/usePermissionTracking.ts +126 -0
- package/src/components/DataTable/context/DataTableContext.tsx +50 -0
- package/src/components/DataTable/core/ColumnFactory.ts +31 -0
- package/src/components/DataTable/core/DataTableContext.tsx +32 -1
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +10 -0
- package/src/components/DataTable/hooks/useColumnReordering.ts +14 -2
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +10 -0
- package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +16 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +124 -32
- package/src/components/DataTable/hooks/useDataTableState.ts +35 -1
- package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +12 -0
- package/src/components/DataTable/hooks/useKeyboardNavigation.ts +2 -2
- package/src/components/DataTable/hooks/useServerSideDataEffect.ts +11 -0
- package/src/components/DataTable/hooks/useTableColumns.ts +8 -0
- package/src/components/DataTable/hooks/useTableHandlers.ts +14 -0
- package/src/components/DataTable/styles.ts +6 -6
- package/src/components/DataTable/types.ts +6 -10
- package/src/components/DataTable/utils/a11yUtils.ts +7 -0
- package/src/components/DataTable/utils/debugTools.ts +18 -113
- package/src/components/DataTable/utils/errorHandling.ts +12 -0
- package/src/components/DataTable/utils/exportUtils.ts +9 -0
- package/src/components/DataTable/utils/flexibleImport.ts +12 -48
- package/src/components/DataTable/utils/paginationUtils.ts +8 -0
- package/src/components/DataTable/utils/performanceUtils.ts +5 -1
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -14
- package/src/components/Dialog/Dialog.tsx +8 -7
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +180 -1
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +46 -6
- package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +129 -0
- package/src/components/ErrorBoundary/index.ts +27 -2
- package/src/components/EventSelector/EventSelector.tsx +4 -1
- package/src/components/FileDisplay/FileDisplay.test.tsx +2 -2
- package/src/components/FileDisplay/FileDisplay.tsx +32 -18
- package/src/components/FileUpload/FileUpload.tsx +22 -2
- package/src/components/Footer/Footer.test.tsx +16 -16
- package/src/components/Footer/Footer.tsx +15 -12
- package/src/components/Form/Form.test.tsx +36 -15
- package/src/components/Form/Form.tsx +31 -26
- package/src/components/Header/Header.tsx +22 -11
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +40 -40
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +1 -1
- package/src/components/Input/Input.test.tsx +2 -2
- package/src/components/Input/Input.tsx +36 -34
- package/src/components/Label/Label.tsx +1 -1
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +4 -4
- package/src/components/LoadingSpinner/LoadingSpinner.tsx +1 -1
- package/src/components/LoginForm/LoginForm.test.tsx +42 -42
- package/src/components/LoginForm/LoginForm.tsx +12 -8
- package/src/components/NavigationMenu/NavigationMenu.tsx +15 -514
- package/src/components/NavigationMenu/types.ts +56 -0
- package/src/components/NavigationMenu/useNavigationFiltering.ts +390 -0
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +3 -0
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +1 -1
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +54 -52
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +33 -12
- package/src/components/PaceAppLayout/README.md +1 -1
- package/src/components/PaceAppLayout/test-setup.tsx +1 -2
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +4 -1
- package/src/components/PasswordChange/PasswordChangeForm.test.tsx +33 -33
- package/src/components/PasswordChange/PasswordChangeForm.tsx +10 -1
- package/src/components/Progress/Progress.tsx +1 -1
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -9
- package/src/components/PublicLayout/PublicPageLayout.tsx +3 -6
- package/src/components/PublicLayout/PublicPageProvider.tsx +4 -0
- package/src/components/Select/Select.tsx +95 -438
- package/src/components/Select/context.ts +23 -0
- package/src/components/Select/hooks/useSelectEvents.ts +87 -0
- package/src/components/Select/hooks/useSelectSearch.ts +91 -0
- package/src/components/Select/hooks/useSelectState.ts +104 -0
- package/src/components/Select/index.ts +9 -1
- package/src/components/Select/types.ts +123 -0
- package/src/components/Select/utils/text.ts +26 -0
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +5 -6
- package/src/components/Switch/Switch.tsx +4 -4
- package/src/components/Table/Table.tsx +1 -1
- package/src/components/Tabs/Tabs.tsx +1 -1
- package/src/components/Textarea/Textarea.tsx +27 -29
- package/src/components/Toast/Toast.tsx +5 -1
- package/src/components/Tooltip/Tooltip.tsx +3 -3
- package/src/components/UserMenu/UserMenu.test.tsx +24 -11
- package/src/components/UserMenu/UserMenu.tsx +22 -19
- package/src/components/index.ts +2 -2
- package/src/hooks/__tests__/hooks.integration.test.tsx +80 -55
- package/src/hooks/__tests__/index.unit.test.ts +2 -5
- package/src/hooks/__tests__/useStorage.unit.test.ts +36 -36
- package/src/hooks/index.ts +1 -2
- package/src/hooks/public/usePublicEvent.ts +5 -1
- package/src/hooks/public/usePublicEventLogo.ts +5 -1
- package/src/hooks/public/usePublicFileDisplay.ts +4 -0
- package/src/hooks/public/usePublicRouteParams.ts +5 -1
- package/src/hooks/services/useAuth.ts +32 -0
- package/src/hooks/services/useCurrentEvent.ts +6 -0
- package/src/hooks/services/useCurrentOrganisation.ts +6 -0
- package/src/hooks/useDataTableState.ts +8 -18
- package/src/hooks/useDebounce.ts +9 -0
- package/src/hooks/useEventTheme.ts +6 -0
- package/src/hooks/useFileDisplay.ts +4 -0
- package/src/hooks/useFileReference.ts +25 -7
- package/src/hooks/useFileUrl.ts +11 -1
- package/src/hooks/useFocusManagement.ts +16 -2
- package/src/hooks/useFocusTrap.ts +7 -4
- package/src/hooks/useFormDialog.ts +8 -7
- package/src/hooks/useInactivityTracker.ts +4 -1
- package/src/hooks/useKeyboardShortcuts.ts +4 -0
- package/src/hooks/useOrganisationPermissions.ts +4 -0
- package/src/hooks/useOrganisationSecurity.ts +4 -0
- package/src/hooks/usePerformanceMonitor.ts +4 -0
- package/src/hooks/usePermissionCache.ts +8 -1
- package/src/hooks/useQueryCache.ts +12 -1
- package/src/hooks/useSessionRestoration.ts +4 -0
- package/src/hooks/useStorage.ts +4 -0
- package/src/hooks/useToast.ts +3 -3
- package/src/index.ts +2 -1
- package/src/providers/__tests__/OrganisationProvider.test.tsx +115 -49
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +21 -6
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +10 -10
- package/src/providers/services/AuthServiceProvider.tsx +18 -0
- package/src/providers/services/EventServiceProvider.tsx +18 -0
- package/src/providers/services/InactivityServiceProvider.tsx +18 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +18 -0
- package/src/providers/services/UnifiedAuthProvider.tsx +58 -22
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +33 -7
- package/src/rbac/README.md +1 -1
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +26 -26
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +4 -5
- package/src/rbac/adapters.tsx +14 -5
- package/src/rbac/api.ts +100 -67
- package/src/rbac/components/EnhancedNavigationMenu.tsx +1 -1
- package/src/rbac/components/NavigationGuard.tsx +1 -1
- package/src/rbac/components/NavigationProvider.tsx +5 -2
- package/src/rbac/components/PagePermissionGuard.tsx +158 -18
- package/src/rbac/components/PagePermissionProvider.tsx +1 -1
- package/src/rbac/components/PermissionEnforcer.tsx +1 -1
- package/src/rbac/components/RoleBasedRouter.tsx +6 -2
- package/src/rbac/components/SecureDataProvider.test.tsx +84 -49
- package/src/rbac/components/SecureDataProvider.tsx +21 -6
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +24 -14
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +7 -0
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -6
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +15 -4
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +148 -24
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +81 -15
- package/src/rbac/engine.ts +38 -14
- package/src/rbac/hooks/permissions/index.ts +7 -0
- package/src/rbac/hooks/permissions/useAccessLevel.ts +105 -0
- package/src/rbac/hooks/permissions/useCachedPermissions.ts +79 -0
- package/src/rbac/hooks/permissions/useCan.ts +347 -0
- package/src/rbac/hooks/permissions/useHasAllPermissions.ts +90 -0
- package/src/rbac/hooks/permissions/useHasAnyPermission.ts +90 -0
- package/src/rbac/hooks/permissions/useMultiplePermissions.ts +93 -0
- package/src/rbac/hooks/permissions/usePermissions.ts +253 -0
- package/src/rbac/hooks/useCan.test.ts +71 -64
- package/src/rbac/hooks/usePermissions.ts +14 -995
- package/src/rbac/hooks/useResourcePermissions.test.ts +54 -18
- package/src/rbac/hooks/useResourcePermissions.ts +14 -4
- package/src/rbac/hooks/useSecureSupabase.ts +33 -13
- package/src/rbac/permissions.ts +0 -30
- package/src/rbac/secureClient.ts +212 -61
- package/src/rbac/types.ts +8 -0
- package/src/theming/__tests__/parseEventColours.test.ts +6 -9
- package/src/theming/parseEventColours.ts +5 -19
- package/src/types/vitest-globals.d.ts +51 -26
- package/src/utils/__mocks__/supabaseMock.ts +1 -3
- package/src/utils/__tests__/formatting.unit.test.ts +4 -4
- package/src/utils/__tests__/index.unit.test.ts +2 -2
- package/src/utils/audit/audit.ts +0 -3
- package/src/utils/core/cn.ts +1 -1
- package/src/utils/file-reference/index.ts +53 -1
- package/src/utils/formatting/formatting.ts +8 -18
- package/src/utils/index.ts +0 -1
- package/src/utils/security/secureDataAccess.test.ts +31 -20
- package/src/utils/security/secureDataAccess.ts +4 -3
- package/dist/chunk-6C4YBBJM.js +0 -628
- package/dist/chunk-6C4YBBJM.js.map +0 -1
- package/dist/chunk-7D4SUZUM.js 2.map +0 -1
- package/dist/chunk-7EQTDTTJ.js 2.map +0 -1
- package/dist/chunk-7EQTDTTJ.js.map +0 -1
- package/dist/chunk-7FLMSG37.js 2.map +0 -1
- package/dist/chunk-7FLMSG37.js.map +0 -1
- package/dist/chunk-BC4IJKSL.js.map +0 -1
- package/dist/chunk-E3SPN4VZ.js +0 -12917
- package/dist/chunk-E3SPN4VZ.js.map +0 -1
- package/dist/chunk-E66EQZE6 5.js +0 -37
- package/dist/chunk-E66EQZE6.js 2.map +0 -1
- package/dist/chunk-HWIIPPNI.js.map +0 -1
- package/dist/chunk-I7PSE6JW 5.js +0 -191
- package/dist/chunk-I7PSE6JW.js 2.map +0 -1
- package/dist/chunk-I7PSE6JW.js.map +0 -1
- package/dist/chunk-IIELH4DL.js.map +0 -1
- package/dist/chunk-KNC55RTG.js 5.map +0 -1
- package/dist/chunk-KNC55RTG.js.map +0 -1
- package/dist/chunk-KQCRWDSA.js 5.map +0 -1
- package/dist/chunk-LFNCN2SP.js +0 -412
- package/dist/chunk-LFNCN2SP.js 2.map +0 -1
- package/dist/chunk-LFNCN2SP.js.map +0 -1
- package/dist/chunk-LMC26NLJ 2.js +0 -84
- package/dist/chunk-NOAYCWCX.js +0 -4993
- package/dist/chunk-NOAYCWCX.js.map +0 -1
- package/dist/chunk-QWWZ5CAQ.js 3.map +0 -1
- package/dist/chunk-QWWZ5CAQ.js.map +0 -1
- package/dist/chunk-QXHPKYJV 3.js +0 -113
- package/dist/chunk-R77UEZ4E.js +0 -68
- package/dist/chunk-R77UEZ4E.js.map +0 -1
- package/dist/chunk-SQGMNID3.js.map +0 -1
- package/dist/chunk-VBXEHIUJ.js 6.map +0 -1
- package/dist/chunk-XNXXZ43G.js.map +0 -1
- package/dist/chunk-ZSAAAMVR 6.js +0 -25
- package/dist/components.js 5.map +0 -1
- package/dist/styles/index 2.js +0 -12
- package/dist/styles/index.js 5.map +0 -1
- package/dist/theming/runtime 5.js +0 -19
- package/dist/theming/runtime.js 5.map +0 -1
- package/docs/api/classes/ErrorBoundary.md +0 -144
- package/docs/migration/quick-migration-guide.md +0 -356
- package/docs/migration/service-architecture.md +0 -281
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +0 -680
- package/src/hooks/useSecureDataAccess.test.ts +0 -559
- package/src/hooks/useSecureDataAccess.ts +0 -666
- /package/dist/{DataTable-5FU7IESH.js.map → DataTable-TPTKCX4D.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-RGJTDE2C.js.map → UnifiedAuthProvider-CH6Z342H.js.map} +0 -0
- /package/dist/{api-N774RPUA.js.map → api-MVVQZLJI.js.map} +0 -0
- /package/docs/migration/{organisation-context-timing-fix.md → V0.3.44_organisation-context-timing-fix.md} +0 -0
- /package/docs/migration/{rbac-migration.md → V0.4.0_rbac-migration.md} +0 -0
- /package/docs/migration/{person-scoped-profiles-migration-guide.md → V0.5.190_person-scoped-profiles-migration-guide.md} +0 -0
- /package/examples/{rbac → RBAC}/CompleteRBACExample.tsx +0 -0
- /package/examples/{rbac → RBAC}/EventBasedApp.tsx +0 -0
- /package/examples/{rbac → RBAC}/PermissionExample.tsx +0 -0
- /package/examples/{rbac → RBAC}/index.ts +0 -0
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
* - Efficient error handling
|
|
62
62
|
*
|
|
63
63
|
* @dependencies
|
|
64
|
-
* - React
|
|
64
|
+
* - React 19+ - Component framework
|
|
65
65
|
* - useCan hook - Permission checking
|
|
66
66
|
* - useUnifiedAuth - Authentication context
|
|
67
67
|
* - RBAC types - Type definitions
|
|
@@ -141,17 +141,86 @@ const PagePermissionGuardComponent = ({
|
|
|
141
141
|
const { user, selectedOrganisation, selectedEvent, supabase, appId: contextAppId, appName } = useUnifiedAuth();
|
|
142
142
|
|
|
143
143
|
const [hasChecked, setHasChecked] = useState(false);
|
|
144
|
+
|
|
145
|
+
// Determine the page ID for permission checking
|
|
146
|
+
const effectivePageId = useMemo((): string => {
|
|
147
|
+
return pageId || pageName;
|
|
148
|
+
}, [pageId, pageName]);
|
|
149
|
+
|
|
150
|
+
// Check super admin status directly - don't rely on useRBAC which might not be loaded yet
|
|
151
|
+
// This ensures super admins get immediate access without waiting for RBAC context to load
|
|
152
|
+
const [isSuperAdmin, setIsSuperAdmin] = useState<boolean | null>(null);
|
|
153
|
+
|
|
154
|
+
useEffect(() => {
|
|
155
|
+
if (!user?.id) {
|
|
156
|
+
setIsSuperAdmin(false);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
let cancelled = false;
|
|
161
|
+
const checkSuperAdmin = async () => {
|
|
162
|
+
const startTime = Date.now();
|
|
163
|
+
try {
|
|
164
|
+
const { isSuperAdmin: checkSuperAdmin } = await import('../api');
|
|
165
|
+
|
|
166
|
+
// Add timeout to prevent hanging
|
|
167
|
+
const timeoutPromise = new Promise<boolean>((_, reject) => {
|
|
168
|
+
setTimeout(() => reject(new Error('Super admin check timeout')), 10000);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
const isSuper = await Promise.race([
|
|
172
|
+
checkSuperAdmin(user.id),
|
|
173
|
+
timeoutPromise
|
|
174
|
+
]);
|
|
175
|
+
|
|
176
|
+
const elapsed = Date.now() - startTime;
|
|
177
|
+
|
|
178
|
+
if (!cancelled) {
|
|
179
|
+
setIsSuperAdmin(isSuper);
|
|
180
|
+
if (process.env.NODE_ENV === 'development') {
|
|
181
|
+
console.log('[PagePermissionGuard] Super admin check completed', {
|
|
182
|
+
userId: user.id,
|
|
183
|
+
isSuperAdmin: isSuper,
|
|
184
|
+
elapsedMs: elapsed
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
} catch (err) {
|
|
189
|
+
const elapsed = Date.now() - startTime;
|
|
190
|
+
if (!cancelled) {
|
|
191
|
+
console.error('[PagePermissionGuard] Error checking super admin', {
|
|
192
|
+
error: err,
|
|
193
|
+
userId: user.id,
|
|
194
|
+
elapsedMs: elapsed
|
|
195
|
+
});
|
|
196
|
+
// On timeout or error, assume not super admin (fail secure)
|
|
197
|
+
// But log it so we can debug
|
|
198
|
+
setIsSuperAdmin(false);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
checkSuperAdmin();
|
|
204
|
+
return () => {
|
|
205
|
+
cancelled = true;
|
|
206
|
+
};
|
|
207
|
+
}, [user?.id]);
|
|
144
208
|
|
|
145
209
|
// Use useResolvedScope hook for consistent scope resolution
|
|
146
210
|
// For event-required apps: selectedOrganisation is null, org derived from event
|
|
147
211
|
// For org-required apps: selectedOrganisation is available, event optional
|
|
148
212
|
// For page-level permissions, PORTAL app allows both contexts to be optional
|
|
213
|
+
// NOTE: Super admins bypass scope requirements, but we still need to call the hook
|
|
149
214
|
const { resolvedScope: hookResolvedScope, isLoading: scopeLoading, error: scopeError } = useResolvedScope({
|
|
150
215
|
supabase,
|
|
151
216
|
selectedOrganisationId: selectedOrganisation?.id || null,
|
|
152
217
|
selectedEventId: selectedEvent?.event_id || null
|
|
153
218
|
});
|
|
154
219
|
|
|
220
|
+
// For super admins, we can use a minimal scope since they bypass all checks
|
|
221
|
+
// This prevents scope resolution from blocking super admin access
|
|
222
|
+
const shouldBypassScopeForSuperAdmin = isSuperAdmin === true;
|
|
223
|
+
|
|
155
224
|
// Use provided scope if available, otherwise use resolved scope
|
|
156
225
|
// For PORTAL app page-level permissions, allow scope without org/event
|
|
157
226
|
// Ensure appId is available for PORTAL/ADMIN (use contextAppId as fallback)
|
|
@@ -171,11 +240,6 @@ const PagePermissionGuardComponent = ({
|
|
|
171
240
|
} : null)));
|
|
172
241
|
const checkError = scopeError;
|
|
173
242
|
|
|
174
|
-
// Determine the page ID for permission checking
|
|
175
|
-
const effectivePageId = useMemo((): string => {
|
|
176
|
-
return pageId || pageName;
|
|
177
|
-
}, [pageId, pageName]);
|
|
178
|
-
|
|
179
243
|
// Build the permission string
|
|
180
244
|
const permission = useMemo((): Permission => {
|
|
181
245
|
return `${operation}:page.${pageName}` as Permission;
|
|
@@ -225,22 +289,44 @@ const PagePermissionGuardComponent = ({
|
|
|
225
289
|
return newScope;
|
|
226
290
|
}, [effectiveScope, appName, contextAppId, selectedEvent?.event_id]);
|
|
227
291
|
|
|
292
|
+
// For super admins, use a minimal valid scope since they bypass all checks
|
|
293
|
+
// This prevents scope validation from blocking super admin access
|
|
294
|
+
const scopeForPermissionCheck = shouldBypassScopeForSuperAdmin && !stableScope?.organisationId
|
|
295
|
+
? {
|
|
296
|
+
organisationId: undefined,
|
|
297
|
+
appId: contextAppId || undefined,
|
|
298
|
+
eventId: selectedEvent?.event_id || undefined
|
|
299
|
+
}
|
|
300
|
+
: stableScope;
|
|
301
|
+
|
|
302
|
+
// CRITICAL: If super admin is confirmed, skip useCan entirely to avoid any blocking
|
|
303
|
+
// Super admins have access to everything, so no need to check permissions
|
|
304
|
+
const shouldSkipPermissionCheck = isSuperAdmin === true;
|
|
305
|
+
|
|
228
306
|
// Check if user has permission - only call useCan when we have a resolved scope with valid organisationId
|
|
229
307
|
// If resolvedScope is null or has no organisationId, useCan will keep isLoading=true
|
|
230
308
|
// Pass appName to useCan so it can be passed to isPermitted for PORTAL/ADMIN special case
|
|
309
|
+
// Pass precomputed super admin status to avoid duplicate checks in useCan
|
|
310
|
+
// For super admins, we can skip the check entirely, but still call useCan with a dummy scope to avoid hook rule violations
|
|
231
311
|
const { can, isLoading: canIsLoading, error: canError } = useCan(
|
|
232
312
|
user?.id || '',
|
|
233
|
-
|
|
313
|
+
shouldSkipPermissionCheck ? { organisationId: undefined, appId: contextAppId || undefined, eventId: undefined } : scopeForPermissionCheck,
|
|
234
314
|
permission,
|
|
235
315
|
effectivePageId,
|
|
236
316
|
true, // Use cache
|
|
317
|
+
isSuperAdmin, // precomputedSuperAdmin - null if checking, true/false if checked
|
|
237
318
|
appName // Pass appName for PORTAL/ADMIN special case
|
|
238
319
|
);
|
|
239
320
|
|
|
321
|
+
// Override can for super admins - they always have access
|
|
322
|
+
const effectiveCan = shouldSkipPermissionCheck ? true : can;
|
|
323
|
+
const effectiveIsLoading = shouldSkipPermissionCheck ? false : canIsLoading;
|
|
324
|
+
|
|
240
325
|
|
|
241
326
|
// Combine loading states - we're loading if scope resolution or permission check is loading
|
|
242
327
|
// For page-level permissions, PORTAL/ADMIN apps allow undefined organisationId
|
|
243
|
-
|
|
328
|
+
// Super admins bypass scope resolution - don't wait for it
|
|
329
|
+
const isLoading = shouldBypassScopeForSuperAdmin ? effectiveIsLoading : (scopeLoading || effectiveIsLoading);
|
|
244
330
|
const error = checkError || canError;
|
|
245
331
|
|
|
246
332
|
// Handle permission check completion
|
|
@@ -248,13 +334,13 @@ const PagePermissionGuardComponent = ({
|
|
|
248
334
|
if (!isLoading && !error) {
|
|
249
335
|
setHasChecked(true);
|
|
250
336
|
|
|
251
|
-
if (!
|
|
337
|
+
if (!effectiveCan && onDenied) {
|
|
252
338
|
onDenied(pageName, operation);
|
|
253
339
|
}
|
|
254
340
|
} else if (error) {
|
|
255
341
|
setHasChecked(true);
|
|
256
342
|
}
|
|
257
|
-
}, [
|
|
343
|
+
}, [effectiveCan, isLoading, error, pageName, operation, onDenied]);
|
|
258
344
|
|
|
259
345
|
// Log page access attempt for audit
|
|
260
346
|
useEffect(() => {
|
|
@@ -265,16 +351,17 @@ const PagePermissionGuardComponent = ({
|
|
|
265
351
|
operation,
|
|
266
352
|
userId: user?.id,
|
|
267
353
|
scope: effectiveScope,
|
|
268
|
-
allowed:
|
|
354
|
+
allowed: effectiveCan,
|
|
355
|
+
isSuperAdmin,
|
|
269
356
|
timestamp: new Date().toISOString()
|
|
270
357
|
});
|
|
271
358
|
}
|
|
272
|
-
}, [auditLog, hasChecked, isLoading, pageName, operation, user?.id, effectiveScope,
|
|
359
|
+
}, [auditLog, hasChecked, isLoading, pageName, operation, user?.id, effectiveScope, effectiveCan, isSuperAdmin]);
|
|
273
360
|
|
|
274
361
|
|
|
275
362
|
// Handle strict mode violations
|
|
276
363
|
useEffect(() => {
|
|
277
|
-
if (strictMode && hasChecked && !isLoading && !
|
|
364
|
+
if (strictMode && hasChecked && !isLoading && !effectiveCan && !shouldBypassScopeForSuperAdmin) {
|
|
278
365
|
const logger = getRBACLogger();
|
|
279
366
|
logger.error(`STRICT MODE VIOLATION: User attempted to access protected page without permission`, {
|
|
280
367
|
pageName,
|
|
@@ -286,20 +373,22 @@ const PagePermissionGuardComponent = ({
|
|
|
286
373
|
scopeValid: allowsOptionalContexts ? true : (effectiveScope !== null), // PORTAL/ADMIN allow scope without org/event
|
|
287
374
|
checkError,
|
|
288
375
|
canError,
|
|
376
|
+
isSuperAdmin,
|
|
289
377
|
timestamp: new Date().toISOString()
|
|
290
378
|
});
|
|
291
379
|
}
|
|
292
|
-
}, [strictMode, hasChecked, isLoading,
|
|
380
|
+
}, [strictMode, hasChecked, isLoading, effectiveCan, shouldBypassScopeForSuperAdmin, pageName, operation, effectivePageId, user?.id, effectiveScope, allowsOptionalContexts, checkError, canError, isSuperAdmin]);
|
|
293
381
|
|
|
294
382
|
// Calculate the actual render state - FIXED: Proper state calculation
|
|
295
383
|
// Add defensive checks to ensure we have valid state
|
|
296
384
|
// For page-level permissions, PORTAL/ADMIN apps allow scope without org/event
|
|
297
|
-
|
|
385
|
+
// Super admins bypass scope validation
|
|
386
|
+
const hasValidScopeForPagePermissions = shouldBypassScopeForSuperAdmin ? true : (allowsOptionalContexts ? true : (effectiveScope !== null));
|
|
298
387
|
const hasValidUser = user && user.id;
|
|
299
388
|
const isPermissionCheckComplete = hasChecked && !isLoading;
|
|
300
389
|
|
|
301
|
-
const shouldShowAccessDenied = isPermissionCheckComplete && hasValidScopeForPagePermissions && hasValidUser && !checkError && !
|
|
302
|
-
const shouldShowContent = isPermissionCheckComplete && hasValidScopeForPagePermissions && hasValidUser && !checkError &&
|
|
390
|
+
const shouldShowAccessDenied = isPermissionCheckComplete && hasValidScopeForPagePermissions && hasValidUser && !checkError && !effectiveCan;
|
|
391
|
+
const shouldShowContent = isPermissionCheckComplete && hasValidScopeForPagePermissions && hasValidUser && !checkError && effectiveCan;
|
|
303
392
|
|
|
304
393
|
// Create a key to force re-render when scope or permission state changes
|
|
305
394
|
const scopeKey = effectiveScope ? `${effectiveScope.organisationId}-${effectiveScope.eventId}-${effectiveScope.appId}` : 'no-scope';
|
|
@@ -307,9 +396,60 @@ const PagePermissionGuardComponent = ({
|
|
|
307
396
|
|
|
308
397
|
|
|
309
398
|
|
|
399
|
+
// Debug logging for permission check state
|
|
400
|
+
useEffect(() => {
|
|
401
|
+
if (process.env.NODE_ENV === 'development') {
|
|
402
|
+
console.log('[PagePermissionGuard] Permission check state', {
|
|
403
|
+
pageName,
|
|
404
|
+
userId: user?.id,
|
|
405
|
+
isSuperAdmin,
|
|
406
|
+
isLoading,
|
|
407
|
+
scopeLoading,
|
|
408
|
+
canIsLoading,
|
|
409
|
+
hasChecked,
|
|
410
|
+
hasValidUser,
|
|
411
|
+
effectiveCan,
|
|
412
|
+
stableScope,
|
|
413
|
+
effectiveScope
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
}, [pageName, user?.id, isSuperAdmin, isLoading, scopeLoading, canIsLoading, hasChecked, hasValidUser, effectiveCan, stableScope, effectiveScope]);
|
|
417
|
+
|
|
310
418
|
// Show loading state - if we're still loading or don't have valid state
|
|
311
419
|
// For page-level permissions, we don't require organisation context, so only check for user and loading state
|
|
312
|
-
|
|
420
|
+
// Add timeout warning for debugging
|
|
421
|
+
useEffect(() => {
|
|
422
|
+
if (isLoading && isSuperAdmin === null && hasValidUser) {
|
|
423
|
+
const timeout = setTimeout(() => {
|
|
424
|
+
console.warn('[PagePermissionGuard] Permission check taking longer than expected', {
|
|
425
|
+
pageName,
|
|
426
|
+
userId: user?.id,
|
|
427
|
+
isSuperAdmin,
|
|
428
|
+
scopeLoading,
|
|
429
|
+
canIsLoading,
|
|
430
|
+
hasChecked,
|
|
431
|
+
stableScope,
|
|
432
|
+
effectiveScope,
|
|
433
|
+
appName
|
|
434
|
+
});
|
|
435
|
+
}, 5000);
|
|
436
|
+
return () => clearTimeout(timeout);
|
|
437
|
+
}
|
|
438
|
+
}, [isLoading, isSuperAdmin, hasValidUser, pageName, user?.id, scopeLoading, canIsLoading, hasChecked, stableScope, effectiveScope, appName]);
|
|
439
|
+
|
|
440
|
+
// CRITICAL: Super admins bypass all checks - show content immediately once confirmed
|
|
441
|
+
// This must be checked AFTER all hooks are called to avoid React hooks rule violations
|
|
442
|
+
if (isSuperAdmin === true && hasValidUser) {
|
|
443
|
+
// Super admin confirmed - grant access immediately
|
|
444
|
+
console.log('[PagePermissionGuard] Super admin access granted - bypassing all checks', {
|
|
445
|
+
pageName,
|
|
446
|
+
userId: user?.id,
|
|
447
|
+
operation
|
|
448
|
+
});
|
|
449
|
+
return <>{children}</>;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if (isLoading || !hasValidUser || !hasChecked || isSuperAdmin === null) {
|
|
313
453
|
return loading || <div>Checking permissions...</div>;
|
|
314
454
|
}
|
|
315
455
|
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
* - Efficient route matching
|
|
57
57
|
*
|
|
58
58
|
* @dependencies
|
|
59
|
-
* - React
|
|
59
|
+
* - React 19+ - Component framework
|
|
60
60
|
* - React Router - Routing functionality
|
|
61
61
|
* - useCan hook - Permission checking
|
|
62
62
|
* - useUnifiedAuth - Authentication context
|
|
@@ -231,11 +231,15 @@ export function RoleBasedRouter({
|
|
|
231
231
|
}, [user?.id, currentScope, routes]);
|
|
232
232
|
|
|
233
233
|
// Use useCan hook for actual permission checking
|
|
234
|
+
// Pass null for super admin status (not checked yet - hook will check if needed)
|
|
234
235
|
const { can: canAccessCurrentRoute, isLoading: permissionLoading } = useCan(
|
|
235
236
|
user?.id || '',
|
|
236
237
|
currentScope || { organisationId: '', eventId: undefined, appId: undefined },
|
|
237
238
|
currentRouteConfig?.permissions?.[0] || 'read:page',
|
|
238
|
-
currentRouteConfig?.pageId
|
|
239
|
+
currentRouteConfig?.pageId,
|
|
240
|
+
true, // useCache
|
|
241
|
+
null, // precomputedSuperAdmin - not checked yet
|
|
242
|
+
undefined // appName
|
|
239
243
|
);
|
|
240
244
|
|
|
241
245
|
// Check if route is public
|
|
@@ -12,7 +12,7 @@ import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
|
12
12
|
import React, { ReactNode } from 'react';
|
|
13
13
|
import { SecureDataProvider, useSecureData } from './SecureDataProvider';
|
|
14
14
|
import { useUnifiedAuth } from '../../providers/services/UnifiedAuthProvider';
|
|
15
|
-
|
|
15
|
+
// useSecureDataAccess has been removed - SecureDataProvider now uses useSecureSupabase internally
|
|
16
16
|
import { UUID, Scope, Permission } from '../types';
|
|
17
17
|
|
|
18
18
|
// Mock the auth provider
|
|
@@ -23,8 +23,77 @@ vi.mock('../../providers/services/UnifiedAuthProvider', () => ({
|
|
|
23
23
|
}));
|
|
24
24
|
|
|
25
25
|
// Mock the secure data access hook
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
// useSecureDataAccess has been removed - no longer needed
|
|
27
|
+
|
|
28
|
+
// Mock useResolvedScope
|
|
29
|
+
const mockUseResolvedScopeFn = vi.fn();
|
|
30
|
+
vi.mock('../../hooks/useResolvedScope', () => ({
|
|
31
|
+
useResolvedScope: () => mockUseResolvedScopeFn(),
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
// Mock useOrganisations to prevent provider requirement
|
|
35
|
+
vi.mock('../../hooks/useOrganisations', () => ({
|
|
36
|
+
useOrganisations: vi.fn(() => ({
|
|
37
|
+
organisations: [],
|
|
38
|
+
isLoading: false,
|
|
39
|
+
error: null,
|
|
40
|
+
refetch: vi.fn(),
|
|
41
|
+
selectedOrganisation: {
|
|
42
|
+
id: 'org-123',
|
|
43
|
+
name: 'Test Org',
|
|
44
|
+
display_name: 'Test Organisation',
|
|
45
|
+
description: 'Test',
|
|
46
|
+
subscription_tier: 'basic',
|
|
47
|
+
settings: {},
|
|
48
|
+
is_active: true,
|
|
49
|
+
created_at: '2023-01-01T00:00:00Z',
|
|
50
|
+
updated_at: '2023-01-01T00:00:00Z'
|
|
51
|
+
}
|
|
52
|
+
}))
|
|
53
|
+
}));
|
|
54
|
+
|
|
55
|
+
// Mock useEvents
|
|
56
|
+
vi.mock('../../hooks/useEvents', () => ({
|
|
57
|
+
useEvents: vi.fn(() => ({
|
|
58
|
+
events: [],
|
|
59
|
+
isLoading: false,
|
|
60
|
+
error: null,
|
|
61
|
+
refetch: vi.fn(),
|
|
62
|
+
selectedEvent: {
|
|
63
|
+
id: 'event-456',
|
|
64
|
+
event_id: 'event-456',
|
|
65
|
+
event_name: 'Test Event',
|
|
66
|
+
event_date: '2023-01-01T00:00:00Z',
|
|
67
|
+
event_venue: 'Test Venue',
|
|
68
|
+
event_participants: 100,
|
|
69
|
+
event_colours: '#FF0000',
|
|
70
|
+
event_logo: '',
|
|
71
|
+
organisation_id: 'org-123' as any,
|
|
72
|
+
is_visible: true,
|
|
73
|
+
created_at: '2023-01-01T00:00:00Z',
|
|
74
|
+
updated_at: '2023-01-01T00:00:00Z'
|
|
75
|
+
},
|
|
76
|
+
eventLoading: false
|
|
77
|
+
}))
|
|
78
|
+
}));
|
|
79
|
+
|
|
80
|
+
// Mock useOrganisationSecurity
|
|
81
|
+
vi.mock('../../hooks/useOrganisationSecurity', () => ({
|
|
82
|
+
useOrganisationSecurity: vi.fn(() => ({
|
|
83
|
+
superAdminContext: {
|
|
84
|
+
isSuperAdmin: false,
|
|
85
|
+
isLoading: false
|
|
86
|
+
},
|
|
87
|
+
organisationSecurity: {
|
|
88
|
+
canAccessOrganisation: vi.fn(() => true),
|
|
89
|
+
canAccessEvent: vi.fn(() => true)
|
|
90
|
+
}
|
|
91
|
+
}))
|
|
92
|
+
}));
|
|
93
|
+
|
|
94
|
+
// Mock useSecureSupabase
|
|
95
|
+
vi.mock('../hooks/useSecureSupabase', () => ({
|
|
96
|
+
useSecureSupabase: vi.fn((supabase) => supabase)
|
|
28
97
|
}));
|
|
29
98
|
|
|
30
99
|
// Mock the RBAC hooks
|
|
@@ -55,7 +124,7 @@ const TestComponent = ({ children }: { children: ReactNode }) => (
|
|
|
55
124
|
);
|
|
56
125
|
|
|
57
126
|
describe('SecureDataProvider', () => {
|
|
58
|
-
|
|
127
|
+
// useSecureDataAccess has been removed
|
|
59
128
|
const mockUseCan = vi.mocked(useCan);
|
|
60
129
|
|
|
61
130
|
beforeEach(() => {
|
|
@@ -67,12 +136,7 @@ describe('SecureDataProvider', () => {
|
|
|
67
136
|
// Add other required properties
|
|
68
137
|
} as any);
|
|
69
138
|
|
|
70
|
-
|
|
71
|
-
isDataAccessAllowed: vi.fn().mockReturnValue(true),
|
|
72
|
-
getDataAccessPermissions: vi.fn().mockReturnValue({}),
|
|
73
|
-
validateDataAccess: vi.fn().mockReturnValue(true),
|
|
74
|
-
// Add other required properties
|
|
75
|
-
} as any);
|
|
139
|
+
// useSecureDataAccess has been removed - SecureDataProvider handles this internally
|
|
76
140
|
});
|
|
77
141
|
|
|
78
142
|
describe('Provider Initialization', () => {
|
|
@@ -160,12 +224,7 @@ describe('SecureDataProvider', () => {
|
|
|
160
224
|
});
|
|
161
225
|
|
|
162
226
|
it('denies data access when user lacks permissions', async () => {
|
|
163
|
-
|
|
164
|
-
isDataAccessAllowed: vi.fn().mockReturnValue(false),
|
|
165
|
-
getDataAccessPermissions: vi.fn().mockReturnValue({}),
|
|
166
|
-
validateDataAccess: vi.fn().mockReturnValue(false),
|
|
167
|
-
// Add other required properties
|
|
168
|
-
} as any);
|
|
227
|
+
// useSecureDataAccess has been removed - SecureDataProvider handles this internally
|
|
169
228
|
|
|
170
229
|
const TestConsumer = () => {
|
|
171
230
|
const context = useSecureData();
|
|
@@ -216,12 +275,7 @@ describe('SecureDataProvider', () => {
|
|
|
216
275
|
'events': ['read', 'update']
|
|
217
276
|
};
|
|
218
277
|
|
|
219
|
-
|
|
220
|
-
isDataAccessAllowed: vi.fn().mockReturnValue(true),
|
|
221
|
-
getDataAccessPermissions: vi.fn().mockReturnValue(mockPermissions),
|
|
222
|
-
validateDataAccess: vi.fn().mockReturnValue(true),
|
|
223
|
-
// Add other required properties
|
|
224
|
-
} as any);
|
|
278
|
+
// useSecureDataAccess has been removed - SecureDataProvider handles this internally
|
|
225
279
|
|
|
226
280
|
const TestConsumer = () => {
|
|
227
281
|
const context = useSecureData();
|
|
@@ -309,13 +363,7 @@ describe('SecureDataProvider', () => {
|
|
|
309
363
|
|
|
310
364
|
it('calls onStrictModeViolation callback when strict mode is violated', async () => {
|
|
311
365
|
const onStrictModeViolation = vi.fn();
|
|
312
|
-
|
|
313
|
-
isDataAccessAllowed: vi.fn().mockReturnValue(false),
|
|
314
|
-
getDataAccessPermissions: vi.fn().mockReturnValue({}),
|
|
315
|
-
validateDataAccess: vi.fn().mockReturnValue(false),
|
|
316
|
-
// Add other required properties
|
|
317
|
-
} as any);
|
|
318
|
-
|
|
366
|
+
// useSecureDataAccess has been removed - SecureDataProvider handles this internally
|
|
319
367
|
const TestConsumer = () => {
|
|
320
368
|
const context = useSecureData();
|
|
321
369
|
context.isDataAccessAllowed('admin_users', 'delete', mockScope);
|
|
@@ -340,14 +388,7 @@ describe('SecureDataProvider', () => {
|
|
|
340
388
|
|
|
341
389
|
describe('Error Handling', () => {
|
|
342
390
|
it('handles data access validation errors gracefully', async () => {
|
|
343
|
-
|
|
344
|
-
isDataAccessAllowed: vi.fn().mockImplementation(() => {
|
|
345
|
-
throw new Error('Data access validation failed');
|
|
346
|
-
}),
|
|
347
|
-
getDataAccessPermissions: vi.fn().mockReturnValue({}),
|
|
348
|
-
validateDataAccess: vi.fn().mockReturnValue(false),
|
|
349
|
-
// Add other required properties
|
|
350
|
-
} as any);
|
|
391
|
+
// useSecureDataAccess has been removed - SecureDataProvider handles this internally
|
|
351
392
|
|
|
352
393
|
const TestConsumer = () => {
|
|
353
394
|
const context = useSecureData();
|
|
@@ -462,7 +503,7 @@ describe('SecureDataProvider', () => {
|
|
|
462
503
|
});
|
|
463
504
|
|
|
464
505
|
describe('Integration with useSecureDataAccess', () => {
|
|
465
|
-
it('integrates with
|
|
506
|
+
it('integrates with secure data access system', () => {
|
|
466
507
|
const TestConsumer = () => {
|
|
467
508
|
const context = useSecureData();
|
|
468
509
|
context.isDataAccessAllowed(mockTable, mockOperation, mockScope);
|
|
@@ -476,19 +517,12 @@ describe('SecureDataProvider', () => {
|
|
|
476
517
|
</SecureDataProvider>
|
|
477
518
|
);
|
|
478
519
|
|
|
479
|
-
|
|
520
|
+
// useSecureDataAccess has been removed - this test verifies the component works
|
|
521
|
+
// expect(mockUseSecureDataAccess).toHaveBeenCalled();
|
|
480
522
|
});
|
|
481
523
|
|
|
482
524
|
it('passes through secure data access functionality', () => {
|
|
483
|
-
|
|
484
|
-
isDataAccessAllowed: vi.fn().mockReturnValue(true),
|
|
485
|
-
getDataAccessPermissions: vi.fn().mockReturnValue({}),
|
|
486
|
-
validateDataAccess: vi.fn().mockReturnValue(true),
|
|
487
|
-
// Add other required properties
|
|
488
|
-
};
|
|
489
|
-
|
|
490
|
-
mockUseSecureDataAccess.mockReturnValue(mockSecureDataAccess as any);
|
|
491
|
-
|
|
525
|
+
// useSecureDataAccess has been removed - SecureDataProvider handles this internally
|
|
492
526
|
const TestConsumer = () => {
|
|
493
527
|
const context = useSecureData();
|
|
494
528
|
context.isDataAccessAllowed(mockTable, mockOperation, mockScope);
|
|
@@ -502,7 +536,8 @@ describe('SecureDataProvider', () => {
|
|
|
502
536
|
</SecureDataProvider>
|
|
503
537
|
);
|
|
504
538
|
|
|
505
|
-
|
|
539
|
+
// Component should render without errors
|
|
540
|
+
expect(screen.getByText('Test')).toBeInTheDocument();
|
|
506
541
|
});
|
|
507
542
|
});
|
|
508
543
|
});
|
|
@@ -50,15 +50,16 @@
|
|
|
50
50
|
* - Cached permission checks
|
|
51
51
|
*
|
|
52
52
|
* @dependencies
|
|
53
|
-
* - React
|
|
53
|
+
* - React 19+ - Context and hooks
|
|
54
54
|
* - useUnifiedAuth - Authentication context
|
|
55
|
-
* -
|
|
55
|
+
* - useSecureSupabase - Secure Supabase client hook
|
|
56
56
|
* - RBAC types - Type definitions
|
|
57
57
|
*/
|
|
58
58
|
|
|
59
59
|
import React, { createContext, useContext, useState, useCallback, useMemo, useEffect } from 'react';
|
|
60
60
|
import { useUnifiedAuth } from '../../providers/services/UnifiedAuthProvider';
|
|
61
|
-
import {
|
|
61
|
+
import { useSecureSupabase } from '../hooks/useSecureSupabase';
|
|
62
|
+
import { useOrganisationSecurity } from '../../hooks/useOrganisationSecurity';
|
|
62
63
|
import { useResolvedScope } from '../hooks/useResolvedScope';
|
|
63
64
|
import { UUID, Scope, Permission } from '../types';
|
|
64
65
|
import { getRBACLogger } from '../config';
|
|
@@ -144,7 +145,8 @@ export function SecureDataProvider({
|
|
|
144
145
|
enforceRLS = true
|
|
145
146
|
}: SecureDataProviderProps) {
|
|
146
147
|
const { user, selectedOrganisation, selectedEvent, supabase } = useUnifiedAuth();
|
|
147
|
-
const
|
|
148
|
+
const secureSupabase = useSecureSupabase(supabase);
|
|
149
|
+
const { superAdminContext } = useOrganisationSecurity();
|
|
148
150
|
const [dataAccessHistory, setDataAccessHistory] = useState<DataAccessRecord[]>([]);
|
|
149
151
|
const [isEnabled, setIsEnabled] = useState(true);
|
|
150
152
|
|
|
@@ -154,6 +156,19 @@ export function SecureDataProvider({
|
|
|
154
156
|
selectedOrganisationId: selectedOrganisation?.id || null,
|
|
155
157
|
selectedEventId: selectedEvent?.event_id || null
|
|
156
158
|
});
|
|
159
|
+
|
|
160
|
+
// Validate context - similar to useSecureDataAccess.validateContext
|
|
161
|
+
const validateContext = useCallback((): void => {
|
|
162
|
+
if (!secureSupabase) {
|
|
163
|
+
throw new Error('No Supabase client available');
|
|
164
|
+
}
|
|
165
|
+
if (!user) {
|
|
166
|
+
throw new Error('User must be authenticated');
|
|
167
|
+
}
|
|
168
|
+
if (!superAdminContext.isSuperAdmin && !resolvedScope?.organisationId) {
|
|
169
|
+
throw new Error('Organisation context is required for data access');
|
|
170
|
+
}
|
|
171
|
+
}, [secureSupabase, user, superAdminContext.isSuperAdmin, resolvedScope?.organisationId]);
|
|
157
172
|
|
|
158
173
|
// Get current scope from resolved scope
|
|
159
174
|
// For event-required apps: org is derived from event
|
|
@@ -174,10 +189,10 @@ export function SecureDataProvider({
|
|
|
174
189
|
|
|
175
190
|
// Use the existing RBAC system to check data access permissions
|
|
176
191
|
// This is a synchronous check for the context - actual permission checking
|
|
177
|
-
// happens
|
|
192
|
+
// happens using the RBAC engine via useSecureSupabase
|
|
178
193
|
const permission = `${operation}:data.${table}` as Permission;
|
|
179
194
|
|
|
180
|
-
// For now, we'll return true and let the
|
|
195
|
+
// For now, we'll return true and let the RBAC system
|
|
181
196
|
// handle the actual permission checking asynchronously
|
|
182
197
|
// This context is mainly for tracking and audit purposes
|
|
183
198
|
return true;
|