@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
|
@@ -71,6 +71,21 @@ export class OrganisationService extends BaseService implements IOrganisationSer
|
|
|
71
71
|
|
|
72
72
|
// Additional methods for testing
|
|
73
73
|
setSelectedOrganisation(organisation: Organisation | null): void {
|
|
74
|
+
// SECURITY: Validate organisation is in user's accessible organisations (only if orgs are loaded)
|
|
75
|
+
if (organisation && this._organisations.length > 0) {
|
|
76
|
+
const isValidOrg = this._organisations.some(org => org.id === organisation.id);
|
|
77
|
+
if (!isValidOrg) {
|
|
78
|
+
logger.warn('OrganisationService', 'Attempted to set invalid organisation - not in user\'s accessible organisations', {
|
|
79
|
+
organisationId: organisation.id,
|
|
80
|
+
organisationName: organisation.name,
|
|
81
|
+
accessibleOrgIds: this._organisations.map(o => o.id)
|
|
82
|
+
});
|
|
83
|
+
// Don't set invalid organisation - this prevents security issues
|
|
84
|
+
// If organisations haven't loaded yet, validation will happen in loadUserOrganisations()
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
74
89
|
this._selectedOrganisation = organisation;
|
|
75
90
|
if (organisation) {
|
|
76
91
|
localStorage.setItem('pace-core-selected-organisation', JSON.stringify(organisation));
|
|
@@ -570,6 +585,16 @@ export class OrganisationService extends BaseService implements IOrganisationSer
|
|
|
570
585
|
throw new Error('No valid organisation found for user') as OrganisationSecurityError;
|
|
571
586
|
}
|
|
572
587
|
|
|
588
|
+
// SECURITY: Validate current selected organisation is still valid (in case it was set before orgs loaded)
|
|
589
|
+
const currentSelectedOrg = this._selectedOrganisation;
|
|
590
|
+
if (currentSelectedOrg && !activeOrgs.some(org => org.id === currentSelectedOrg.id)) {
|
|
591
|
+
logger.warn('OrganisationService', 'Current selected organisation is no longer valid, resetting', {
|
|
592
|
+
invalidOrgId: currentSelectedOrg.id,
|
|
593
|
+
validOrgIds: activeOrgs.map(o => o.id)
|
|
594
|
+
});
|
|
595
|
+
this._selectedOrganisation = null;
|
|
596
|
+
}
|
|
597
|
+
|
|
573
598
|
this._selectedOrganisation = initialOrg;
|
|
574
599
|
|
|
575
600
|
// Persist selection
|
|
@@ -583,14 +608,24 @@ export class OrganisationService extends BaseService implements IOrganisationSer
|
|
|
583
608
|
this.hasFailedRef = false;
|
|
584
609
|
|
|
585
610
|
} catch (err) {
|
|
586
|
-
|
|
587
|
-
|
|
611
|
+
const error = err as Error;
|
|
612
|
+
// "User has no access to active organisations" is a valid state for users without orgs (e.g., profile pages)
|
|
613
|
+
// Log it as a warning instead of an error to reduce noise
|
|
614
|
+
if (error.message === 'User has no access to active organisations') {
|
|
615
|
+
logger.warn("OrganisationService", "User has no active organisations (this is expected for users without organisation access):", error);
|
|
616
|
+
} else {
|
|
617
|
+
logger.error("OrganisationService", "Failed to load organisations:", err);
|
|
618
|
+
}
|
|
619
|
+
this._error = error;
|
|
588
620
|
// Increment retry count on error
|
|
589
621
|
this.retryCount = this.retryCount + 1;
|
|
590
622
|
// Set failed flag to prevent further attempts
|
|
591
623
|
this.hasFailedRef = true;
|
|
592
624
|
// Clear all cached data on error to prevent corruption
|
|
593
625
|
this.clearAllCachedData();
|
|
626
|
+
// Mark context as ready even on error - this allows the app to proceed
|
|
627
|
+
// The app can check hasValidOrganisationContext() to determine if org context is available
|
|
628
|
+
this._isContextReady = true;
|
|
594
629
|
} finally {
|
|
595
630
|
// Always cleanup refs and abort controller
|
|
596
631
|
this.isLoadingRef = false;
|
|
@@ -40,6 +40,16 @@ vi.mock('../../utils/security/secureStorage', () => {
|
|
|
40
40
|
import { secureStorage } from '../../utils/security/secureStorage';
|
|
41
41
|
const mockSecureStorage = secureStorage as any;
|
|
42
42
|
|
|
43
|
+
// Mock getAppConfigByName to return org-required app config by default
|
|
44
|
+
vi.mock('../../rbac/api', async () => {
|
|
45
|
+
const actual = await vi.importActual('../../rbac/api');
|
|
46
|
+
return {
|
|
47
|
+
...actual,
|
|
48
|
+
getAppConfigByName: vi.fn().mockResolvedValue({ requires_event: false }),
|
|
49
|
+
isSuperAdmin: vi.fn().mockResolvedValue(false),
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
|
|
43
53
|
// Mock Supabase client
|
|
44
54
|
const createMockSupabaseClient = () => ({
|
|
45
55
|
rpc: vi.fn(),
|
|
@@ -175,9 +185,11 @@ describe('EventService', () => {
|
|
|
175
185
|
|
|
176
186
|
await eventService.initialize();
|
|
177
187
|
|
|
188
|
+
// For org-required apps: uses selectedOrganisation.id
|
|
189
|
+
// For event-required apps: uses selectedEvent.organisation_id or null for super admins
|
|
178
190
|
expect(mockSupabase.rpc).toHaveBeenCalledWith('data_user_events_get', {
|
|
179
191
|
p_user_id: mockUser.id,
|
|
180
|
-
p_organisation_id: mockOrganisation.id,
|
|
192
|
+
p_organisation_id: mockOrganisation.id, // Org-required app uses selectedOrganisation
|
|
181
193
|
p_app_name: 'test-app'
|
|
182
194
|
});
|
|
183
195
|
|
|
@@ -229,7 +241,7 @@ describe('EventService', () => {
|
|
|
229
241
|
expect(mockSetSelectedEventId).toHaveBeenCalledWith(null);
|
|
230
242
|
});
|
|
231
243
|
|
|
232
|
-
it('should
|
|
244
|
+
it('should allow selecting event from any organisation (no validation)', () => {
|
|
233
245
|
// Clear any auto-selected event first
|
|
234
246
|
eventService.setSelectedEvent(null);
|
|
235
247
|
|
|
@@ -240,8 +252,8 @@ describe('EventService', () => {
|
|
|
240
252
|
|
|
241
253
|
eventService.setSelectedEvent(eventFromDifferentOrg);
|
|
242
254
|
|
|
243
|
-
// Should
|
|
244
|
-
expect(eventService.getSelectedEvent()).
|
|
255
|
+
// Should allow selection - org validation removed (org derived from event for event-required apps)
|
|
256
|
+
expect(eventService.getSelectedEvent()).toEqual(eventFromDifferentOrg);
|
|
245
257
|
});
|
|
246
258
|
|
|
247
259
|
it('should refresh events', async () => {
|
|
@@ -976,8 +988,8 @@ describe('EventService', () => {
|
|
|
976
988
|
});
|
|
977
989
|
});
|
|
978
990
|
|
|
979
|
-
describe('Event
|
|
980
|
-
it('should
|
|
991
|
+
describe('Event Selection', () => {
|
|
992
|
+
it('should allow selecting event without organisation validation', () => {
|
|
981
993
|
vi.clearAllMocks();
|
|
982
994
|
|
|
983
995
|
const eventFromDifferentOrg: Event = {
|
|
@@ -985,22 +997,16 @@ describe('EventService', () => {
|
|
|
985
997
|
organisation_id: 'org-2'
|
|
986
998
|
};
|
|
987
999
|
|
|
988
|
-
// Should not throw error
|
|
1000
|
+
// Should not throw error - validation removed (org derived from event for event-required apps)
|
|
989
1001
|
eventService.setSelectedEvent(eventFromDifferentOrg);
|
|
990
1002
|
|
|
991
|
-
//
|
|
992
|
-
expect(
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
expect.objectContaining({
|
|
996
|
-
eventOrganisationId: 'org-2',
|
|
997
|
-
selectedOrganisationId: 'org-1',
|
|
998
|
-
eventName: expect.any(String)
|
|
999
|
-
})
|
|
1000
|
-
);
|
|
1003
|
+
// Event should be selected successfully
|
|
1004
|
+
expect(eventService.getSelectedEvent()).toEqual(eventFromDifferentOrg);
|
|
1005
|
+
// No error should be logged
|
|
1006
|
+
expect(mockLoggerFunctions.error).not.toHaveBeenCalled();
|
|
1001
1007
|
});
|
|
1002
1008
|
|
|
1003
|
-
it('should
|
|
1009
|
+
it('should allow selecting event when organisation is null (event-required apps)', () => {
|
|
1004
1010
|
const serviceWithoutOrg = new EventService(
|
|
1005
1011
|
mockSupabase as any,
|
|
1006
1012
|
mockUser,
|
|
@@ -1010,11 +1016,10 @@ describe('EventService', () => {
|
|
|
1010
1016
|
mockSetSelectedEventId
|
|
1011
1017
|
);
|
|
1012
1018
|
|
|
1013
|
-
// Should not throw error
|
|
1019
|
+
// Should not throw error - org is derived from event for event-required apps
|
|
1014
1020
|
serviceWithoutOrg.setSelectedEvent(mockEvent);
|
|
1015
1021
|
|
|
1016
|
-
//
|
|
1017
|
-
// So the event can still be selected
|
|
1022
|
+
// Event should be selected successfully
|
|
1018
1023
|
expect(serviceWithoutOrg.getSelectedEvent()).toEqual(mockEvent);
|
|
1019
1024
|
});
|
|
1020
1025
|
});
|
|
@@ -9,7 +9,7 @@ export interface FileReference {
|
|
|
9
9
|
record_id: string;
|
|
10
10
|
file_path: string;
|
|
11
11
|
file_metadata: FileMetadata;
|
|
12
|
-
organisation_id: string;
|
|
12
|
+
organisation_id: string | null; // Nullable for user-scoped files (e.g., profile photos)
|
|
13
13
|
app_id: AppId;
|
|
14
14
|
is_public: boolean;
|
|
15
15
|
created_at: string;
|
|
@@ -56,11 +56,13 @@ export enum FileCategory {
|
|
|
56
56
|
* @property pageContext - The page context where the file upload occurs (e.g., 'configuration', 'forms', 'applications')
|
|
57
57
|
* Used for context-aware permission checks. Required to check appropriate page-level permissions.
|
|
58
58
|
* @property event_id - Optional event ID for event-scoped permission checks. Required for event-based apps.
|
|
59
|
+
* @property organisation_id - Optional organisation ID. If not provided, the file is user-owned (record_id must match user_id).
|
|
60
|
+
* For user-owned files, users can only access their own files.
|
|
59
61
|
*/
|
|
60
62
|
export interface FileUploadOptions {
|
|
61
63
|
table_name: string;
|
|
62
64
|
record_id: string;
|
|
63
|
-
organisation_id: string;
|
|
65
|
+
organisation_id: string | null; // Nullable for user-scoped files (e.g., profile photos)
|
|
64
66
|
app_id: AppId;
|
|
65
67
|
category: FileCategory;
|
|
66
68
|
folder: string; // Folder name in storage bucket (e.g., 'profile_photos', 'documents')
|
|
@@ -68,20 +70,21 @@ export interface FileUploadOptions {
|
|
|
68
70
|
event_id?: string;
|
|
69
71
|
is_public?: boolean;
|
|
70
72
|
custom_metadata?: Record<string, unknown>;
|
|
73
|
+
userId?: string; // Optional userId for user-scoped files
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
|
|
74
77
|
export interface FileReferenceService {
|
|
75
78
|
createFileReference(options: FileUploadOptions, file: File): Promise<FileReference>;
|
|
76
|
-
getFileReference(table_name: string, record_id: string, organisation_id
|
|
77
|
-
getFileReferenceById(id: string, organisation_id
|
|
78
|
-
getFileUrl(table_name: string, record_id: string, organisation_id
|
|
79
|
-
getSignedUrl(table_name: string, record_id: string, organisation_id
|
|
79
|
+
getFileReference(table_name: string, record_id: string, organisation_id?: string): Promise<FileReference | null>;
|
|
80
|
+
getFileReferenceById(id: string, organisation_id?: string): Promise<FileReference | null>;
|
|
81
|
+
getFileUrl(table_name: string, record_id: string, organisation_id?: string): Promise<string | null>;
|
|
82
|
+
getSignedUrl(table_name: string, record_id: string, organisation_id?: string, expires_in?: number): Promise<string | null>;
|
|
80
83
|
updateFileReference(id: string, updates: Partial<FileReference>): Promise<FileReference>;
|
|
81
|
-
deleteFileReference(table_name: string, record_id: string, organisation_id
|
|
82
|
-
listFileReferences(table_name: string, record_id: string, organisation_id
|
|
83
|
-
getFilesByCategory(table_name: string, record_id: string, category: FileCategory, organisation_id
|
|
84
|
-
getFileCount(table_name: string, record_id: string, organisation_id
|
|
84
|
+
deleteFileReference(table_name: string, record_id: string, organisation_id?: string, delete_file?: boolean): Promise<boolean>;
|
|
85
|
+
listFileReferences(table_name: string, record_id: string, organisation_id?: string): Promise<FileReference[]>;
|
|
86
|
+
getFilesByCategory(table_name: string, record_id: string, category: FileCategory, organisation_id?: string): Promise<FileReference[]>;
|
|
87
|
+
getFileCount(table_name: string, record_id: string, organisation_id?: string): Promise<number>;
|
|
85
88
|
uploadMultipleFiles(options: FileUploadOptions, files: File[]): Promise<BulkUploadResult>;
|
|
86
89
|
}
|
|
87
90
|
|