@jmruthers/pace-core 0.5.188 → 0.5.190
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/core-usage-manifest.json +0 -4
- package/dist/{AuthService-B-cd2MA4.d.ts → AuthService-CbP_utw2.d.ts} +7 -3
- package/dist/{DataTable-GUFUNZ3N.js → DataTable-ON3IXISJ.js} +8 -8
- package/dist/{PublicPageProvider-DrLDztHt.d.ts → PublicPageProvider-C4uxosp6.d.ts} +129 -40
- package/dist/{UnifiedAuthProvider-BG0AL5eE.d.ts → UnifiedAuthProvider-BYA9qB-o.d.ts} +4 -3
- package/dist/{UnifiedAuthProvider-643PUAIM.js → UnifiedAuthProvider-X5NXANVI.js} +4 -2
- package/dist/{api-YP7XD5L6.js → api-I6UCQ5S6.js} +4 -2
- package/dist/{chunk-DDM4CCYT.js → chunk-4QYC5L4K.js} +60 -35
- package/dist/chunk-4QYC5L4K.js.map +1 -0
- package/dist/{chunk-IM4QE42D.js → chunk-73HSNNOQ.js} +141 -326
- package/dist/chunk-73HSNNOQ.js.map +1 -0
- package/dist/{chunk-YHCN776L.js → chunk-DZWK57KZ.js} +2 -75
- package/dist/chunk-DZWK57KZ.js.map +1 -0
- package/dist/{chunk-3GOZZZYH.js → chunk-HQVPB5MZ.js} +238 -301
- package/dist/chunk-HQVPB5MZ.js.map +1 -0
- package/dist/{chunk-THRPYOFK.js → chunk-HW3OVDUF.js} +5 -5
- package/dist/chunk-HW3OVDUF.js.map +1 -0
- package/dist/{chunk-F2IMUDXZ.js → chunk-I7PSE6JW.js} +75 -2
- package/dist/chunk-I7PSE6JW.js.map +1 -0
- package/dist/{chunk-VGZZXKBR.js → chunk-J2XXC7R5.js} +280 -52
- package/dist/chunk-J2XXC7R5.js.map +1 -0
- package/dist/{chunk-UNOTYLQF.js → chunk-NIU6J6OX.js} +772 -725
- package/dist/chunk-NIU6J6OX.js.map +1 -0
- package/dist/{chunk-HESYZWZW.js → chunk-QWWZ5CAQ.js} +2 -2
- package/dist/{chunk-HEHYGYOX.js → chunk-RUYZKXOD.js} +401 -46
- package/dist/chunk-RUYZKXOD.js.map +1 -0
- package/dist/{chunk-2UUZZJFT.js → chunk-SDMHPX3X.js} +176 -160
- package/dist/{chunk-2UUZZJFT.js.map → chunk-SDMHPX3X.js.map} +1 -1
- package/dist/{chunk-IPCH26AG.js → chunk-STYK4OH2.js} +11 -11
- package/dist/chunk-STYK4OH2.js.map +1 -0
- package/dist/{chunk-EFCLXK7F.js → chunk-VVBAW5A5.js} +4201 -3809
- package/dist/chunk-VVBAW5A5.js.map +1 -0
- package/dist/chunk-Y4BUBBHD.js +614 -0
- package/dist/chunk-Y4BUBBHD.js.map +1 -0
- package/dist/{chunk-SAUPYVLF.js → chunk-ZSAAAMVR.js} +1 -1
- package/dist/chunk-ZSAAAMVR.js.map +1 -0
- package/dist/components.d.ts +3 -5
- package/dist/components.js +19 -23
- package/dist/components.js.map +1 -1
- package/dist/eslint-rules/pace-core-compliance.cjs +0 -2
- package/dist/{file-reference-D037xOFK.d.ts → file-reference-BavO2eQj.d.ts} +13 -10
- package/dist/hooks.d.ts +10 -5
- package/dist/hooks.js +14 -8
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +13 -12
- package/dist/index.js +79 -73
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +3 -3
- package/dist/providers.js +3 -1
- package/dist/rbac/index.d.ts +76 -12
- package/dist/rbac/index.js +12 -9
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/{usePublicRouteParams-CTDELQ7H.d.ts → usePublicRouteParams-DxIDS4bC.d.ts} +16 -9
- package/dist/utils.js +16 -16
- package/docs/README.md +2 -2
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +2 -2
- package/docs/api/classes/Logger.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +2 -2
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +4 -4
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +2 -2
- package/docs/api/classes/SecureSupabaseClient.md +21 -16
- package/docs/api/classes/StorageUtils.md +7 -4
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/enums/LogLevel.md +1 -1
- package/docs/api/enums/RBACErrorCode.md +1 -1
- package/docs/api/enums/RPCFunction.md +1 -1
- package/docs/api/interfaces/AddressFieldProps.md +1 -1
- package/docs/api/interfaces/AddressFieldRef.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/AutocompleteOptions.md +1 -1
- package/docs/api/interfaces/AvatarProps.md +128 -0
- package/docs/api/interfaces/BadgeProps.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CalendarProps.md +20 -6
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/ComplianceResult.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +9 -9
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
- package/docs/api/interfaces/DatabaseIssue.md +1 -1
- 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 +1 -1
- package/docs/api/interfaces/ExportOptions.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +62 -16
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +2 -2
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +26 -12
- package/docs/api/interfaces/FileUploadProps.md +30 -19
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/FormFieldProps.md +1 -1
- package/docs/api/interfaces/FormProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoggerConfig.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 +1 -1
- 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 +1 -1
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PageAccessRecord.md +8 -8
- package/docs/api/interfaces/PagePermissionContextType.md +8 -8
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/ParsedAddress.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProgressProps.md +3 -11
- package/docs/api/interfaces/ProtectedRouteProps.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/QuickFix.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
- package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
- package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContext.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
- package/docs/api/interfaces/RBACResult.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
- package/docs/api/interfaces/RBACRolesListParams.md +1 -1
- package/docs/api/interfaces/RBACRolesListResult.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
- package/docs/api/interfaces/ResourcePermissions.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +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/RuntimeComplianceResult.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +9 -9
- package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
- package/docs/api/interfaces/SetupIssue.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +4 -4
- package/docs/api/interfaces/StorageFileInfo.md +7 -7
- package/docs/api/interfaces/StorageFileMetadata.md +25 -14
- package/docs/api/interfaces/StorageListOptions.md +22 -9
- package/docs/api/interfaces/StorageListResult.md +4 -4
- package/docs/api/interfaces/StorageUploadOptions.md +21 -8
- package/docs/api/interfaces/StorageUploadResult.md +6 -6
- package/docs/api/interfaces/StorageUrlOptions.md +19 -6
- 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 +1 -1
- package/docs/api/interfaces/TextareaProps.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/UseFormDialogOptions.md +1 -1
- package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
- 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/UseResourcePermissionsOptions.md +1 -1
- 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 +155 -135
- package/docs/api-reference/components.md +72 -29
- package/docs/api-reference/providers.md +2 -2
- package/docs/api-reference/rpc-functions.md +1 -0
- package/docs/best-practices/README.md +1 -1
- package/docs/best-practices/deployment.md +8 -8
- package/docs/getting-started/examples/README.md +2 -2
- package/docs/getting-started/installation-guide.md +4 -4
- package/docs/getting-started/quick-start.md +3 -3
- package/docs/migration/MIGRATION_GUIDE.md +3 -3
- package/docs/rbac/compliance/compliance-guide.md +2 -2
- package/docs/rbac/event-based-apps.md +2 -2
- package/docs/rbac/getting-started.md +2 -2
- package/docs/rbac/quick-start.md +2 -2
- package/docs/security/README.md +4 -4
- package/docs/standards/07-rbac-and-rls-standard.md +430 -7
- package/docs/troubleshooting/README.md +2 -2
- package/docs/troubleshooting/migration.md +3 -3
- package/package.json +1 -4
- package/scripts/check-pace-core-compliance.cjs +1 -1
- package/scripts/check-pace-core-compliance.js +1 -1
- package/src/__tests__/fixtures/supabase.ts +301 -0
- package/src/__tests__/public-recipe-view.test.ts +9 -9
- package/src/__tests__/rls-policies.test.ts +197 -61
- package/src/components/AddressField/AddressField.test.tsx +42 -0
- package/src/components/AddressField/AddressField.tsx +71 -60
- package/src/components/AddressField/README.md +1 -0
- package/src/components/Alert/Alert.test.tsx +50 -10
- package/src/components/Alert/Alert.tsx +5 -3
- package/src/components/Avatar/Avatar.test.tsx +252 -226
- package/src/components/Avatar/Avatar.tsx +179 -53
- package/src/components/Avatar/index.ts +1 -1
- package/src/components/Button/Button.test.tsx +2 -1
- package/src/components/Button/Button.tsx +3 -3
- package/src/components/Calendar/Calendar.test.tsx +53 -37
- package/src/components/Calendar/Calendar.tsx +409 -82
- package/src/components/Card/Card.test.tsx +7 -4
- package/src/components/Card/Card.tsx +3 -6
- package/src/components/Checkbox/Checkbox.tsx +2 -2
- package/src/components/DataTable/components/ActionButtons.tsx +5 -5
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
- package/src/components/DataTable/components/ColumnFilter.tsx +1 -1
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +3 -3
- package/src/components/DataTable/components/DataTableBody.tsx +12 -12
- package/src/components/DataTable/components/DataTableCore.tsx +3 -3
- package/src/components/DataTable/components/DataTableToolbar.tsx +5 -5
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +3 -3
- package/src/components/DataTable/components/EditableRow.tsx +2 -2
- package/src/components/DataTable/components/EmptyState.tsx +3 -3
- package/src/components/DataTable/components/GroupHeader.tsx +2 -2
- package/src/components/DataTable/components/GroupingDropdown.tsx +1 -1
- package/src/components/DataTable/components/ImportModal.tsx +4 -4
- package/src/components/DataTable/components/LoadingState.tsx +1 -1
- package/src/components/DataTable/components/PaginationControls.tsx +11 -11
- package/src/components/DataTable/components/UnifiedTableBody.tsx +9 -9
- package/src/components/DataTable/components/ViewRowModal.tsx +2 -2
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +11 -37
- package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +157 -0
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +2 -1
- package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +128 -0
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +19 -0
- package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +51 -0
- package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +84 -0
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +14 -0
- package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +136 -0
- package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +16 -0
- package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +18 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +28 -7
- package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +30 -1
- package/src/components/DataTable/utils/hierarchicalUtils.ts +38 -10
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -3
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +4 -4
- package/src/components/Dialog/Dialog.tsx +2 -2
- package/src/components/EventSelector/EventSelector.tsx +7 -7
- package/src/components/FileDisplay/FileDisplay.tsx +291 -179
- package/src/components/FileUpload/FileUpload.tsx +7 -4
- package/src/components/Header/Header.test.tsx +28 -0
- package/src/components/Header/Header.tsx +22 -9
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +2 -2
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +19 -14
- package/src/components/LoadingSpinner/LoadingSpinner.tsx +5 -5
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +127 -1
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +8 -8
- package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +4 -0
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +3 -0
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +3 -0
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +16 -6
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +37 -3
- package/src/components/PaceAppLayout/test-setup.tsx +1 -0
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +66 -45
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +6 -4
- package/src/components/Progress/Progress.test.tsx +18 -19
- package/src/components/Progress/Progress.tsx +31 -32
- package/src/components/PublicLayout/PublicLayout.test.tsx +6 -6
- package/src/components/PublicLayout/PublicPageProvider.tsx +5 -3
- package/src/components/Select/Select.tsx +5 -5
- package/src/components/Switch/Switch.test.tsx +2 -1
- package/src/components/Switch/Switch.tsx +1 -1
- package/src/components/Toast/Toast.tsx +1 -1
- package/src/components/Tooltip/Tooltip.test.tsx +8 -2
- package/src/components/UserMenu/UserMenu.test.tsx +7 -9
- package/src/components/UserMenu/UserMenu.tsx +10 -8
- package/src/components/index.ts +2 -1
- package/src/eslint-rules/pace-core-compliance.cjs +0 -2
- package/src/eslint-rules/pace-core-compliance.js +0 -2
- package/src/hooks/__tests__/hooks.integration.test.tsx +4 -1
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +76 -5
- package/src/hooks/__tests__/useDataTableState.test.ts +76 -0
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +25 -69
- package/src/hooks/__tests__/useFileUrlCache.test.ts +129 -0
- package/src/hooks/__tests__/usePreventTabReload.test.ts +88 -0
- package/src/hooks/__tests__/{usePublicEvent.unit.test.ts → usePublicEvent.test.ts} +28 -1
- package/src/hooks/__tests__/useQueryCache.test.ts +144 -0
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +58 -16
- package/src/hooks/index.ts +1 -1
- package/src/hooks/public/usePublicEvent.ts +2 -2
- package/src/hooks/public/usePublicFileDisplay.ts +173 -87
- package/src/hooks/useAppConfig.ts +24 -5
- package/src/hooks/useFileDisplay.ts +297 -34
- package/src/hooks/useFileReference.ts +56 -11
- package/src/hooks/useFileUrl.ts +1 -1
- package/src/hooks/useInactivityTracker.ts +16 -7
- package/src/hooks/usePermissionCache.test.ts +85 -8
- package/src/hooks/useQueryCache.ts +21 -0
- package/src/hooks/useSecureDataAccess.test.ts +80 -35
- package/src/hooks/useSecureDataAccess.ts +80 -37
- package/src/index.ts +2 -1
- package/src/providers/services/EventServiceProvider.tsx +37 -17
- package/src/providers/services/InactivityServiceProvider.tsx +4 -4
- package/src/providers/services/OrganisationServiceProvider.tsx +8 -1
- package/src/providers/services/UnifiedAuthProvider.tsx +115 -29
- package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +451 -0
- package/src/rbac/__tests__/engine.comprehensive.test.ts +12 -0
- package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +8 -0
- package/src/rbac/__tests__/rbac-engine-simplified.test.ts +4 -0
- package/src/rbac/api.ts +240 -36
- package/src/rbac/cache-invalidation.ts +21 -7
- package/src/rbac/compliance/quick-fix-suggestions.ts +1 -1
- package/src/rbac/components/NavigationGuard.tsx +23 -63
- package/src/rbac/components/NavigationProvider.test.tsx +52 -23
- package/src/rbac/components/NavigationProvider.tsx +13 -11
- package/src/rbac/components/PagePermissionGuard.tsx +77 -203
- package/src/rbac/components/PagePermissionProvider.tsx +13 -11
- package/src/rbac/components/PermissionEnforcer.tsx +24 -62
- package/src/rbac/components/RoleBasedRouter.tsx +14 -12
- package/src/rbac/components/SecureDataProvider.tsx +13 -11
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +104 -41
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +49 -12
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +22 -1
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +161 -82
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +22 -1
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +77 -30
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +39 -5
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +47 -4
- package/src/rbac/engine.ts +4 -2
- package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +144 -52
- package/src/rbac/hooks/index.ts +3 -0
- package/src/rbac/hooks/useCan.test.ts +101 -53
- package/src/rbac/hooks/usePermissions.ts +108 -41
- package/src/rbac/hooks/useRBAC.test.ts +11 -3
- package/src/rbac/hooks/useRBAC.ts +83 -40
- package/src/rbac/hooks/useResolvedScope.test.ts +189 -63
- package/src/rbac/hooks/useResolvedScope.ts +128 -70
- package/src/rbac/hooks/useSecureSupabase.ts +36 -19
- package/src/rbac/hooks/useSuperAdminBypass.ts +126 -0
- package/src/rbac/request-deduplication.ts +1 -1
- package/src/rbac/secureClient.ts +72 -12
- package/src/rbac/security.ts +29 -23
- package/src/rbac/types.ts +10 -0
- package/src/rbac/utils/__tests__/contextValidator.test.ts +150 -0
- package/src/rbac/utils/__tests__/deep-equal.test.ts +53 -0
- package/src/rbac/utils/__tests__/eventContext.test.ts +6 -1
- package/src/rbac/utils/contextValidator.ts +288 -0
- package/src/rbac/utils/eventContext.ts +48 -2
- package/src/services/EventService.ts +165 -21
- package/src/services/OrganisationService.ts +37 -2
- package/src/services/__tests__/EventService.test.ts +26 -21
- package/src/types/file-reference.ts +13 -10
- package/src/utils/app/appNameResolver.test.ts +346 -73
- package/src/utils/context/superAdminOverride.ts +58 -0
- package/src/utils/file-reference/index.ts +61 -33
- package/src/utils/google-places/googlePlacesUtils.test.ts +98 -0
- package/src/utils/google-places/loadGoogleMapsScript.test.ts +83 -0
- package/src/utils/storage/helpers.test.ts +1 -1
- package/src/utils/storage/helpers.ts +38 -19
- package/src/utils/storage/types.ts +15 -8
- package/src/utils/validation/__tests__/csrf.test.ts +105 -0
- package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +92 -0
- package/src/vite-env.d.ts +2 -2
- package/dist/chunk-3GOZZZYH.js.map +0 -1
- package/dist/chunk-DDM4CCYT.js.map +0 -1
- package/dist/chunk-E7UAOUMY.js +0 -75
- package/dist/chunk-E7UAOUMY.js.map +0 -1
- package/dist/chunk-EFCLXK7F.js.map +0 -1
- package/dist/chunk-F2IMUDXZ.js.map +0 -1
- package/dist/chunk-HEHYGYOX.js.map +0 -1
- package/dist/chunk-IM4QE42D.js.map +0 -1
- package/dist/chunk-IPCH26AG.js.map +0 -1
- package/dist/chunk-SAUPYVLF.js.map +0 -1
- package/dist/chunk-THRPYOFK.js.map +0 -1
- package/dist/chunk-UNOTYLQF.js.map +0 -1
- package/dist/chunk-VGZZXKBR.js.map +0 -1
- package/dist/chunk-YHCN776L.js.map +0 -1
- package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
- package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +0 -703
- package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
- package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -428
- /package/dist/{DataTable-GUFUNZ3N.js.map → DataTable-ON3IXISJ.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-643PUAIM.js.map → UnifiedAuthProvider-X5NXANVI.js.map} +0 -0
- /package/dist/{api-YP7XD5L6.js.map → api-I6UCQ5S6.js.map} +0 -0
- /package/dist/{chunk-HESYZWZW.js.map → chunk-QWWZ5CAQ.js.map} +0 -0
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getAppConfigByName,
|
|
3
|
+
isSuperAdmin
|
|
4
|
+
} from "./chunk-RUYZKXOD.js";
|
|
1
5
|
import {
|
|
2
6
|
assertOrganisationId,
|
|
3
7
|
assertUserId
|
|
@@ -653,6 +657,17 @@ var OrganisationService = class extends BaseService {
|
|
|
653
657
|
}
|
|
654
658
|
// Additional methods for testing
|
|
655
659
|
setSelectedOrganisation(organisation) {
|
|
660
|
+
if (organisation && this._organisations.length > 0) {
|
|
661
|
+
const isValidOrg = this._organisations.some((org) => org.id === organisation.id);
|
|
662
|
+
if (!isValidOrg) {
|
|
663
|
+
logger.warn("OrganisationService", "Attempted to set invalid organisation - not in user's accessible organisations", {
|
|
664
|
+
organisationId: organisation.id,
|
|
665
|
+
organisationName: organisation.name,
|
|
666
|
+
accessibleOrgIds: this._organisations.map((o) => o.id)
|
|
667
|
+
});
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
656
671
|
this._selectedOrganisation = organisation;
|
|
657
672
|
if (organisation) {
|
|
658
673
|
localStorage.setItem("pace-core-selected-organisation", JSON.stringify(organisation));
|
|
@@ -1009,17 +1024,31 @@ var OrganisationService = class extends BaseService {
|
|
|
1009
1024
|
if (!initialOrg) {
|
|
1010
1025
|
throw new Error("No valid organisation found for user");
|
|
1011
1026
|
}
|
|
1027
|
+
const currentSelectedOrg = this._selectedOrganisation;
|
|
1028
|
+
if (currentSelectedOrg && !activeOrgs.some((org) => org.id === currentSelectedOrg.id)) {
|
|
1029
|
+
logger.warn("OrganisationService", "Current selected organisation is no longer valid, resetting", {
|
|
1030
|
+
invalidOrgId: currentSelectedOrg.id,
|
|
1031
|
+
validOrgIds: activeOrgs.map((o) => o.id)
|
|
1032
|
+
});
|
|
1033
|
+
this._selectedOrganisation = null;
|
|
1034
|
+
}
|
|
1012
1035
|
this._selectedOrganisation = initialOrg;
|
|
1013
1036
|
localStorage.setItem("pace-core-selected-organisation", JSON.stringify(initialOrg));
|
|
1014
1037
|
await this.setDatabaseOrganisationContext(initialOrg);
|
|
1015
1038
|
this.retryCount = 0;
|
|
1016
1039
|
this.hasFailedRef = false;
|
|
1017
1040
|
} catch (err) {
|
|
1018
|
-
|
|
1019
|
-
|
|
1041
|
+
const error = err;
|
|
1042
|
+
if (error.message === "User has no access to active organisations") {
|
|
1043
|
+
logger.warn("OrganisationService", "User has no active organisations (this is expected for users without organisation access):", error);
|
|
1044
|
+
} else {
|
|
1045
|
+
logger.error("OrganisationService", "Failed to load organisations:", err);
|
|
1046
|
+
}
|
|
1047
|
+
this._error = error;
|
|
1020
1048
|
this.retryCount = this.retryCount + 1;
|
|
1021
1049
|
this.hasFailedRef = true;
|
|
1022
1050
|
this.clearAllCachedData();
|
|
1051
|
+
this._isContextReady = true;
|
|
1023
1052
|
} finally {
|
|
1024
1053
|
this.isLoadingRef = false;
|
|
1025
1054
|
this._isLoading = false;
|
|
@@ -1058,7 +1087,12 @@ function OrganisationServiceProvider({
|
|
|
1058
1087
|
let isMounted = true;
|
|
1059
1088
|
organisationService.initialize().catch((error) => {
|
|
1060
1089
|
if (isMounted) {
|
|
1061
|
-
|
|
1090
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1091
|
+
if (errorMessage === "User has no access to active organisations") {
|
|
1092
|
+
logger.warn("OrganisationServiceProvider", "User has no active organisations (this is expected for users without organisation access):", error);
|
|
1093
|
+
} else {
|
|
1094
|
+
logger.error("OrganisationServiceProvider", "Failed to initialize organisation service:", error);
|
|
1095
|
+
}
|
|
1062
1096
|
}
|
|
1063
1097
|
});
|
|
1064
1098
|
return () => {
|
|
@@ -1095,6 +1129,10 @@ var EventService = class extends BaseService {
|
|
|
1095
1129
|
this.appName = "";
|
|
1096
1130
|
this.selectedOrganisation = null;
|
|
1097
1131
|
this.setSelectedEventId = null;
|
|
1132
|
+
this.isSuperAdmin = false;
|
|
1133
|
+
// Track super admin status for conditional validation
|
|
1134
|
+
this.appConfig = null;
|
|
1135
|
+
// Cache app config to avoid repeated lookups
|
|
1098
1136
|
// Internal state management
|
|
1099
1137
|
this.isInitializedRef = false;
|
|
1100
1138
|
this.isFetchingRef = false;
|
|
@@ -1120,6 +1158,7 @@ var EventService = class extends BaseService {
|
|
|
1120
1158
|
const newOrgId = selectedOrganisation?.id;
|
|
1121
1159
|
const previousUserId = this.user?.id || null;
|
|
1122
1160
|
const newUserId = user?.id || null;
|
|
1161
|
+
const previousAppName = this.appName;
|
|
1123
1162
|
if (previousUserId !== newUserId) {
|
|
1124
1163
|
if (previousUserId !== null) {
|
|
1125
1164
|
await this.clearEventSelectionForUser(previousUserId);
|
|
@@ -1128,6 +1167,9 @@ var EventService = class extends BaseService {
|
|
|
1128
1167
|
this.selectedEvent = null;
|
|
1129
1168
|
this.setSelectedEventId?.(null);
|
|
1130
1169
|
}
|
|
1170
|
+
this.resetInitialization();
|
|
1171
|
+
this.isInitializedRef = false;
|
|
1172
|
+
this.isFetchingRef = false;
|
|
1131
1173
|
}
|
|
1132
1174
|
this.supabaseClient = supabaseClient;
|
|
1133
1175
|
this.user = user;
|
|
@@ -1135,6 +1177,23 @@ var EventService = class extends BaseService {
|
|
|
1135
1177
|
this.appName = appName;
|
|
1136
1178
|
this.selectedOrganisation = selectedOrganisation;
|
|
1137
1179
|
this.setSelectedEventId = setSelectedEventId;
|
|
1180
|
+
if (previousAppName !== appName) {
|
|
1181
|
+
this.appConfig = null;
|
|
1182
|
+
}
|
|
1183
|
+
if (user?.id) {
|
|
1184
|
+
try {
|
|
1185
|
+
this.isSuperAdmin = await isSuperAdmin(user.id);
|
|
1186
|
+
logger.debug("EventService", "Updated super admin status", {
|
|
1187
|
+
userId: user.id,
|
|
1188
|
+
isSuperAdmin: this.isSuperAdmin
|
|
1189
|
+
});
|
|
1190
|
+
} catch (error) {
|
|
1191
|
+
logger.warn("EventService", "Failed to check super admin status", { error });
|
|
1192
|
+
this.isSuperAdmin = false;
|
|
1193
|
+
}
|
|
1194
|
+
} else {
|
|
1195
|
+
this.isSuperAdmin = false;
|
|
1196
|
+
}
|
|
1138
1197
|
if (previousOrgId !== newOrgId) {
|
|
1139
1198
|
this.resetInitialization();
|
|
1140
1199
|
this.isInitializedRef = false;
|
|
@@ -1165,18 +1224,6 @@ var EventService = class extends BaseService {
|
|
|
1165
1224
|
// Event methods
|
|
1166
1225
|
setSelectedEvent(event) {
|
|
1167
1226
|
if (event) {
|
|
1168
|
-
try {
|
|
1169
|
-
if (this.selectedOrganisation && event.organisation_id !== this.selectedOrganisation.id) {
|
|
1170
|
-
logger.error("EventService", "Event organisation_id does not match selected organisation", {
|
|
1171
|
-
eventOrganisationId: event.organisation_id,
|
|
1172
|
-
selectedOrganisationId: this.selectedOrganisation.id,
|
|
1173
|
-
eventName: event.event_name
|
|
1174
|
-
});
|
|
1175
|
-
return;
|
|
1176
|
-
}
|
|
1177
|
-
} catch (error) {
|
|
1178
|
-
logger.error("EventService", "Error during event validation:", error);
|
|
1179
|
-
}
|
|
1180
1227
|
this.selectedEvent = event;
|
|
1181
1228
|
this.setSelectedEventId?.(event.event_id);
|
|
1182
1229
|
this.persistEventSelection(event.event_id).catch((error) => {
|
|
@@ -1273,16 +1320,31 @@ var EventService = class extends BaseService {
|
|
|
1273
1320
|
}
|
|
1274
1321
|
// Lifecycle methods
|
|
1275
1322
|
async initialize() {
|
|
1323
|
+
logger.debug("EventService", "initialize() called", {
|
|
1324
|
+
isInitializedRef: this.isInitializedRef,
|
|
1325
|
+
hasUser: !!this.user,
|
|
1326
|
+
hasSession: !!this.session,
|
|
1327
|
+
appName: this.appName
|
|
1328
|
+
});
|
|
1276
1329
|
await super.initialize();
|
|
1277
1330
|
}
|
|
1278
1331
|
cleanup() {
|
|
1279
1332
|
super.cleanup();
|
|
1280
1333
|
}
|
|
1281
1334
|
async doInitialize() {
|
|
1335
|
+
logger.debug("EventService", "doInitialize() called", {
|
|
1336
|
+
isInitializedRef: this.isInitializedRef,
|
|
1337
|
+
isFetchingRef: this.isFetchingRef,
|
|
1338
|
+
hasUser: !!this.user,
|
|
1339
|
+
hasSession: !!this.session,
|
|
1340
|
+
appName: this.appName
|
|
1341
|
+
});
|
|
1282
1342
|
if (this.isInitializedRef) {
|
|
1343
|
+
logger.debug("EventService", "Skipping initialization - already initialized");
|
|
1283
1344
|
return;
|
|
1284
1345
|
}
|
|
1285
1346
|
if (this.isFetchingRef) {
|
|
1347
|
+
logger.debug("EventService", "Skipping initialization - already fetching");
|
|
1286
1348
|
return;
|
|
1287
1349
|
}
|
|
1288
1350
|
try {
|
|
@@ -1292,31 +1354,107 @@ var EventService = class extends BaseService {
|
|
|
1292
1354
|
} catch (error) {
|
|
1293
1355
|
logger.warn("EventService", "Failed to clean up old storage keys:", error);
|
|
1294
1356
|
}
|
|
1295
|
-
if (!this.user
|
|
1357
|
+
if (!this.user) {
|
|
1358
|
+
logger.debug("EventService", "Skipping initialization - missing user");
|
|
1296
1359
|
return;
|
|
1297
1360
|
}
|
|
1361
|
+
logger.debug("EventService", "Initializing - fetching events", {
|
|
1362
|
+
userId: this.user.id,
|
|
1363
|
+
organisationId: this.selectedOrganisation?.id || "derived-from-event",
|
|
1364
|
+
appName: this.appName
|
|
1365
|
+
});
|
|
1298
1366
|
await this.fetchEvents(false);
|
|
1367
|
+
this.isInitializedRef = true;
|
|
1299
1368
|
}
|
|
1300
1369
|
doCleanup() {
|
|
1301
1370
|
}
|
|
1302
1371
|
async fetchEvents(skipLoadPersisted = false) {
|
|
1303
|
-
if (!this.user || !this.session || !this.supabaseClient || !this.appName
|
|
1372
|
+
if (!this.user || !this.session || !this.supabaseClient || !this.appName) {
|
|
1373
|
+
logger.debug("EventService", "Skipping fetchEvents - missing dependencies", {
|
|
1374
|
+
hasUser: !!this.user,
|
|
1375
|
+
hasSession: !!this.session,
|
|
1376
|
+
hasSupabaseClient: !!this.supabaseClient,
|
|
1377
|
+
appName: this.appName
|
|
1378
|
+
});
|
|
1304
1379
|
this.notify();
|
|
1305
1380
|
return;
|
|
1306
1381
|
}
|
|
1307
1382
|
this._isLoading = true;
|
|
1308
1383
|
this.notify();
|
|
1309
1384
|
if (this.isFetchingRef) {
|
|
1385
|
+
logger.debug("EventService", "Skipping fetchEvents - already fetching");
|
|
1310
1386
|
return;
|
|
1311
1387
|
}
|
|
1312
1388
|
this.isFetchingRef = true;
|
|
1313
1389
|
let isMounted = true;
|
|
1314
1390
|
try {
|
|
1315
|
-
|
|
1391
|
+
if (!this.appConfig && this.appName) {
|
|
1392
|
+
try {
|
|
1393
|
+
this.appConfig = await getAppConfigByName(this.appName);
|
|
1394
|
+
} catch (configError) {
|
|
1395
|
+
logger.warn("EventService", "Failed to load app config, defaulting to event-required", {
|
|
1396
|
+
error: configError
|
|
1397
|
+
});
|
|
1398
|
+
this.appConfig = { requires_event: true };
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
let organisationIdForRpc = null;
|
|
1402
|
+
let userIsSuperAdmin = false;
|
|
1403
|
+
try {
|
|
1404
|
+
userIsSuperAdmin = await isSuperAdmin(this.user.id);
|
|
1405
|
+
if (userIsSuperAdmin) {
|
|
1406
|
+
organisationIdForRpc = null;
|
|
1407
|
+
logger.debug("EventService", "Super admin detected - fetching all events", {
|
|
1408
|
+
userId: this.user.id
|
|
1409
|
+
});
|
|
1410
|
+
} else {
|
|
1411
|
+
if (this.selectedEvent) {
|
|
1412
|
+
organisationIdForRpc = this.selectedEvent.organisation_id;
|
|
1413
|
+
} else if (this.appConfig?.requires_event === true) {
|
|
1414
|
+
organisationIdForRpc = null;
|
|
1415
|
+
logger.debug("EventService", "Event-required app: fetching all accessible events (no event selected yet)", {
|
|
1416
|
+
userId: this.user.id,
|
|
1417
|
+
appName: this.appName
|
|
1418
|
+
});
|
|
1419
|
+
} else if (this.selectedOrganisation) {
|
|
1420
|
+
organisationIdForRpc = this.selectedOrganisation.id;
|
|
1421
|
+
} else {
|
|
1422
|
+
logger.warn("EventService", "No organisation context available for event fetch", {
|
|
1423
|
+
hasSelectedEvent: !!this.selectedEvent,
|
|
1424
|
+
hasSelectedOrganisation: !!this.selectedOrganisation,
|
|
1425
|
+
appRequiresEvent: this.appConfig?.requires_event
|
|
1426
|
+
});
|
|
1427
|
+
organisationIdForRpc = null;
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
} catch (superAdminCheckError) {
|
|
1431
|
+
logger.warn("EventService", "Failed to check super admin status, using organisation-scoped query", {
|
|
1432
|
+
error: superAdminCheckError
|
|
1433
|
+
});
|
|
1434
|
+
if (this.selectedEvent) {
|
|
1435
|
+
organisationIdForRpc = this.selectedEvent.organisation_id;
|
|
1436
|
+
} else if (this.appConfig?.requires_event === true) {
|
|
1437
|
+
organisationIdForRpc = null;
|
|
1438
|
+
} else if (this.selectedOrganisation) {
|
|
1439
|
+
organisationIdForRpc = this.selectedOrganisation.id;
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
logger.debug("EventService", "Fetching events via RPC", {
|
|
1443
|
+
userId: this.user.id,
|
|
1444
|
+
organisationId: organisationIdForRpc,
|
|
1445
|
+
appName: this.appName
|
|
1446
|
+
});
|
|
1447
|
+
let { data, error: rpcError } = await this.supabaseClient.rpc("data_user_events_get", {
|
|
1316
1448
|
p_user_id: this.user.id,
|
|
1317
|
-
p_organisation_id:
|
|
1449
|
+
p_organisation_id: organisationIdForRpc,
|
|
1318
1450
|
p_app_name: this.appName
|
|
1319
1451
|
});
|
|
1452
|
+
logger.debug("EventService", "RPC response received", {
|
|
1453
|
+
hasData: !!data,
|
|
1454
|
+
dataLength: Array.isArray(data) ? data.length : "not array",
|
|
1455
|
+
hasError: !!rpcError,
|
|
1456
|
+
error: rpcError
|
|
1457
|
+
});
|
|
1320
1458
|
if (rpcError) {
|
|
1321
1459
|
logger.error("EventService", "RPC error fetching events:", rpcError);
|
|
1322
1460
|
throw new Error(rpcError.message || "Failed to fetch events");
|
|
@@ -1428,24 +1566,41 @@ function EventServiceProvider({
|
|
|
1428
1566
|
setSelectedEventId
|
|
1429
1567
|
}) {
|
|
1430
1568
|
const eventServiceRef = useRef2(null);
|
|
1569
|
+
const initializingRef = useRef2(false);
|
|
1431
1570
|
if (!eventServiceRef.current) {
|
|
1432
1571
|
eventServiceRef.current = new EventService(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId);
|
|
1433
1572
|
}
|
|
1434
1573
|
const eventService = eventServiceRef.current;
|
|
1435
1574
|
useEffect3(() => {
|
|
1436
1575
|
let isMounted = true;
|
|
1576
|
+
if (initializingRef.current) {
|
|
1577
|
+
return;
|
|
1578
|
+
}
|
|
1437
1579
|
const updateAndInitialize = async () => {
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1580
|
+
initializingRef.current = true;
|
|
1581
|
+
try {
|
|
1582
|
+
logger.debug("EventServiceProvider", "Updating dependencies and initializing", {
|
|
1583
|
+
hasUser: !!user,
|
|
1584
|
+
hasSession: !!session,
|
|
1585
|
+
appName,
|
|
1586
|
+
hasSelectedOrganisation: !!selectedOrganisation,
|
|
1587
|
+
organisationId: selectedOrganisation?.id
|
|
1588
|
+
});
|
|
1589
|
+
await eventService.updateDependencies(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId);
|
|
1590
|
+
if (!isMounted) return;
|
|
1591
|
+
await eventService.initialize().catch((error) => {
|
|
1592
|
+
if (isMounted) {
|
|
1593
|
+
logger.error("EventServiceProvider", "Failed to initialize event service:", error);
|
|
1594
|
+
}
|
|
1595
|
+
});
|
|
1596
|
+
} finally {
|
|
1597
|
+
initializingRef.current = false;
|
|
1598
|
+
}
|
|
1445
1599
|
};
|
|
1446
1600
|
updateAndInitialize();
|
|
1447
1601
|
return () => {
|
|
1448
1602
|
isMounted = false;
|
|
1603
|
+
initializingRef.current = false;
|
|
1449
1604
|
};
|
|
1450
1605
|
}, [supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId]);
|
|
1451
1606
|
useEffect3(() => {
|
|
@@ -1750,8 +1905,10 @@ function InactivityServiceProvider({
|
|
|
1750
1905
|
supabaseClient,
|
|
1751
1906
|
user,
|
|
1752
1907
|
session,
|
|
1753
|
-
idleTimeoutMs
|
|
1754
|
-
|
|
1908
|
+
idleTimeoutMs,
|
|
1909
|
+
// REQUIRED: No default - must be explicitly provided
|
|
1910
|
+
warnBeforeMs,
|
|
1911
|
+
// REQUIRED: No default - must be explicitly provided
|
|
1755
1912
|
onIdleLogout
|
|
1756
1913
|
}) {
|
|
1757
1914
|
const inactivityServiceRef = useRef3(null);
|
|
@@ -1810,6 +1967,29 @@ function useOrganisationService() {
|
|
|
1810
1967
|
return context.organisationService;
|
|
1811
1968
|
}
|
|
1812
1969
|
|
|
1970
|
+
// src/hooks/useOrganisations.ts
|
|
1971
|
+
function useOrganisations() {
|
|
1972
|
+
const organisationService = useOrganisationService();
|
|
1973
|
+
const selectedOrg = organisationService.getSelectedOrganisation();
|
|
1974
|
+
return {
|
|
1975
|
+
selectedOrganisation: selectedOrg,
|
|
1976
|
+
organisations: organisationService.getOrganisations(),
|
|
1977
|
+
userMemberships: organisationService.getUserMemberships(),
|
|
1978
|
+
isLoading: organisationService.isLoading(),
|
|
1979
|
+
error: organisationService.getError(),
|
|
1980
|
+
hasValidOrganisationContext: organisationService.hasValidOrganisationContext(),
|
|
1981
|
+
isContextReady: organisationService.isContextReady(),
|
|
1982
|
+
setSelectedOrganisation: (org) => organisationService.setSelectedOrganisation(org),
|
|
1983
|
+
switchOrganisation: (orgId) => organisationService.switchOrganisation(orgId),
|
|
1984
|
+
getUserRole: (orgId) => organisationService.getUserRole(orgId),
|
|
1985
|
+
validateOrganisationAccess: (orgId) => organisationService.validateOrganisationAccess(orgId),
|
|
1986
|
+
refreshOrganisations: () => organisationService.refreshOrganisations(),
|
|
1987
|
+
ensureOrganisationContext: () => organisationService.ensureOrganisationContext(),
|
|
1988
|
+
isOrganisationSecure: () => organisationService.isOrganisationSecure(),
|
|
1989
|
+
getPrimaryOrganisation: () => organisationService.getPrimaryOrganisation()
|
|
1990
|
+
};
|
|
1991
|
+
}
|
|
1992
|
+
|
|
1813
1993
|
// src/hooks/services/useEventService.ts
|
|
1814
1994
|
import { useContext as useContext3, useReducer as useReducer3, useEffect as useEffect7 } from "react";
|
|
1815
1995
|
function useEventService() {
|
|
@@ -1893,6 +2073,7 @@ function UnifiedAuthContextProvider({
|
|
|
1893
2073
|
appName,
|
|
1894
2074
|
appConfig = { requires_event: true },
|
|
1895
2075
|
// Default to requiring events
|
|
2076
|
+
supabaseClient: supabaseClientProp,
|
|
1896
2077
|
...props
|
|
1897
2078
|
}) {
|
|
1898
2079
|
const authService = useAuthService();
|
|
@@ -1932,15 +2113,31 @@ function UnifiedAuthContextProvider({
|
|
|
1932
2113
|
const currentUser = authService.getUser();
|
|
1933
2114
|
const currentSession = authService.getSession();
|
|
1934
2115
|
const isAuth = !!(currentUser && currentSession);
|
|
1935
|
-
const supabase =
|
|
2116
|
+
const supabase = useMemo6(() => supabaseClientProp, [supabaseClientProp]);
|
|
1936
2117
|
const [appId, setAppId] = useState3(void 0);
|
|
1937
2118
|
const isResolvingAppIdRef = useRef4(false);
|
|
2119
|
+
const resolvedAppIdRef = useRef4(void 0);
|
|
2120
|
+
const resolvedUserIdRef = useRef4(void 0);
|
|
1938
2121
|
useEffect10(() => {
|
|
1939
|
-
if (isAuth
|
|
2122
|
+
if (!isAuth) {
|
|
2123
|
+
resolvedAppIdRef.current = void 0;
|
|
2124
|
+
resolvedUserIdRef.current = void 0;
|
|
2125
|
+
setAppId(void 0);
|
|
2126
|
+
return;
|
|
2127
|
+
}
|
|
2128
|
+
if (currentUser?.id && resolvedUserIdRef.current && resolvedUserIdRef.current !== currentUser.id) {
|
|
2129
|
+
resolvedAppIdRef.current = void 0;
|
|
2130
|
+
resolvedUserIdRef.current = void 0;
|
|
2131
|
+
setAppId(void 0);
|
|
2132
|
+
}
|
|
2133
|
+
const currentUserId = currentUser?.id;
|
|
2134
|
+
if (isAuth && currentUserId && supabase && appName && resolvedUserIdRef.current !== currentUserId && // Haven't resolved for this user yet
|
|
2135
|
+
!isResolvingAppIdRef.current) {
|
|
1940
2136
|
isResolvingAppIdRef.current = true;
|
|
1941
|
-
|
|
2137
|
+
resolvedUserIdRef.current = currentUserId;
|
|
2138
|
+
const userId = currentUserId;
|
|
1942
2139
|
const appNameValue = appName;
|
|
1943
|
-
import("./api-
|
|
2140
|
+
import("./api-I6UCQ5S6.js").then(async ({ resolveAppContext, setupRBAC }) => {
|
|
1944
2141
|
try {
|
|
1945
2142
|
setupRBAC(supabase);
|
|
1946
2143
|
const result = await resolveAppContext({
|
|
@@ -1948,11 +2145,14 @@ function UnifiedAuthContextProvider({
|
|
|
1948
2145
|
appName: appNameValue
|
|
1949
2146
|
});
|
|
1950
2147
|
if (result?.appId) {
|
|
2148
|
+
resolvedAppIdRef.current = result.appId;
|
|
1951
2149
|
setAppId(result.appId);
|
|
1952
2150
|
logger.debug("UnifiedAuthProvider", "appId resolved on login", {
|
|
1953
2151
|
appId: result.appId,
|
|
1954
2152
|
appName: appNameValue
|
|
1955
2153
|
});
|
|
2154
|
+
} else {
|
|
2155
|
+
resolvedUserIdRef.current = void 0;
|
|
1956
2156
|
}
|
|
1957
2157
|
} catch (error) {
|
|
1958
2158
|
logger.error("UnifiedAuthProvider", "Failed to resolve appId on login", {
|
|
@@ -1960,41 +2160,64 @@ function UnifiedAuthContextProvider({
|
|
|
1960
2160
|
appName: appNameValue,
|
|
1961
2161
|
userId
|
|
1962
2162
|
});
|
|
2163
|
+
resolvedUserIdRef.current = void 0;
|
|
1963
2164
|
} finally {
|
|
1964
2165
|
isResolvingAppIdRef.current = false;
|
|
1965
2166
|
}
|
|
1966
2167
|
}).catch((importError) => {
|
|
1967
2168
|
logger.error("UnifiedAuthProvider", "Failed to import RBAC API", importError);
|
|
1968
2169
|
isResolvingAppIdRef.current = false;
|
|
2170
|
+
resolvedUserIdRef.current = void 0;
|
|
1969
2171
|
});
|
|
1970
2172
|
}
|
|
1971
|
-
|
|
1972
|
-
setAppId(void 0);
|
|
1973
|
-
}
|
|
1974
|
-
}, [isAuth, currentUser?.id, supabase, appName, appId]);
|
|
2173
|
+
}, [isAuth, currentUser?.id, supabase, appName]);
|
|
1975
2174
|
const [, forceUpdate] = useReducer5((x) => x + 1, 0);
|
|
2175
|
+
const forceUpdateTimeoutRef = useRef4(null);
|
|
2176
|
+
const debouncedForceUpdate = useCallback(() => {
|
|
2177
|
+
if (forceUpdateTimeoutRef.current) {
|
|
2178
|
+
clearTimeout(forceUpdateTimeoutRef.current);
|
|
2179
|
+
}
|
|
2180
|
+
forceUpdateTimeoutRef.current = setTimeout(() => {
|
|
2181
|
+
forceUpdate();
|
|
2182
|
+
forceUpdateTimeoutRef.current = null;
|
|
2183
|
+
}, 0);
|
|
2184
|
+
}, [forceUpdate]);
|
|
2185
|
+
const authServiceRef = useRef4(authService);
|
|
2186
|
+
const organisationServiceRef = useRef4(organisationService);
|
|
2187
|
+
const eventServiceRef = useRef4(eventService);
|
|
2188
|
+
const inactivityServiceRef = useRef4(inactivityService);
|
|
2189
|
+
useEffect10(() => {
|
|
2190
|
+
authServiceRef.current = authService;
|
|
2191
|
+
organisationServiceRef.current = organisationService;
|
|
2192
|
+
eventServiceRef.current = eventService;
|
|
2193
|
+
inactivityServiceRef.current = inactivityService;
|
|
2194
|
+
}, [authService, organisationService, eventService, inactivityService]);
|
|
1976
2195
|
useEffect10(() => {
|
|
1977
|
-
const unsubscribeAuth =
|
|
1978
|
-
const unsubscribeOrg =
|
|
1979
|
-
const unsubscribeEvent =
|
|
1980
|
-
const unsubscribeInactivity =
|
|
2196
|
+
const unsubscribeAuth = authServiceRef.current.subscribe(debouncedForceUpdate);
|
|
2197
|
+
const unsubscribeOrg = organisationServiceRef.current.subscribe(debouncedForceUpdate);
|
|
2198
|
+
const unsubscribeEvent = eventServiceRef.current.subscribe(debouncedForceUpdate);
|
|
2199
|
+
const unsubscribeInactivity = inactivityServiceRef.current.subscribe(debouncedForceUpdate);
|
|
1981
2200
|
return () => {
|
|
1982
2201
|
unsubscribeAuth();
|
|
1983
2202
|
unsubscribeOrg();
|
|
1984
2203
|
unsubscribeEvent();
|
|
1985
2204
|
unsubscribeInactivity();
|
|
2205
|
+
if (forceUpdateTimeoutRef.current) {
|
|
2206
|
+
clearTimeout(forceUpdateTimeoutRef.current);
|
|
2207
|
+
}
|
|
1986
2208
|
};
|
|
1987
|
-
}, [
|
|
2209
|
+
}, [debouncedForceUpdate]);
|
|
1988
2210
|
const authLoading = authService.isLoading();
|
|
1989
2211
|
const orgLoading = organisationService.isLoading();
|
|
1990
2212
|
const eventLoading = eventService.isLoading();
|
|
1991
2213
|
const restorationLoading = sessionRestoration.isRestoring && !sessionRestorationTimedOut && !sessionRestoration.restorationError;
|
|
1992
2214
|
const totalLoading = restorationLoading || authLoading || orgLoading || eventLoading;
|
|
1993
2215
|
const authError = authService.getError();
|
|
1994
|
-
const
|
|
2216
|
+
const rawSelectedOrganisation = organisationService.getSelectedOrganisation();
|
|
1995
2217
|
const organisations = organisationService.getOrganisations();
|
|
1996
2218
|
const userMemberships = organisationService.getUserMemberships();
|
|
1997
2219
|
const organisationError = organisationService.getError();
|
|
2220
|
+
const selectedOrganisation = appConfig?.requires_event ? null : rawSelectedOrganisation;
|
|
1998
2221
|
const hasValidOrganisationContext = organisationService.hasValidOrganisationContext();
|
|
1999
2222
|
const isContextReady = organisationService.isContextReady();
|
|
2000
2223
|
const events = eventService.getEvents();
|
|
@@ -2170,10 +2393,13 @@ function EventServiceProviderWrapper({
|
|
|
2170
2393
|
supabaseClient,
|
|
2171
2394
|
user,
|
|
2172
2395
|
session,
|
|
2173
|
-
appName
|
|
2396
|
+
appName,
|
|
2397
|
+
appConfig
|
|
2174
2398
|
}) {
|
|
2175
|
-
const
|
|
2176
|
-
const selectedOrganisation =
|
|
2399
|
+
const { selectedOrganisation: rawSelectedOrganisation } = useOrganisations();
|
|
2400
|
+
const selectedOrganisation = appConfig?.requires_event ? null : rawSelectedOrganisation;
|
|
2401
|
+
const setSelectedEventId = useCallback(() => {
|
|
2402
|
+
}, []);
|
|
2177
2403
|
return /* @__PURE__ */ jsx5(
|
|
2178
2404
|
EventServiceProvider,
|
|
2179
2405
|
{
|
|
@@ -2182,8 +2408,7 @@ function EventServiceProviderWrapper({
|
|
|
2182
2408
|
session,
|
|
2183
2409
|
appName,
|
|
2184
2410
|
selectedOrganisation,
|
|
2185
|
-
setSelectedEventId
|
|
2186
|
-
},
|
|
2411
|
+
setSelectedEventId,
|
|
2187
2412
|
children
|
|
2188
2413
|
}
|
|
2189
2414
|
);
|
|
@@ -2216,6 +2441,7 @@ function ServiceAwareProviders({
|
|
|
2216
2441
|
user: authService.getUser(),
|
|
2217
2442
|
session: authService.getSession(),
|
|
2218
2443
|
appName,
|
|
2444
|
+
appConfig,
|
|
2219
2445
|
children: /* @__PURE__ */ jsx5(
|
|
2220
2446
|
InactivityServiceProvider,
|
|
2221
2447
|
{
|
|
@@ -2258,11 +2484,12 @@ function UnifiedAuthProvider({
|
|
|
2258
2484
|
persistState = true,
|
|
2259
2485
|
enablePersistence,
|
|
2260
2486
|
requireOrganisationContext = true,
|
|
2261
|
-
idleTimeoutMs
|
|
2262
|
-
//
|
|
2263
|
-
warnBeforeMs
|
|
2264
|
-
//
|
|
2487
|
+
idleTimeoutMs,
|
|
2488
|
+
// REQUIRED: No default - must be explicitly provided
|
|
2489
|
+
warnBeforeMs,
|
|
2490
|
+
// REQUIRED: No default - must be explicitly provided
|
|
2265
2491
|
onIdleLogout,
|
|
2492
|
+
// REQUIRED: No default - must be explicitly provided
|
|
2266
2493
|
renderInactivityWarning,
|
|
2267
2494
|
dangerouslyDisableInactivity = false
|
|
2268
2495
|
}) {
|
|
@@ -2307,6 +2534,7 @@ export {
|
|
|
2307
2534
|
InactivityServiceProvider,
|
|
2308
2535
|
useAuthService,
|
|
2309
2536
|
useOrganisationService,
|
|
2537
|
+
useOrganisations,
|
|
2310
2538
|
useEventService,
|
|
2311
2539
|
useInactivityService,
|
|
2312
2540
|
useSessionRestoration,
|
|
@@ -2314,4 +2542,4 @@ export {
|
|
|
2314
2542
|
useUnifiedAuth,
|
|
2315
2543
|
UnifiedAuthProvider
|
|
2316
2544
|
};
|
|
2317
|
-
//# sourceMappingURL=chunk-
|
|
2545
|
+
//# sourceMappingURL=chunk-J2XXC7R5.js.map
|