@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
|
@@ -91,7 +91,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
describe('PermissionGuard Component', () => {
|
|
94
|
-
const
|
|
94
|
+
const baseProps = {
|
|
95
95
|
userId: 'user-123' as UUID,
|
|
96
96
|
scope: { organisationId: 'org-123' as UUID },
|
|
97
97
|
permission: 'read:users' as Permission,
|
|
@@ -106,7 +106,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
106
106
|
error: null,
|
|
107
107
|
});
|
|
108
108
|
|
|
109
|
-
render(<PermissionGuard {...
|
|
109
|
+
render(<PermissionGuard {...baseProps} />);
|
|
110
110
|
|
|
111
111
|
expect(screen.getByText('Protected Content')).toBeInTheDocument();
|
|
112
112
|
});
|
|
@@ -119,7 +119,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
119
119
|
});
|
|
120
120
|
|
|
121
121
|
const fallback = <div>Access Denied</div>;
|
|
122
|
-
render(<PermissionGuard {...
|
|
122
|
+
render(<PermissionGuard {...baseProps} fallback={fallback} />);
|
|
123
123
|
|
|
124
124
|
expect(screen.getByText('Access Denied')).toBeInTheDocument();
|
|
125
125
|
expect(screen.queryByText('Protected Content')).not.toBeInTheDocument();
|
|
@@ -133,7 +133,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
133
133
|
});
|
|
134
134
|
|
|
135
135
|
const loading = <div>Checking permissions...</div>;
|
|
136
|
-
render(<PermissionGuard {...
|
|
136
|
+
render(<PermissionGuard {...baseProps} loading={loading} />);
|
|
137
137
|
|
|
138
138
|
expect(screen.getByText('Checking permissions...')).toBeInTheDocument();
|
|
139
139
|
expect(screen.queryByText('Protected Content')).not.toBeInTheDocument();
|
|
@@ -146,7 +146,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
146
146
|
error: null,
|
|
147
147
|
});
|
|
148
148
|
|
|
149
|
-
render(<PermissionGuard {...
|
|
149
|
+
render(<PermissionGuard {...baseProps} />);
|
|
150
150
|
|
|
151
151
|
expect(screen.getByRole('status')).toBeInTheDocument();
|
|
152
152
|
expect(screen.getByText('Checking permissions...')).toBeInTheDocument();
|
|
@@ -160,7 +160,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
160
160
|
});
|
|
161
161
|
|
|
162
162
|
const fallback = <div>Error occurred</div>;
|
|
163
|
-
render(<PermissionGuard {...
|
|
163
|
+
render(<PermissionGuard {...baseProps} fallback={fallback} />);
|
|
164
164
|
|
|
165
165
|
expect(screen.getByText('Error occurred')).toBeInTheDocument();
|
|
166
166
|
expect(screen.queryByText('Protected Content')).not.toBeInTheDocument();
|
|
@@ -180,7 +180,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
180
180
|
|
|
181
181
|
render(
|
|
182
182
|
<PermissionGuard
|
|
183
|
-
{...
|
|
183
|
+
{...baseProps}
|
|
184
184
|
userId={'' as any}
|
|
185
185
|
fallback={<div>No Access</div>}
|
|
186
186
|
/>
|
|
@@ -202,13 +202,13 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
202
202
|
|
|
203
203
|
render(
|
|
204
204
|
<PermissionGuard
|
|
205
|
-
{...
|
|
205
|
+
{...baseProps}
|
|
206
206
|
userId={'' as any}
|
|
207
207
|
fallback={<div>No Access</div>}
|
|
208
208
|
/>
|
|
209
209
|
);
|
|
210
210
|
|
|
211
|
-
expect(mockUseCan).toHaveBeenCalledWith('', expect.any(Object), expect.any(String), undefined);
|
|
211
|
+
expect(mockUseCan).toHaveBeenCalledWith('', expect.any(Object), expect.any(String), undefined, true, null, undefined);
|
|
212
212
|
});
|
|
213
213
|
});
|
|
214
214
|
|
|
@@ -221,7 +221,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
221
221
|
error: null,
|
|
222
222
|
});
|
|
223
223
|
|
|
224
|
-
render(<PermissionGuard {...
|
|
224
|
+
render(<PermissionGuard {...baseProps} onDenied={onDenied} />);
|
|
225
225
|
|
|
226
226
|
expect(onDenied).toHaveBeenCalledTimes(1);
|
|
227
227
|
});
|
|
@@ -234,7 +234,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
234
234
|
error: null,
|
|
235
235
|
});
|
|
236
236
|
|
|
237
|
-
render(<PermissionGuard {...
|
|
237
|
+
render(<PermissionGuard {...baseProps} onDenied={onDenied} />);
|
|
238
238
|
|
|
239
239
|
expect(onDenied).not.toHaveBeenCalled();
|
|
240
240
|
});
|
|
@@ -255,7 +255,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
255
255
|
error: null,
|
|
256
256
|
});
|
|
257
257
|
|
|
258
|
-
render(<PermissionGuard {...
|
|
258
|
+
render(<PermissionGuard {...baseProps} auditLog={true} />);
|
|
259
259
|
|
|
260
260
|
// Note: Audit logging is currently commented out in PermissionGuard
|
|
261
261
|
// The component checks auditLog but doesn't actually log - this is expected behavior
|
|
@@ -278,7 +278,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
278
278
|
error: null,
|
|
279
279
|
});
|
|
280
280
|
|
|
281
|
-
render(<PermissionGuard {...
|
|
281
|
+
render(<PermissionGuard {...baseProps} auditLog={true} />);
|
|
282
282
|
|
|
283
283
|
// Note: Audit logging is currently commented out in PermissionGuard
|
|
284
284
|
// The component checks auditLog but doesn't actually log - this is expected behavior
|
|
@@ -301,7 +301,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
301
301
|
error: null,
|
|
302
302
|
});
|
|
303
303
|
|
|
304
|
-
render(<PermissionGuard {...
|
|
304
|
+
render(<PermissionGuard {...baseProps} strictMode={true} />);
|
|
305
305
|
|
|
306
306
|
expect(mockLoggerInstance.error).toHaveBeenCalledWith(
|
|
307
307
|
expect.stringContaining('STRICT MODE VIOLATION:'),
|
|
@@ -316,7 +316,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
316
316
|
});
|
|
317
317
|
|
|
318
318
|
describe('AccessLevelGuard Component', () => {
|
|
319
|
-
const
|
|
319
|
+
const baseProps = {
|
|
320
320
|
userId: 'user-123' as UUID,
|
|
321
321
|
scope: { organisationId: 'org-123' as UUID },
|
|
322
322
|
minLevel: 'admin' as const,
|
|
@@ -331,7 +331,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
331
331
|
error: null,
|
|
332
332
|
});
|
|
333
333
|
|
|
334
|
-
render(<AccessLevelGuard {...
|
|
334
|
+
render(<AccessLevelGuard {...baseProps} />);
|
|
335
335
|
|
|
336
336
|
expect(screen.getByText('Admin Content')).toBeInTheDocument();
|
|
337
337
|
});
|
|
@@ -344,7 +344,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
344
344
|
});
|
|
345
345
|
|
|
346
346
|
const fallback = <div>Insufficient Access</div>;
|
|
347
|
-
render(<AccessLevelGuard {...
|
|
347
|
+
render(<AccessLevelGuard {...baseProps} fallback={fallback} />);
|
|
348
348
|
|
|
349
349
|
expect(screen.getByText('Insufficient Access')).toBeInTheDocument();
|
|
350
350
|
expect(screen.queryByText('Admin Content')).not.toBeInTheDocument();
|
|
@@ -358,7 +358,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
358
358
|
});
|
|
359
359
|
|
|
360
360
|
const loading = <div>Checking access level...</div>;
|
|
361
|
-
render(<AccessLevelGuard {...
|
|
361
|
+
render(<AccessLevelGuard {...baseProps} loading={loading} />);
|
|
362
362
|
|
|
363
363
|
expect(screen.getByText('Checking access level...')).toBeInTheDocument();
|
|
364
364
|
expect(screen.queryByText('Admin Content')).not.toBeInTheDocument();
|
|
@@ -372,7 +372,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
372
372
|
});
|
|
373
373
|
|
|
374
374
|
const fallback = <div>Error occurred</div>;
|
|
375
|
-
render(<AccessLevelGuard {...
|
|
375
|
+
render(<AccessLevelGuard {...baseProps} fallback={fallback} />);
|
|
376
376
|
|
|
377
377
|
expect(screen.getByText('Error occurred')).toBeInTheDocument();
|
|
378
378
|
expect(screen.queryByText('Admin Content')).not.toBeInTheDocument();
|
|
@@ -387,7 +387,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
387
387
|
error: null,
|
|
388
388
|
});
|
|
389
389
|
|
|
390
|
-
render(<AccessLevelGuard {...
|
|
390
|
+
render(<AccessLevelGuard {...baseProps} minLevel="admin" />);
|
|
391
391
|
|
|
392
392
|
expect(screen.getByText('Admin Content')).toBeInTheDocument();
|
|
393
393
|
});
|
|
@@ -399,7 +399,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
399
399
|
error: null,
|
|
400
400
|
});
|
|
401
401
|
|
|
402
|
-
render(<AccessLevelGuard {...
|
|
402
|
+
render(<AccessLevelGuard {...baseProps} minLevel="admin" />);
|
|
403
403
|
|
|
404
404
|
expect(screen.getByText('Admin Content')).toBeInTheDocument();
|
|
405
405
|
});
|
|
@@ -411,7 +411,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
411
411
|
error: null,
|
|
412
412
|
});
|
|
413
413
|
|
|
414
|
-
render(<AccessLevelGuard {...
|
|
414
|
+
render(<AccessLevelGuard {...baseProps} minLevel="admin" />);
|
|
415
415
|
|
|
416
416
|
expect(screen.queryByText('Admin Content')).not.toBeInTheDocument();
|
|
417
417
|
});
|
|
@@ -423,7 +423,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
423
423
|
error: null,
|
|
424
424
|
});
|
|
425
425
|
|
|
426
|
-
render(<AccessLevelGuard {...
|
|
426
|
+
render(<AccessLevelGuard {...baseProps} minLevel="planner" />);
|
|
427
427
|
|
|
428
428
|
expect(screen.getByText('Admin Content')).toBeInTheDocument();
|
|
429
429
|
});
|
|
@@ -439,7 +439,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
439
439
|
|
|
440
440
|
render(
|
|
441
441
|
<AccessLevelGuard
|
|
442
|
-
{...
|
|
442
|
+
{...baseProps}
|
|
443
443
|
userId={'' as any}
|
|
444
444
|
minLevel="admin"
|
|
445
445
|
fallback={<div>No Access</div>}
|
|
@@ -462,7 +462,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
462
462
|
|
|
463
463
|
render(
|
|
464
464
|
<AccessLevelGuard
|
|
465
|
-
{...
|
|
465
|
+
{...baseProps}
|
|
466
466
|
userId={'' as any}
|
|
467
467
|
minLevel="admin"
|
|
468
468
|
fallback={<div>No Access</div>}
|
|
@@ -499,7 +499,7 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
|
|
|
499
499
|
scope: { organisationId: 'org-123', eventId: 'event-123', appId: 'app-123' },
|
|
500
500
|
permission: 'read:users',
|
|
501
501
|
pageId: undefined,
|
|
502
|
-
});
|
|
502
|
+
}, null, undefined, null);
|
|
503
503
|
expect(handler).toHaveBeenCalledWith(req);
|
|
504
504
|
expect(result).toEqual({ success: true });
|
|
505
505
|
});
|
|
@@ -85,7 +85,7 @@ vi.mock('../hooks/useRBAC', () => ({
|
|
|
85
85
|
}));
|
|
86
86
|
import { useRBAC } from '../hooks/useRBAC';
|
|
87
87
|
import { useOrganisationSecurity } from '../../hooks/useOrganisationSecurity';
|
|
88
|
-
|
|
88
|
+
// useSecureDataAccess has been removed - use useSecureSupabase from @jmruthers/pace-core/rbac instead
|
|
89
89
|
import { usePermissions } from '../hooks';
|
|
90
90
|
import { useCan, useAccessLevel, useHasAnyPermission, useHasAllPermissions } from '../hooks';
|
|
91
91
|
import { useCachedPermissions } from '../hooks';
|
|
@@ -104,9 +104,7 @@ vi.mock('../hooks', () => ({
|
|
|
104
104
|
useHasAllPermissions: () => ({ hasAllPermissions: () => true, isLoading: false, error: null }),
|
|
105
105
|
useCachedPermissions: () => ({ cachedPermissions: [], isLoading: false, error: null }),
|
|
106
106
|
}));
|
|
107
|
-
|
|
108
|
-
useSecureDataAccess: () => ({ secureDataAccess: { secureQuery: vi.fn().mockResolvedValue([]) } })
|
|
109
|
-
}));
|
|
107
|
+
// useSecureDataAccess has been removed - no longer needed
|
|
110
108
|
vi.mock('../../hooks/usePermissionCache', () => ({
|
|
111
109
|
usePermissionCache: () => ({
|
|
112
110
|
permissionCache: new Map([
|
|
@@ -197,7 +195,8 @@ const TestComponent = () => {
|
|
|
197
195
|
const { cachedPermissions } = useCachedPermissions();
|
|
198
196
|
const { permissionCache } = usePermissionCache();
|
|
199
197
|
const { organisationPermissions } = useOrganisationPermissions();
|
|
200
|
-
|
|
198
|
+
// useSecureDataAccess has been removed - use useSecureSupabase from @jmruthers/pace-core/rbac instead
|
|
199
|
+
const secureData = { secureQuery: vi.fn().mockResolvedValue([]) };
|
|
201
200
|
|
|
202
201
|
if (isLoading) return <div>Loading...</div>;
|
|
203
202
|
if (!isAuthenticated) return <div>Not authenticated</div>;
|
package/src/rbac/adapters.tsx
CHANGED
|
@@ -90,7 +90,16 @@ export function PermissionGuard({
|
|
|
90
90
|
const effectiveUserId = userId ?? authContext?.user?.id ?? null;
|
|
91
91
|
|
|
92
92
|
// Always call useCan hook, but handle the case where userId might be undefined
|
|
93
|
-
|
|
93
|
+
// Pass null for super admin status (not checked yet - hook will check if needed)
|
|
94
|
+
const { can, isLoading, error } = useCan(
|
|
95
|
+
effectiveUserId || '',
|
|
96
|
+
scope,
|
|
97
|
+
permission,
|
|
98
|
+
pageId,
|
|
99
|
+
true, // useCache
|
|
100
|
+
null, // precomputedSuperAdmin - not checked yet
|
|
101
|
+
undefined // appName
|
|
102
|
+
);
|
|
94
103
|
|
|
95
104
|
// If still no userId, show helpful error
|
|
96
105
|
if (!effectiveUserId) {
|
|
@@ -294,7 +303,7 @@ export function withPermissionGuard<T extends any[]>(
|
|
|
294
303
|
scope: { organisationId, eventId, appId },
|
|
295
304
|
permission: config.permission,
|
|
296
305
|
pageId: config.pageId,
|
|
297
|
-
});
|
|
306
|
+
}, null, undefined, null);
|
|
298
307
|
|
|
299
308
|
if (!hasPermission) {
|
|
300
309
|
throw new Error(`Permission denied: ${config.permission}`);
|
|
@@ -516,7 +525,7 @@ export function createRBACMiddleware(config: {
|
|
|
516
525
|
pageId?: UUID;
|
|
517
526
|
}>;
|
|
518
527
|
fallbackUrl?: string;
|
|
519
|
-
}) {
|
|
528
|
+
}): (req: { nextUrl: { pathname: string }; user?: { id: string }; organisationId?: string }, res: { redirect: (url: string) => void }, next: () => void) => Promise<void> {
|
|
520
529
|
return async (req: { nextUrl: { pathname: string }; user?: { id: string }; organisationId?: string }, res: { redirect: (url: string) => void }, next: () => void) => {
|
|
521
530
|
const { pathname } = req.nextUrl;
|
|
522
531
|
const userId = req.user?.id;
|
|
@@ -539,7 +548,7 @@ export function createRBACMiddleware(config: {
|
|
|
539
548
|
scope: { organisationId },
|
|
540
549
|
permission: protectedRoute.permission,
|
|
541
550
|
pageId: protectedRoute.pageId,
|
|
542
|
-
});
|
|
551
|
+
}, null, undefined, null);
|
|
543
552
|
|
|
544
553
|
if (!hasPermission) {
|
|
545
554
|
return res.redirect(config.fallbackUrl || '/access-denied');
|
|
@@ -579,7 +588,7 @@ export function createRBACMiddleware(config: {
|
|
|
579
588
|
export function createRBACExpressMiddleware(config: {
|
|
580
589
|
permission: Permission;
|
|
581
590
|
pageId?: UUID;
|
|
582
|
-
}) {
|
|
591
|
+
}): (req: { user?: { id: string }; organisationId?: string; eventId?: string; appId?: string }, res: { status: (code: number) => { json: (data: object) => void } }, next: () => void) => Promise<void> {
|
|
583
592
|
return async (req: { user?: { id: string }; organisationId?: string; eventId?: string; appId?: string }, res: { status: (code: number) => { json: (data: object) => void } }, next: () => void) => {
|
|
584
593
|
const userId = req.user?.id;
|
|
585
594
|
const organisationId = req.organisationId;
|
package/src/rbac/api.ts
CHANGED
|
@@ -129,39 +129,44 @@ export async function getAccessLevel(
|
|
|
129
129
|
appConfig?: AppConfig | null,
|
|
130
130
|
appName?: string
|
|
131
131
|
): Promise<AccessLevel> {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
resolvedAppConfig
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
132
|
+
try {
|
|
133
|
+
const engine = getEngine();
|
|
134
|
+
|
|
135
|
+
// Check super admin status first - super admins bypass context requirements
|
|
136
|
+
const isSuperAdminUser = await engine['checkSuperAdmin'](input.userId);
|
|
137
|
+
if (isSuperAdminUser) {
|
|
138
|
+
return 'super';
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Fetch app config if not provided
|
|
142
|
+
let resolvedAppConfig: AppConfig | null = appConfig ?? null;
|
|
143
|
+
let resolvedAppName = appName;
|
|
144
|
+
|
|
145
|
+
if (!resolvedAppConfig && input.scope.appId) {
|
|
146
|
+
resolvedAppConfig = await getAppConfig(input.scope.appId);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Validate context using ContextValidator
|
|
150
|
+
const validation = await ContextValidator.resolveRequiredContext(
|
|
151
|
+
input.scope,
|
|
152
|
+
resolvedAppConfig,
|
|
153
|
+
resolvedAppName,
|
|
154
|
+
engine['supabase']
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
if (!validation.isValid || !validation.resolvedScope) {
|
|
158
|
+
throw validation.error || new OrganisationContextRequiredError();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Use resolved scope
|
|
162
|
+
return engine.getAccessLevel({
|
|
163
|
+
...input,
|
|
164
|
+
scope: validation.resolvedScope
|
|
165
|
+
});
|
|
166
|
+
} catch (error) {
|
|
167
|
+
// Re-throw the error - this is an API function that should propagate errors
|
|
168
|
+
throw error;
|
|
158
169
|
}
|
|
159
|
-
|
|
160
|
-
// Use resolved scope
|
|
161
|
-
return engine.getAccessLevel({
|
|
162
|
-
...input,
|
|
163
|
-
scope: validation.resolvedScope
|
|
164
|
-
});
|
|
165
170
|
}
|
|
166
171
|
|
|
167
172
|
/**
|
|
@@ -192,41 +197,51 @@ export async function getPermissionMap(
|
|
|
192
197
|
appConfig?: AppConfig | null,
|
|
193
198
|
appName?: string
|
|
194
199
|
): Promise<PermissionMap> {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
resolvedAppConfig
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
200
|
+
try {
|
|
201
|
+
const engine = getEngine();
|
|
202
|
+
|
|
203
|
+
// Fetch app config if not provided
|
|
204
|
+
let resolvedAppConfig: AppConfig | null = appConfig ?? null;
|
|
205
|
+
let resolvedAppName = appName;
|
|
206
|
+
|
|
207
|
+
if (!resolvedAppConfig && input.scope.appId) {
|
|
208
|
+
resolvedAppConfig = await getAppConfig(input.scope.appId);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Validate context using ContextValidator
|
|
212
|
+
const validation = await ContextValidator.resolveRequiredContext(
|
|
213
|
+
input.scope,
|
|
214
|
+
resolvedAppConfig,
|
|
215
|
+
resolvedAppName,
|
|
216
|
+
engine['supabase']
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
if (!validation.isValid || !validation.resolvedScope) {
|
|
220
|
+
throw validation.error || new OrganisationContextRequiredError();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Use resolved scope
|
|
224
|
+
return engine.getPermissionMap({
|
|
225
|
+
...input,
|
|
226
|
+
scope: validation.resolvedScope
|
|
227
|
+
});
|
|
228
|
+
} catch (error) {
|
|
229
|
+
// Re-throw the error - this is an API function that should propagate errors
|
|
230
|
+
throw error;
|
|
215
231
|
}
|
|
216
|
-
|
|
217
|
-
// Use resolved scope
|
|
218
|
-
return engine.getPermissionMap({
|
|
219
|
-
...input,
|
|
220
|
-
scope: validation.resolvedScope
|
|
221
|
-
});
|
|
222
232
|
}
|
|
223
233
|
|
|
224
234
|
export async function resolveAppContext(input: {
|
|
225
235
|
userId: UUID;
|
|
226
236
|
appName: string;
|
|
227
237
|
}): Promise<RBACAppContext | null> {
|
|
228
|
-
|
|
229
|
-
|
|
238
|
+
try {
|
|
239
|
+
const engine = getEngine();
|
|
240
|
+
return await engine.resolveAppContext(input);
|
|
241
|
+
} catch (error) {
|
|
242
|
+
// Re-throw the error - this is an API function that should propagate errors
|
|
243
|
+
throw error;
|
|
244
|
+
}
|
|
230
245
|
}
|
|
231
246
|
|
|
232
247
|
export async function getRoleContext(
|
|
@@ -287,17 +302,33 @@ export async function getRoleContext(
|
|
|
287
302
|
export async function isPermitted(
|
|
288
303
|
input: PermissionCheck,
|
|
289
304
|
appConfig?: AppConfig | null,
|
|
290
|
-
appName?: string
|
|
305
|
+
appName?: string,
|
|
306
|
+
/**
|
|
307
|
+
* Pre-computed super admin status to avoid duplicate checks.
|
|
308
|
+
* Pass null if not checked yet (will check), true if already checked and is super admin,
|
|
309
|
+
* or false if already checked and is not super admin.
|
|
310
|
+
* @default null
|
|
311
|
+
*/
|
|
312
|
+
precomputedSuperAdmin: boolean | null = null
|
|
291
313
|
): Promise<boolean> {
|
|
292
314
|
const engine = getEngine();
|
|
293
315
|
|
|
294
316
|
// Check super admin status first - super admins bypass context requirements
|
|
295
317
|
// Super admins have access to all permissions regardless of organisation context
|
|
296
|
-
|
|
297
|
-
if (
|
|
318
|
+
// PERFORMANCE: Use precomputed value if provided to avoid duplicate checks
|
|
319
|
+
if (precomputedSuperAdmin === true) {
|
|
298
320
|
return true;
|
|
299
321
|
}
|
|
300
322
|
|
|
323
|
+
// If null, check super admin status
|
|
324
|
+
if (precomputedSuperAdmin === null) {
|
|
325
|
+
const isSuperAdminUser = await engine['checkSuperAdmin'](input.userId);
|
|
326
|
+
if (isSuperAdminUser) {
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
// If precomputedSuperAdmin === false, skip check and proceed with permission check
|
|
331
|
+
|
|
301
332
|
// Fetch app config if not provided and we have appId
|
|
302
333
|
let resolvedAppConfig: AppConfig | null = appConfig ?? null;
|
|
303
334
|
let resolvedAppName = appName;
|
|
@@ -391,7 +422,9 @@ export async function isPermittedCached(
|
|
|
391
422
|
// Use request deduplication - if same request is in-flight, share the promise
|
|
392
423
|
return getOrCreateRequest(input, async (checkInput) => {
|
|
393
424
|
// Check permission with context validation
|
|
394
|
-
|
|
425
|
+
// Note: We can't pass precomputedSuperAdmin here because getOrCreateRequest doesn't support it
|
|
426
|
+
// The super admin check in isPermitted will be cached, so it's not a huge performance hit
|
|
427
|
+
const result = await isPermitted(checkInput, appConfig, appName, null);
|
|
395
428
|
|
|
396
429
|
// Determine if this is a page-level check (has pageId or permission contains 'page.')
|
|
397
430
|
const isPageLevelCheck = !!pageId || permission.includes('page.');
|
|
@@ -410,7 +443,7 @@ export async function isPermittedCached(
|
|
|
410
443
|
* @returns Promise<boolean> - True if user has permission
|
|
411
444
|
*/
|
|
412
445
|
export async function hasPermission(input: PermissionCheck): Promise<boolean> {
|
|
413
|
-
return isPermitted(input);
|
|
446
|
+
return isPermitted(input, null, undefined, null);
|
|
414
447
|
}
|
|
415
448
|
|
|
416
449
|
/**
|
|
@@ -431,7 +464,7 @@ export async function hasAnyPermission(input: {
|
|
|
431
464
|
const hasPermission = await isPermitted({
|
|
432
465
|
...baseInput,
|
|
433
466
|
permission,
|
|
434
|
-
});
|
|
467
|
+
}, null, undefined, null);
|
|
435
468
|
|
|
436
469
|
if (hasPermission) {
|
|
437
470
|
return true;
|
|
@@ -459,7 +492,7 @@ export async function hasAllPermissions(input: {
|
|
|
459
492
|
const hasPermission = await isPermitted({
|
|
460
493
|
...baseInput,
|
|
461
494
|
permission,
|
|
462
|
-
});
|
|
495
|
+
}, null, undefined, null);
|
|
463
496
|
|
|
464
497
|
if (!hasPermission) {
|
|
465
498
|
return false;
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
* - Efficient filtering
|
|
50
50
|
*
|
|
51
51
|
* @dependencies
|
|
52
|
-
* - React
|
|
52
|
+
* - React 19+ - Component framework
|
|
53
53
|
* - NavigationProvider - Navigation permission context
|
|
54
54
|
* - NavigationGuard - Individual navigation item protection
|
|
55
55
|
* - RBAC types - Type definitions
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
* - Cached permission checks
|
|
50
50
|
*
|
|
51
51
|
* @dependencies
|
|
52
|
-
* - React
|
|
52
|
+
* - React 19+ - Context and hooks
|
|
53
53
|
* - useUnifiedAuth - Authentication context
|
|
54
54
|
* - RBAC types - Type definitions
|
|
55
55
|
*/
|
|
@@ -211,12 +211,15 @@ export function NavigationProvider({
|
|
|
211
211
|
const permission = item.permissions[0];
|
|
212
212
|
|
|
213
213
|
// Call useCan hook for actual permission checking
|
|
214
|
+
// Pass null for super admin status (not checked yet - hook will check if needed)
|
|
214
215
|
const { can, error } = useCan(
|
|
215
216
|
user.id,
|
|
216
217
|
currentScope,
|
|
217
218
|
permission,
|
|
218
219
|
item.pageId,
|
|
219
|
-
true // useCache
|
|
220
|
+
true, // useCache
|
|
221
|
+
null, // precomputedSuperAdmin - not checked yet
|
|
222
|
+
undefined // appName
|
|
220
223
|
);
|
|
221
224
|
|
|
222
225
|
// Handle errors gracefully - allow access when there are permission check errors (graceful degradation)
|