@jmruthers/pace-core 0.5.180 → 0.5.182
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 +1 -1
- package/README.md +16 -2
- package/dist/{AuthService-DYuQPJj6.d.ts → AuthService-B-cd2MA4.d.ts} +9 -11
- package/dist/{DataTable-CWAZZcXC.d.ts → DataTable-Bz8ffqyA.d.ts} +1 -1
- package/dist/{DataTable-4VSEJQ7D.js → DataTable-QAB34V6K.js} +14 -15
- package/dist/UnifiedAuthProvider-7F6T4B6K.js +13 -0
- package/dist/{UnifiedAuthProvider-DJxGTftH.d.ts → UnifiedAuthProvider-F86d7dSi.d.ts} +5 -6
- package/dist/{api-45XYYO2A.js → api-ROMBCNKU.js} +5 -5
- package/dist/{audit-64X3VJXB.js → audit-WRS3KJKI.js} +4 -4
- package/dist/auth-BZOJqrdd.d.ts +49 -0
- package/dist/{chunk-CX5M4ZAG.js → chunk-5DRSZLL2.js} +1 -1
- package/dist/chunk-5DRSZLL2.js.map +1 -0
- package/dist/{chunk-BESYRHQM.js → chunk-6C4YBBJM.js} +10 -7
- package/dist/chunk-6C4YBBJM.js.map +1 -0
- package/dist/{chunk-PLDDJCW6.js → chunk-7D4SUZUM.js} +2 -13
- package/dist/{chunk-6HLVGAZG.js → chunk-CSOFYHAG.js} +55 -162
- package/dist/chunk-CSOFYHAG.js.map +1 -0
- package/dist/{chunk-ANBQRTPX.js → chunk-E66EQZE6.js} +3 -5
- package/dist/{chunk-ANBQRTPX.js.map → chunk-E66EQZE6.js.map} +1 -1
- package/dist/{chunk-Q5QRDWKI.js → chunk-F2IMUDXZ.js} +4 -6
- package/dist/chunk-F2IMUDXZ.js.map +1 -0
- package/dist/{chunk-SBVILCCA.js → chunk-FSFQFJCU.js} +28 -6
- package/dist/chunk-FSFQFJCU.js.map +1 -0
- package/dist/chunk-FUEYYMX5.js +2296 -0
- package/dist/chunk-FUEYYMX5.js.map +1 -0
- package/dist/{chunk-FFKNH6U5.js → chunk-HKIT6O7W.js} +3 -5
- package/dist/{chunk-FFKNH6U5.js.map → chunk-HKIT6O7W.js.map} +1 -1
- package/dist/chunk-KQCRWDSA.js +1 -0
- package/dist/{chunk-S5OFRT4M.js → chunk-KUEN3HFB.js} +6 -6
- package/dist/chunk-KUEN3HFB.js.map +1 -0
- package/dist/chunk-LMC26NLJ.js +84 -0
- package/dist/chunk-LMC26NLJ.js.map +1 -0
- package/dist/{chunk-BVYWGZVV.js → chunk-M7W4CP3M.js} +52 -19
- package/dist/chunk-M7W4CP3M.js.map +1 -0
- package/dist/{chunk-CPTUD43C.js → chunk-MI7HBHN3.js} +164 -243
- package/dist/chunk-MI7HBHN3.js.map +1 -0
- package/dist/{chunk-N5YCCUG5.js → chunk-PWAHJW4G.js} +180 -29
- package/dist/chunk-PWAHJW4G.js.map +1 -0
- package/dist/chunk-PWLANIRT.js +127 -0
- package/dist/{chunk-XDNLUEXI.js.map → chunk-PWLANIRT.js.map} +1 -1
- package/dist/chunk-QCDXODCA.js +75 -0
- package/dist/chunk-QCDXODCA.js.map +1 -0
- package/dist/{chunk-P6UUHOIF.js → chunk-QETLRQI6.js} +526 -887
- package/dist/chunk-QETLRQI6.js.map +1 -0
- package/dist/{chunk-GQA2LIAE.js → chunk-QUVSNGIP.js} +264 -262
- package/dist/chunk-QUVSNGIP.js.map +1 -0
- package/dist/chunk-QXHPKYJV.js +113 -0
- package/dist/chunk-QXHPKYJV.js.map +1 -0
- package/dist/{chunk-OWAG3GSU.js → chunk-R77UEZ4E.js} +11 -1
- package/dist/chunk-R77UEZ4E.js.map +1 -0
- package/dist/{chunk-ONI7Y733.js → chunk-RA3JUFMW.js} +314 -161
- package/dist/chunk-RA3JUFMW.js.map +1 -0
- package/dist/{chunk-ERISIBYU.js → chunk-SQGMNID3.js} +3 -8
- package/dist/chunk-SQGMNID3.js.map +1 -0
- package/dist/{chunk-XJ2HZOBU.js → chunk-UHNYIBXL.js} +1 -1
- package/dist/chunk-UHNYIBXL.js.map +1 -0
- package/{src/utils/secureStorage.ts → dist/chunk-VBXEHIUJ.js} +113 -88
- package/dist/{chunk-7QCC6MCP.js.map → chunk-VBXEHIUJ.js.map} +1 -1
- package/dist/{chunk-R53TUSFK.js → chunk-W22JP75J.js} +5 -13
- package/dist/{chunk-R53TUSFK.js.map → chunk-W22JP75J.js.map} +1 -1
- package/dist/components.d.ts +12 -93
- package/dist/components.js +23 -106
- package/dist/components.js.map +1 -1
- package/dist/core-CUElvH_C.d.ts +164 -0
- package/dist/database.generated-CBmg2950.d.ts +8284 -0
- package/dist/event-CW5YB_2p.d.ts +239 -0
- package/dist/{file-reference-C6Gkn77H.d.ts → file-reference-D06mEEWW.d.ts} +7 -5
- package/dist/functions-D_kgHktt.d.ts +208 -0
- package/dist/hooks.d.ts +54 -7
- package/dist/hooks.js +204 -17
- package/dist/hooks.js.map +1 -1
- package/dist/{EventLogo-B3V3otev.d.ts → index-Bl--n7-T.d.ts} +387 -397
- package/dist/index.d.ts +94 -261
- package/dist/index.js +314 -126
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +7 -8
- package/dist/providers.js +6 -13
- package/dist/rbac/index.d.ts +171 -101
- package/dist/rbac/index.js +23 -17
- package/dist/styles/index.d.ts +1 -3
- package/dist/styles/index.js +2 -17
- package/dist/theming/runtime.js +3 -3
- package/dist/types-UU913iLA.d.ts +102 -0
- package/dist/{types-Dfz9dmVH.d.ts → types-_x1f4QBF.d.ts} +6 -6
- package/dist/types.d.ts +88 -227
- package/dist/types.js +64 -112
- package/dist/types.js.map +1 -1
- package/dist/{usePublicRouteParams-B7PabvuH.d.ts → usePublicRouteParams-JJczomYq.d.ts} +203 -6
- package/dist/utils.d.ts +299 -13
- package/dist/utils.js +481 -55
- package/dist/utils.js.map +1 -1
- package/dist/validation-643vUDZW.d.ts +177 -0
- package/docs/DOCUMENTATION_REVIEW_TRACKER.md +511 -0
- package/docs/README.md +9 -8
- package/docs/api/README.md +16 -2
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +4 -4
- 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 +14 -14
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +2 -2
- package/docs/api/classes/RBACError.md +4 -4
- package/docs/api/classes/RBACNotInitializedError.md +4 -4
- package/docs/api/classes/SecureSupabaseClient.md +29 -9
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +17 -17
- package/docs/api/enums/RBACErrorCode.md +228 -0
- package/docs/api/enums/RPCFunction.md +118 -0
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +2 -2
- package/docs/api/interfaces/CalendarProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +29 -3
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +2 -2
- package/docs/api/interfaces/DataTableColumn.md +6 -6
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +2 -2
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/ExportColumn.md +5 -5
- package/docs/api/interfaces/ExportOptions.md +4 -4
- package/docs/api/interfaces/FileDisplayProps.md +1 -1
- package/docs/api/interfaces/FileMetadata.md +13 -13
- package/docs/api/interfaces/FileReference.md +12 -12
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +10 -10
- package/docs/api/interfaces/FileUploadProps.md +19 -19
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/FormFieldProps.md +166 -0
- package/docs/api/interfaces/FormProps.md +113 -0
- package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +8 -8
- package/docs/api/interfaces/InputProps.md +2 -2
- package/docs/api/interfaces/LabelProps.md +8 -8
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +17 -73
- package/docs/api/interfaces/NavigationMenuProps.md +38 -53
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +13 -13
- package/docs/api/interfaces/OrganisationContextType.md +21 -21
- package/docs/api/interfaces/OrganisationMembership.md +15 -15
- package/docs/api/interfaces/OrganisationProviderProps.md +59 -2
- package/docs/api/interfaces/OrganisationSecurityError.md +5 -5
- package/docs/api/interfaces/PaceAppLayoutProps.md +26 -39
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProgressProps.md +50 -0
- package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +9 -9
- package/docs/api/interfaces/PublicPageHeaderProps.md +10 -10
- package/docs/api/interfaces/PublicPageLayoutProps.md +15 -15
- package/docs/api/interfaces/RBACAccessValidateParams.md +52 -0
- package/docs/api/interfaces/RBACAccessValidateResult.md +41 -0
- package/docs/api/interfaces/RBACAuditLogParams.md +85 -0
- package/docs/api/interfaces/RBACAuditLogResult.md +52 -0
- package/docs/api/interfaces/RBACConfig.md +2 -2
- package/docs/api/interfaces/RBACContext.md +52 -0
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +74 -0
- package/docs/api/interfaces/RBACPermissionCheckParams.md +74 -0
- package/docs/api/interfaces/RBACPermissionCheckResult.md +52 -0
- package/docs/api/interfaces/RBACPermissionsGetParams.md +63 -0
- package/docs/api/interfaces/RBACPermissionsGetResult.md +63 -0
- package/docs/api/interfaces/RBACResult.md +58 -0
- package/docs/api/interfaces/RBACRoleGrantParams.md +63 -0
- package/docs/api/interfaces/RBACRoleGrantResult.md +52 -0
- package/docs/api/interfaces/RBACRoleRevokeParams.md +63 -0
- package/docs/api/interfaces/RBACRoleRevokeResult.md +52 -0
- package/docs/api/interfaces/RBACRoleValidateParams.md +52 -0
- package/docs/api/interfaces/RBACRoleValidateResult.md +63 -0
- package/docs/api/interfaces/RBACRolesListParams.md +52 -0
- package/docs/api/interfaces/RBACRolesListResult.md +74 -0
- package/docs/api/interfaces/RBACSessionTrackParams.md +74 -0
- package/docs/api/interfaces/RBACSessionTrackResult.md +52 -0
- 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/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +15 -2
- 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 +43 -2
- package/docs/api/interfaces/TextareaProps.md +2 -2
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +61 -61
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +87 -0
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +81 -0
- package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
- package/docs/api/interfaces/UsePublicEventReturn.md +5 -5
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +2 -2
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +2 -2
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +4 -4
- package/docs/api/interfaces/UserProfile.md +7 -7
- package/docs/api/modules.md +484 -462
- package/docs/api-reference/components.md +186 -15
- package/docs/api-reference/deprecated.md +376 -0
- package/docs/api-reference/hooks.md +149 -19
- package/docs/api-reference/providers.md +61 -6
- package/docs/api-reference/rpc-functions.md +397 -0
- package/docs/api-reference/types.md +135 -78
- package/docs/api-reference/utilities.md +51 -380
- package/docs/architecture/README.md +49 -3
- package/docs/architecture/database-schema-requirements.md +40 -3
- package/docs/architecture/rbac-security-architecture.md +41 -4
- package/docs/architecture/services.md +127 -42
- package/docs/best-practices/README.md +51 -5
- package/docs/best-practices/accessibility.md +32 -3
- package/docs/best-practices/common-patterns.md +50 -3
- package/docs/best-practices/deployment.md +50 -4
- package/docs/best-practices/performance.md +50 -3
- package/docs/best-practices/security.md +94 -41
- package/docs/best-practices/testing.md +33 -4
- package/docs/core-concepts/authentication.md +5 -5
- package/docs/core-concepts/events.md +3 -3
- package/docs/core-concepts/organisations.md +3 -3
- package/docs/core-concepts/permissions.md +3 -3
- package/docs/core-concepts/rbac-system.md +5 -5
- package/docs/documentation-index.md +30 -8
- package/docs/getting-started/documentation-index.md +1 -1
- package/docs/getting-started/examples/README.md +7 -5
- package/docs/getting-started/examples/basic-auth-app.md +3 -0
- package/docs/getting-started/examples/full-featured-app.md +5 -3
- package/docs/getting-started/faq.md +6 -6
- package/docs/getting-started/installation-guide.md +192 -13
- package/docs/getting-started/local-development.md +303 -0
- package/docs/getting-started/quick-reference.md +3 -3
- package/docs/getting-started/quick-start.md +517 -0
- package/docs/implementation-guides/app-layout.md +45 -3
- package/docs/implementation-guides/authentication.md +66 -7
- package/docs/implementation-guides/component-styling.md +53 -3
- package/docs/implementation-guides/data-tables.md +76 -7
- package/docs/implementation-guides/datatable-filtering.md +1 -2
- package/docs/implementation-guides/datatable-rbac-usage.md +0 -1
- package/docs/implementation-guides/dynamic-colors.md +155 -4
- package/docs/implementation-guides/file-reference-system.md +72 -3
- package/docs/implementation-guides/file-upload-storage.md +72 -3
- package/docs/implementation-guides/forms.md +53 -3
- package/docs/implementation-guides/inactivity-tracking.md +53 -3
- package/docs/implementation-guides/large-datasets.md +1 -1
- package/docs/implementation-guides/navigation.md +55 -5
- package/docs/implementation-guides/organisation-security.md +72 -3
- package/docs/implementation-guides/performance.md +57 -1
- package/docs/implementation-guides/permission-enforcement.md +81 -8
- package/docs/implementation-guides/public-pages.md +560 -14
- package/docs/migration/MIGRATION_GUIDE.md +409 -50
- package/docs/migration/README.md +37 -3
- package/docs/migration/organisation-context-timing-fix.md +39 -4
- package/docs/migration/quick-migration-guide.md +41 -5
- package/docs/migration/rbac-migration.md +59 -3
- package/docs/migration/service-architecture.md +77 -14
- package/docs/rbac/README.md +79 -3
- package/docs/rbac/advanced-patterns.md +47 -3
- package/docs/rbac/api-reference.md +77 -8
- package/docs/rbac/event-based-apps.md +50 -5
- package/docs/rbac/examples/rbac-rls-integration-example.md +3 -3
- package/docs/rbac/examples.md +39 -3
- package/docs/rbac/getting-started.md +63 -4
- package/docs/rbac/quick-start.md +57 -5
- package/docs/rbac/rbac-rls-integration.md +68 -6
- package/docs/rbac/super-admin-guide.md +47 -3
- package/docs/rbac/troubleshooting.md +3 -3
- package/docs/security/README.md +68 -3
- package/docs/security/checklist.md +50 -3
- package/docs/standards/01-architecture-standard.md +39 -0
- package/docs/standards/02-api-and-rpc-standard.md +39 -0
- package/docs/standards/03-component-standard.md +32 -0
- package/docs/standards/04-code-style-standard.md +32 -0
- package/docs/standards/05-security-standard.md +30 -0
- package/docs/standards/06-testing-and-docs-standard.md +29 -0
- package/docs/standards/README.md +35 -0
- package/docs/styles/README.md +89 -8
- package/docs/testing/README.md +175 -24
- package/docs/troubleshooting/README.md +50 -3
- package/docs/troubleshooting/common-issues.md +271 -5
- package/docs/troubleshooting/debugging.md +54 -1
- package/docs/troubleshooting/migration.md +54 -1
- package/docs/troubleshooting/organisation-context-setup.md +29 -3
- package/docs/troubleshooting/styling-issues.md +246 -4
- package/{src/components/DataTable/examples → examples/DataTable}/GroupingAggregationExample.tsx +1 -1
- package/examples/{components 2/DataTable/HierarchicalActionsExample.tsx → DataTable/HierarchicalActionsExample.tsx} +7 -6
- package/examples/{components 2/DataTable/HierarchicalExample.tsx → DataTable/HierarchicalExample.tsx} +8 -6
- package/examples/{components 2/DataTable/PerformanceExample.tsx → DataTable/PerformanceExample.tsx} +2 -2
- package/examples/{components 2/DataTable/index.ts → DataTable/index.ts} +1 -0
- package/{src/components/Dialog/examples → examples/Dialog}/HtmlDialogExample.tsx +3 -3
- package/examples/{components 2/Dialog/ScrollableDialogExample.tsx → Dialog/ScrollableDialogExample.tsx} +1 -1
- package/{src/components/Dialog/examples → examples/Dialog}/SmartDialogExample.tsx +1 -1
- package/examples/{components 2/Dialog/index.ts → Dialog/index.ts} +0 -3
- package/examples/{features/public-pages → PublicPages}/CorrectPublicPageImplementation.tsx +52 -17
- package/examples/{features/public-pages → PublicPages}/PublicEventPage.tsx +65 -35
- package/examples/{features/public-pages → PublicPages}/PublicPageApp.tsx +52 -18
- package/examples/{features/public-pages → PublicPages}/PublicPageUsageExample.tsx +28 -15
- package/examples/README.md +81 -33
- package/examples/index.ts +14 -12
- package/examples/{RBAC → rbac}/CompleteRBACExample.tsx +1 -1
- package/examples/{features/rbac → rbac}/EventBasedApp.tsx +4 -4
- package/examples/{features/rbac → rbac}/PermissionExample.tsx +5 -3
- package/package.json +21 -27
- package/src/__tests__/helpers/test-utils.tsx +29 -3
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +7 -5
- package/src/components/Alert/Alert.test.tsx +2 -2
- package/src/components/Alert/Alert.tsx +4 -4
- package/src/components/Avatar/Avatar.test.tsx +17 -6
- package/src/components/Badge/Badge.test.tsx +1 -1
- package/src/components/Badge/Badge.tsx +2 -2
- package/src/components/Button/Button.test.tsx +2 -2
- package/src/components/Button/Button.tsx +11 -7
- package/src/components/Calendar/Calendar.test.tsx +41 -8
- package/src/components/Calendar/Calendar.tsx +39 -36
- package/src/components/Card/Card.tsx +51 -13
- package/src/components/Checkbox/Checkbox.test.tsx +36 -12
- package/src/components/DataTable/DataTable.test.tsx +1 -1
- package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +13 -7
- package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +14 -42
- package/src/components/DataTable/__tests__/DataTable.export.test.tsx +13 -10
- package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +14 -11
- package/src/components/DataTable/__tests__/DataTable.hooks.test.tsx +4 -2
- package/src/components/DataTable/__tests__/DataTable.test.tsx +13 -7
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +13 -10
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +15 -11
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +12 -6
- package/src/components/DataTable/__tests__/keyboard.test.tsx +12 -6
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +10 -6
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +1 -1
- package/src/components/DataTable/components/DataTableBody.tsx +10 -25
- package/src/components/DataTable/components/DataTableCore.tsx +1 -1
- package/src/components/DataTable/components/FilterRow.tsx +3 -1
- package/src/components/DataTable/components/ImportModal.tsx +1 -1
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +9 -9
- package/src/components/DataTable/core/ColumnFactory.ts +6 -6
- package/src/components/DataTable/core/DataTableContext.tsx +14 -10
- package/src/components/DataTable/core/LocalDataAdapter.ts +2 -1
- package/src/components/DataTable/core/PluginRegistry.ts +3 -3
- package/src/components/DataTable/core/StateManager.ts +12 -11
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +104 -0
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +101 -0
- package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +84 -0
- package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +102 -0
- package/src/components/DataTable/core/__tests__/StateManager.test.ts +104 -0
- package/src/components/DataTable/core/interfaces.ts +17 -17
- package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +124 -0
- package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +117 -0
- package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +102 -0
- package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +53 -0
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +0 -2
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +9 -8
- package/src/components/DataTable/types.ts +5 -5
- package/src/components/DataTable/utils/aggregationUtils.ts +4 -4
- package/src/components/DataTable/utils/columnUtils.ts +3 -2
- package/src/components/DataTable/utils/debugTools.ts +1 -1
- package/src/components/DataTable/utils/exportUtils.ts +6 -6
- package/src/components/DataTable/utils/hierarchicalSorting.ts +6 -6
- package/src/components/DataTable/utils/hierarchicalUtils.ts +0 -8
- package/src/components/DataTable/utils/index.ts +0 -1
- package/src/components/DataTable/utils/performanceUtils.ts +9 -4
- package/src/components/Dialog/Dialog.test.tsx +49 -27
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +13 -8
- package/src/components/EventSelector/EventSelector.test.tsx +60 -12
- package/src/components/EventSelector/EventSelector.tsx +38 -15
- package/src/components/EventSelector/index.ts +2 -2
- package/src/components/FileDisplay/FileDisplay.test.tsx +143 -85
- package/src/components/FileDisplay/FileDisplay.tsx +1 -0
- package/src/components/FileUpload/FileUpload.test.tsx +532 -152
- package/src/components/FileUpload/FileUpload.tsx +43 -8
- package/src/components/Footer/Footer.test.tsx +19 -14
- package/src/components/Form/Form.test.tsx +96 -14
- package/src/components/Form/Form.tsx +210 -1
- package/src/components/Form/index.ts +3 -7
- package/src/components/Header/Header.test.tsx +24 -17
- package/src/components/Header/Header.tsx +3 -1
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +2 -4
- package/src/components/Input/Input.test.tsx +61 -36
- package/src/components/Label/{__tests__/Label.test.tsx → Label.test.tsx} +2 -2
- package/src/components/Label/Label.tsx +2 -3
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +6 -5
- package/src/components/LoadingSpinner/LoadingSpinner.tsx +6 -2
- package/src/components/LoginForm/LoginForm.test.tsx +14 -13
- package/src/components/LoginForm/LoginForm.tsx +1 -1
- package/src/components/LoginForm/index.ts +7 -0
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +233 -20
- package/src/components/NavigationMenu/NavigationMenu.tsx +191 -55
- package/src/components/NavigationMenu/index.ts +1 -1
- package/src/components/OrganisationSelector/OrganisationSelector.test.tsx +20 -11
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +1 -1
- package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.integration.test.tsx → PaceAppLayout.integration.test.tsx} +272 -79
- package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.performance.test.tsx → PaceAppLayout.performance.test.tsx} +155 -32
- package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.security.test.tsx → PaceAppLayout.security.test.tsx} +211 -65
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +498 -210
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +63 -64
- package/src/components/PaceAppLayout/test-setup.tsx +192 -0
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +193 -39
- package/src/components/{PasswordReset → PasswordChange}/PasswordChangeForm.test.tsx +2 -2
- package/src/components/{PasswordReset → PasswordChange}/PasswordChangeForm.tsx +10 -4
- package/src/components/PasswordChange/index.ts +2 -0
- package/src/components/Progress/Progress.test.tsx +11 -0
- package/src/components/Progress/Progress.tsx +1 -1
- package/src/components/Progress/index.ts +10 -0
- package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +2 -1
- package/src/components/PublicLayout/PublicLayout.test.tsx +1210 -0
- package/src/components/PublicLayout/PublicPageLayout.tsx +190 -36
- package/src/components/PublicLayout/PublicPageProvider.tsx +8 -7
- package/src/components/PublicLayout/index.ts +10 -28
- package/src/components/Select/Select.test.tsx +7 -7
- package/src/components/Select/Select.tsx +277 -11
- package/src/components/Select/index.ts +1 -2
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +232 -0
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +40 -19
- package/src/components/Table/{__tests__/Table.test.tsx → Table.test.tsx} +94 -41
- package/src/components/Tabs/Tabs.test.tsx +10 -9
- package/src/components/Tabs/Tabs.tsx +61 -33
- package/src/components/Textarea/Textarea.test.tsx +31 -18
- package/src/components/Toast/Toast.tsx +2 -2
- package/src/components/Tooltip/Tooltip.test.tsx +1 -1
- package/src/components/UserMenu/UserMenu.test.tsx +7 -6
- package/src/components/UserMenu/UserMenu.tsx +2 -2
- package/src/components/index.ts +5 -4
- package/src/constants/performance.ts +19 -8
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +21 -22
- package/src/hooks/__tests__/useEvents.unit.test.ts +5 -4
- package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +2 -2
- package/src/hooks/__tests__/usePermissionCache.simple.test.ts +17 -0
- package/src/hooks/__tests__/usePermissionCache.unit.test.ts +16 -11
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +1 -3
- package/src/hooks/__tests__/usePublicEvent.unit.test.ts +1 -3
- package/src/hooks/__tests__/useRBAC.unit.test.ts +24 -2
- package/src/hooks/index.ts +4 -0
- package/src/hooks/public/index.ts +2 -0
- package/src/hooks/public/usePublicEvent.ts +4 -6
- package/src/hooks/public/usePublicRouteParams.ts +1 -1
- package/src/hooks/services/useAuth.ts +2 -4
- package/src/hooks/services/useCurrentEvent.ts +1 -1
- package/src/hooks/useAppConfig.ts +1 -1
- package/src/hooks/useDataTablePerformance.ts +2 -2
- package/src/hooks/useEventTheme.ts +1 -1
- package/src/hooks/useEvents.ts +51 -10
- package/src/hooks/useOrganisationPermissions.test.ts +3 -3
- package/src/hooks/useOrganisationPermissions.ts +1 -1
- package/src/hooks/useOrganisationSecurity.ts +2 -2
- package/src/hooks/usePermissionCache.test.ts +9 -9
- package/src/hooks/usePermissionCache.ts +2 -2
- package/src/index.ts +19 -12
- package/src/providers/OrganisationProvider.tsx +73 -9
- package/src/providers/UnifiedAuthProvider.smoke.test.tsx +113 -13
- package/src/providers/__tests__/AuthProvider.test.tsx +2 -1
- package/src/providers/__tests__/EventProvider.test.tsx +24 -15
- package/src/providers/__tests__/OrganisationProvider.test.tsx +87 -36
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +80 -24
- package/src/providers/index.ts +0 -3
- package/src/providers/services/AuthServiceProvider.tsx +2 -17
- package/src/providers/services/EventServiceProvider.tsx +11 -16
- package/src/providers/services/InactivityServiceProvider.tsx +9 -12
- package/src/providers/services/OrganisationServiceProvider.tsx +9 -12
- package/src/providers/services/UnifiedAuthProvider.tsx +85 -18
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +11 -4
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +105 -21
- package/src/rbac/adapters.tsx +1 -1
- package/src/rbac/api.ts +20 -4
- package/src/rbac/audit-enhanced.ts +47 -2
- package/src/rbac/audit.ts +47 -2
- package/src/rbac/components/NavigationGuard.tsx +1 -1
- package/src/rbac/components/NavigationProvider.test.tsx +7 -6
- package/src/rbac/components/NavigationProvider.tsx +1 -1
- package/src/rbac/components/PagePermissionGuard.tsx +1 -1
- package/src/rbac/components/PagePermissionProvider.test.tsx +7 -6
- package/src/rbac/components/PagePermissionProvider.tsx +1 -1
- package/src/rbac/components/PermissionEnforcer.tsx +1 -1
- package/src/rbac/components/RoleBasedRouter.tsx +1 -1
- package/src/rbac/components/SecureDataProvider.test.tsx +7 -6
- package/src/rbac/components/SecureDataProvider.tsx +1 -1
- package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +6 -6
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +11 -10
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +10 -11
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +19 -15
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +13 -12
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +19 -15
- package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +18 -18
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +11 -10
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +8 -7
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +10 -11
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +48 -19
- package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +476 -0
- package/src/rbac/hooks/index.ts +3 -0
- package/src/rbac/hooks/usePermissions.ts +31 -85
- package/src/rbac/hooks/useRBAC.test.ts +13 -1
- package/src/rbac/hooks/useRBAC.ts +13 -67
- package/src/rbac/hooks/useResolvedScope.ts +11 -0
- package/src/rbac/hooks/useSecureSupabase.ts +308 -0
- package/src/rbac/index.ts +3 -0
- package/src/rbac/secureClient.ts +53 -6
- package/src/rbac/security.ts +37 -1
- package/src/{types/rbac-functions.ts → rbac/types/functions.ts} +30 -30
- package/src/rbac/types.ts +3 -2
- package/src/services/AuthService.ts +33 -25
- package/src/services/EventService.ts +57 -31
- package/src/services/InactivityService.ts +33 -53
- package/src/services/OrganisationService.ts +36 -40
- package/src/services/__tests__/AuthService.restoreSession.test.ts +6 -2
- package/src/services/__tests__/EventService.test.ts +67 -33
- package/src/services/interfaces/IEventService.ts +1 -1
- package/src/styles/core.css +2 -2
- package/src/styles/index.ts +1 -5
- package/src/types/__tests__/guards.test.ts +1 -1
- package/src/types/__tests__/type-validation.test.ts +0 -1
- package/src/types/auth.ts +42 -2
- package/src/types/core.ts +251 -0
- package/src/types/database.ts +11 -496
- package/src/types/event.ts +102 -0
- package/src/types/file-reference.ts +6 -4
- package/src/types/guards.ts +2 -1
- package/src/types/index.ts +48 -14
- package/src/types/lodash.debounce.d.ts +15 -0
- package/src/types/organisation.ts +14 -10
- package/src/types/supabase.ts +15 -17
- package/src/utils/__tests__/secureErrors.unit.test.ts +1 -1
- package/src/utils/__tests__/validationUtils.unit.test.ts +0 -29
- package/src/utils/app/appNameResolver.ts +1 -1
- package/src/utils/dynamic/dynamicUtils.ts +3 -2
- package/src/utils/file-reference/index.ts +25 -6
- package/src/utils/security/secureErrors.ts +1 -1
- package/src/utils/validation/index.ts +6 -12
- package/src/utils/validation/validationUtils.ts +0 -13
- package/dist/UnifiedAuthProvider-BMJAP6Z7.js +0 -16
- package/dist/auth-DReDSLq9.d.ts +0 -16
- package/dist/chunk-56XJ3TU6.js +0 -11
- package/dist/chunk-56XJ3TU6.js.map +0 -1
- package/dist/chunk-6HLVGAZG.js.map +0 -1
- package/dist/chunk-7QCC6MCP.js +0 -288
- package/dist/chunk-BESYRHQM.js.map +0 -1
- package/dist/chunk-BJPBT3CU.js +0 -21
- package/dist/chunk-BJPBT3CU.js.map +0 -1
- package/dist/chunk-BVYWGZVV.js.map +0 -1
- package/dist/chunk-CPTUD43C.js.map +0 -1
- package/dist/chunk-CX5M4ZAG.js.map +0 -1
- package/dist/chunk-ERGKJX4D.js +0 -15
- package/dist/chunk-ERGKJX4D.js.map +0 -1
- package/dist/chunk-ERISIBYU.js.map +0 -1
- package/dist/chunk-GQA2LIAE.js.map +0 -1
- package/dist/chunk-JISYG63F.js +0 -70
- package/dist/chunk-JISYG63F.js.map +0 -1
- package/dist/chunk-MSHEVJXS.js +0 -27
- package/dist/chunk-MSHEVJXS.js.map +0 -1
- package/dist/chunk-N5YCCUG5.js.map +0 -1
- package/dist/chunk-ONI7Y733.js.map +0 -1
- package/dist/chunk-OWAG3GSU.js.map +0 -1
- package/dist/chunk-P6UUHOIF.js.map +0 -1
- package/dist/chunk-PKW27QVS.js +0 -61
- package/dist/chunk-PKW27QVS.js.map +0 -1
- package/dist/chunk-Q5QRDWKI.js.map +0 -1
- package/dist/chunk-S5OFRT4M.js.map +0 -1
- package/dist/chunk-SBVILCCA.js.map +0 -1
- package/dist/chunk-WM26XK7I.js +0 -2432
- package/dist/chunk-WM26XK7I.js.map +0 -1
- package/dist/chunk-XDNLUEXI.js +0 -138
- package/dist/chunk-XJ2HZOBU.js.map +0 -1
- package/dist/chunk-ZZ2SS7NI.js +0 -237
- package/dist/chunk-ZZ2SS7NI.js.map +0 -1
- package/dist/database-C6jy7EOu.d.ts +0 -500
- package/dist/organisation-D6qRDtbF.d.ts +0 -93
- package/dist/schema-DTDZQe2u.d.ts +0 -28
- package/dist/unified-DQ4VcT7H.d.ts +0 -198
- package/dist/useInactivityTracker-TO6ZOF35.js +0 -11
- package/dist/validation.d.ts +0 -47
- package/dist/validation.js +0 -24
- package/dist/validation.js.map +0 -1
- package/docs/DOCUMENTATION_AUDIT.md +0 -172
- package/docs/DOCUMENTATION_STANDARD.md +0 -137
- package/docs/api/classes/PublicErrorBoundary.md +0 -132
- package/docs/api/interfaces/EventLogoProps.md +0 -152
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +0 -94
- package/docs/api/interfaces/PublicErrorBoundaryState.md +0 -68
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +0 -86
- package/docs/architecture/rpc-function-standards.md +0 -1106
- package/docs/getting-started/consuming-app-vite-config.md +0 -239
- package/docs/implementation-guides/event-theming-summary.md +0 -226
- package/docs/implementation-guides/public-pages-advanced.md +0 -1038
- package/docs/migration/v0.4.15-tailwind-scanning.md +0 -278
- package/docs/migration/v0.4.16-css-first-approach.md +0 -312
- package/docs/migration/v0.4.17-source-path-fix.md +0 -235
- package/docs/rbac/RBAC_EVENT_CONTEXT_LOADING.md +0 -222
- package/docs/rbac/RBAC_LOGIN_SAFETY_FIX.md +0 -95
- package/docs/rbac/RBAC_V0.5.147_FIX.md +0 -117
- package/docs/rbac/README-rbac-rls-integration.md +0 -374
- package/docs/styles/usage.md +0 -227
- package/docs/testing/visual-testing.md +0 -120
- package/docs/troubleshooting/DEBUG_NETWORK_ERROR.md +0 -152
- package/docs/troubleshooting/FIX_SUPABASE_CORS.md +0 -184
- package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +0 -193
- package/docs/troubleshooting/database-view-compatibility.md +0 -125
- package/docs/troubleshooting/react-hooks-issue-analysis.md +0 -172
- package/docs/troubleshooting/tailwind-content-scanning.md +0 -219
- package/examples/RBAC/EventBasedApp.tsx +0 -239
- package/examples/RBAC/PermissionExample.tsx +0 -151
- package/examples/STRUCTURE.md +0 -125
- package/examples/components 2/Dialog/BasicHtmlTest.tsx +0 -55
- package/examples/components 2/Dialog/DebugHtmlExample.tsx +0 -68
- package/examples/components 2/Dialog/HtmlDialogExample.tsx +0 -202
- package/examples/components 2/Dialog/SimpleHtmlTest.tsx +0 -61
- package/examples/components 2/Dialog/SmartDialogExample.tsx +0 -322
- package/examples/components 2/index.ts +0 -11
- package/examples/features/index.ts +0 -12
- package/examples/features/rbac/CompleteRBACExample.tsx +0 -324
- package/examples/features/rbac/index.ts +0 -13
- package/examples/public-pages/CorrectPublicPageImplementation.tsx +0 -301
- package/examples/public-pages/PublicEventPage.tsx +0 -274
- package/examples/public-pages/PublicPageApp.tsx +0 -308
- package/examples/public-pages/PublicPageUsageExample.tsx +0 -216
- package/examples/public-pages/index.ts +0 -14
- package/src/__tests__/TEST_STANDARD.md +0 -1008
- package/src/components/Checkbox/__mocks__/Checkbox.tsx +0 -2
- package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +0 -421
- package/src/components/DataTable/examples/HierarchicalExample.tsx +0 -475
- package/src/components/DataTable/examples/InitialPageSizeExample.tsx +0 -177
- package/src/components/DataTable/examples/PerformanceExample.tsx +0 -506
- package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +0 -316
- package/src/components/DataTable/examples/__tests__/HierarchicalExample.test.tsx +0 -45
- package/src/components/DataTable/examples/__tests__/InitialPageSizeExample.test.tsx +0 -211
- package/src/components/DataTable/examples/__tests__/PerformanceExample.test.tsx +0 -126
- package/src/components/Dialog/README.md +0 -804
- package/src/components/Dialog/examples/BasicHtmlTest.tsx +0 -55
- package/src/components/Dialog/examples/DebugHtmlExample.tsx +0 -68
- package/src/components/Dialog/examples/ScrollableDialogExample.tsx +0 -290
- package/src/components/Dialog/examples/SimpleHtmlTest.tsx +0 -61
- package/src/components/Dialog/examples/__tests__/HtmlDialogExample.test.tsx +0 -71
- package/src/components/Dialog/examples/__tests__/SimpleHtmlTest.test.tsx +0 -122
- package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +0 -147
- package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +0 -611
- package/src/components/Dialog/utils/safeHtml.ts +0 -185
- package/src/components/EventSelector/types.ts +0 -79
- package/src/components/Form/FormErrorSummary.tsx +0 -113
- package/src/components/Form/FormField.tsx +0 -249
- package/src/components/Form/FormFieldset.tsx +0 -127
- package/src/components/Form/FormLiveRegion.tsx +0 -198
- package/src/components/Input/__mocks__/Input.tsx +0 -2
- package/src/components/NavigationMenu/types.ts +0 -85
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +0 -326
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -1078
- package/src/components/PasswordReset/PasswordResetForm.test.tsx +0 -597
- package/src/components/PasswordReset/PasswordResetForm.tsx +0 -201
- package/src/components/PasswordReset/index.ts +0 -2
- package/src/components/ProtectedRoute/README.md +0 -164
- package/src/components/PublicLayout/EventLogo.tsx +0 -175
- package/src/components/PublicLayout/PublicErrorBoundary.tsx +0 -282
- package/src/components/PublicLayout/PublicLoadingSpinner.tsx +0 -216
- package/src/components/PublicLayout/PublicPageContextChecker.tsx +0 -131
- package/src/components/PublicLayout/PublicPageDebugger.tsx +0 -104
- package/src/components/PublicLayout/PublicPageDiagnostic.tsx +0 -162
- package/src/components/PublicLayout/PublicPageFooter.tsx +0 -124
- package/src/components/PublicLayout/PublicPageHeader.tsx +0 -209
- package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +0 -449
- package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +0 -393
- package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +0 -192
- package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +0 -351
- package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +0 -402
- package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +0 -460
- package/src/components/PublicLayout/__tests__/PublicPageProvider.test.tsx +0 -313
- package/src/components/Select/hooks.ts +0 -289
- package/src/hooks/useCounter.test.ts +0 -131
- package/src/hooks/useDebounce.test.ts +0 -375
- package/src/providers/AuthProvider.tsx +0 -15
- package/src/providers/EventProvider.tsx +0 -16
- package/src/providers/InactivityProvider.tsx +0 -15
- package/src/providers/OrganisationProvider.context.test.tsx +0 -169
- package/src/providers/UnifiedAuthProvider.tsx +0 -15
- package/src/types/theme.ts +0 -6
- package/src/types/unified.ts +0 -265
- package/src/utils/appConfig.ts +0 -47
- package/src/utils/appIdResolver.test.ts +0 -499
- package/src/utils/appIdResolver.ts +0 -130
- package/src/utils/appNameResolver.simple.test.ts +0 -212
- package/src/utils/appNameResolver.test.ts +0 -121
- package/src/utils/appNameResolver.ts +0 -191
- package/src/utils/audit.ts +0 -127
- package/src/utils/auth-utils.ts +0 -96
- package/src/utils/bundleAnalysis.ts +0 -129
- package/src/utils/debugLogger.ts +0 -67
- package/src/utils/deviceFingerprint.ts +0 -215
- package/src/utils/dynamicUtils.ts +0 -105
- package/src/utils/file-reference.test.ts +0 -788
- package/src/utils/file-reference.ts +0 -519
- package/src/utils/formatDate.test.ts +0 -237
- package/src/utils/formatting.ts +0 -170
- package/src/utils/lazyLoad.tsx +0 -44
- package/src/utils/logger.ts +0 -179
- package/src/utils/organisationContext.test.ts +0 -322
- package/src/utils/organisationContext.ts +0 -153
- package/src/utils/performanceBenchmark.ts +0 -64
- package/src/utils/performanceBudgets.ts +0 -110
- package/src/utils/permissionTypes.ts +0 -37
- package/src/utils/permissionUtils.test.ts +0 -393
- package/src/utils/permissionUtils.ts +0 -34
- package/src/utils/sanitization.ts +0 -264
- package/src/utils/schemaUtils.ts +0 -37
- package/src/utils/secureDataAccess.test.ts +0 -711
- package/src/utils/secureDataAccess.ts +0 -377
- package/src/utils/secureErrors.ts +0 -79
- package/src/utils/security.ts +0 -156
- package/src/utils/securityMonitor.ts +0 -45
- package/src/utils/sessionTracking.ts +0 -126
- package/src/utils/validation.ts +0 -111
- package/src/utils/validationUtils.ts +0 -120
- package/src/validation/index.ts +0 -12
- /package/dist/{DataTable-4VSEJQ7D.js.map → DataTable-QAB34V6K.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-BMJAP6Z7.js.map → UnifiedAuthProvider-7F6T4B6K.js.map} +0 -0
- /package/dist/{api-45XYYO2A.js.map → api-ROMBCNKU.js.map} +0 -0
- /package/dist/{audit-64X3VJXB.js.map → audit-WRS3KJKI.js.map} +0 -0
- /package/dist/{chunk-PLDDJCW6.js.map → chunk-7D4SUZUM.js.map} +0 -0
- /package/dist/{useInactivityTracker-TO6ZOF35.js.map → chunk-KQCRWDSA.js.map} +0 -0
- /package/examples/{components 2/DataTable → DataTable}/InitialPageSizeExample.tsx +0 -0
- /package/examples/{features/public-pages → PublicPages}/index.ts +0 -0
- /package/examples/{RBAC → rbac}/index.ts +0 -0
|
@@ -194,16 +194,69 @@
|
|
|
194
194
|
import * as React from "react";
|
|
195
195
|
import { Menu, ChevronDown } from "lucide-react";
|
|
196
196
|
import { cn } from "../../utils/core/cn";
|
|
197
|
-
import { NavigationMenuProps, NavigationItem } from "./types";
|
|
198
197
|
import { Button } from "../Button";
|
|
199
198
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../Select";
|
|
200
|
-
import { useUnifiedAuth } from "../../providers/UnifiedAuthProvider";
|
|
199
|
+
import { useUnifiedAuth } from "../../providers/services/UnifiedAuthProvider";
|
|
201
200
|
import { useRBAC } from "../../rbac/hooks/useRBAC";
|
|
202
201
|
import { useResolvedScope } from "../../rbac/hooks";
|
|
203
202
|
import { usePermissions } from "../../rbac/hooks/usePermissions";
|
|
204
|
-
import type { Permission, AccessLevel as RBACAccessLevel } from "../../rbac/types";
|
|
203
|
+
import type { Permission, AccessLevel as RBACAccessLevel, UUID } from "../../rbac/types";
|
|
205
204
|
import { logger } from "../../utils/core/logger";
|
|
206
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Navigation mode type
|
|
208
|
+
*/
|
|
209
|
+
export type NavigationMode = 'dropdown' | 'hierarchical';
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Navigation item metadata
|
|
213
|
+
*/
|
|
214
|
+
export interface NavigationItemMeta {
|
|
215
|
+
hidden?: boolean;
|
|
216
|
+
[key: string]: unknown;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Navigation item interface
|
|
221
|
+
*/
|
|
222
|
+
export interface NavigationItem {
|
|
223
|
+
id: string;
|
|
224
|
+
label: string;
|
|
225
|
+
href?: string;
|
|
226
|
+
icon?: string;
|
|
227
|
+
children?: NavigationItem[];
|
|
228
|
+
permissions?: (Permission | string)[];
|
|
229
|
+
roles?: string[];
|
|
230
|
+
accessLevel?: RBACAccessLevel | string;
|
|
231
|
+
meta?: NavigationItemMeta;
|
|
232
|
+
pageId?: string;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Navigation menu component props
|
|
237
|
+
*/
|
|
238
|
+
export interface NavigationMenuProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
239
|
+
items: NavigationItem[];
|
|
240
|
+
mode?: NavigationMode;
|
|
241
|
+
currentPath?: string;
|
|
242
|
+
onNavigate?: (item: NavigationItem) => void;
|
|
243
|
+
className?: string;
|
|
244
|
+
disabled?: boolean;
|
|
245
|
+
buttonText?: string;
|
|
246
|
+
showIcons?: boolean;
|
|
247
|
+
navigationLabel?: string;
|
|
248
|
+
strictMode?: boolean;
|
|
249
|
+
auditLog?: boolean;
|
|
250
|
+
onNavigationAccessDenied?: (item: NavigationItem) => void;
|
|
251
|
+
onStrictModeViolation?: (item: NavigationItem, reason: string) => void;
|
|
252
|
+
/**
|
|
253
|
+
* If true, indicates that items have already been filtered by the parent component (e.g., PaceAppLayout).
|
|
254
|
+
* When true, NavigationMenu will skip expensive permission checks and trust the provided items.
|
|
255
|
+
* This significantly improves performance when items are pre-filtered.
|
|
256
|
+
*/
|
|
257
|
+
itemsPreFiltered?: boolean;
|
|
258
|
+
}
|
|
259
|
+
|
|
207
260
|
/**
|
|
208
261
|
* Unified NavigationMenu component that supports both dropdown and hierarchical navigation modes.
|
|
209
262
|
*
|
|
@@ -346,7 +399,7 @@ import { logger } from "../../utils/core/logger";
|
|
|
346
399
|
* onNavigate={(item) => navigate(item.href)}
|
|
347
400
|
* buttonText="Navigation"
|
|
348
401
|
* navigationLabel="Main application navigation"
|
|
349
|
-
*
|
|
402
|
+
* // Permission filtering is always enabled - no prop needed
|
|
350
403
|
* auditLog={true}
|
|
351
404
|
* />
|
|
352
405
|
* );
|
|
@@ -413,7 +466,7 @@ export const NavigationMenu = React.forwardRef<
|
|
|
413
466
|
auditLog = true,
|
|
414
467
|
onNavigationAccessDenied,
|
|
415
468
|
onStrictModeViolation,
|
|
416
|
-
|
|
469
|
+
itemsPreFiltered = false,
|
|
417
470
|
...props
|
|
418
471
|
}, ref) => {
|
|
419
472
|
const [expandedItems, setExpandedItems] = React.useState<Set<string>>(new Set());
|
|
@@ -448,13 +501,14 @@ export const NavigationMenu = React.forwardRef<
|
|
|
448
501
|
|
|
449
502
|
// Get resolved scope for permission checks
|
|
450
503
|
// Note: Always call useResolvedScope (hooks must be called unconditionally)
|
|
451
|
-
//
|
|
504
|
+
// However, if itemsPreFiltered is true, we'll skip using the results to avoid blocking
|
|
505
|
+
// Permission filtering is always enabled - scope is always needed (unless items are pre-filtered)
|
|
452
506
|
const { supabase } = authContext || {};
|
|
453
507
|
const { selectedOrganisation } = authContext || {};
|
|
454
508
|
const { resolvedScope, isLoading: scopeLoading, error: scopeError } = useResolvedScope({
|
|
455
|
-
supabase:
|
|
456
|
-
selectedOrganisationId:
|
|
457
|
-
selectedEventId:
|
|
509
|
+
supabase: itemsPreFiltered ? null : (supabase || null), // Skip expensive resolution if pre-filtered
|
|
510
|
+
selectedOrganisationId: itemsPreFiltered ? null : (selectedOrganisation?.id || null),
|
|
511
|
+
selectedEventId: itemsPreFiltered ? null : (selectedEvent?.event_id || null)
|
|
458
512
|
});
|
|
459
513
|
|
|
460
514
|
// Resolve appId when useResolvedScope fails but context is ready
|
|
@@ -500,13 +554,18 @@ export const NavigationMenu = React.forwardRef<
|
|
|
500
554
|
// Build scope from resolvedScope if available, otherwise fall back to context values
|
|
501
555
|
// This handles the case where useResolvedScope errored initially but context is now ready
|
|
502
556
|
// IMPORTANT: We need appId for usePermissions to work correctly
|
|
557
|
+
// CRITICAL: Use selectedOrganisation?.id immediately when available, even during loading
|
|
558
|
+
// This prevents usePermissions from skipping fetch due to empty organisationId
|
|
503
559
|
const effectiveScope = React.useMemo(() => {
|
|
504
|
-
if (
|
|
505
|
-
|
|
560
|
+
// Prefer resolvedScope if available (includes appId)
|
|
561
|
+
if (resolvedScope?.organisationId) {
|
|
506
562
|
return resolvedScope;
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// Fall back to building scope from context if resolvedScope is not available yet
|
|
566
|
+
// Use selectedOrganisation?.id immediately when available, even if scopeLoading is true
|
|
567
|
+
// This prevents delay in permission fetching
|
|
568
|
+
if (selectedOrganisation?.id) {
|
|
510
569
|
const fallbackScope = {
|
|
511
570
|
organisationId: selectedOrganisation.id,
|
|
512
571
|
eventId: selectedEvent?.event_id || undefined,
|
|
@@ -514,8 +573,9 @@ export const NavigationMenu = React.forwardRef<
|
|
|
514
573
|
};
|
|
515
574
|
return fallbackScope;
|
|
516
575
|
}
|
|
576
|
+
|
|
517
577
|
return null;
|
|
518
|
-
}, [
|
|
578
|
+
}, [resolvedScope, selectedOrganisation?.id, selectedEvent?.event_id, resolvedAppId]);
|
|
519
579
|
|
|
520
580
|
// Create a stable scope object that changes when effectiveScope changes
|
|
521
581
|
// This ensures usePermissions detects scope changes and re-runs
|
|
@@ -543,16 +603,21 @@ export const NavigationMenu = React.forwardRef<
|
|
|
543
603
|
}, [scopeKey, effectiveScope]);
|
|
544
604
|
|
|
545
605
|
// Get permissions map for synchronous permission checks
|
|
546
|
-
|
|
606
|
+
// Skip expensive permission fetching if items are pre-filtered
|
|
607
|
+
const userId = (authContext?.user?.id || '') as UUID;
|
|
547
608
|
|
|
548
609
|
// Call usePermissions with primitive parameters
|
|
610
|
+
// If itemsPreFiltered is true, pass null/undefined to skip expensive permission fetching
|
|
611
|
+
// CRITICAL: Pass null for userId and undefined for organisationId to skip the 3-second timeout
|
|
612
|
+
// Empty string '' triggers the timeout, but null/undefined allows immediate early return
|
|
549
613
|
const { permissions: permissionMap, hasAnyPermission, isLoading: permissionsLoading, error: permissionsError } = usePermissions(
|
|
550
|
-
|
|
551
|
-
stableScope.organisationId,
|
|
552
|
-
stableScope.eventId,
|
|
553
|
-
stableScope.appId
|
|
614
|
+
itemsPreFiltered ? (null as any) : userId, // Pass null to trigger early return (empty string would wait 3s)
|
|
615
|
+
itemsPreFiltered ? undefined : stableScope.organisationId, // Pass undefined to skip timeout
|
|
616
|
+
itemsPreFiltered ? undefined : stableScope.eventId, // Skip if pre-filtered
|
|
617
|
+
itemsPreFiltered ? undefined : stableScope.appId // Skip if pre-filtered
|
|
554
618
|
);
|
|
555
619
|
|
|
620
|
+
|
|
556
621
|
|
|
557
622
|
// NEW: Phase 2 - Enhanced Security Features
|
|
558
623
|
// Filter navigation items based on permissions using RBAC hooks
|
|
@@ -560,10 +625,21 @@ export const NavigationMenu = React.forwardRef<
|
|
|
560
625
|
const previousFilteredItemsRef = React.useRef<NavigationItem[]>([]);
|
|
561
626
|
|
|
562
627
|
const filteredItems = React.useMemo(() => {
|
|
563
|
-
//
|
|
628
|
+
// PERFORMANCE OPTIMIZATION: If items are pre-filtered, skip all expensive permission checks
|
|
629
|
+
// This significantly improves load time when PaceAppLayout has already filtered items
|
|
630
|
+
if (itemsPreFiltered && items && items.length > 0) {
|
|
631
|
+
// Items are pre-filtered by parent (e.g., PaceAppLayout) - trust them and only filter hidden items
|
|
632
|
+
const visibleItems = (items || []).filter(item => !item.meta?.hidden);
|
|
633
|
+
previousFilteredItemsRef.current = visibleItems;
|
|
634
|
+
// Don't log here - logging happens in useEffect to avoid spam on re-renders
|
|
635
|
+
return visibleItems;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// SECURITY: Permission filtering is ALWAYS enabled - users only see navigation items they have permission to access
|
|
639
|
+
// Security: If we're missing required context or still loading, show NO items
|
|
564
640
|
// This prevents security risk of showing items before permissions are verified
|
|
565
|
-
|
|
566
|
-
|
|
641
|
+
|
|
642
|
+
// CRITICAL: Wait for BOTH organisation AND event context to be ready before checking permissions
|
|
567
643
|
// This prevents the error "No organisation or event context available" when event context is still loading
|
|
568
644
|
const isOrgContextReady = orgContextReady && selectedOrganisation?.id;
|
|
569
645
|
// Event context is ready when not loading
|
|
@@ -581,7 +657,22 @@ export const NavigationMenu = React.forwardRef<
|
|
|
581
657
|
const shouldWaitForScope = scopeLoading || (!hasValidContext);
|
|
582
658
|
const shouldRetryAfterError = scopeError && hasValidContext && !scopeLoading;
|
|
583
659
|
|
|
584
|
-
// During initial load or when scope/context is loading,
|
|
660
|
+
// During initial load or when scope/context is loading, check if we can trust PaceAppLayout's filtering
|
|
661
|
+
// CRITICAL: If items are provided and we have valid context, trust PaceAppLayout's filtering
|
|
662
|
+
// This prevents delay - PaceAppLayout already filtered items, so show them immediately
|
|
663
|
+
// even if scope is still loading or rbacContext is not yet available
|
|
664
|
+
if (items && items.length > 0 && selectedOrganisation?.id) {
|
|
665
|
+
// Items are provided by PaceAppLayout - trust its filtering and show immediately
|
|
666
|
+
// This eliminates delay while usePermissions/useResolvedScope are still loading
|
|
667
|
+
// Items provided - trusting PaceAppLayout filtering (removed verbose logging)
|
|
668
|
+
// Filter out hidden items only - PaceAppLayout already did permission filtering
|
|
669
|
+
const visibleItems = (items || []).filter(item => !item.meta?.hidden);
|
|
670
|
+
// Store in ref for use during permission refetches
|
|
671
|
+
previousFilteredItemsRef.current = visibleItems;
|
|
672
|
+
return visibleItems;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// If no items provided or no valid context, wait for context to be ready
|
|
585
676
|
if (!authContext || !rbacContext || (shouldWaitForScope && !shouldRetryAfterError)) {
|
|
586
677
|
// Still loading - show nothing to prevent security risk
|
|
587
678
|
// Note: We check both org and event context readiness to prevent premature permission checks
|
|
@@ -601,24 +692,58 @@ export const NavigationMenu = React.forwardRef<
|
|
|
601
692
|
if (previousFilteredItemsRef.current.length > 0) {
|
|
602
693
|
return previousFilteredItemsRef.current;
|
|
603
694
|
}
|
|
695
|
+
// CRITICAL: If items are provided and we have valid scope, trust PaceAppLayout's filtering
|
|
696
|
+
// This prevents delay - PaceAppLayout already filtered items, so show them immediately
|
|
697
|
+
// even if usePermissions is still loading
|
|
698
|
+
if (items && items.length > 0 && stableScope.organisationId) {
|
|
699
|
+
// Permissions loading but items provided - trusting PaceAppLayout filtering (removed verbose logging)
|
|
700
|
+
// Filter out hidden items only - PaceAppLayout already did permission filtering
|
|
701
|
+
return (items || []).filter(item => !item.meta?.hidden);
|
|
702
|
+
}
|
|
604
703
|
// Otherwise, show nothing during initial load
|
|
605
704
|
return [];
|
|
606
705
|
}
|
|
607
706
|
|
|
608
|
-
// If there's an error
|
|
707
|
+
// If there's an error after loading, show nothing
|
|
609
708
|
// Security: Better to show nothing than risk showing unauthorized items
|
|
610
|
-
if (permissionsError
|
|
611
|
-
logger.warn('NavigationMenu', 'Permission
|
|
612
|
-
permissionsError: permissionsError?.message
|
|
613
|
-
permissionMapSize: permissionMap ? Object.keys(permissionMap).length : 0
|
|
709
|
+
if (permissionsError) {
|
|
710
|
+
logger.warn('NavigationMenu', 'Permission check error - showing no items for security', {
|
|
711
|
+
permissionsError: permissionsError?.message
|
|
614
712
|
});
|
|
615
713
|
return [];
|
|
616
714
|
}
|
|
617
|
-
|
|
618
|
-
//
|
|
619
|
-
|
|
620
|
-
|
|
715
|
+
|
|
716
|
+
// If permission map is empty after loading, we need to handle this carefully:
|
|
717
|
+
// 1. If items were already filtered by PaceAppLayout (which uses getPermissionMap directly),
|
|
718
|
+
// we should trust those items and show them (they've already been filtered)
|
|
719
|
+
// 2. If NavigationMenu is used standalone, we need permissions to filter - show nothing
|
|
720
|
+
//
|
|
721
|
+
// Since PaceAppLayout filters items before passing to NavigationMenu, and NavigationMenu
|
|
722
|
+
// uses usePermissions hook which may return empty map while PaceAppLayout gets permissions,
|
|
723
|
+
// we should trust items that are provided if permission map is empty but we have valid scope.
|
|
724
|
+
// This is safe because PaceAppLayout already filtered them using getPermissionMap.
|
|
725
|
+
if (!permissionMap || Object.keys(permissionMap).length === 0) {
|
|
726
|
+
// If we have valid scope and items are provided, they were likely already filtered by PaceAppLayout
|
|
727
|
+
// In this case, trust the items and show them (they've already been filtered for security)
|
|
728
|
+
if (stableScope.organisationId && items && items.length > 0) {
|
|
729
|
+
// Permission map empty but items provided - trusting PaceAppLayout filtering (removed verbose logging)
|
|
730
|
+
// Items were already filtered by PaceAppLayout - trust them and only filter hidden items
|
|
731
|
+
return (items || []).filter(item => !item.meta?.hidden);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
// If no items provided or no valid scope, show nothing (can't verify permissions)
|
|
735
|
+
if (stableScope.organisationId) {
|
|
736
|
+
logger.warn('NavigationMenu', 'Permission map is empty and no items provided - showing nothing', {
|
|
737
|
+
permissionMapSize: 0,
|
|
738
|
+
organisationId: stableScope.organisationId,
|
|
739
|
+
eventId: stableScope.eventId,
|
|
740
|
+
appId: stableScope.appId
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
return [];
|
|
744
|
+
}
|
|
621
745
|
|
|
746
|
+
// SECURITY: Permission filtering is always enabled - filtering cannot be disabled
|
|
622
747
|
// Helper function to derive page ID from href
|
|
623
748
|
const getPageIdFromHref = (href?: string): string | null => {
|
|
624
749
|
if (!href) return null;
|
|
@@ -780,7 +905,7 @@ export const NavigationMenu = React.forwardRef<
|
|
|
780
905
|
return filtered;
|
|
781
906
|
}, [
|
|
782
907
|
items,
|
|
783
|
-
|
|
908
|
+
itemsPreFiltered, // Add itemsPreFiltered to dependencies
|
|
784
909
|
authContext,
|
|
785
910
|
rbacContext,
|
|
786
911
|
permissionMap,
|
|
@@ -799,22 +924,8 @@ export const NavigationMenu = React.forwardRef<
|
|
|
799
924
|
selectedOrganisation?.id
|
|
800
925
|
]);
|
|
801
926
|
|
|
802
|
-
//
|
|
803
|
-
|
|
804
|
-
if (auditLog && authContext) {
|
|
805
|
-
// Find the current navigation item to log its actual permissions
|
|
806
|
-
const currentItem = items?.find(item => item.href === currentPath || item.id === 'navigation-menu');
|
|
807
|
-
logger.debug('NavigationMenu', 'Navigation access attempt:', {
|
|
808
|
-
itemId: currentItem?.id || 'navigation-menu',
|
|
809
|
-
label: currentItem?.label || 'Navigation Menu',
|
|
810
|
-
href: currentPath,
|
|
811
|
-
permissions: currentItem?.permissions || null,
|
|
812
|
-
roles: currentItem?.roles || null,
|
|
813
|
-
accessLevel: currentItem?.accessLevel || null,
|
|
814
|
-
timestamp: new Date().toISOString()
|
|
815
|
-
});
|
|
816
|
-
}
|
|
817
|
-
}, [auditLog, authContext, currentPath, items]);
|
|
927
|
+
// Note: Navigation access attempts are logged in handleItemClick, not here
|
|
928
|
+
// This prevents excessive logging on every render
|
|
818
929
|
|
|
819
930
|
|
|
820
931
|
// Handle keyboard navigation for hierarchical mode
|
|
@@ -851,7 +962,7 @@ export const NavigationMenu = React.forwardRef<
|
|
|
851
962
|
// Handle navigation item click
|
|
852
963
|
const handleItemClick = (item: NavigationItem) => {
|
|
853
964
|
// NEW: Phase 2 - Enhanced Security Features
|
|
854
|
-
// Log navigation access attempt for audit
|
|
965
|
+
// Log navigation access attempt for audit (minimal logging)
|
|
855
966
|
if (auditLog) {
|
|
856
967
|
logger.debug('NavigationMenu', 'Navigation access attempt:', {
|
|
857
968
|
itemId: item.id,
|
|
@@ -876,12 +987,28 @@ export const NavigationMenu = React.forwardRef<
|
|
|
876
987
|
}
|
|
877
988
|
|
|
878
989
|
// Check if item should be visible (already filtered)
|
|
990
|
+
// If item is in filteredItems, it has already passed permission checks in PaceAppLayout
|
|
879
991
|
const isItemVisible = filteredItems.some(filtered => filtered.id === item.id);
|
|
880
992
|
|
|
993
|
+
// If item is not visible, it was filtered out - don't allow navigation
|
|
994
|
+
if (!isItemVisible) {
|
|
995
|
+
logger.warn('NavigationMenu', 'Navigation attempt to filtered item blocked', {
|
|
996
|
+
itemId: item.id,
|
|
997
|
+
label: item.label,
|
|
998
|
+
href: item.href
|
|
999
|
+
});
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
881
1003
|
// Check permissions if the item requires them using RBAC hooks
|
|
1004
|
+
// Only check if item has explicit permission requirements AND we have permission checking capability
|
|
882
1005
|
let hasPermission = true; // Default to true if no permission requirements
|
|
883
1006
|
|
|
884
|
-
|
|
1007
|
+
// Only check permissions if:
|
|
1008
|
+
// 1. Item has explicit permission requirements
|
|
1009
|
+
// 2. We have RBAC context
|
|
1010
|
+
// 3. We have hasAnyPermission function AND permission map is loaded (not empty)
|
|
1011
|
+
if (item.permissions && item.permissions.length > 0 && rbacContext && hasAnyPermission && permissionMap && Object.keys(permissionMap).length > 0) {
|
|
885
1012
|
// Convert string permissions to Permission type and check
|
|
886
1013
|
const permissions = item.permissions
|
|
887
1014
|
.filter((p): p is string => typeof p === 'string')
|
|
@@ -892,6 +1019,7 @@ export const NavigationMenu = React.forwardRef<
|
|
|
892
1019
|
}
|
|
893
1020
|
}
|
|
894
1021
|
|
|
1022
|
+
// If permission check failed, try role-based access
|
|
895
1023
|
if (!hasPermission && rbacContext) {
|
|
896
1024
|
// Check roles if permissions check failed or item has role requirements
|
|
897
1025
|
if (item.roles && item.roles.length > 0) {
|
|
@@ -922,10 +1050,19 @@ export const NavigationMenu = React.forwardRef<
|
|
|
922
1050
|
}
|
|
923
1051
|
}
|
|
924
1052
|
|
|
1053
|
+
// If permission map is empty but item is in filteredItems, trust PaceAppLayout's filtering
|
|
1054
|
+
// This handles the case where NavigationMenu's usePermissions returns empty map
|
|
1055
|
+
// but PaceAppLayout already filtered items correctly
|
|
1056
|
+
if (!hasPermission && (!permissionMap || Object.keys(permissionMap).length === 0) && isItemVisible) {
|
|
1057
|
+
// Permission map is empty but item passed filtering - trust PaceAppLayout
|
|
1058
|
+
// Permission map empty but item passed filtering - trusting PaceAppLayout (removed verbose logging)
|
|
1059
|
+
hasPermission = true;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
925
1062
|
if (!hasPermission) {
|
|
926
1063
|
// Handle access denied
|
|
927
1064
|
if (onNavigationAccessDenied) {
|
|
928
|
-
onNavigationAccessDenied(item
|
|
1065
|
+
onNavigationAccessDenied(item);
|
|
929
1066
|
}
|
|
930
1067
|
|
|
931
1068
|
if (strictMode) {
|
|
@@ -940,7 +1077,7 @@ export const NavigationMenu = React.forwardRef<
|
|
|
940
1077
|
});
|
|
941
1078
|
|
|
942
1079
|
if (onStrictModeViolation) {
|
|
943
|
-
onStrictModeViolation(item
|
|
1080
|
+
onStrictModeViolation(item, 'Insufficient permissions');
|
|
944
1081
|
}
|
|
945
1082
|
}
|
|
946
1083
|
|
|
@@ -957,7 +1094,6 @@ export const NavigationMenu = React.forwardRef<
|
|
|
957
1094
|
|
|
958
1095
|
// Check if item is currently active
|
|
959
1096
|
const isActiveItem = (item: NavigationItem): boolean => {
|
|
960
|
-
if (item.isActive !== undefined) return item.isActive;
|
|
961
1097
|
if (currentPath === item.href) return true;
|
|
962
1098
|
if (item.children && item.children.length > 0) {
|
|
963
1099
|
return item.children.some(child => isActiveItem(child));
|
|
@@ -15,10 +15,19 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
|
15
15
|
import { OrganisationSelector, OrganisationSelectorProps } from './OrganisationSelector';
|
|
16
16
|
import { renderWithProviders } from '../../__tests__/helpers/test-utils';
|
|
17
17
|
import type { Organisation } from '../../types/organisation';
|
|
18
|
+
import type { SelectProps, SelectContentProps, SelectItemProps, SelectTriggerProps, SelectValueProps } from '../Select';
|
|
19
|
+
import type { ButtonProps } from '../Button/Button';
|
|
20
|
+
import type { LoadingSpinnerProps } from '../LoadingSpinner/LoadingSpinner';
|
|
21
|
+
|
|
22
|
+
// Mock the useOrganisationService hook (used internally by useOrganisations)
|
|
23
|
+
const mockUseOrganisationService = vi.fn();
|
|
24
|
+
vi.mock('../../hooks/services/useOrganisationService', () => ({
|
|
25
|
+
useOrganisationService: () => mockUseOrganisationService(),
|
|
26
|
+
}));
|
|
18
27
|
|
|
19
28
|
// Mock the useOrganisations hook
|
|
20
29
|
const mockUseOrganisations = vi.fn();
|
|
21
|
-
vi.mock('../../
|
|
30
|
+
vi.mock('../../hooks/useOrganisations', () => ({
|
|
22
31
|
useOrganisations: () => mockUseOrganisations(),
|
|
23
32
|
}));
|
|
24
33
|
|
|
@@ -26,19 +35,19 @@ vi.mock('../../providers/OrganisationProvider', () => ({
|
|
|
26
35
|
let mockOnValueChange: ((value: string) => void) | null = null;
|
|
27
36
|
|
|
28
37
|
vi.mock('../Select', () => ({
|
|
29
|
-
Select: ({ children, value, onValueChange, disabled }:
|
|
38
|
+
Select: ({ children, value, onValueChange, disabled }: SelectProps & { value?: string; onValueChange?: (value: string) => void; disabled?: boolean }) => {
|
|
30
39
|
// Store the onValueChange callback for SelectItem to use
|
|
31
|
-
mockOnValueChange = onValueChange;
|
|
40
|
+
mockOnValueChange = onValueChange || null;
|
|
32
41
|
return (
|
|
33
42
|
<div data-testid="select" data-value={value} data-disabled={disabled}>
|
|
34
43
|
{children}
|
|
35
44
|
</div>
|
|
36
45
|
);
|
|
37
46
|
},
|
|
38
|
-
SelectContent: ({ children }:
|
|
47
|
+
SelectContent: ({ children }: SelectContentProps) => (
|
|
39
48
|
<div data-testid="select-content">{children}</div>
|
|
40
49
|
),
|
|
41
|
-
SelectItem: ({ children, value, disabled, className }:
|
|
50
|
+
SelectItem: ({ children, value, disabled, className }: SelectItemProps) => (
|
|
42
51
|
<div
|
|
43
52
|
data-testid={`select-item-${value}`}
|
|
44
53
|
data-disabled={disabled}
|
|
@@ -48,29 +57,29 @@ vi.mock('../Select', () => ({
|
|
|
48
57
|
{children}
|
|
49
58
|
</div>
|
|
50
59
|
),
|
|
51
|
-
SelectTrigger: ({ children, className }:
|
|
60
|
+
SelectTrigger: ({ children, className }: SelectTriggerProps) => (
|
|
52
61
|
<button data-testid="select-trigger" className={className}>
|
|
53
62
|
{children}
|
|
54
63
|
</button>
|
|
55
64
|
),
|
|
56
|
-
SelectValue: ({ placeholder }:
|
|
65
|
+
SelectValue: ({ placeholder }: SelectValueProps) => (
|
|
57
66
|
<span data-testid="select-value">{placeholder}</span>
|
|
58
67
|
),
|
|
59
68
|
}));
|
|
60
69
|
|
|
61
70
|
vi.mock('../Alert/Alert', () => ({
|
|
62
|
-
Alert: ({ children, variant }:
|
|
71
|
+
Alert: ({ children, variant }: React.HTMLAttributes<HTMLDivElement> & { variant?: "default" | "destructive" | "inline" }) => (
|
|
63
72
|
<div data-testid="alert" data-variant={variant}>
|
|
64
73
|
{children}
|
|
65
74
|
</div>
|
|
66
75
|
),
|
|
67
|
-
AlertDescription: ({ children }:
|
|
76
|
+
AlertDescription: ({ children }: React.HTMLAttributes<HTMLDivElement>) => (
|
|
68
77
|
<div data-testid="alert-description">{children}</div>
|
|
69
78
|
),
|
|
70
79
|
}));
|
|
71
80
|
|
|
72
81
|
vi.mock('../Button/Button', () => ({
|
|
73
|
-
Button: ({ children, onClick, disabled, variant, size, className }:
|
|
82
|
+
Button: ({ children, onClick, disabled, variant, size, className }: ButtonProps) => (
|
|
74
83
|
<button
|
|
75
84
|
data-testid="button"
|
|
76
85
|
onClick={onClick}
|
|
@@ -85,7 +94,7 @@ vi.mock('../Button/Button', () => ({
|
|
|
85
94
|
}));
|
|
86
95
|
|
|
87
96
|
vi.mock('../LoadingSpinner/LoadingSpinner', () => ({
|
|
88
|
-
LoadingSpinner: ({ size }:
|
|
97
|
+
LoadingSpinner: ({ size }: LoadingSpinnerProps) => (
|
|
89
98
|
<div data-testid="loading-spinner" data-size={size}>Loading...</div>
|
|
90
99
|
),
|
|
91
100
|
}));
|
|
@@ -59,7 +59,7 @@ import { Alert, AlertDescription } from '../Alert/Alert';
|
|
|
59
59
|
import { Button } from '../Button/Button';
|
|
60
60
|
import { LoadingSpinner } from '../LoadingSpinner/LoadingSpinner';
|
|
61
61
|
import { RefreshCw, AlertCircle, Building2, Shield } from 'lucide-react';
|
|
62
|
-
import { useOrganisations } from '../../
|
|
62
|
+
import { useOrganisations } from '../../hooks/useOrganisations';
|
|
63
63
|
import type { Organisation } from '../../types/organisation';
|
|
64
64
|
import { logger } from '../../utils/core/logger';
|
|
65
65
|
|