@jmruthers/pace-core 0.5.135 → 0.5.136
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{DataTable-C7GaRZye.d.ts → DataTable-CWAZZcXC.d.ts} +1 -1
- package/dist/{DataTable-A36PJG6N.js → DataTable-CYOHOX3O.js} +25 -13
- package/dist/{PublicLoadingSpinner-CUAnTvcg.d.ts → EventLogo-801uofbR.d.ts} +51 -135
- package/dist/UnifiedAuthProvider-5E5TUNMS.js +17 -0
- package/dist/{UnifiedAuthProvider-BVKmQd9u.d.ts → UnifiedAuthProvider-DJxGTftH.d.ts} +1 -1
- package/dist/{api-TNIBJWLM.js → api-45XYYO2A.js} +4 -3
- package/dist/{audit-T36HM7IM.js → audit-64X3VJXB.js} +3 -2
- package/dist/{chunk-CTJRBUX2.js → chunk-2TWNJ46Y.js} +2 -2
- package/dist/{chunk-UJI6WSMD.js → chunk-444EZN6N.js} +3 -3
- package/dist/chunk-444EZN6N.js.map +1 -0
- package/dist/{chunk-3CG5L6RN.js → chunk-4MT5BGGL.js} +90 -73
- package/dist/chunk-4MT5BGGL.js.map +1 -0
- package/dist/{chunk-PYUXFQJ3.js → chunk-56XJ3TU6.js} +2 -2
- package/dist/chunk-56XJ3TU6.js.map +1 -0
- package/dist/chunk-5DPZ5EAT.js +60 -0
- package/dist/chunk-5DPZ5EAT.js.map +1 -0
- package/dist/{chunk-66C4BSAY.js → chunk-ANBQRTPX.js} +9 -2
- package/dist/chunk-ANBQRTPX.js.map +1 -0
- package/dist/chunk-APIBCTL2.js +670 -0
- package/dist/chunk-APIBCTL2.js.map +1 -0
- package/dist/{chunk-GKHF54DI.js → chunk-BESYRHQM.js} +10 -4
- package/dist/chunk-BESYRHQM.js.map +1 -0
- package/dist/{chunk-WP5I5GLN.js → chunk-BVYWGZVV.js} +112 -97
- package/dist/chunk-BVYWGZVV.js.map +1 -0
- package/dist/{chunk-GEVIB2UB.js → chunk-ERISIBYU.js} +14 -5
- package/dist/chunk-ERISIBYU.js.map +1 -0
- package/dist/{chunk-CQZU6TFE.js → chunk-FHWWBIHA.js} +100 -62
- package/dist/chunk-FHWWBIHA.js.map +1 -0
- package/dist/{chunk-O3NWNXDY.js → chunk-FMUCXFII.js} +2 -2
- package/dist/chunk-FMUCXFII.js.map +1 -0
- package/dist/{chunk-GVDR7WNV.js → chunk-HJGGOMQ6.js} +194 -518
- package/dist/chunk-HJGGOMQ6.js.map +1 -0
- package/dist/{chunk-BDZUMRBD.js → chunk-K2WWTH7O.js} +13 -6
- package/dist/chunk-K2WWTH7O.js.map +1 -0
- package/dist/{chunk-BYXRHAIF.js → chunk-L6PGMCMD.js} +23 -14
- package/dist/chunk-L6PGMCMD.js.map +1 -0
- package/dist/chunk-LMC26NLJ.js +84 -0
- package/dist/chunk-LMC26NLJ.js.map +1 -0
- package/dist/{chunk-M6DDYFUD.js → chunk-LS353YLY.js} +19 -16
- package/dist/chunk-LS353YLY.js.map +1 -0
- package/dist/{chunk-ZYZCRSBD.js → chunk-LTV3XIJJ.js} +16 -11
- package/dist/chunk-LTV3XIJJ.js.map +1 -0
- package/dist/{chunk-HMNOSGVA.js → chunk-NOHEVYVX.js} +377 -666
- package/dist/chunk-NOHEVYVX.js.map +1 -0
- package/dist/{chunk-JCQZ6LA7.js → chunk-Q5QRDWKI.js} +9 -3
- package/dist/chunk-Q5QRDWKI.js.map +1 -0
- package/dist/chunk-S5OFRT4M.js +94 -0
- package/dist/chunk-S5OFRT4M.js.map +1 -0
- package/dist/{chunk-3DBFLLLU.js → chunk-SBVILCCA.js} +14 -9
- package/dist/chunk-SBVILCCA.js.map +1 -0
- package/dist/{chunk-TGIY2AR2.js → chunk-SL2YQDR6.js} +4 -3
- package/dist/{chunk-TGIY2AR2.js.map → chunk-SL2YQDR6.js.map} +1 -1
- package/dist/{chunk-VZ5OR6HD.js → chunk-TVYPTYOY.js} +55 -179
- package/dist/chunk-TVYPTYOY.js.map +1 -0
- package/dist/{chunk-ZV77RZMU.js → chunk-XARJS7CD.js} +2 -2
- package/dist/chunk-XDNLUEXI.js +138 -0
- package/dist/chunk-XDNLUEXI.js.map +1 -0
- package/dist/{chunk-F64FFPOZ.js → chunk-YLKIDTUK.js} +26 -20
- package/dist/chunk-YLKIDTUK.js.map +1 -0
- package/dist/{chunk-5F3NDPJV.js → chunk-ZZ2SS7NI.js} +10 -5
- package/dist/chunk-ZZ2SS7NI.js.map +1 -0
- package/dist/components.d.ts +7 -287
- package/dist/components.js +26 -157
- package/dist/components.js.map +1 -1
- package/dist/{file-reference-C9isKNPn.d.ts → file-reference-C6Gkn77H.d.ts} +1 -1
- package/dist/{formatting-DFcCxUEk.d.ts → formatting-CvUXy2mF.d.ts} +1 -1
- package/dist/hooks.d.ts +3 -3
- package/dist/hooks.js +22 -16
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +101 -9
- package/dist/index.js +43 -31
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +5 -4
- package/dist/rbac/index.js +13 -12
- package/dist/styles/index.js +2 -1
- package/dist/theming/runtime.d.ts +2 -19
- package/dist/theming/runtime.js +2 -1
- package/dist/{types-D5rqZQXk.d.ts → types-Dfz9dmVH.d.ts} +12 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.js +1 -1
- package/dist/{useInactivityTracker-MRUU55XI.js → useInactivityTracker-TO6ZOF35.js} +3 -2
- package/dist/{usePublicRouteParams-Dyt1tzI9.d.ts → usePublicRouteParams-B7PabvuH.d.ts} +1 -1
- package/dist/utils.d.ts +195 -232
- package/dist/utils.js +173 -331
- package/dist/utils.js.map +1 -1
- package/dist/{validation-DnhrNMju.d.ts → validation-8npbysjg.d.ts} +26 -8
- package/dist/validation.d.ts +261 -10
- package/dist/validation.js +82 -440
- package/dist/validation.js.map +1 -1
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +6 -6
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +6 -6
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +7 -7
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +4 -4
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +29 -4
- package/docs/api/interfaces/DataAccessRecord.md +9 -9
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +18 -18
- package/docs/api/interfaces/DataTableColumn.md +61 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
- package/docs/api/interfaces/EmptyStateConfig.md +5 -5
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +14 -14
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +152 -0
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +8 -8
- package/docs/api/interfaces/FileDisplayProps.md +15 -15
- 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 +1 -1
- package/docs/api/interfaces/FooterProps.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 +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +10 -10
- package/docs/api/interfaces/NavigationContextType.md +9 -9
- package/docs/api/interfaces/NavigationGuardProps.md +10 -10
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +7 -7
- 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 +27 -27
- package/docs/api/interfaces/PaceLoginPageProps.md +4 -4
- package/docs/api/interfaces/PageAccessRecord.md +8 -8
- package/docs/api/interfaces/PagePermissionContextType.md +8 -8
- package/docs/api/interfaces/PagePermissionGuardProps.md +11 -11
- package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
- package/docs/api/interfaces/PaletteData.md +4 -4
- package/docs/api/interfaces/PermissionEnforcerProps.md +11 -11
- package/docs/api/interfaces/ProtectedRouteProps.md +6 -6
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
- package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +10 -10
- package/docs/api/interfaces/RouteConfig.md +10 -10
- package/docs/api/interfaces/SecureDataContextType.md +9 -9
- package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +21 -0
- 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/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +53 -53
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +9 -9
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
- package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
- package/docs/api/interfaces/UsePublicEventReturn.md +5 -5
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +9 -9
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +4 -4
- package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
- package/docs/api/interfaces/UserEventAccess.md +11 -11
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +514 -212
- package/docs/api-reference/components.md +106 -26
- package/docs/architecture/README.md +0 -2
- package/docs/implementation-guides/data-tables.md +277 -13
- package/docs/implementation-guides/forms.md +1 -16
- package/docs/implementation-guides/permission-enforcement.md +8 -2
- package/examples/README.md +30 -14
- package/examples/STRUCTURE.md +125 -0
- package/examples/components/DataTable/HierarchicalActionsExample.tsx +421 -0
- package/examples/components/DataTable/HierarchicalExample.tsx +475 -0
- package/examples/components/DataTable/InitialPageSizeExample.tsx +177 -0
- package/examples/components/DataTable/PerformanceExample.tsx +506 -0
- package/examples/components/DataTable/index.ts +13 -0
- package/examples/components/Dialog/BasicHtmlTest.tsx +55 -0
- package/examples/components/Dialog/DebugHtmlExample.tsx +68 -0
- package/examples/components/Dialog/HtmlDialogExample.tsx +202 -0
- package/examples/components/Dialog/ScrollableDialogExample.tsx +290 -0
- package/examples/components/Dialog/SimpleHtmlTest.tsx +61 -0
- package/examples/components/Dialog/SmartDialogExample.tsx +322 -0
- package/examples/components/Dialog/index.ts +15 -0
- package/examples/components/index.ts +11 -0
- package/examples/features/index.ts +12 -0
- package/examples/{public-pages → features/public-pages}/CorrectPublicPageImplementation.tsx +1 -1
- package/examples/{public-pages → features/public-pages}/PublicEventPage.tsx +1 -1
- package/examples/{public-pages → features/public-pages}/PublicPageApp.tsx +1 -1
- package/examples/{public-pages → features/public-pages}/PublicPageUsageExample.tsx +1 -1
- package/examples/index.ts +11 -3
- package/package.json +30 -10
- package/src/components/Alert/Alert.tsx +1 -1
- package/src/components/Avatar/Avatar.tsx +1 -1
- package/src/components/Button/Button.tsx +1 -1
- package/src/components/Card/Card.tsx +1 -1
- package/src/components/Checkbox/Checkbox.tsx +1 -1
- package/src/components/DataTable/DataTable.test.tsx +1 -1
- package/src/components/DataTable/DataTable.tsx +1 -30
- package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +562 -0
- package/src/components/DataTable/__tests__/styles.test.ts +2 -2
- package/src/components/DataTable/components/ActionButtons.tsx +0 -15
- package/src/components/DataTable/components/DataTableCore.tsx +4 -185
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +1 -1
- package/src/components/DataTable/components/DataTableModals.tsx +1 -27
- package/src/components/DataTable/components/EditableRow.tsx +1 -1
- package/src/components/DataTable/components/ImportModal.tsx +2 -14
- package/src/components/DataTable/components/PaginationControls.tsx +1 -1
- package/src/components/DataTable/components/UnifiedTableBody.tsx +109 -82
- package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +1 -1
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +1 -1
- package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +1 -1
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +1 -1
- package/src/components/DataTable/examples/GroupingAggregationExample.tsx +273 -0
- package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +1 -1
- package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +1 -1
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +1 -1
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +1 -1
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +2 -23
- package/src/components/DataTable/index.ts +4 -0
- package/src/components/DataTable/styles.ts +1 -1
- package/src/components/DataTable/types.ts +13 -0
- package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +1 -1
- package/src/components/DataTable/utils/aggregationUtils.ts +161 -0
- package/src/components/DataTable/utils/exportUtils.ts +1 -1
- package/src/components/DataTable/utils/flexibleImport.ts +1 -11
- package/src/components/DataTable/utils/index.ts +1 -0
- package/src/components/DataTable/utils/paginationUtils.ts +1 -1
- package/src/components/Dialog/Dialog.tsx +2 -2
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +35 -7
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +5 -4
- package/src/components/EventSelector/EventSelector.tsx +3 -2
- package/src/components/FileDisplay/FileDisplay.tsx +2 -36
- package/src/components/FileUpload/FileUpload.test.tsx +2 -2
- package/src/components/FileUpload/FileUpload.tsx +2 -2
- package/src/components/Footer/Footer.tsx +1 -1
- package/src/components/Form/Form.test.tsx +4 -509
- package/src/components/Form/Form.tsx +1 -1
- package/src/components/Form/FormField.tsx +1 -1
- package/src/components/Form/index.ts +0 -12
- package/src/components/Header/Header.tsx +1 -1
- package/src/components/Input/Input.tsx +1 -1
- package/src/components/Label/Label.tsx +1 -1
- package/src/components/LoginForm/LoginForm.tsx +1 -1
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -3
- package/src/components/NavigationMenu/NavigationMenu.tsx +9 -8
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +4 -3
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -12
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +0 -16
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +0 -1
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -9
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +35 -3
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +13 -12
- package/src/components/PasswordReset/PasswordChangeForm.tsx +1 -1
- package/src/components/PasswordReset/index.ts +0 -2
- package/src/components/Progress/Progress.tsx +1 -1
- package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +35 -8
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -2
- package/src/components/PublicLayout/PublicErrorBoundary.tsx +1 -1
- package/src/components/PublicLayout/PublicLoadingSpinner.tsx +1 -1
- package/src/components/PublicLayout/PublicPageContextChecker.tsx +44 -43
- package/src/components/PublicLayout/PublicPageFooter.tsx +1 -1
- package/src/components/PublicLayout/PublicPageHeader.tsx +1 -15
- package/src/components/PublicLayout/PublicPageProvider.tsx +3 -2
- package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +2 -0
- package/src/components/PublicLayout/index.ts +4 -2
- package/src/components/Select/Select.tsx +1 -1
- package/src/components/{SessionRestorationLoader.tsx → SessionRestorationLoader/SessionRestorationLoader.tsx} +3 -2
- package/src/components/SessionRestorationLoader/index.ts +3 -0
- package/src/components/Switch/Switch.tsx +1 -1
- package/src/components/Table/Table.tsx +1 -1
- package/src/components/Toast/Toast.tsx +1 -1
- package/src/components/Tooltip/Tooltip.tsx +1 -1
- package/src/components/index.ts +4 -10
- package/src/hooks/__tests__/hooks.integration.test.tsx +37 -22
- package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +33 -17
- package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +28 -3
- package/src/hooks/__tests__/useFileDisplay.unit.test.ts +36 -9
- package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +26 -2
- package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +19 -6
- package/src/hooks/__tests__/usePermissionCache.simple.test.ts +17 -4
- package/src/hooks/__tests__/usePermissionCache.unit.test.ts +17 -4
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +26 -6
- package/src/hooks/__tests__/usePublicFileDisplay.test.ts +16 -6
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +3 -3
- package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +17 -3
- package/src/hooks/public/usePublicEvent.ts +7 -6
- package/src/hooks/public/usePublicEventLogo.ts +7 -4
- package/src/hooks/public/usePublicFileDisplay.ts +6 -150
- package/src/hooks/useComponentPerformance.ts +4 -1
- package/src/hooks/useDataTablePerformance.ts +4 -3
- package/src/hooks/useEventTheme.test.ts +18 -5
- package/src/hooks/useEventTheme.ts +4 -1
- package/src/hooks/useEvents.ts +2 -0
- package/src/hooks/useFileDisplay.ts +9 -8
- package/src/hooks/useFileReference.ts +4 -1
- package/src/hooks/useFileUrl.ts +4 -1
- package/src/hooks/useInactivityTracker.ts +5 -4
- package/src/hooks/useOrganisationSecurity.test.ts +33 -12
- package/src/hooks/useOrganisationSecurity.ts +8 -7
- package/src/hooks/usePerformanceMonitor.ts +6 -3
- package/src/hooks/usePermissionCache.ts +13 -6
- package/src/hooks/useSecureDataAccess.test.ts +2 -2
- package/src/hooks/useSecureDataAccess.ts +9 -8
- package/src/hooks/useSessionRestoration.ts +4 -1
- package/src/hooks/useStorage.ts +4 -1
- package/src/index.ts +16 -7
- package/src/providers/services/AuthServiceProvider.tsx +3 -2
- package/src/providers/services/EventServiceProvider.tsx +2 -1
- package/src/providers/services/InactivityServiceProvider.tsx +2 -1
- package/src/providers/services/OrganisationServiceProvider.tsx +2 -1
- package/src/providers/services/UnifiedAuthProvider.tsx +4 -3
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +22 -2
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +24 -2
- package/src/rbac/__tests__/cache-invalidation.test.ts +20 -6
- package/src/rbac/api.ts +5 -2
- package/src/rbac/audit-enhanced.ts +6 -6
- package/src/rbac/audit.test.ts +60 -38
- package/src/rbac/audit.ts +8 -8
- package/src/rbac/cache-invalidation.ts +7 -4
- package/src/rbac/components/EnhancedNavigationMenu.tsx +11 -5
- package/src/rbac/components/NavigationGuard.tsx +7 -3
- package/src/rbac/components/NavigationProvider.tsx +6 -3
- package/src/rbac/components/PagePermissionGuard.tsx +28 -16
- package/src/rbac/components/PagePermissionProvider.tsx +4 -1
- package/src/rbac/components/PermissionEnforcer.tsx +9 -3
- package/src/rbac/components/RoleBasedRouter.tsx +3 -1
- package/src/rbac/components/SecureDataProvider.tsx +7 -3
- package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +87 -61
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +83 -33
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +36 -13
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +2 -2
- package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +22 -8
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +19 -6
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +43 -17
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +42 -17
- package/src/rbac/engine.ts +15 -7
- package/src/rbac/hooks/usePermissions.ts +7 -3
- package/src/rbac/hooks/useResolvedScope.test.ts +2 -2
- package/src/rbac/hooks/useResolvedScope.ts +10 -7
- package/src/rbac/permissions.ts +5 -2
- package/src/rbac/security.test.ts +27 -16
- package/src/rbac/security.ts +5 -4
- package/src/services/AuthService.ts +22 -21
- package/src/services/EventService.ts +12 -12
- package/src/services/InactivityService.ts +5 -4
- package/src/services/OrganisationService.ts +26 -25
- package/src/services/__tests__/AuthService.test.ts +51 -19
- package/src/services/__tests__/EventService.test.ts +37 -5
- package/src/services/__tests__/InactivityService.test.ts +38 -4
- package/src/services/__tests__/OrganisationService.test.ts +3 -8
- package/src/services/base/BaseService.ts +3 -1
- package/src/theming/__tests__/runtime.test.ts +21 -12
- package/src/theming/parseEventColours.ts +5 -19
- package/src/theming/runtime.ts +8 -4
- package/src/types/validation.ts +2 -29
- package/src/utils/__tests__/appConfig.unit.test.ts +1 -1
- package/src/utils/__tests__/audit.unit.test.ts +1 -1
- package/src/utils/__tests__/auth-utils.unit.test.ts +1 -1
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +19 -19
- package/src/utils/__tests__/cn.unit.test.ts +1 -1
- package/src/utils/__tests__/debugLogger.test.ts +1 -1
- package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -1
- package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -1
- package/src/utils/__tests__/formatting.unit.test.ts +1 -1
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +1 -1
- package/src/utils/__tests__/logger.unit.test.ts +1 -1
- package/src/utils/__tests__/organisationContext.unit.test.ts +1 -1
- package/src/utils/__tests__/performanceBenchmark.test.ts +1 -1
- package/src/utils/__tests__/performanceBudgets.unit.test.ts +1 -1
- package/src/utils/__tests__/permissionTypes.unit.test.ts +1 -1
- package/src/utils/__tests__/permissionUtils.unit.test.ts +1 -1
- package/src/utils/__tests__/sanitization.unit.test.ts +1 -1
- package/src/utils/__tests__/schemaUtils.unit.test.ts +1 -1
- package/src/utils/__tests__/secureDataAccess.unit.test.ts +1 -1
- package/src/utils/__tests__/secureErrors.unit.test.ts +33 -15
- package/src/utils/__tests__/secureStorage.unit.test.ts +1 -1
- package/src/utils/__tests__/security.unit.test.ts +40 -18
- package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -1
- package/src/utils/__tests__/sessionTracking.unit.test.ts +40 -29
- package/src/utils/__tests__/validationUtils.unit.test.ts +19 -6
- package/src/utils/{appIdResolver.test.ts → app/appIdResolver.test.ts} +28 -30
- package/src/utils/{appIdResolver.ts → app/appIdResolver.ts} +8 -5
- package/src/utils/{appNameResolver.test.ts → app/appNameResolver.test.ts} +1 -1
- package/src/utils/{appNameResolver.ts → app/appNameResolver.ts} +5 -1
- package/src/utils/{organisationContext.ts → context/organisationContext.ts} +6 -3
- package/src/utils/{sessionTracking.ts → context/sessionTracking.ts} +11 -12
- package/src/utils/{logger.ts → core/logger.ts} +4 -2
- package/src/utils/{deviceFingerprint.ts → device/deviceFingerprint.ts} +1 -1
- package/src/utils/{lazyLoad.tsx → dynamic/lazyLoad.tsx} +2 -2
- package/src/utils/{file-reference.test.ts → file-reference/__tests__/file-reference.test.ts} +5 -5
- package/src/utils/{file-reference.ts → file-reference/index.ts} +20 -38
- package/src/utils/index.ts +32 -54
- package/src/utils/{secureErrors.ts → security/secureErrors.ts} +6 -3
- package/src/utils/{security.ts → security/security.ts} +5 -2
- package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -4
- package/src/utils/storage/helpers.ts +15 -8
- package/src/{components/Dialog/utils/__tests__/safeHtml.unit.test.ts → utils/validation/__tests__/htmlSanitization.unit.test.ts} +9 -15
- package/src/{validation → utils/validation}/csrf.ts +1 -1
- package/src/{components/Dialog/utils/safeHtml.ts → utils/validation/htmlSanitization.ts} +9 -10
- package/src/utils/validation/index.ts +79 -0
- package/src/utils/{sanitization.ts → validation/sanitization.ts} +71 -2
- package/src/{validation/schemaUtils.ts → utils/validation/schema.ts} +11 -6
- package/src/{validation → utils/validation}/sqlInjectionProtection.ts +2 -0
- package/src/utils/{validationUtils.ts → validation/validationUtils.ts} +4 -1
- package/src/validation/index.ts +3 -34
- package/dist/UnifiedAuthProvider-CQDZRJIS.js +0 -16
- package/dist/chunk-24MKLB7U.js +0 -81
- package/dist/chunk-24MKLB7U.js.map +0 -1
- package/dist/chunk-3CG5L6RN.js.map +0 -1
- package/dist/chunk-3DBFLLLU.js.map +0 -1
- package/dist/chunk-5F3NDPJV.js.map +0 -1
- package/dist/chunk-66C4BSAY.js.map +0 -1
- package/dist/chunk-BDZUMRBD.js.map +0 -1
- package/dist/chunk-BYXRHAIF.js.map +0 -1
- package/dist/chunk-CDQ3PX7L.js +0 -18
- package/dist/chunk-CDQ3PX7L.js.map +0 -1
- package/dist/chunk-CQZU6TFE.js.map +0 -1
- package/dist/chunk-F64FFPOZ.js.map +0 -1
- package/dist/chunk-GEVIB2UB.js.map +0 -1
- package/dist/chunk-GKHF54DI.js.map +0 -1
- package/dist/chunk-GVDR7WNV.js.map +0 -1
- package/dist/chunk-HMNOSGVA.js.map +0 -1
- package/dist/chunk-JCQZ6LA7.js.map +0 -1
- package/dist/chunk-M6DDYFUD.js.map +0 -1
- package/dist/chunk-O3NWNXDY.js.map +0 -1
- package/dist/chunk-PYUXFQJ3.js.map +0 -1
- package/dist/chunk-UJI6WSMD.js.map +0 -1
- package/dist/chunk-VZ5OR6HD.js.map +0 -1
- package/dist/chunk-WP5I5GLN.js.map +0 -1
- package/dist/chunk-ZYZCRSBD.js.map +0 -1
- package/src/components/Dialog/README.md +0 -804
- package/src/components/Form/FormErrorSummary.tsx +0 -113
- package/src/components/Form/FormFieldset.tsx +0 -127
- package/src/components/Form/FormLiveRegion.tsx +0 -198
- package/src/components/PasswordReset/PasswordResetForm.test.tsx +0 -597
- package/src/components/PasswordReset/PasswordResetForm.tsx +0 -201
- package/src/components/PublicLayout/PublicPageDebugger.tsx +0 -104
- package/src/components/PublicLayout/PublicPageDiagnostic.tsx +0 -162
- package/src/components/PublicLayout/__tests__/PublicPageDebugger.test.tsx +0 -185
- package/src/examples/CorrectPublicPageImplementation.tsx +0 -304
- package/src/examples/PublicEventPage.tsx +0 -287
- package/src/examples/PublicPageApp.tsx +0 -321
- package/src/examples/PublicPageUsageExample.tsx +0 -218
- package/src/utils/schemaUtils.ts +0 -37
- package/src/validation/__tests__/common.unit.test.ts +0 -101
- package/src/validation/__tests__/csrf.unit.test.ts +0 -365
- package/src/validation/__tests__/passwordSchema.unit.test.ts +0 -203
- package/src/validation/__tests__/sanitization.unit.test.ts +0 -250
- package/src/validation/__tests__/schemaUtils.unit.test.ts +0 -451
- package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +0 -462
- package/src/validation/__tests__/user.unit.test.ts +0 -440
- package/src/validation/sanitization.ts +0 -96
- /package/dist/{DataTable-A36PJG6N.js.map → DataTable-CYOHOX3O.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-CQDZRJIS.js.map → UnifiedAuthProvider-5E5TUNMS.js.map} +0 -0
- /package/dist/{api-TNIBJWLM.js.map → api-45XYYO2A.js.map} +0 -0
- /package/dist/{audit-T36HM7IM.js.map → audit-64X3VJXB.js.map} +0 -0
- /package/dist/{chunk-CTJRBUX2.js.map → chunk-2TWNJ46Y.js.map} +0 -0
- /package/dist/{chunk-ZV77RZMU.js.map → chunk-XARJS7CD.js.map} +0 -0
- /package/dist/{useInactivityTracker-MRUU55XI.js.map → useInactivityTracker-TO6ZOF35.js.map} +0 -0
- /package/examples/{public-pages → features/public-pages}/index.ts +0 -0
- /package/examples/{RBAC → features/rbac}/CompleteRBACExample.tsx +0 -0
- /package/examples/{RBAC → features/rbac}/EventBasedApp.tsx +0 -0
- /package/examples/{RBAC → features/rbac}/PermissionExample.tsx +0 -0
- /package/examples/{RBAC → features/rbac}/index.ts +0 -0
- /package/src/utils/{appConfig.ts → app/appConfig.ts} +0 -0
- /package/src/utils/{appNameResolver.simple.test.ts → app/appNameResolver.simple.test.ts} +0 -0
- /package/src/utils/{audit.ts → audit/audit.ts} +0 -0
- /package/src/utils/{organisationContext.test.ts → context/organisationContext.test.ts} +0 -0
- /package/src/utils/{cn.ts → core/cn.ts} +0 -0
- /package/src/utils/{debugLogger.ts → core/debugLogger.ts} +0 -0
- /package/src/utils/{dynamicUtils.ts → dynamic/dynamicUtils.ts} +0 -0
- /package/src/utils/{formatDate.test.ts → formatting/formatDate.test.ts} +0 -0
- /package/src/utils/{formatting.ts → formatting/formatting.ts} +0 -0
- /package/src/utils/{bundleAnalysis.ts → performance/bundleAnalysis.ts} +0 -0
- /package/src/utils/{performanceBenchmark.ts → performance/performanceBenchmark.ts} +0 -0
- /package/src/utils/{performanceBudgets.ts → performance/performanceBudgets.ts} +0 -0
- /package/src/utils/{permissionTypes.ts → permissions/permissionTypes.ts} +0 -0
- /package/src/utils/{permissionUtils.test.ts → permissions/permissionUtils.test.ts} +0 -0
- /package/src/utils/{permissionUtils.ts → permissions/permissionUtils.ts} +0 -0
- /package/src/utils/{auth-utils.ts → security/auth-utils.ts} +0 -0
- /package/src/utils/{secureDataAccess.test.ts → security/secureDataAccess.test.ts} +0 -0
- /package/src/utils/{secureDataAccess.ts → security/secureDataAccess.ts} +0 -0
- /package/src/utils/{secureStorage.ts → security/secureStorage.ts} +0 -0
- /package/src/utils/{securityMonitor.ts → security/securityMonitor.ts} +0 -0
- /package/src/{validation → utils/validation}/common.ts +0 -0
- /package/src/{validation → utils/validation}/passwordSchema.ts +0 -0
- /package/src/{validation → utils/validation}/user.ts +0 -0
- /package/src/utils/{validation.ts → validation/validation.ts} +0 -0
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
AuditEventSource,
|
|
16
16
|
RBACAuditEvent
|
|
17
17
|
} from './types';
|
|
18
|
+
import { logger } from '../utils/core/logger';
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Enhanced audit event payload for permission checks
|
|
@@ -154,7 +155,7 @@ export class EnhancedRBACAuditManager {
|
|
|
154
155
|
|
|
155
156
|
// Validate required fields before attempting to insert
|
|
156
157
|
if (!event.userId || !event.organisationId) {
|
|
157
|
-
|
|
158
|
+
logger.warn('RBAC Audit', 'Skipping audit event - missing required fields:', {
|
|
158
159
|
userId: event.userId,
|
|
159
160
|
organisationId: event.organisationId,
|
|
160
161
|
eventType: event.type
|
|
@@ -184,7 +185,7 @@ export class EnhancedRBACAuditManager {
|
|
|
184
185
|
|
|
185
186
|
if (error) {
|
|
186
187
|
// Log the error for debugging
|
|
187
|
-
|
|
188
|
+
logger.warn('RBAC Audit', 'Failed to insert audit event:', {
|
|
188
189
|
error: error.message,
|
|
189
190
|
code: error.code,
|
|
190
191
|
details: error.details,
|
|
@@ -199,7 +200,7 @@ export class EnhancedRBACAuditManager {
|
|
|
199
200
|
}
|
|
200
201
|
} catch (error) {
|
|
201
202
|
// Log unexpected errors
|
|
202
|
-
|
|
203
|
+
logger.error('RBAC Audit', 'Unexpected error during audit logging:', error);
|
|
203
204
|
|
|
204
205
|
// Use fallback logging if enabled
|
|
205
206
|
if (this.fallbackEnabled) {
|
|
@@ -215,11 +216,10 @@ export class EnhancedRBACAuditManager {
|
|
|
215
216
|
* @param error - The error that occurred
|
|
216
217
|
*/
|
|
217
218
|
private logFallbackEvent(event: EnhancedAuditEventPayload, error: any): void {
|
|
218
|
-
|
|
219
|
+
logger.debug('RBAC Audit Fallback', 'Database audit logging failed, using console fallback', {
|
|
219
220
|
timestamp: new Date().toISOString(),
|
|
220
221
|
event,
|
|
221
|
-
error: error?.message || error
|
|
222
|
-
note: 'Database audit logging failed, using console fallback'
|
|
222
|
+
error: error?.message || error
|
|
223
223
|
});
|
|
224
224
|
}
|
|
225
225
|
|
package/src/rbac/audit.test.ts
CHANGED
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
} from './audit';
|
|
25
25
|
import { UUID, AuditEventSource } from './types';
|
|
26
26
|
import { Database } from '../types/database';
|
|
27
|
+
import { Logger, LogLevel } from '../utils/core/logger';
|
|
27
28
|
|
|
28
29
|
// Mock Supabase client
|
|
29
30
|
const createMockSupabaseClient = () => {
|
|
@@ -350,17 +351,38 @@ describe('RBACAuditManager', () => {
|
|
|
350
351
|
});
|
|
351
352
|
|
|
352
353
|
describe('Fallback Logging', () => {
|
|
353
|
-
let
|
|
354
|
+
let consoleDebugSpy: any;
|
|
354
355
|
let consoleWarnSpy: any;
|
|
356
|
+
let consoleErrorSpy: any;
|
|
357
|
+
let originalMode: string | undefined;
|
|
355
358
|
|
|
356
359
|
beforeEach(() => {
|
|
357
|
-
|
|
360
|
+
// Ensure logger is enabled by setting MODE to development
|
|
361
|
+
originalMode = import.meta.env.MODE;
|
|
362
|
+
(import.meta.env as any).MODE = 'development';
|
|
363
|
+
|
|
364
|
+
// Configure logger to ensure it logs in test environment
|
|
365
|
+
Logger.configure({
|
|
366
|
+
level: LogLevel.DEBUG,
|
|
367
|
+
includeTimestamp: false,
|
|
368
|
+
includeComponent: true,
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
// Logger uses console.debug for debug logs, console.warn for warnings, console.error for errors
|
|
372
|
+
consoleDebugSpy = vi.spyOn(console, 'debug').mockImplementation(() => {});
|
|
358
373
|
consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
374
|
+
consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
359
375
|
});
|
|
360
376
|
|
|
361
377
|
afterEach(() => {
|
|
362
|
-
|
|
378
|
+
consoleDebugSpy.mockRestore();
|
|
363
379
|
consoleWarnSpy.mockRestore();
|
|
380
|
+
consoleErrorSpy.mockRestore();
|
|
381
|
+
|
|
382
|
+
// Restore original mode
|
|
383
|
+
if (originalMode !== undefined) {
|
|
384
|
+
(import.meta.env as any).MODE = originalMode;
|
|
385
|
+
}
|
|
364
386
|
});
|
|
365
387
|
|
|
366
388
|
it('uses fallback logging when database insert fails', async () => {
|
|
@@ -388,9 +410,9 @@ describe('RBACAuditManager', () => {
|
|
|
388
410
|
|
|
389
411
|
await auditManager.emitPermissionCheck(event);
|
|
390
412
|
|
|
391
|
-
// Verify fallback logging was called
|
|
392
|
-
expect(
|
|
393
|
-
'[RBAC Audit Fallback]',
|
|
413
|
+
// Verify fallback logging was called (logger.debug calls console.debug)
|
|
414
|
+
expect(consoleDebugSpy).toHaveBeenCalledWith(
|
|
415
|
+
expect.stringContaining('[RBAC Audit Fallback]'),
|
|
394
416
|
expect.objectContaining({
|
|
395
417
|
timestamp: expect.any(String),
|
|
396
418
|
event: expect.objectContaining({
|
|
@@ -399,8 +421,7 @@ describe('RBACAuditManager', () => {
|
|
|
399
421
|
organisationId: 'org-456',
|
|
400
422
|
permission: 'read:users'
|
|
401
423
|
}),
|
|
402
|
-
error: 'Database connection failed'
|
|
403
|
-
note: 'Database audit logging failed, using console fallback'
|
|
424
|
+
error: 'Database connection failed'
|
|
404
425
|
})
|
|
405
426
|
);
|
|
406
427
|
});
|
|
@@ -421,9 +442,9 @@ describe('RBACAuditManager', () => {
|
|
|
421
442
|
|
|
422
443
|
await auditManager.emitPermissionCheck(event);
|
|
423
444
|
|
|
424
|
-
// Verify fallback logging was called
|
|
425
|
-
expect(
|
|
426
|
-
'[RBAC Audit Fallback]',
|
|
445
|
+
// Verify fallback logging was called (logger.debug calls console.debug)
|
|
446
|
+
expect(consoleDebugSpy).toHaveBeenCalledWith(
|
|
447
|
+
expect.stringContaining('[RBAC Audit Fallback]'),
|
|
427
448
|
expect.objectContaining({
|
|
428
449
|
timestamp: expect.any(String),
|
|
429
450
|
event: expect.objectContaining({
|
|
@@ -435,8 +456,7 @@ describe('RBACAuditManager', () => {
|
|
|
435
456
|
source: 'api',
|
|
436
457
|
duration_ms: 100
|
|
437
458
|
}),
|
|
438
|
-
error: 'Network error'
|
|
439
|
-
note: 'Database audit logging failed, using console fallback'
|
|
459
|
+
error: 'Network error' // Error is converted to string message
|
|
440
460
|
})
|
|
441
461
|
);
|
|
442
462
|
});
|
|
@@ -467,9 +487,9 @@ describe('RBACAuditManager', () => {
|
|
|
467
487
|
await auditManager.emitPermissionCheck(event);
|
|
468
488
|
|
|
469
489
|
// Verify fallback logging was NOT called
|
|
470
|
-
expect(
|
|
490
|
+
expect(consoleDebugSpy).not.toHaveBeenCalled();
|
|
471
491
|
|
|
472
|
-
// But warning should still be logged
|
|
492
|
+
// But warning should still be logged (logger.warn calls console.warn)
|
|
473
493
|
expect(consoleWarnSpy).toHaveBeenCalled();
|
|
474
494
|
});
|
|
475
495
|
|
|
@@ -499,8 +519,8 @@ describe('RBACAuditManager', () => {
|
|
|
499
519
|
|
|
500
520
|
await auditManager.emitPermissionCheck(event);
|
|
501
521
|
|
|
502
|
-
// Verify fallback logging was called after re-enabling
|
|
503
|
-
expect(
|
|
522
|
+
// Verify fallback logging was called after re-enabling (logger.debug calls console.debug)
|
|
523
|
+
expect(consoleDebugSpy).toHaveBeenCalled();
|
|
504
524
|
});
|
|
505
525
|
|
|
506
526
|
it('fallback logging includes correct event data', async () => {
|
|
@@ -531,27 +551,29 @@ describe('RBACAuditManager', () => {
|
|
|
531
551
|
|
|
532
552
|
await auditManager.emitPermissionCheck(event);
|
|
533
553
|
|
|
534
|
-
|
|
535
|
-
expect(
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
554
|
+
// Logger.debug formats the message, so we check the formatted string and the data object
|
|
555
|
+
expect(consoleDebugSpy).toHaveBeenCalledWith(
|
|
556
|
+
expect.stringContaining('[RBAC Audit Fallback]'),
|
|
557
|
+
expect.objectContaining({
|
|
558
|
+
timestamp: expect.any(String),
|
|
559
|
+
event: expect.objectContaining({
|
|
560
|
+
type: 'permission_check',
|
|
561
|
+
userId: 'user-123',
|
|
562
|
+
organisationId: 'org-456',
|
|
563
|
+
eventId: 'event-789',
|
|
564
|
+
appId: 'app-101',
|
|
565
|
+
permission: 'read:users',
|
|
566
|
+
decision: false,
|
|
567
|
+
source: 'ui',
|
|
568
|
+
bypass: true,
|
|
569
|
+
duration_ms: 250,
|
|
570
|
+
cache_hit: true,
|
|
571
|
+
cache_source: 'memory',
|
|
572
|
+
metadata: { test: 'data' }
|
|
573
|
+
}),
|
|
574
|
+
error: 'Database error'
|
|
575
|
+
})
|
|
576
|
+
);
|
|
555
577
|
});
|
|
556
578
|
});
|
|
557
579
|
|
package/src/rbac/audit.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
AuditEventSource,
|
|
15
15
|
RBACAuditEvent
|
|
16
16
|
} from './types';
|
|
17
|
+
import { logger } from '../utils/core/logger';
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* Audit event payload for permission checks
|
|
@@ -155,7 +156,7 @@ export class RBACAuditManager {
|
|
|
155
156
|
// Validate required fields before attempting to insert
|
|
156
157
|
// MANDATORY: All audit events must have userId
|
|
157
158
|
if (!event.userId) {
|
|
158
|
-
|
|
159
|
+
logger.error('RBAC Audit', 'CRITICAL: Cannot log audit event without userId:', {
|
|
159
160
|
eventType: event.type,
|
|
160
161
|
organisationId: event.organisationId
|
|
161
162
|
});
|
|
@@ -165,7 +166,7 @@ export class RBACAuditManager {
|
|
|
165
166
|
// WARNING: Some audit events may not have organisationId (e.g., global admin operations)
|
|
166
167
|
// Log these for security monitoring even if organisationId is missing
|
|
167
168
|
if (!event.organisationId) {
|
|
168
|
-
|
|
169
|
+
logger.warn('RBAC Audit', 'Audit event without organisation context:', {
|
|
169
170
|
userId: event.userId,
|
|
170
171
|
eventType: event.type,
|
|
171
172
|
note: 'This should be investigated for security compliance'
|
|
@@ -176,7 +177,7 @@ export class RBACAuditManager {
|
|
|
176
177
|
// Since organisationId is now required in SecurityContext, this should rarely happen
|
|
177
178
|
// But we still handle the edge case properly without masking it
|
|
178
179
|
if (!event.organisationId) {
|
|
179
|
-
|
|
180
|
+
logger.warn('RBAC Audit', 'Audit event without organisation context - this should be investigated:', {
|
|
180
181
|
userId: event.userId,
|
|
181
182
|
eventType: event.type,
|
|
182
183
|
note: 'Organisation context is required for RBAC operations. This may indicate a security issue or missing context derivation.'
|
|
@@ -222,7 +223,7 @@ export class RBACAuditManager {
|
|
|
222
223
|
|
|
223
224
|
if (error) {
|
|
224
225
|
// Log the error for debugging
|
|
225
|
-
|
|
226
|
+
logger.warn('RBAC Audit', 'Failed to insert audit event:', {
|
|
226
227
|
error: error.message,
|
|
227
228
|
code: error.code,
|
|
228
229
|
details: error.details,
|
|
@@ -237,7 +238,7 @@ export class RBACAuditManager {
|
|
|
237
238
|
}
|
|
238
239
|
} catch (error) {
|
|
239
240
|
// Log unexpected errors
|
|
240
|
-
|
|
241
|
+
logger.error('RBAC Audit', 'Unexpected error during audit logging:', error);
|
|
241
242
|
|
|
242
243
|
// Use fallback logging if enabled
|
|
243
244
|
if (this.fallbackEnabled) {
|
|
@@ -253,11 +254,10 @@ export class RBACAuditManager {
|
|
|
253
254
|
* @param error - The error that occurred
|
|
254
255
|
*/
|
|
255
256
|
private logFallbackEvent(event: AuditEventPayload, error: any): void {
|
|
256
|
-
|
|
257
|
+
logger.debug('RBAC Audit Fallback', 'Database audit logging failed, using console fallback', {
|
|
257
258
|
timestamp: new Date().toISOString(),
|
|
258
259
|
event,
|
|
259
|
-
error: error?.message || error
|
|
260
|
-
note: 'Database audit logging failed, using console fallback'
|
|
260
|
+
error: error?.message || error
|
|
261
261
|
});
|
|
262
262
|
}
|
|
263
263
|
|
|
@@ -12,6 +12,9 @@ import { Database } from '../types/database';
|
|
|
12
12
|
import { rbacCache, CACHE_PATTERNS } from './cache';
|
|
13
13
|
import { emitAuditEvent } from './audit';
|
|
14
14
|
import { UUID } from './types';
|
|
15
|
+
import { createLogger } from '../utils/core/logger';
|
|
16
|
+
|
|
17
|
+
const log = createLogger('RBACCache');
|
|
15
18
|
|
|
16
19
|
/**
|
|
17
20
|
* Cache invalidation patterns for different RBAC changes
|
|
@@ -143,7 +146,7 @@ export class RBACCacheInvalidationManager {
|
|
|
143
146
|
* @param reason - Reason for invalidation
|
|
144
147
|
*/
|
|
145
148
|
private invalidatePatterns(patterns: string[], reason: string): void {
|
|
146
|
-
|
|
149
|
+
log.debug(`Invalidating patterns: ${patterns.join(', ')} (${reason})`);
|
|
147
150
|
|
|
148
151
|
patterns.forEach(pattern => {
|
|
149
152
|
rbacCache.invalidate(pattern);
|
|
@@ -170,7 +173,7 @@ export class RBACCacheInvalidationManager {
|
|
|
170
173
|
cache_invalidation: true
|
|
171
174
|
}
|
|
172
175
|
}).catch(error => {
|
|
173
|
-
|
|
176
|
+
log.warn('Failed to log cache invalidation audit event:', error);
|
|
174
177
|
});
|
|
175
178
|
}
|
|
176
179
|
|
|
@@ -180,7 +183,7 @@ export class RBACCacheInvalidationManager {
|
|
|
180
183
|
private setupRealtimeSubscriptions(): void {
|
|
181
184
|
// Check if realtime is available (skip in test environments)
|
|
182
185
|
if (!this.supabase.channel || typeof this.supabase.channel !== 'function') {
|
|
183
|
-
|
|
186
|
+
log.debug('Realtime not available, skipping subscriptions');
|
|
184
187
|
return;
|
|
185
188
|
}
|
|
186
189
|
|
|
@@ -287,7 +290,7 @@ export class RBACCacheInvalidationManager {
|
|
|
287
290
|
* Clear all cache entries
|
|
288
291
|
*/
|
|
289
292
|
clearAllCache(): void {
|
|
290
|
-
|
|
293
|
+
log.debug('Clearing all cache entries');
|
|
291
294
|
rbacCache.clear();
|
|
292
295
|
}
|
|
293
296
|
}
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
import React, { useMemo, useCallback, useEffect, useState } from 'react';
|
|
59
59
|
import { useNavigationPermissions, NavigationItem } from './NavigationProvider';
|
|
60
60
|
import NavigationGuard from './NavigationGuard';
|
|
61
|
+
import { getRBACLogger } from '../config';
|
|
61
62
|
|
|
62
63
|
export interface EnhancedNavigationMenuProps {
|
|
63
64
|
/** Navigation items to display */
|
|
@@ -148,7 +149,8 @@ export function EnhancedNavigationMenu({
|
|
|
148
149
|
}
|
|
149
150
|
|
|
150
151
|
if (auditLog) {
|
|
151
|
-
|
|
152
|
+
const logger = getRBACLogger();
|
|
153
|
+
logger.debug('Navigation access attempt:', {
|
|
152
154
|
item: item.id,
|
|
153
155
|
allowed,
|
|
154
156
|
strictMode,
|
|
@@ -164,7 +166,8 @@ export function EnhancedNavigationMenu({
|
|
|
164
166
|
}
|
|
165
167
|
|
|
166
168
|
if (strictMode) {
|
|
167
|
-
|
|
169
|
+
const logger = getRBACLogger();
|
|
170
|
+
logger.error(`STRICT MODE VIOLATION: User attempted to access protected navigation item without permission`, {
|
|
168
171
|
item: item.id,
|
|
169
172
|
path: item.path,
|
|
170
173
|
permissions: item.permissions,
|
|
@@ -187,7 +190,8 @@ export function EnhancedNavigationMenu({
|
|
|
187
190
|
|
|
188
191
|
// Record navigation attempt
|
|
189
192
|
if (auditLog) {
|
|
190
|
-
|
|
193
|
+
const logger = getRBACLogger();
|
|
194
|
+
logger.debug('Navigation item clicked:', {
|
|
191
195
|
item: item.id,
|
|
192
196
|
path: item.path,
|
|
193
197
|
permissions: item.permissions,
|
|
@@ -266,14 +270,16 @@ export function EnhancedNavigationMenu({
|
|
|
266
270
|
// Log strict mode violations
|
|
267
271
|
useEffect(() => {
|
|
268
272
|
if (strictMode && auditLog) {
|
|
269
|
-
|
|
273
|
+
const logger = getRBACLogger();
|
|
274
|
+
logger.debug('Strict mode enabled - all navigation access attempts will be logged and enforced');
|
|
270
275
|
}
|
|
271
276
|
}, [strictMode, auditLog]);
|
|
272
277
|
|
|
273
278
|
// Log navigation menu initialization
|
|
274
279
|
useEffect(() => {
|
|
275
280
|
if (auditLog) {
|
|
276
|
-
|
|
281
|
+
const logger = getRBACLogger();
|
|
282
|
+
logger.debug('Navigation menu initialized:', {
|
|
277
283
|
totalItems: items.length,
|
|
278
284
|
filteredItems: filteredItems.length,
|
|
279
285
|
strictMode,
|
|
@@ -70,6 +70,7 @@ import { useUnifiedAuth } from '../../providers/UnifiedAuthProvider';
|
|
|
70
70
|
import { UUID, Permission, Scope } from '../types';
|
|
71
71
|
import { createScopeFromEvent } from '../utils/eventContext';
|
|
72
72
|
import { NavigationItem } from './NavigationProvider';
|
|
73
|
+
import { getRBACLogger } from '../config';
|
|
73
74
|
|
|
74
75
|
export interface NavigationGuardProps {
|
|
75
76
|
/** Navigation item being protected */
|
|
@@ -215,7 +216,8 @@ export function NavigationGuard({
|
|
|
215
216
|
// Log navigation access attempt for audit
|
|
216
217
|
useEffect(() => {
|
|
217
218
|
if (auditLog && hasChecked && !isLoading) {
|
|
218
|
-
|
|
219
|
+
const logger = getRBACLogger();
|
|
220
|
+
logger.debug('Navigation access attempt:', {
|
|
219
221
|
navigationItem: navigationItem.id,
|
|
220
222
|
permissions: navigationItem.permissions,
|
|
221
223
|
userId: user?.id,
|
|
@@ -230,7 +232,8 @@ export function NavigationGuard({
|
|
|
230
232
|
// Handle strict mode violations
|
|
231
233
|
useEffect(() => {
|
|
232
234
|
if (strictMode && hasChecked && !isLoading && !hasRequiredPermissions) {
|
|
233
|
-
|
|
235
|
+
const logger = getRBACLogger();
|
|
236
|
+
logger.error(`STRICT MODE VIOLATION: User attempted to access protected navigation item without permission`, {
|
|
234
237
|
navigationItem: navigationItem.id,
|
|
235
238
|
permissions: navigationItem.permissions,
|
|
236
239
|
userId: user?.id,
|
|
@@ -248,7 +251,8 @@ export function NavigationGuard({
|
|
|
248
251
|
|
|
249
252
|
// Show error state
|
|
250
253
|
if (checkError) {
|
|
251
|
-
|
|
254
|
+
const logger = getRBACLogger();
|
|
255
|
+
logger.error(`Permission check failed for navigation item ${navigationItem.id}:`, checkError);
|
|
252
256
|
return <>{fallback}</>;
|
|
253
257
|
}
|
|
254
258
|
|
|
@@ -58,6 +58,8 @@ import React, { createContext, useContext, useState, useCallback, useMemo, useEf
|
|
|
58
58
|
import { useUnifiedAuth } from '../../providers/UnifiedAuthProvider';
|
|
59
59
|
import { useCan } from '../hooks';
|
|
60
60
|
import { UUID, Scope, Permission } from '../types';
|
|
61
|
+
import { getRBACLogger } from '../config';
|
|
62
|
+
import { logger } from '../../utils/core/logger';
|
|
61
63
|
|
|
62
64
|
export interface NavigationItem {
|
|
63
65
|
/** Unique identifier for the navigation item */
|
|
@@ -199,7 +201,7 @@ export function NavigationProvider({
|
|
|
199
201
|
|
|
200
202
|
// If no permissions are defined for the navigation item, deny access by default
|
|
201
203
|
if (!item.permissions || item.permissions.length === 0) {
|
|
202
|
-
|
|
204
|
+
logger.warn('NavigationProvider', `Navigation item "${item.id}" has no permissions defined - denying access`);
|
|
203
205
|
return false;
|
|
204
206
|
}
|
|
205
207
|
|
|
@@ -218,7 +220,7 @@ export function NavigationProvider({
|
|
|
218
220
|
// Handle errors gracefully - allow access when there are permission check errors (graceful degradation)
|
|
219
221
|
// This ensures navigation doesn't break when the permission service has issues
|
|
220
222
|
if (error) {
|
|
221
|
-
|
|
223
|
+
logger.warn('NavigationProvider', `Permission check error for "${item.id}": ${error.message} - allowing access for graceful degradation`);
|
|
222
224
|
return true;
|
|
223
225
|
}
|
|
224
226
|
|
|
@@ -308,7 +310,8 @@ export function NavigationProvider({
|
|
|
308
310
|
// Log strict mode violations
|
|
309
311
|
useEffect(() => {
|
|
310
312
|
if (strictMode && auditLog) {
|
|
311
|
-
|
|
313
|
+
const logger = getRBACLogger();
|
|
314
|
+
logger.debug('Strict mode enabled - all navigation access attempts will be logged and enforced');
|
|
312
315
|
}
|
|
313
316
|
}, [strictMode, auditLog]);
|
|
314
317
|
|
|
@@ -72,7 +72,8 @@ import { useCan } from '../hooks';
|
|
|
72
72
|
import { useUnifiedAuth } from '../../providers/UnifiedAuthProvider';
|
|
73
73
|
import { UUID, Permission, Scope } from '../types';
|
|
74
74
|
import { createScopeFromEvent } from '../utils/eventContext';
|
|
75
|
-
import { getCurrentAppName } from '../../utils/appNameResolver';
|
|
75
|
+
import { getCurrentAppName } from '../../utils/app/appNameResolver';
|
|
76
|
+
import { getRBACLogger } from '../config';
|
|
76
77
|
|
|
77
78
|
export interface PagePermissionGuardProps {
|
|
78
79
|
/** Name of the page being protected */
|
|
@@ -198,7 +199,8 @@ const PagePermissionGuardComponent = ({
|
|
|
198
199
|
}
|
|
199
200
|
|
|
200
201
|
if (error) {
|
|
201
|
-
|
|
202
|
+
const logger = getRBACLogger();
|
|
203
|
+
logger.error('Database error resolving app ID:', error);
|
|
202
204
|
if (signal.aborted) {
|
|
203
205
|
return;
|
|
204
206
|
}
|
|
@@ -213,23 +215,26 @@ const PagePermissionGuardComponent = ({
|
|
|
213
215
|
}
|
|
214
216
|
|
|
215
217
|
if (inactiveApp) {
|
|
216
|
-
|
|
218
|
+
logger.error(`App "${appName}" exists but is inactive (is_active: ${inactiveApp.is_active})`);
|
|
217
219
|
} else {
|
|
218
|
-
|
|
220
|
+
logger.error(`App "${appName}" not found in rbac_apps table`);
|
|
219
221
|
}
|
|
220
222
|
} else if (app) {
|
|
221
223
|
appId = app.id;
|
|
222
224
|
} else {
|
|
223
|
-
|
|
225
|
+
const logger = getRBACLogger();
|
|
226
|
+
logger.error('No app data returned for:', appName);
|
|
224
227
|
}
|
|
225
228
|
} catch (error) {
|
|
226
229
|
if (signal.aborted) {
|
|
227
230
|
return;
|
|
228
231
|
}
|
|
229
|
-
|
|
232
|
+
const logger = getRBACLogger();
|
|
233
|
+
logger.error('Unexpected error resolving app ID:', error);
|
|
230
234
|
}
|
|
231
235
|
} else {
|
|
232
|
-
|
|
236
|
+
const logger = getRBACLogger();
|
|
237
|
+
logger.error('No app name found. Make sure to call setRBACAppName() in your app setup.');
|
|
233
238
|
}
|
|
234
239
|
}
|
|
235
240
|
|
|
@@ -240,10 +245,11 @@ const PagePermissionGuardComponent = ({
|
|
|
240
245
|
// If we have both organisation and event, use them directly
|
|
241
246
|
if (selectedOrganisation && selectedEvent) {
|
|
242
247
|
if (!appId) {
|
|
248
|
+
const logger = getRBACLogger();
|
|
243
249
|
if (import.meta.env.MODE === 'test') {
|
|
244
|
-
|
|
250
|
+
logger.warn('App ID not resolved in test environment, proceeding without it');
|
|
245
251
|
} else {
|
|
246
|
-
|
|
252
|
+
logger.error('CRITICAL: App ID not resolved. Check console for details.');
|
|
247
253
|
safeSetCheckError(new Error('App ID not resolved. Check console for database errors.'));
|
|
248
254
|
safeSetResolvedScope(null);
|
|
249
255
|
return;
|
|
@@ -253,7 +259,8 @@ const PagePermissionGuardComponent = ({
|
|
|
253
259
|
if (import.meta.env.MODE === 'production' && appId) {
|
|
254
260
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
255
261
|
if (!uuidRegex.test(appId)) {
|
|
256
|
-
|
|
262
|
+
const logger = getRBACLogger();
|
|
263
|
+
logger.error('CRITICAL: App ID is not a valid UUID:', appId);
|
|
257
264
|
safeSetCheckError(new Error(`Invalid app ID format: ${appId}. Expected UUID.`));
|
|
258
265
|
safeSetResolvedScope(null);
|
|
259
266
|
return;
|
|
@@ -276,10 +283,11 @@ const PagePermissionGuardComponent = ({
|
|
|
276
283
|
// If we only have organisation, use it
|
|
277
284
|
if (selectedOrganisation) {
|
|
278
285
|
if (!appId) {
|
|
286
|
+
const logger = getRBACLogger();
|
|
279
287
|
if (import.meta.env.MODE === 'test') {
|
|
280
|
-
|
|
288
|
+
logger.warn('App ID not resolved in test environment, proceeding without it');
|
|
281
289
|
} else {
|
|
282
|
-
|
|
290
|
+
logger.error('CRITICAL: App ID not resolved. Check console for details.');
|
|
283
291
|
safeSetCheckError(new Error('App ID not resolved. Check console for database errors.'));
|
|
284
292
|
safeSetResolvedScope(null);
|
|
285
293
|
return;
|
|
@@ -289,7 +297,8 @@ const PagePermissionGuardComponent = ({
|
|
|
289
297
|
if (import.meta.env.MODE === 'production' && appId) {
|
|
290
298
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
291
299
|
if (!uuidRegex.test(appId)) {
|
|
292
|
-
|
|
300
|
+
const logger = getRBACLogger();
|
|
301
|
+
logger.error('CRITICAL: App ID is not a valid UUID:', appId);
|
|
293
302
|
safeSetCheckError(new Error(`Invalid app ID format: ${appId}. Expected UUID.`));
|
|
294
303
|
safeSetResolvedScope(null);
|
|
295
304
|
return;
|
|
@@ -346,7 +355,8 @@ const PagePermissionGuardComponent = ({
|
|
|
346
355
|
? 'Either organisation context or event context is required for page permission checking'
|
|
347
356
|
: 'Insufficient context for permission checking. Please ensure you are properly authenticated and have selected an organisation or event.';
|
|
348
357
|
|
|
349
|
-
|
|
358
|
+
const logger = getRBACLogger();
|
|
359
|
+
logger.error('Context resolution failed:', {
|
|
350
360
|
selectedOrganisation: selectedOrganisation ? (selectedOrganisation as any).id : null,
|
|
351
361
|
selectedEvent: selectedEvent ? (selectedEvent as any).event_id : null,
|
|
352
362
|
appId,
|
|
@@ -425,7 +435,8 @@ const PagePermissionGuardComponent = ({
|
|
|
425
435
|
// Log page access attempt for audit
|
|
426
436
|
useEffect(() => {
|
|
427
437
|
if (auditLog && hasChecked && !isLoading) {
|
|
428
|
-
|
|
438
|
+
const rbacLogger = getRBACLogger();
|
|
439
|
+
rbacLogger.debug('Page access attempt:', {
|
|
429
440
|
pageName,
|
|
430
441
|
operation,
|
|
431
442
|
userId: user?.id,
|
|
@@ -440,7 +451,8 @@ const PagePermissionGuardComponent = ({
|
|
|
440
451
|
// Handle strict mode violations
|
|
441
452
|
useEffect(() => {
|
|
442
453
|
if (strictMode && hasChecked && !isLoading && !can) {
|
|
443
|
-
|
|
454
|
+
const logger = getRBACLogger();
|
|
455
|
+
logger.error(`STRICT MODE VIOLATION: User attempted to access protected page without permission`, {
|
|
444
456
|
pageName,
|
|
445
457
|
operation,
|
|
446
458
|
permission: `${operation}:page.${pageName}`,
|
|
@@ -57,6 +57,9 @@
|
|
|
57
57
|
import React, { createContext, useContext, useState, useCallback, useMemo, useEffect } from 'react';
|
|
58
58
|
import { useUnifiedAuth } from '../../providers/UnifiedAuthProvider';
|
|
59
59
|
import { UUID, Scope, Permission } from '../types';
|
|
60
|
+
import { createLogger } from '../../utils/core/logger';
|
|
61
|
+
|
|
62
|
+
const log = createLogger('PagePermissionProvider');
|
|
60
63
|
|
|
61
64
|
export interface PagePermissionContextType {
|
|
62
65
|
/** Check if user has permission for a page */
|
|
@@ -244,7 +247,7 @@ export function PagePermissionProvider({
|
|
|
244
247
|
// Log strict mode violations
|
|
245
248
|
useEffect(() => {
|
|
246
249
|
if (strictMode && auditLog) {
|
|
247
|
-
|
|
250
|
+
log.debug('Strict mode enabled - all page access attempts will be logged and enforced');
|
|
248
251
|
}
|
|
249
252
|
}, [strictMode, auditLog]);
|
|
250
253
|
|
|
@@ -71,6 +71,10 @@ import { useMultiplePermissions } from '../hooks/usePermissions';
|
|
|
71
71
|
import { useUnifiedAuth } from '../../providers/UnifiedAuthProvider';
|
|
72
72
|
import { UUID, Permission, Scope } from '../types';
|
|
73
73
|
import { createScopeFromEvent } from '../utils/eventContext';
|
|
74
|
+
import { getRBACLogger } from '../config';
|
|
75
|
+
import { createLogger } from '../../utils/core/logger';
|
|
76
|
+
|
|
77
|
+
const log = createLogger('PermissionEnforcer');
|
|
74
78
|
|
|
75
79
|
export interface PermissionEnforcerProps {
|
|
76
80
|
/** Permissions required for access */
|
|
@@ -225,7 +229,7 @@ export function PermissionEnforcer({
|
|
|
225
229
|
// Log permission check attempt for audit
|
|
226
230
|
useEffect(() => {
|
|
227
231
|
if (auditLog && hasChecked && !isLoading) {
|
|
228
|
-
|
|
232
|
+
log.debug('Permission check attempt:', {
|
|
229
233
|
permissions,
|
|
230
234
|
operation,
|
|
231
235
|
userId: user?.id,
|
|
@@ -240,7 +244,8 @@ export function PermissionEnforcer({
|
|
|
240
244
|
// Handle strict mode violations
|
|
241
245
|
useEffect(() => {
|
|
242
246
|
if (strictMode && hasChecked && !isLoading && !hasRequiredPermissions) {
|
|
243
|
-
|
|
247
|
+
const logger = getRBACLogger();
|
|
248
|
+
logger.error(`STRICT MODE VIOLATION: User attempted to perform operation without permission`, {
|
|
244
249
|
permissions,
|
|
245
250
|
operation,
|
|
246
251
|
userId: user?.id,
|
|
@@ -258,7 +263,8 @@ export function PermissionEnforcer({
|
|
|
258
263
|
|
|
259
264
|
// Show error state
|
|
260
265
|
if (checkError) {
|
|
261
|
-
|
|
266
|
+
const logger = getRBACLogger();
|
|
267
|
+
logger.error(`Permission check failed for operation ${operation}:`, checkError);
|
|
262
268
|
return <>{fallback}</>;
|
|
263
269
|
}
|
|
264
270
|
|