@jmruthers/pace-core 0.5.189 → 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-B8HaLe69.d.ts → PublicPageProvider-C4uxosp6.d.ts} +83 -24
- 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-UCQSRW7Z.js → chunk-NIU6J6OX.js} +425 -378
- 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-MX64ZF6I.js → chunk-STYK4OH2.js} +11 -11
- package/dist/chunk-STYK4OH2.js.map +1 -0
- package/dist/{chunk-YGPFYGA6.js → chunk-VVBAW5A5.js} +822 -498
- 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 -4
- package/dist/components.js +19 -19
- 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 -11
- package/dist/index.js +79 -69
- 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 +1 -1
- 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 +151 -92
- package/docs/api-reference/components.md +15 -7
- 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 -3
- 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 +95 -43
- package/src/components/Avatar/Avatar.tsx +16 -16
- 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.tsx +3 -3
- 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/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-F2IMUDXZ.js.map +0 -1
- package/dist/chunk-HEHYGYOX.js.map +0 -1
- package/dist/chunk-IM4QE42D.js.map +0 -1
- package/dist/chunk-MX64ZF6I.js.map +0 -1
- package/dist/chunk-SAUPYVLF.js.map +0 -1
- package/dist/chunk-THRPYOFK.js.map +0 -1
- package/dist/chunk-UCQSRW7Z.js.map +0 -1
- package/dist/chunk-VGZZXKBR.js.map +0 -1
- package/dist/chunk-YGPFYGA6.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
|
@@ -69,17 +69,24 @@ describe('useSecureSupabase Hook', () => {
|
|
|
69
69
|
const mockUseResolvedScope = vi.mocked(useResolvedScope);
|
|
70
70
|
const mockCreateSecureClient = vi.mocked(createSecureClient);
|
|
71
71
|
|
|
72
|
-
const originalEnv = import.meta.env;
|
|
73
|
-
|
|
74
72
|
beforeEach(() => {
|
|
75
73
|
vi.clearAllMocks();
|
|
76
74
|
|
|
77
|
-
//
|
|
75
|
+
// Clear the secure client cache by accessing it through a test helper
|
|
76
|
+
// The cache is module-level, so we need to ensure it's cleared
|
|
77
|
+
// We'll use unique org IDs in each test to avoid cache hits
|
|
78
|
+
|
|
79
|
+
// Setup environment variables - mock both import.meta.env and process.env
|
|
80
|
+
// The getSupabaseConfig function checks both
|
|
81
|
+
vi.stubEnv('VITE_SUPABASE_URL', 'https://test.supabase.co');
|
|
82
|
+
vi.stubEnv('VITE_SUPABASE_PUBLISHABLE_KEY', 'test-key');
|
|
83
|
+
|
|
84
|
+
// Also set import.meta.env directly since the function checks it first
|
|
78
85
|
Object.defineProperty(import.meta, 'env', {
|
|
79
86
|
value: {
|
|
80
87
|
VITE_SUPABASE_URL: 'https://test.supabase.co',
|
|
81
|
-
|
|
82
|
-
...
|
|
88
|
+
VITE_SUPABASE_PUBLISHABLE_KEY: 'test-key',
|
|
89
|
+
...import.meta.env
|
|
83
90
|
},
|
|
84
91
|
writable: true,
|
|
85
92
|
configurable: true
|
|
@@ -128,9 +135,11 @@ describe('useSecureSupabase Hook', () => {
|
|
|
128
135
|
|
|
129
136
|
afterEach(() => {
|
|
130
137
|
vi.clearAllMocks();
|
|
131
|
-
// Restore
|
|
138
|
+
// Restore environment
|
|
139
|
+
vi.unstubAllEnvs();
|
|
140
|
+
// Restore import.meta.env
|
|
132
141
|
Object.defineProperty(import.meta, 'env', {
|
|
133
|
-
value:
|
|
142
|
+
value: import.meta.env,
|
|
134
143
|
writable: true,
|
|
135
144
|
configurable: true
|
|
136
145
|
});
|
|
@@ -138,15 +147,36 @@ describe('useSecureSupabase Hook', () => {
|
|
|
138
147
|
|
|
139
148
|
describe('Client Creation', () => {
|
|
140
149
|
it('should create a secure client when context is available', async () => {
|
|
150
|
+
// Use a unique org ID to avoid cache hits from previous tests
|
|
151
|
+
const uniqueOrgId = `org-${Date.now()}`;
|
|
152
|
+
mockUseOrganisations.mockReturnValue({
|
|
153
|
+
selectedOrganisation: { id: uniqueOrgId },
|
|
154
|
+
organisations: [],
|
|
155
|
+
isLoading: false,
|
|
156
|
+
error: null,
|
|
157
|
+
selectOrganisation: vi.fn(),
|
|
158
|
+
refreshOrganisations: vi.fn()
|
|
159
|
+
} as any);
|
|
160
|
+
|
|
161
|
+
mockUseResolvedScope.mockReturnValue({
|
|
162
|
+
resolvedScope: {
|
|
163
|
+
organisationId: uniqueOrgId,
|
|
164
|
+
eventId: mockEventId,
|
|
165
|
+
appId: mockAppId
|
|
166
|
+
},
|
|
167
|
+
isLoading: false,
|
|
168
|
+
error: null
|
|
169
|
+
});
|
|
170
|
+
|
|
141
171
|
const { result } = renderHook(() => useSecureSupabase());
|
|
142
172
|
|
|
143
173
|
await waitFor(() => {
|
|
144
|
-
expect(
|
|
145
|
-
});
|
|
174
|
+
expect(mockCreateSecureClient).toHaveBeenCalled();
|
|
175
|
+
}, { timeout: 2000 });
|
|
146
176
|
|
|
147
|
-
expect(
|
|
177
|
+
expect(result.current).toBe(mockSupabaseClient);
|
|
148
178
|
const call = mockCreateSecureClient.mock.calls[0];
|
|
149
|
-
expect(call[2]).toBe(
|
|
179
|
+
expect(call[2]).toBe(uniqueOrgId);
|
|
150
180
|
expect(call[3]).toBe(mockEventId);
|
|
151
181
|
expect(call[4]).toBe(mockAppId);
|
|
152
182
|
});
|
|
@@ -179,6 +209,13 @@ describe('useSecureSupabase Hook', () => {
|
|
|
179
209
|
selectOrganisation: vi.fn(),
|
|
180
210
|
refreshOrganisations: vi.fn()
|
|
181
211
|
} as any);
|
|
212
|
+
|
|
213
|
+
// Mock useResolvedScope to return null scope when organisation is not available
|
|
214
|
+
mockUseResolvedScope.mockReturnValue({
|
|
215
|
+
resolvedScope: null,
|
|
216
|
+
isLoading: false,
|
|
217
|
+
error: null
|
|
218
|
+
});
|
|
182
219
|
|
|
183
220
|
const baseClient = mockSupabaseClient;
|
|
184
221
|
const { result } = renderHook(() => useSecureSupabase(baseClient));
|
|
@@ -256,18 +293,39 @@ describe('useSecureSupabase Hook', () => {
|
|
|
256
293
|
});
|
|
257
294
|
|
|
258
295
|
it('should create new client when context changes', async () => {
|
|
296
|
+
const uniqueOrgId1 = `org-${Date.now()}-1`;
|
|
297
|
+
mockUseOrganisations.mockReturnValue({
|
|
298
|
+
selectedOrganisation: { id: uniqueOrgId1 },
|
|
299
|
+
organisations: [],
|
|
300
|
+
isLoading: false,
|
|
301
|
+
error: null,
|
|
302
|
+
selectOrganisation: vi.fn(),
|
|
303
|
+
refreshOrganisations: vi.fn()
|
|
304
|
+
} as any);
|
|
305
|
+
|
|
306
|
+
mockUseResolvedScope.mockReturnValue({
|
|
307
|
+
resolvedScope: {
|
|
308
|
+
organisationId: uniqueOrgId1,
|
|
309
|
+
eventId: mockEventId,
|
|
310
|
+
appId: mockAppId
|
|
311
|
+
},
|
|
312
|
+
isLoading: false,
|
|
313
|
+
error: null
|
|
314
|
+
});
|
|
315
|
+
|
|
259
316
|
const { result: result1, rerender: rerender1 } = renderHook(() => useSecureSupabase());
|
|
260
317
|
|
|
261
318
|
await waitFor(() => {
|
|
262
|
-
expect(
|
|
263
|
-
});
|
|
319
|
+
expect(mockCreateSecureClient).toHaveBeenCalled();
|
|
320
|
+
}, { timeout: 2000 });
|
|
264
321
|
|
|
265
322
|
// Clear the mock to count new calls
|
|
266
323
|
mockCreateSecureClient.mockClear();
|
|
267
324
|
|
|
268
325
|
// Change organisation - this should create a new client with different cache key
|
|
326
|
+
const uniqueOrgId2 = `org-${Date.now()}-2`;
|
|
269
327
|
mockUseOrganisations.mockReturnValue({
|
|
270
|
-
selectedOrganisation: { id:
|
|
328
|
+
selectedOrganisation: { id: uniqueOrgId2 },
|
|
271
329
|
organisations: [],
|
|
272
330
|
isLoading: false,
|
|
273
331
|
error: null,
|
|
@@ -278,7 +336,7 @@ describe('useSecureSupabase Hook', () => {
|
|
|
278
336
|
// Also update resolved scope to match
|
|
279
337
|
mockUseResolvedScope.mockReturnValue({
|
|
280
338
|
resolvedScope: {
|
|
281
|
-
organisationId:
|
|
339
|
+
organisationId: uniqueOrgId2,
|
|
282
340
|
eventId: mockEventId,
|
|
283
341
|
appId: mockAppId
|
|
284
342
|
},
|
|
@@ -296,14 +354,9 @@ describe('useSecureSupabase Hook', () => {
|
|
|
296
354
|
|
|
297
355
|
describe('Environment Variables', () => {
|
|
298
356
|
it('should fallback to base client when Supabase URL is missing', () => {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
...originalEnv
|
|
303
|
-
},
|
|
304
|
-
writable: true,
|
|
305
|
-
configurable: true
|
|
306
|
-
});
|
|
357
|
+
vi.unstubAllEnvs();
|
|
358
|
+
vi.stubEnv('VITE_SUPABASE_PUBLISHABLE_KEY', 'test-key');
|
|
359
|
+
// VITE_SUPABASE_URL is not set
|
|
307
360
|
|
|
308
361
|
const baseClient = mockSupabaseClient;
|
|
309
362
|
const { result } = renderHook(() => useSecureSupabase(baseClient));
|
|
@@ -313,14 +366,9 @@ describe('useSecureSupabase Hook', () => {
|
|
|
313
366
|
});
|
|
314
367
|
|
|
315
368
|
it('should fallback to base client when Supabase key is missing', () => {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
...originalEnv
|
|
320
|
-
},
|
|
321
|
-
writable: true,
|
|
322
|
-
configurable: true
|
|
323
|
-
});
|
|
369
|
+
vi.unstubAllEnvs();
|
|
370
|
+
vi.stubEnv('VITE_SUPABASE_URL', 'https://test.supabase.co');
|
|
371
|
+
// VITE_SUPABASE_PUBLISHABLE_KEY is not set
|
|
324
372
|
|
|
325
373
|
const baseClient = mockSupabaseClient;
|
|
326
374
|
const { result } = renderHook(() => useSecureSupabase(baseClient));
|
|
@@ -342,30 +390,54 @@ describe('useSecureSupabase Hook', () => {
|
|
|
342
390
|
expect(result.current).toBe(baseClient);
|
|
343
391
|
});
|
|
344
392
|
|
|
345
|
-
it('should handle missing resolved scope gracefully', () => {
|
|
393
|
+
it('should handle missing resolved scope gracefully', async () => {
|
|
394
|
+
// Use unique org ID to avoid cache
|
|
395
|
+
const uniqueOrgId = `org-${Date.now()}-missing-scope`;
|
|
396
|
+
mockUseOrganisations.mockReturnValue({
|
|
397
|
+
selectedOrganisation: { id: uniqueOrgId },
|
|
398
|
+
organisations: [],
|
|
399
|
+
isLoading: false,
|
|
400
|
+
error: null,
|
|
401
|
+
selectOrganisation: vi.fn(),
|
|
402
|
+
refreshOrganisations: vi.fn()
|
|
403
|
+
} as any);
|
|
404
|
+
|
|
405
|
+
// When resolvedScope is null but selectedOrganisation exists,
|
|
406
|
+
// useSecureSupabase should still create a client using selectedOrganisation.id
|
|
407
|
+
// This is a fallback behavior when scope resolution fails
|
|
346
408
|
mockUseResolvedScope.mockReturnValue({
|
|
347
409
|
resolvedScope: null,
|
|
348
410
|
isLoading: false,
|
|
349
411
|
error: null
|
|
350
412
|
});
|
|
351
413
|
|
|
352
|
-
const
|
|
414
|
+
const baseClient = mockSupabaseClient;
|
|
415
|
+
const { result } = renderHook(() => useSecureSupabase(baseClient));
|
|
353
416
|
|
|
354
|
-
//
|
|
355
|
-
expect(
|
|
356
|
-
|
|
357
|
-
expect(
|
|
358
|
-
expect(call[3]).toBe(mockEventId);
|
|
359
|
-
expect(call[4]).toBeUndefined();
|
|
417
|
+
// When resolvedScope is null, should return base client (fallback)
|
|
418
|
+
expect(result.current).toBe(baseClient);
|
|
419
|
+
// Should not create secure client when resolvedScope is null
|
|
420
|
+
expect(mockCreateSecureClient).not.toHaveBeenCalled();
|
|
360
421
|
});
|
|
361
422
|
});
|
|
362
423
|
|
|
363
424
|
describe('Context Resolution', () => {
|
|
364
425
|
it('should use appId from resolved scope', async () => {
|
|
426
|
+
const uniqueOrgId = `org-${Date.now()}-custom-app`;
|
|
365
427
|
const customAppId = 'custom-app-123';
|
|
428
|
+
|
|
429
|
+
mockUseOrganisations.mockReturnValue({
|
|
430
|
+
selectedOrganisation: { id: uniqueOrgId },
|
|
431
|
+
organisations: [],
|
|
432
|
+
isLoading: false,
|
|
433
|
+
error: null,
|
|
434
|
+
selectOrganisation: vi.fn(),
|
|
435
|
+
refreshOrganisations: vi.fn()
|
|
436
|
+
} as any);
|
|
437
|
+
|
|
366
438
|
mockUseResolvedScope.mockReturnValue({
|
|
367
439
|
resolvedScope: {
|
|
368
|
-
organisationId:
|
|
440
|
+
organisationId: uniqueOrgId,
|
|
369
441
|
eventId: mockEventId,
|
|
370
442
|
appId: customAppId
|
|
371
443
|
},
|
|
@@ -377,14 +449,17 @@ describe('useSecureSupabase Hook', () => {
|
|
|
377
449
|
|
|
378
450
|
await waitFor(() => {
|
|
379
451
|
expect(mockCreateSecureClient).toHaveBeenCalled();
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
452
|
+
}, { timeout: 2000 });
|
|
453
|
+
|
|
454
|
+
const call = mockCreateSecureClient.mock.calls[0];
|
|
455
|
+
expect(call[2]).toBe(uniqueOrgId);
|
|
456
|
+
expect(call[3]).toBe(mockEventId);
|
|
457
|
+
expect(call[4]).toBe(customAppId);
|
|
385
458
|
});
|
|
386
459
|
|
|
387
460
|
it('should work without event context', async () => {
|
|
461
|
+
const uniqueOrgId = `org-${Date.now()}-no-event`;
|
|
462
|
+
|
|
388
463
|
mockUseEvents.mockReturnValue({
|
|
389
464
|
events: [],
|
|
390
465
|
selectedEvent: null,
|
|
@@ -396,9 +471,18 @@ describe('useSecureSupabase Hook', () => {
|
|
|
396
471
|
eventLoading: false
|
|
397
472
|
} as any);
|
|
398
473
|
|
|
474
|
+
mockUseOrganisations.mockReturnValue({
|
|
475
|
+
selectedOrganisation: { id: uniqueOrgId },
|
|
476
|
+
organisations: [],
|
|
477
|
+
isLoading: false,
|
|
478
|
+
error: null,
|
|
479
|
+
selectOrganisation: vi.fn(),
|
|
480
|
+
refreshOrganisations: vi.fn()
|
|
481
|
+
} as any);
|
|
482
|
+
|
|
399
483
|
mockUseResolvedScope.mockReturnValue({
|
|
400
484
|
resolvedScope: {
|
|
401
|
-
organisationId:
|
|
485
|
+
organisationId: uniqueOrgId,
|
|
402
486
|
eventId: undefined,
|
|
403
487
|
appId: mockAppId
|
|
404
488
|
},
|
|
@@ -410,11 +494,12 @@ describe('useSecureSupabase Hook', () => {
|
|
|
410
494
|
|
|
411
495
|
await waitFor(() => {
|
|
412
496
|
expect(mockCreateSecureClient).toHaveBeenCalled();
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
497
|
+
}, { timeout: 2000 });
|
|
498
|
+
|
|
499
|
+
const call = mockCreateSecureClient.mock.calls[0];
|
|
500
|
+
expect(call[2]).toBe(uniqueOrgId);
|
|
501
|
+
expect(call[3]).toBeUndefined();
|
|
502
|
+
expect(call[4]).toBe(mockAppId);
|
|
418
503
|
});
|
|
419
504
|
});
|
|
420
505
|
|
|
@@ -428,8 +513,15 @@ describe('useSecureSupabase Hook', () => {
|
|
|
428
513
|
selectOrganisation: vi.fn(),
|
|
429
514
|
refreshOrganisations: vi.fn()
|
|
430
515
|
} as any);
|
|
516
|
+
|
|
517
|
+
// Mock useResolvedScope to return null scope when context is unavailable
|
|
518
|
+
mockUseResolvedScope.mockReturnValue({
|
|
519
|
+
resolvedScope: null,
|
|
520
|
+
isLoading: false,
|
|
521
|
+
error: null
|
|
522
|
+
});
|
|
431
523
|
|
|
432
|
-
const customBaseClient = { from: vi.fn() } as unknown as SupabaseClient<Database>;
|
|
524
|
+
const customBaseClient = { from: vi.fn(), auth: { getUser: vi.fn(), getSession: vi.fn() } } as unknown as SupabaseClient<Database>;
|
|
433
525
|
const { result } = renderHook(() => useSecureSupabase(customBaseClient));
|
|
434
526
|
|
|
435
527
|
expect(result.current).toBe(customBaseClient);
|
package/src/rbac/hooks/index.ts
CHANGED
|
@@ -23,7 +23,8 @@ import { isPermitted, isPermittedCached } from '../api';
|
|
|
23
23
|
const mockUserId = 'user-123';
|
|
24
24
|
const mockScope = {
|
|
25
25
|
organisationId: 'org-123',
|
|
26
|
-
eventId: 'event-123'
|
|
26
|
+
eventId: 'event-123',
|
|
27
|
+
appId: 'app-123' // Required for page name resolution
|
|
27
28
|
};
|
|
28
29
|
const mockPermission = 'read:users';
|
|
29
30
|
const mockPageId = 'dashboard';
|
|
@@ -32,6 +33,13 @@ describe('useCan Hook', () => {
|
|
|
32
33
|
const mockIsPermitted = vi.mocked(isPermitted);
|
|
33
34
|
const mockIsPermittedCached = vi.mocked(isPermittedCached);
|
|
34
35
|
|
|
36
|
+
beforeEach(() => {
|
|
37
|
+
vi.clearAllMocks();
|
|
38
|
+
// Reset mocks to return resolved promises by default
|
|
39
|
+
mockIsPermitted.mockResolvedValue(true);
|
|
40
|
+
mockIsPermittedCached.mockResolvedValue(true);
|
|
41
|
+
});
|
|
42
|
+
|
|
35
43
|
describe('Permission Checking', () => {
|
|
36
44
|
it('returns true for allowed permissions', async () => {
|
|
37
45
|
mockIsPermitted.mockResolvedValue(true);
|
|
@@ -103,12 +111,16 @@ describe('useCan Hook', () => {
|
|
|
103
111
|
await waitFor(() => {
|
|
104
112
|
expect(result.current.isLoading).toBe(false);
|
|
105
113
|
expect(result.current.can).toBe(true);
|
|
106
|
-
expect(mockIsPermittedCached).toHaveBeenCalledWith(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
114
|
+
expect(mockIsPermittedCached).toHaveBeenCalledWith(
|
|
115
|
+
{
|
|
116
|
+
userId: mockUserId,
|
|
117
|
+
scope: mockScope,
|
|
118
|
+
permission: mockPermission,
|
|
119
|
+
pageId: mockPageId
|
|
120
|
+
},
|
|
121
|
+
undefined,
|
|
122
|
+
undefined
|
|
123
|
+
);
|
|
112
124
|
expect(mockIsPermitted).not.toHaveBeenCalled();
|
|
113
125
|
});
|
|
114
126
|
});
|
|
@@ -123,12 +135,16 @@ describe('useCan Hook', () => {
|
|
|
123
135
|
await waitFor(() => {
|
|
124
136
|
expect(result.current.isLoading).toBe(false);
|
|
125
137
|
expect(result.current.can).toBe(true);
|
|
126
|
-
expect(mockIsPermitted).toHaveBeenCalledWith(
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
138
|
+
expect(mockIsPermitted).toHaveBeenCalledWith(
|
|
139
|
+
{
|
|
140
|
+
userId: mockUserId,
|
|
141
|
+
scope: mockScope,
|
|
142
|
+
permission: mockPermission,
|
|
143
|
+
pageId: mockPageId
|
|
144
|
+
},
|
|
145
|
+
undefined,
|
|
146
|
+
undefined
|
|
147
|
+
);
|
|
132
148
|
expect(mockIsPermittedCached).not.toHaveBeenCalled();
|
|
133
149
|
});
|
|
134
150
|
});
|
|
@@ -158,12 +174,16 @@ describe('useCan Hook', () => {
|
|
|
158
174
|
|
|
159
175
|
await waitFor(() => {
|
|
160
176
|
expect(result.current.isLoading).toBe(false);
|
|
161
|
-
expect(mockIsPermitted).toHaveBeenCalledWith(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
177
|
+
expect(mockIsPermitted).toHaveBeenCalledWith(
|
|
178
|
+
{
|
|
179
|
+
userId: mockUserId,
|
|
180
|
+
scope: mockScope,
|
|
181
|
+
permission: mockPermission,
|
|
182
|
+
pageId: 'custom-page'
|
|
183
|
+
},
|
|
184
|
+
undefined,
|
|
185
|
+
undefined
|
|
186
|
+
);
|
|
167
187
|
});
|
|
168
188
|
});
|
|
169
189
|
|
|
@@ -176,12 +196,16 @@ describe('useCan Hook', () => {
|
|
|
176
196
|
|
|
177
197
|
await waitFor(() => {
|
|
178
198
|
expect(result.current.isLoading).toBe(false);
|
|
179
|
-
expect(mockIsPermitted).toHaveBeenCalledWith(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
199
|
+
expect(mockIsPermitted).toHaveBeenCalledWith(
|
|
200
|
+
{
|
|
201
|
+
userId: mockUserId,
|
|
202
|
+
scope: mockScope,
|
|
203
|
+
permission: mockPermission,
|
|
204
|
+
pageId: undefined
|
|
205
|
+
},
|
|
206
|
+
undefined,
|
|
207
|
+
undefined
|
|
208
|
+
);
|
|
185
209
|
});
|
|
186
210
|
});
|
|
187
211
|
});
|
|
@@ -214,12 +238,16 @@ describe('useCan Hook', () => {
|
|
|
214
238
|
|
|
215
239
|
await waitFor(() => {
|
|
216
240
|
expect(mockIsPermitted).toHaveBeenCalledTimes(2);
|
|
217
|
-
expect(mockIsPermitted).toHaveBeenLastCalledWith(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
241
|
+
expect(mockIsPermitted).toHaveBeenLastCalledWith(
|
|
242
|
+
{
|
|
243
|
+
userId: 'user-456',
|
|
244
|
+
scope: mockScope,
|
|
245
|
+
permission: mockPermission,
|
|
246
|
+
pageId: undefined
|
|
247
|
+
},
|
|
248
|
+
undefined,
|
|
249
|
+
undefined
|
|
250
|
+
);
|
|
223
251
|
});
|
|
224
252
|
});
|
|
225
253
|
|
|
@@ -251,12 +279,16 @@ describe('useCan Hook', () => {
|
|
|
251
279
|
|
|
252
280
|
await waitFor(() => {
|
|
253
281
|
expect(mockIsPermitted).toHaveBeenCalledTimes(2);
|
|
254
|
-
expect(mockIsPermitted).toHaveBeenLastCalledWith(
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
282
|
+
expect(mockIsPermitted).toHaveBeenLastCalledWith(
|
|
283
|
+
{
|
|
284
|
+
userId: mockUserId,
|
|
285
|
+
scope: newScope,
|
|
286
|
+
permission: mockPermission,
|
|
287
|
+
pageId: undefined
|
|
288
|
+
},
|
|
289
|
+
undefined,
|
|
290
|
+
undefined
|
|
291
|
+
);
|
|
260
292
|
});
|
|
261
293
|
});
|
|
262
294
|
|
|
@@ -287,12 +319,16 @@ describe('useCan Hook', () => {
|
|
|
287
319
|
|
|
288
320
|
await waitFor(() => {
|
|
289
321
|
expect(mockIsPermitted).toHaveBeenCalledTimes(2);
|
|
290
|
-
expect(mockIsPermitted).toHaveBeenLastCalledWith(
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
322
|
+
expect(mockIsPermitted).toHaveBeenLastCalledWith(
|
|
323
|
+
{
|
|
324
|
+
userId: mockUserId,
|
|
325
|
+
scope: mockScope,
|
|
326
|
+
permission: 'create:users',
|
|
327
|
+
pageId: undefined
|
|
328
|
+
},
|
|
329
|
+
undefined,
|
|
330
|
+
undefined
|
|
331
|
+
);
|
|
296
332
|
});
|
|
297
333
|
});
|
|
298
334
|
});
|
|
@@ -359,12 +395,16 @@ describe('useCan Hook', () => {
|
|
|
359
395
|
expect(result.current.error).toBeNull();
|
|
360
396
|
});
|
|
361
397
|
|
|
362
|
-
|
|
398
|
+
expect(mockIsPermitted).toHaveBeenCalledWith(
|
|
399
|
+
{
|
|
363
400
|
userId: mockUserId,
|
|
364
401
|
scope: mockScope,
|
|
365
402
|
permission: 'update:organisations',
|
|
366
403
|
pageId: undefined
|
|
367
|
-
}
|
|
404
|
+
},
|
|
405
|
+
undefined,
|
|
406
|
+
undefined
|
|
407
|
+
);
|
|
368
408
|
});
|
|
369
409
|
|
|
370
410
|
it('denies super admin permissions for regular users', async () => {
|
|
@@ -495,12 +535,16 @@ describe('useCan Hook', () => {
|
|
|
495
535
|
expect(result.current.error).toBeNull();
|
|
496
536
|
});
|
|
497
537
|
|
|
498
|
-
|
|
538
|
+
expect(mockIsPermittedCached).toHaveBeenCalledWith(
|
|
539
|
+
{
|
|
499
540
|
userId: mockUserId,
|
|
500
541
|
scope: mockScope,
|
|
501
542
|
permission: mockPermission,
|
|
502
543
|
pageId: mockPageId
|
|
503
|
-
}
|
|
544
|
+
},
|
|
545
|
+
undefined,
|
|
546
|
+
undefined
|
|
547
|
+
);
|
|
504
548
|
});
|
|
505
549
|
|
|
506
550
|
it('handles permission denied with fallback to false', async () => {
|
|
@@ -579,12 +623,16 @@ describe('useCan Hook', () => {
|
|
|
579
623
|
await waitFor(() => {
|
|
580
624
|
expect(result.current.isLoading).toBe(false);
|
|
581
625
|
expect(result.current.can).toBe(false);
|
|
582
|
-
expect(mockIsPermitted).toHaveBeenCalledWith(
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
626
|
+
expect(mockIsPermitted).toHaveBeenCalledWith(
|
|
627
|
+
{
|
|
628
|
+
userId: mockUserId,
|
|
629
|
+
scope: mockScope,
|
|
630
|
+
permission: '',
|
|
631
|
+
pageId: undefined
|
|
632
|
+
},
|
|
633
|
+
undefined,
|
|
634
|
+
undefined
|
|
635
|
+
);
|
|
588
636
|
});
|
|
589
637
|
});
|
|
590
638
|
|