@jmruthers/pace-core 0.5.76 → 0.5.78

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.
Files changed (447) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/{RBACService-C4udt_Zp.d.ts → AuthService-Df3IozMG.d.ts} +10 -118
  3. package/dist/{DataTable-ntgmhO2W.d.ts → DataTable-BE0OXZKQ.d.ts} +9 -2
  4. package/dist/{DataTable-4GAVPIEG.js → DataTable-ETGVF4Y5.js} +50 -13
  5. package/dist/{PublicLoadingSpinner-BiNER8F5.d.ts → PublicLoadingSpinner-CnUaz0vG.d.ts} +5 -2
  6. package/dist/{UnifiedAuthProvider-Bj6YCf7c.d.ts → UnifiedAuthProvider-B391Aqum.d.ts} +42 -45
  7. package/dist/{UnifiedAuthProvider-3NKDOSOK.js → UnifiedAuthProvider-P5SOJAQ6.js} +4 -5
  8. package/dist/{api-DDMUKIUD.js → api-KG4A2X7P.js} +9 -3
  9. package/dist/{audit-6TOCAMKO.js → audit-65VNHEV2.js} +2 -2
  10. package/dist/{chunk-K34IM5CT.js → chunk-2OGV6IRV.js} +196 -626
  11. package/dist/chunk-2OGV6IRV.js.map +1 -0
  12. package/dist/{chunk-NTNILOBC.js → chunk-5BO3MI5Y.js} +4 -4
  13. package/dist/{chunk-XLZ7U46Z.js → chunk-CVMVPYAL.js} +9 -60
  14. package/dist/chunk-CVMVPYAL.js.map +1 -0
  15. package/dist/{chunk-URUTVZ7N.js → chunk-FL4ZCQLD.js} +2 -2
  16. package/dist/{chunk-LW7MMEAQ.js → chunk-FT2M4R4F.js} +2 -2
  17. package/dist/{chunk-5BSLGBYI.js → chunk-JCQZ6LA7.js} +2 -8
  18. package/dist/{chunk-5BSLGBYI.js.map → chunk-JCQZ6LA7.js.map} +1 -1
  19. package/dist/{chunk-KHJS6VIA.js → chunk-LRQ6RBJC.js} +157 -112
  20. package/dist/chunk-LRQ6RBJC.js.map +1 -0
  21. package/dist/{chunk-WN6XJWOS.js → chunk-MNJXXD6C.js} +274 -743
  22. package/dist/chunk-MNJXXD6C.js.map +1 -0
  23. package/dist/{chunk-KK73ZB4E.js → chunk-PTR5PMPE.js} +153 -132
  24. package/dist/chunk-PTR5PMPE.js.map +1 -0
  25. package/dist/{chunk-B2WTCLCV.js → chunk-Q7APDV6H.js} +18 -8
  26. package/dist/chunk-Q7APDV6H.js.map +1 -0
  27. package/dist/{chunk-A4FUBC7B.js → chunk-QGVSOUJ2.js} +2 -4
  28. package/dist/{chunk-A4FUBC7B.js.map → chunk-QGVSOUJ2.js.map} +1 -1
  29. package/dist/{chunk-FGMFQSHX.js → chunk-S63MFSY6.js} +500 -551
  30. package/dist/chunk-S63MFSY6.js.map +1 -0
  31. package/dist/{chunk-AFGTSUAD.js → chunk-VSOKOFRF.js} +4 -4
  32. package/dist/chunk-WUXCWRL6.js +20 -0
  33. package/dist/chunk-WUXCWRL6.js.map +1 -0
  34. package/dist/{chunk-Y6TXWPJO.js → chunk-YVVGHRGI.js} +105 -31
  35. package/dist/chunk-YVVGHRGI.js.map +1 -0
  36. package/dist/{chunk-M5IWZRBT.js → chunk-ZMNXIJP4.js} +2187 -981
  37. package/dist/chunk-ZMNXIJP4.js.map +1 -0
  38. package/dist/components.d.ts +6 -6
  39. package/dist/components.js +14 -18
  40. package/dist/components.js.map +1 -1
  41. package/dist/{database-C3Szpi5J.d.ts → database-BXAfr2Y_.d.ts} +18 -0
  42. package/dist/hooks.d.ts +5 -5
  43. package/dist/hooks.js +8 -9
  44. package/dist/hooks.js.map +1 -1
  45. package/dist/index.d.ts +19 -27
  46. package/dist/index.js +21 -29
  47. package/dist/index.js.map +1 -1
  48. package/dist/{organisation-BtshODVF.d.ts → organisation-D6qRDtbF.d.ts} +1 -1
  49. package/dist/providers.d.ts +7 -21
  50. package/dist/providers.js +3 -10
  51. package/dist/rbac/index.d.ts +71 -221
  52. package/dist/rbac/index.js +15 -16
  53. package/dist/{types-CGX9Vyf5.d.ts → types-BDg1mAGG.d.ts} +36 -6
  54. package/dist/types.d.ts +3 -3
  55. package/dist/types.js +61 -18
  56. package/dist/types.js.map +1 -1
  57. package/dist/{unified-CM7T0aTK.d.ts → unified-DQ4VcT7H.d.ts} +1 -1
  58. package/dist/{usePublicRouteParams-B-CumWRc.d.ts → usePublicRouteParams-BlgwXweB.d.ts} +3 -3
  59. package/dist/utils.d.ts +2 -2
  60. package/dist/utils.js +52 -9
  61. package/dist/utils.js.map +1 -1
  62. package/docs/CONTENT_AUDIT_REPORT.md +253 -0
  63. package/docs/DOCUMENTATION_AUDIT.md +172 -0
  64. package/docs/README.md +142 -147
  65. package/docs/STYLE_GUIDE.md +37 -0
  66. package/docs/api/classes/ColumnFactory.md +17 -17
  67. package/docs/api/classes/ErrorBoundary.md +1 -1
  68. package/docs/api/classes/InvalidScopeError.md +4 -4
  69. package/docs/api/classes/MissingUserContextError.md +4 -4
  70. package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
  71. package/docs/api/classes/PermissionDeniedError.md +5 -5
  72. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  73. package/docs/api/classes/RBACAuditManager.md +8 -8
  74. package/docs/api/classes/RBACCache.md +35 -5
  75. package/docs/api/classes/RBACEngine.md +49 -20
  76. package/docs/api/classes/RBACError.md +4 -4
  77. package/docs/api/classes/RBACNotInitializedError.md +4 -4
  78. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  79. package/docs/api/classes/StorageUtils.md +1 -1
  80. package/docs/api/enums/FileCategory.md +1 -1
  81. package/docs/api/interfaces/AggregateConfig.md +4 -4
  82. package/docs/api/interfaces/ButtonProps.md +1 -1
  83. package/docs/api/interfaces/CardProps.md +1 -1
  84. package/docs/api/interfaces/ColorPalette.md +1 -1
  85. package/docs/api/interfaces/ColorShade.md +1 -1
  86. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  87. package/docs/api/interfaces/DataRecord.md +11 -0
  88. package/docs/api/interfaces/DataTableAction.md +65 -29
  89. package/docs/api/interfaces/DataTableColumn.md +36 -23
  90. package/docs/api/interfaces/DataTableProps.md +80 -38
  91. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  92. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  93. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  94. package/docs/api/interfaces/EventLogoProps.md +1 -1
  95. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  96. package/docs/api/interfaces/FileMetadata.md +1 -1
  97. package/docs/api/interfaces/FileReference.md +1 -1
  98. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  99. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  100. package/docs/api/interfaces/FileUploadProps.md +1 -1
  101. package/docs/api/interfaces/FooterProps.md +1 -1
  102. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  103. package/docs/api/interfaces/InputProps.md +1 -1
  104. package/docs/api/interfaces/LabelProps.md +1 -1
  105. package/docs/api/interfaces/LoginFormProps.md +1 -1
  106. package/docs/api/interfaces/NavigationAccessRecord.md +11 -11
  107. package/docs/api/interfaces/NavigationContextType.md +9 -9
  108. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  109. package/docs/api/interfaces/NavigationItem.md +1 -1
  110. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  111. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  112. package/docs/api/interfaces/Organisation.md +1 -1
  113. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  114. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  115. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  116. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  117. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  118. package/docs/api/interfaces/PaceLoginPageProps.md +16 -3
  119. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  120. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  121. package/docs/api/interfaces/PagePermissionGuardProps.md +2 -2
  122. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  123. package/docs/api/interfaces/PaletteData.md +1 -1
  124. package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
  125. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  126. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  127. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  128. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  129. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  130. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  131. package/docs/api/interfaces/RBACConfig.md +1 -1
  132. package/docs/api/interfaces/RBACLogger.md +1 -1
  133. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  134. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  135. package/docs/api/interfaces/RouteAccessRecord.md +2 -2
  136. package/docs/api/interfaces/RouteConfig.md +2 -2
  137. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  138. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  139. package/docs/api/interfaces/StorageConfig.md +1 -1
  140. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  141. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  142. package/docs/api/interfaces/StorageListOptions.md +1 -1
  143. package/docs/api/interfaces/StorageListResult.md +1 -1
  144. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  145. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  146. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  147. package/docs/api/interfaces/StyleImport.md +1 -1
  148. package/docs/api/interfaces/SwitchProps.md +1 -1
  149. package/docs/api/interfaces/ToastActionElement.md +1 -1
  150. package/docs/api/interfaces/ToastProps.md +1 -1
  151. package/docs/api/interfaces/UnifiedAuthContextType.md +94 -521
  152. package/docs/api/interfaces/UnifiedAuthProviderProps.md +16 -16
  153. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  154. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  155. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  156. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  157. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  158. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  159. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  160. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  161. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  162. package/docs/api/interfaces/UserEventAccess.md +11 -11
  163. package/docs/api/interfaces/UserMenuProps.md +1 -1
  164. package/docs/api/interfaces/UserProfile.md +1 -1
  165. package/docs/api/modules.md +251 -269
  166. package/docs/api-reference/components.md +193 -0
  167. package/docs/api-reference/hooks.md +265 -0
  168. package/docs/api-reference/providers.md +6 -0
  169. package/docs/api-reference/types.md +6 -0
  170. package/docs/api-reference/utilities.md +207 -0
  171. package/docs/architecture/README.md +6 -0
  172. package/docs/{database-schema-requirements.md → architecture/database-schema-requirements.md} +6 -0
  173. package/docs/architecture/rbac-security-architecture.md +258 -0
  174. package/docs/architecture/services.md +9 -1
  175. package/docs/best-practices/README.md +6 -0
  176. package/docs/best-practices/accessibility.md +6 -0
  177. package/docs/{common-patterns.md → best-practices/common-patterns.md} +6 -0
  178. package/docs/best-practices/deployment.md +6 -0
  179. package/docs/best-practices/performance.md +475 -2
  180. package/docs/best-practices/security.md +6 -0
  181. package/docs/best-practices/testing.md +6 -0
  182. package/docs/core-concepts/authentication.md +6 -0
  183. package/docs/core-concepts/events.md +6 -0
  184. package/docs/core-concepts/organisations.md +6 -0
  185. package/docs/core-concepts/permissions.md +6 -0
  186. package/docs/core-concepts/rbac-system.md +8 -0
  187. package/docs/documentation-index.md +121 -182
  188. package/docs/{consuming-app-vite-config.md → getting-started/consuming-app-vite-config.md} +6 -0
  189. package/docs/getting-started/documentation-index.md +40 -0
  190. package/docs/getting-started/examples/README.md +878 -35
  191. package/docs/{faq.md → getting-started/faq.md} +7 -1
  192. package/docs/getting-started/installation-guide.md +6 -0
  193. package/docs/{quick-reference.md → getting-started/quick-reference.md} +6 -0
  194. package/docs/implementation-guides/app-layout.md +6 -0
  195. package/docs/implementation-guides/authentication.md +1021 -0
  196. package/docs/implementation-guides/component-styling.md +6 -0
  197. package/docs/implementation-guides/data-tables.md +1264 -2076
  198. package/docs/implementation-guides/dynamic-colors.md +6 -0
  199. package/docs/implementation-guides/event-theming-summary.md +6 -0
  200. package/docs/{file-reference-system.md → implementation-guides/file-reference-system.md} +6 -0
  201. package/docs/implementation-guides/file-upload-storage.md +6 -0
  202. package/docs/implementation-guides/forms.md +6 -0
  203. package/docs/implementation-guides/inactivity-tracking.md +6 -0
  204. package/docs/implementation-guides/navigation.md +6 -0
  205. package/docs/implementation-guides/organisation-security.md +6 -0
  206. package/docs/implementation-guides/permission-enforcement.md +6 -0
  207. package/docs/implementation-guides/public-pages-advanced.md +6 -0
  208. package/docs/implementation-guides/public-pages.md +6 -0
  209. package/docs/migration/MIGRATION_GUIDE.md +827 -351
  210. package/docs/migration/README.md +7 -1
  211. package/docs/migration/organisation-context-timing-fix.md +6 -0
  212. package/docs/migration/rbac-migration.md +44 -1
  213. package/docs/migration/service-architecture.md +6 -0
  214. package/docs/migration/v0.4.15-tailwind-scanning.md +6 -0
  215. package/docs/migration/v0.4.16-css-first-approach.md +6 -0
  216. package/docs/migration/v0.4.17-source-path-fix.md +6 -0
  217. package/docs/rbac/README-rbac-rls-integration.md +6 -0
  218. package/docs/rbac/README.md +6 -0
  219. package/docs/rbac/advanced-patterns.md +6 -0
  220. package/docs/rbac/api-reference.md +7 -1
  221. package/docs/rbac/breaking-changes-v3.md +222 -0
  222. package/docs/rbac/examples/rbac-rls-integration-example.md +6 -0
  223. package/docs/rbac/examples.md +6 -0
  224. package/docs/rbac/getting-started.md +6 -0
  225. package/docs/rbac/migration-guide.md +260 -0
  226. package/docs/rbac/quick-start.md +70 -13
  227. package/docs/rbac/rbac-rls-integration.md +6 -0
  228. package/docs/rbac/super-admin-guide.md +6 -0
  229. package/docs/rbac/troubleshooting.md +6 -0
  230. package/docs/security/README.md +6 -0
  231. package/docs/security/checklist.md +6 -0
  232. package/docs/styles/README.md +7 -1
  233. package/docs/{usage.md → styles/usage.md} +6 -0
  234. package/docs/testing/README.md +6 -0
  235. package/docs/{visual-testing.md → testing/visual-testing.md} +6 -0
  236. package/docs/troubleshooting/README.md +387 -5
  237. package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +6 -0
  238. package/docs/troubleshooting/common-issues.md +6 -0
  239. package/docs/troubleshooting/database-view-compatibility.md +6 -0
  240. package/docs/troubleshooting/organisation-context-setup.md +6 -0
  241. package/docs/troubleshooting/react-hooks-issue-analysis.md +6 -0
  242. package/docs/troubleshooting/styling-issues.md +6 -0
  243. package/docs/troubleshooting/tailwind-content-scanning.md +6 -0
  244. package/package.json +1 -1
  245. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -1
  246. package/src/__tests__/helpers/test-providers.tsx +3 -53
  247. package/src/components/DataTable/DataTable.test.tsx +319 -0
  248. package/src/components/DataTable/DataTable.tsx +32 -11
  249. package/src/components/DataTable/__tests__/{DataTable.comprehensive.test.tsx → DataTable.comprehensive.test.tsx.skip} +6 -4
  250. package/src/components/DataTable/__tests__/{DataTable.test.tsx → DataTable.test.tsx.skip} +6 -4
  251. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +31 -9
  252. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +601 -0
  253. package/src/components/DataTable/__tests__/keyboard.test.tsx +615 -0
  254. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +639 -0
  255. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx.skip +330 -0
  256. package/src/components/DataTable/components/AccessDeniedPage.tsx +2 -2
  257. package/src/components/DataTable/components/ActionButtons.tsx +88 -104
  258. package/src/components/DataTable/components/DataTableCore.tsx +309 -337
  259. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +4 -2
  260. package/src/components/DataTable/components/DataTableModals.tsx +22 -1
  261. package/src/components/DataTable/components/EditableRow.tsx +69 -84
  262. package/src/components/DataTable/components/EmptyState.tsx +5 -1
  263. package/src/components/DataTable/components/ImportModal.tsx +65 -36
  264. package/src/components/DataTable/components/PaginationControls.tsx +40 -100
  265. package/src/components/DataTable/components/UnifiedTableBody.tsx +125 -148
  266. package/src/components/DataTable/context/DataTableContext.tsx +1 -1
  267. package/src/components/DataTable/core/ColumnFactory.ts +5 -0
  268. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +12 -10
  269. package/src/components/DataTable/examples/HierarchicalExample.tsx +1 -1
  270. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +1 -0
  271. package/src/components/DataTable/examples/PerformanceExample.tsx +1 -0
  272. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +1 -5
  273. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +167 -0
  274. package/src/components/DataTable/hooks/index.ts +7 -0
  275. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +32 -15
  276. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +102 -0
  277. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +89 -0
  278. package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +117 -0
  279. package/src/components/DataTable/hooks/useDataTablePermissions.ts +71 -27
  280. package/src/components/DataTable/hooks/useDataTableState.ts +39 -11
  281. package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +33 -0
  282. package/src/components/DataTable/hooks/useHierarchicalState.ts +15 -1
  283. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +447 -0
  284. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +94 -0
  285. package/src/components/DataTable/hooks/useTableColumns.ts +10 -7
  286. package/src/components/DataTable/hooks/useTableHandlers.ts +174 -0
  287. package/src/components/DataTable/index.ts +12 -3
  288. package/src/components/DataTable/types.ts +129 -9
  289. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +159 -22
  290. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +111 -0
  291. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +15 -29
  292. package/src/components/DataTable/utils/a11yUtils.ts +244 -0
  293. package/src/components/DataTable/utils/debugTools.ts +609 -0
  294. package/src/components/DataTable/utils/exportUtils.ts +114 -16
  295. package/src/components/DataTable/utils/flexibleImport.ts +202 -32
  296. package/src/components/DataTable/utils/hierarchicalUtils.ts +1 -1
  297. package/src/components/DataTable/utils/index.ts +2 -0
  298. package/src/components/DataTable/utils/paginationUtils.ts +350 -0
  299. package/src/components/DataTable/utils/rowUtils.ts +6 -5
  300. package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -24
  301. package/src/components/NavigationMenu/NavigationMenu.tsx +19 -8
  302. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +1 -23
  303. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +56 -6
  304. package/src/components/PaceLoginPage/PaceLoginPage.tsx +137 -13
  305. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +1 -1
  306. package/src/components/Select/Select.tsx +1 -0
  307. package/src/components/examples/PermissionExample.tsx +173 -0
  308. package/src/examples/CorrectPublicPageImplementation.tsx +301 -0
  309. package/src/examples/PublicEventPage.tsx +274 -0
  310. package/src/examples/PublicPageApp.tsx +308 -0
  311. package/src/examples/PublicPageUsageExample.tsx +216 -0
  312. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +12 -1
  313. package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +129 -17
  314. package/src/hooks/__tests__/useRBAC.unit.test.ts +151 -846
  315. package/src/hooks/useOrganisationPermissions.test.ts +42 -18
  316. package/src/hooks/useOrganisationPermissions.ts +12 -6
  317. package/src/hooks/useOrganisationSecurity.test.ts +138 -85
  318. package/src/hooks/useOrganisationSecurity.ts +41 -10
  319. package/src/index.ts +0 -1
  320. package/src/providers/AuthProvider.simplified.tsx +880 -0
  321. package/src/providers/UnifiedAuthProvider.test.simple.tsx +8 -8
  322. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +29 -19
  323. package/src/providers/index.ts +0 -1
  324. package/src/providers/services/EventServiceProvider.tsx +19 -15
  325. package/src/providers/services/InactivityServiceProvider.tsx +19 -15
  326. package/src/providers/services/OrganisationServiceProvider.tsx +19 -15
  327. package/src/providers/services/UnifiedAuthProvider.tsx +156 -127
  328. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +1 -1
  329. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -3
  330. package/src/rbac/README.md +1 -1
  331. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +25 -27
  332. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +313 -0
  333. package/src/rbac/__tests__/engine.comprehensive.test.ts +114 -348
  334. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +28 -110
  335. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +33 -85
  336. package/src/rbac/__tests__/scenarios.user-role.test.tsx +2 -2
  337. package/src/rbac/adapters.tsx +26 -69
  338. package/src/rbac/api.test.ts +90 -27
  339. package/src/rbac/api.ts +61 -10
  340. package/src/rbac/audit.test.ts +33 -38
  341. package/src/rbac/audit.ts +21 -6
  342. package/src/rbac/cache.ts +33 -1
  343. package/src/rbac/components/NavigationGuard.tsx +11 -11
  344. package/src/rbac/components/NavigationProvider.test.tsx +11 -5
  345. package/src/rbac/components/NavigationProvider.tsx +37 -13
  346. package/src/rbac/components/PagePermissionGuard.tsx +111 -50
  347. package/src/rbac/components/PagePermissionProvider.tsx +5 -5
  348. package/src/rbac/components/PermissionEnforcer.tsx +11 -11
  349. package/src/rbac/components/RoleBasedRouter.tsx +5 -5
  350. package/src/rbac/components/SecureDataProvider.tsx +5 -5
  351. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +8 -8
  352. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +14 -14
  353. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +12 -12
  354. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +6 -6
  355. package/src/rbac/engine.test.simple.ts +19 -13
  356. package/src/rbac/engine.test.ts +1 -0
  357. package/src/rbac/engine.ts +330 -766
  358. package/src/rbac/errors.ts +156 -0
  359. package/src/rbac/hooks/usePermissions.ts +32 -10
  360. package/src/rbac/hooks/useRBAC.test.ts +126 -512
  361. package/src/rbac/hooks/useRBAC.ts +147 -193
  362. package/src/rbac/hooks/useResolvedScope.ts +12 -0
  363. package/src/rbac/index.ts +7 -4
  364. package/src/rbac/security.ts +109 -18
  365. package/src/rbac/types.ts +12 -1
  366. package/src/services/AuthService.ts +2 -15
  367. package/src/services/EventService.ts +43 -46
  368. package/src/services/OrganisationService.ts +51 -31
  369. package/src/services/__tests__/AuthService.test.ts +1 -1
  370. package/src/services/__tests__/EventService.test.ts +1 -1
  371. package/src/services/__tests__/OrganisationService.test.ts +1 -1
  372. package/src/services/base/BaseService.ts +8 -0
  373. package/src/styles/base.css +208 -0
  374. package/src/styles/semantic.css +24 -0
  375. package/src/types/database.generated.ts +7347 -0
  376. package/src/types/database.ts +20 -0
  377. package/src/utils/logger.ts +179 -0
  378. package/src/utils/organisationContext.ts +11 -4
  379. package/src/utils/storage/__tests__/helpers.unit.test.ts +6 -2
  380. package/dist/appNameResolver-UURKN7NF.js +0 -22
  381. package/dist/audit-6TOCAMKO.js.map +0 -1
  382. package/dist/chunk-B2WTCLCV.js.map +0 -1
  383. package/dist/chunk-FGMFQSHX.js.map +0 -1
  384. package/dist/chunk-K34IM5CT.js.map +0 -1
  385. package/dist/chunk-KHJS6VIA.js.map +0 -1
  386. package/dist/chunk-KK73ZB4E.js.map +0 -1
  387. package/dist/chunk-M5IWZRBT.js.map +0 -1
  388. package/dist/chunk-ULBI5JGB.js +0 -109
  389. package/dist/chunk-ULBI5JGB.js.map +0 -1
  390. package/dist/chunk-WN6XJWOS.js.map +0 -1
  391. package/dist/chunk-XLZ7U46Z.js.map +0 -1
  392. package/dist/chunk-Y6TXWPJO.js.map +0 -1
  393. package/docs/DOCUMENTATION_CHECKLIST.md +0 -281
  394. package/docs/TERMINOLOGY.md +0 -231
  395. package/docs/api/interfaces/RBACContextType.md +0 -468
  396. package/docs/api/interfaces/RBACProviderProps.md +0 -107
  397. package/docs/best-practices/performance-expansion.md +0 -473
  398. package/docs/breaking-changes.md +0 -179
  399. package/docs/consuming-app-example.md +0 -290
  400. package/docs/documentation-templates.md +0 -539
  401. package/docs/examples/navigation-menu-auth-fix.md +0 -344
  402. package/docs/getting-started/examples/basic-auth-app.md +0 -520
  403. package/docs/getting-started/examples/full-featured-app.md +0 -616
  404. package/docs/getting-started/quick-start.md +0 -376
  405. package/docs/implementation-guides/datatable-filtering.md +0 -313
  406. package/docs/implementation-guides/datatable-rbac-usage.md +0 -317
  407. package/docs/implementation-guides/hierarchical-datatable.md +0 -850
  408. package/docs/implementation-guides/large-datasets.md +0 -281
  409. package/docs/implementation-guides/performance.md +0 -403
  410. package/docs/migration/quick-migration-guide.md +0 -320
  411. package/docs/migration-guide.md +0 -193
  412. package/docs/migration-guides/unified-auth-provider-mandatory-timeouts.md +0 -226
  413. package/docs/performance/README.md +0 -551
  414. package/docs/style-guide.md +0 -964
  415. package/docs/troubleshooting/authentication-issues.md +0 -334
  416. package/docs/troubleshooting/debugging.md +0 -1117
  417. package/docs/troubleshooting/migration.md +0 -918
  418. package/src/__tests__/hooks/usePermissions.test.ts +0 -261
  419. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +0 -574
  420. package/src/hooks/__tests__/ServiceHooks.test.tsx +0 -613
  421. package/src/hooks/services/__tests__/useServiceHooks.test.tsx +0 -137
  422. package/src/hooks/services/usePermissions.ts +0 -70
  423. package/src/hooks/services/useRBACService.ts +0 -30
  424. package/src/hooks/usePermissionCheck.ts +0 -150
  425. package/src/providers/__tests__/ServiceProviders.test.tsx +0 -477
  426. package/src/providers/services/RBACServiceProvider.tsx +0 -79
  427. package/src/rbac/__tests__/integration.authflow.test.tsx +0 -119
  428. package/src/rbac/__tests__/integration.navigation.test.tsx +0 -69
  429. package/src/rbac/__tests__/integration.securedata.test.tsx +0 -92
  430. package/src/rbac/__tests__/integration.smoke.test.tsx +0 -73
  431. package/src/rbac/providers/RBACProvider.tsx +0 -645
  432. package/src/rbac/providers/__tests__/RBACProvider.integration.test.tsx +0 -688
  433. package/src/rbac/providers/__tests__/RBACProvider.test.tsx +0 -1186
  434. package/src/rbac/providers/index.ts +0 -11
  435. package/src/services/RBACService.ts +0 -522
  436. package/src/services/__tests__/RBACService.test.ts +0 -492
  437. package/src/services/interfaces/IRBACService.ts +0 -62
  438. package/src/utils/appNameResolver.test 2.ts +0 -494
  439. /package/dist/{DataTable-4GAVPIEG.js.map → DataTable-ETGVF4Y5.js.map} +0 -0
  440. /package/dist/{UnifiedAuthProvider-3NKDOSOK.js.map → UnifiedAuthProvider-P5SOJAQ6.js.map} +0 -0
  441. /package/dist/{api-DDMUKIUD.js.map → api-KG4A2X7P.js.map} +0 -0
  442. /package/dist/{appNameResolver-UURKN7NF.js.map → audit-65VNHEV2.js.map} +0 -0
  443. /package/dist/{chunk-NTNILOBC.js.map → chunk-5BO3MI5Y.js.map} +0 -0
  444. /package/dist/{chunk-URUTVZ7N.js.map → chunk-FL4ZCQLD.js.map} +0 -0
  445. /package/dist/{chunk-LW7MMEAQ.js.map → chunk-FT2M4R4F.js.map} +0 -0
  446. /package/dist/{chunk-AFGTSUAD.js.map → chunk-VSOKOFRF.js.map} +0 -0
  447. /package/docs/{app.css.example → styles/app.css.example} +0 -0
@@ -1,1186 +0,0 @@
1
- /**
2
- * @file RBACProvider Tests
3
- * @package @jmruthers/pace-core
4
- * @module Providers/RBACProvider
5
- * @since 1.0.0
6
- *
7
- * Comprehensive tests for the RBACProvider component covering all critical functionality.
8
- */
9
-
10
- import { render, screen, waitFor } from '@testing-library/react';
11
- import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
12
- import { ReactNode } from 'react';
13
- import { RBACProvider } from '../RBACProvider';
14
- import { useRBAC } from '../../hooks/useRBAC';
15
-
16
- // Mock the RBAC hooks
17
- vi.mock('../../hooks/useRBAC', () => ({
18
- useRBAC: vi.fn(),
19
- }));
20
-
21
- // Mock the auth provider
22
- vi.mock('../../../providers/UnifiedAuthProvider', () => ({
23
- useUnifiedAuth: vi.fn(),
24
- }));
25
-
26
- // Mock the organisation provider
27
- vi.mock('../../../providers/OrganisationProvider', () => ({
28
- useOrganisations: vi.fn(),
29
- }));
30
-
31
- // Mock the event provider
32
- vi.mock('../../../providers/EventProvider', () => ({
33
- useEvents: vi.fn(),
34
- }));
35
-
36
- // Mock the RBAC API
37
- vi.mock('../../api', () => ({
38
- setupRBAC: vi.fn(),
39
- check_page_permission: vi.fn(),
40
- getPermissionMap: vi.fn(),
41
- isPermitted: vi.fn(),
42
- }));
43
-
44
- // Test component that uses RBAC context
45
- const TestComponent = () => {
46
- const rbac = useRBAC();
47
-
48
- return (
49
- <div data-testid="test-component">
50
- <div data-testid="permissions">
51
- {rbac.permissions.permissions?.join(', ') || 'No permissions'}
52
- </div>
53
- <div data-testid="can-read-users">
54
- {rbac.can.can('read:users') ? 'Can read users' : 'Cannot read users'}
55
- </div>
56
- <div data-testid="organisation-permissions">
57
- {rbac.organisationPermissions.permissions?.join(', ') || 'No org permissions'}
58
- </div>
59
- <div data-testid="can-access-org">
60
- {rbac.organisationSecurity.canAccessOrganisation() ? 'Can access org' : 'Cannot access org'}
61
- </div>
62
- </div>
63
- );
64
- };
65
-
66
- describe('RBACProvider', () => {
67
- const mockUseRBAC = vi.mocked(useRBAC);
68
-
69
- describe('Basic functionality', () => {
70
- it('should provide RBAC context to children', () => {
71
- mockUseRBAC.mockReturnValue({
72
- permissions: {
73
- permissions: ['read:users', 'write:events'],
74
- isLoading: false,
75
- error: null,
76
- refetch: vi.fn(),
77
- },
78
- can: {
79
- can: vi.fn().mockReturnValue(true),
80
- canAny: vi.fn().mockReturnValue(true),
81
- canAll: vi.fn().mockReturnValue(true),
82
- isLoading: false,
83
- error: null,
84
- },
85
- organisationPermissions: {
86
- permissions: ['read:organisation', 'write:organisation'],
87
- isLoading: false,
88
- error: null,
89
- refetch: vi.fn(),
90
- },
91
- permissionCache: {
92
- getCachedPermission: vi.fn(),
93
- setCachedPermission: vi.fn(),
94
- clearCache: vi.fn(),
95
- isCacheValid: vi.fn().mockReturnValue(true),
96
- },
97
- organisationSecurity: {
98
- canAccessOrganisation: vi.fn().mockReturnValue(true),
99
- canAccessEvent: vi.fn().mockReturnValue(true),
100
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
101
- isEventAdmin: vi.fn().mockReturnValue(false),
102
- isLoading: false,
103
- error: null,
104
- },
105
- });
106
-
107
- render(
108
- <RBACProvider>
109
- <TestComponent />
110
- </RBACProvider>
111
- );
112
-
113
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
114
- expect(screen.getByTestId('permissions')).toHaveTextContent('read:users, write:events');
115
- expect(screen.getByTestId('can-read-users')).toHaveTextContent('Can read users');
116
- expect(screen.getByTestId('organisation-permissions')).toHaveTextContent('read:organisation, write:organisation');
117
- expect(screen.getByTestId('can-access-org')).toHaveTextContent('Can access org');
118
- });
119
-
120
- it('should handle loading states', () => {
121
- mockUseRBAC.mockReturnValue({
122
- permissions: {
123
- permissions: [],
124
- isLoading: true,
125
- error: null,
126
- refetch: vi.fn(),
127
- },
128
- can: {
129
- can: vi.fn(),
130
- canAny: vi.fn(),
131
- canAll: vi.fn(),
132
- isLoading: true,
133
- error: null,
134
- },
135
- organisationPermissions: {
136
- permissions: [],
137
- isLoading: true,
138
- error: null,
139
- refetch: vi.fn(),
140
- },
141
- permissionCache: {
142
- getCachedPermission: vi.fn(),
143
- setCachedPermission: vi.fn(),
144
- clearCache: vi.fn(),
145
- isCacheValid: vi.fn().mockReturnValue(false),
146
- },
147
- organisationSecurity: {
148
- canAccessOrganisation: vi.fn(),
149
- canAccessEvent: vi.fn(),
150
- isOrganisationAdmin: vi.fn(),
151
- isEventAdmin: vi.fn(),
152
- isLoading: true,
153
- error: null,
154
- },
155
- });
156
-
157
- render(
158
- <RBACProvider>
159
- <TestComponent />
160
- </RBACProvider>
161
- );
162
-
163
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
164
- expect(screen.getByTestId('permissions')).toHaveTextContent('No permissions');
165
- });
166
-
167
- it('should handle error states', () => {
168
- const error = new Error('RBAC error');
169
- mockUseRBAC.mockReturnValue({
170
- permissions: {
171
- permissions: [],
172
- isLoading: false,
173
- error,
174
- refetch: vi.fn(),
175
- },
176
- can: {
177
- can: vi.fn(),
178
- canAny: vi.fn(),
179
- canAll: vi.fn(),
180
- isLoading: false,
181
- error,
182
- },
183
- organisationPermissions: {
184
- permissions: [],
185
- isLoading: false,
186
- error,
187
- refetch: vi.fn(),
188
- },
189
- permissionCache: {
190
- getCachedPermission: vi.fn(),
191
- setCachedPermission: vi.fn(),
192
- clearCache: vi.fn(),
193
- isCacheValid: vi.fn().mockReturnValue(false),
194
- },
195
- organisationSecurity: {
196
- canAccessOrganisation: vi.fn(),
197
- canAccessEvent: vi.fn(),
198
- isOrganisationAdmin: vi.fn(),
199
- isEventAdmin: vi.fn(),
200
- isLoading: false,
201
- error,
202
- },
203
- });
204
-
205
- render(
206
- <RBACProvider>
207
- <TestComponent />
208
- </RBACProvider>
209
- );
210
-
211
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
212
- expect(screen.getByTestId('permissions')).toHaveTextContent('No permissions');
213
- });
214
- });
215
-
216
- describe('Context updates', () => {
217
- it('should update context when permissions change', async () => {
218
- // Initial state
219
- mockUseRBAC.mockReturnValue({
220
- permissions: {
221
- permissions: ['read:users'],
222
- isLoading: false,
223
- error: null,
224
- refetch: vi.fn(),
225
- },
226
- can: {
227
- can: vi.fn().mockReturnValue(true),
228
- canAny: vi.fn().mockReturnValue(true),
229
- canAll: vi.fn().mockReturnValue(true),
230
- isLoading: false,
231
- error: null,
232
- },
233
- organisationPermissions: {
234
- permissions: ['read:organisation'],
235
- isLoading: false,
236
- error: null,
237
- refetch: vi.fn(),
238
- },
239
- permissionCache: {
240
- getCachedPermission: vi.fn(),
241
- setCachedPermission: vi.fn(),
242
- clearCache: vi.fn(),
243
- isCacheValid: vi.fn().mockReturnValue(true),
244
- },
245
- organisationSecurity: {
246
- canAccessOrganisation: vi.fn().mockReturnValue(true),
247
- canAccessEvent: vi.fn().mockReturnValue(true),
248
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
249
- isEventAdmin: vi.fn().mockReturnValue(false),
250
- isLoading: false,
251
- error: null,
252
- },
253
- });
254
-
255
- const { rerender } = render(
256
- <RBACProvider>
257
- <TestComponent />
258
- </RBACProvider>
259
- );
260
-
261
- expect(screen.getByTestId('permissions')).toHaveTextContent('read:users');
262
-
263
- // Updated state
264
- mockUseRBAC.mockReturnValue({
265
- permissions: {
266
- permissions: ['read:users', 'write:events'],
267
- isLoading: false,
268
- error: null,
269
- refetch: vi.fn(),
270
- },
271
- can: {
272
- can: vi.fn().mockReturnValue(true),
273
- canAny: vi.fn().mockReturnValue(true),
274
- canAll: vi.fn().mockReturnValue(true),
275
- isLoading: false,
276
- error: null,
277
- },
278
- organisationPermissions: {
279
- permissions: ['read:organisation', 'write:organisation'],
280
- isLoading: false,
281
- error: null,
282
- refetch: vi.fn(),
283
- },
284
- permissionCache: {
285
- getCachedPermission: vi.fn(),
286
- setCachedPermission: vi.fn(),
287
- clearCache: vi.fn(),
288
- isCacheValid: vi.fn().mockReturnValue(true),
289
- },
290
- organisationSecurity: {
291
- canAccessOrganisation: vi.fn().mockReturnValue(true),
292
- canAccessEvent: vi.fn().mockReturnValue(true),
293
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
294
- isEventAdmin: vi.fn().mockReturnValue(false),
295
- isLoading: false,
296
- error: null,
297
- },
298
- });
299
-
300
- rerender(
301
- <RBACProvider>
302
- <TestComponent />
303
- </RBACProvider>
304
- );
305
-
306
- await waitFor(() => {
307
- expect(screen.getByTestId('permissions')).toHaveTextContent('read:users, write:events');
308
- });
309
- });
310
-
311
- it('should handle permission refetch', async () => {
312
- const mockRefetch = vi.fn();
313
- mockUseRBAC.mockReturnValue({
314
- permissions: {
315
- permissions: ['read:users'],
316
- isLoading: false,
317
- error: null,
318
- refetch: mockRefetch,
319
- },
320
- can: {
321
- can: vi.fn().mockReturnValue(true),
322
- canAny: vi.fn().mockReturnValue(true),
323
- canAll: vi.fn().mockReturnValue(true),
324
- isLoading: false,
325
- error: null,
326
- },
327
- organisationPermissions: {
328
- permissions: ['read:organisation'],
329
- isLoading: false,
330
- error: null,
331
- refetch: vi.fn(),
332
- },
333
- permissionCache: {
334
- getCachedPermission: vi.fn(),
335
- setCachedPermission: vi.fn(),
336
- clearCache: vi.fn(),
337
- isCacheValid: vi.fn().mockReturnValue(true),
338
- },
339
- organisationSecurity: {
340
- canAccessOrganisation: vi.fn().mockReturnValue(true),
341
- canAccessEvent: vi.fn().mockReturnValue(true),
342
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
343
- isEventAdmin: vi.fn().mockReturnValue(false),
344
- isLoading: false,
345
- error: null,
346
- },
347
- });
348
-
349
- render(
350
- <RBACProvider>
351
- <TestComponent />
352
- </RBACProvider>
353
- );
354
-
355
- // Trigger refetch
356
- mockRefetch();
357
-
358
- expect(mockRefetch).toHaveBeenCalled();
359
- });
360
- });
361
-
362
- describe('Error handling', () => {
363
- it('should handle RBAC initialization errors', () => {
364
- mockUseRBAC.mockImplementation(() => {
365
- throw new Error('RBAC initialization failed');
366
- });
367
-
368
- expect(() => {
369
- render(
370
- <RBACProvider>
371
- <TestComponent />
372
- </RBACProvider>
373
- );
374
- }).toThrow('RBAC initialization failed');
375
- });
376
-
377
- it('should handle permission check errors gracefully', () => {
378
- const error = new Error('Permission check failed');
379
- mockUseRBAC.mockReturnValue({
380
- permissions: {
381
- permissions: [],
382
- isLoading: false,
383
- error,
384
- refetch: vi.fn(),
385
- },
386
- can: {
387
- can: vi.fn().mockReturnValue(false),
388
- canAny: vi.fn().mockReturnValue(false),
389
- canAll: vi.fn().mockReturnValue(false),
390
- isLoading: false,
391
- error,
392
- },
393
- organisationPermissions: {
394
- permissions: [],
395
- isLoading: false,
396
- error,
397
- refetch: vi.fn(),
398
- },
399
- permissionCache: {
400
- getCachedPermission: vi.fn(),
401
- setCachedPermission: vi.fn(),
402
- clearCache: vi.fn(),
403
- isCacheValid: vi.fn().mockReturnValue(false),
404
- },
405
- organisationSecurity: {
406
- canAccessOrganisation: vi.fn().mockReturnValue(false),
407
- canAccessEvent: vi.fn().mockReturnValue(false),
408
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
409
- isEventAdmin: vi.fn().mockReturnValue(false),
410
- isLoading: false,
411
- error,
412
- },
413
- });
414
-
415
- render(
416
- <RBACProvider>
417
- <TestComponent />
418
- </RBACProvider>
419
- );
420
-
421
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
422
- });
423
- });
424
-
425
- describe('Performance', () => {
426
- it('should maintain stable references for same props', () => {
427
- mockUseRBAC.mockReturnValue({
428
- permissions: {
429
- permissions: ['read:users'],
430
- isLoading: false,
431
- error: null,
432
- refetch: vi.fn(),
433
- },
434
- can: {
435
- can: vi.fn().mockReturnValue(true),
436
- canAny: vi.fn().mockReturnValue(true),
437
- canAll: vi.fn().mockReturnValue(true),
438
- isLoading: false,
439
- error: null,
440
- },
441
- organisationPermissions: {
442
- permissions: ['read:organisation'],
443
- isLoading: false,
444
- error: null,
445
- refetch: vi.fn(),
446
- },
447
- permissionCache: {
448
- getCachedPermission: vi.fn(),
449
- setCachedPermission: vi.fn(),
450
- clearCache: vi.fn(),
451
- isCacheValid: vi.fn().mockReturnValue(true),
452
- },
453
- organisationSecurity: {
454
- canAccessOrganisation: vi.fn().mockReturnValue(true),
455
- canAccessEvent: vi.fn().mockReturnValue(true),
456
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
457
- isEventAdmin: vi.fn().mockReturnValue(false),
458
- isLoading: false,
459
- error: null,
460
- },
461
- });
462
-
463
- const { rerender } = render(
464
- <RBACProvider>
465
- <TestComponent />
466
- </RBACProvider>
467
- );
468
-
469
- const firstRender = screen.getByTestId('test-component');
470
- rerender(
471
- <RBACProvider>
472
- <TestComponent />
473
- </RBACProvider>
474
- );
475
- const secondRender = screen.getByTestId('test-component');
476
-
477
- expect(firstRender).toBe(secondRender);
478
- });
479
-
480
- it('should handle rapid context changes efficiently', () => {
481
- mockUseRBAC.mockReturnValue({
482
- permissions: {
483
- permissions: ['read:users'],
484
- isLoading: false,
485
- error: null,
486
- refetch: vi.fn(),
487
- },
488
- can: {
489
- can: vi.fn().mockReturnValue(true),
490
- canAny: vi.fn().mockReturnValue(true),
491
- canAll: vi.fn().mockReturnValue(true),
492
- isLoading: false,
493
- error: null,
494
- },
495
- organisationPermissions: {
496
- permissions: ['read:organisation'],
497
- isLoading: false,
498
- error: null,
499
- refetch: vi.fn(),
500
- },
501
- permissionCache: {
502
- getCachedPermission: vi.fn(),
503
- setCachedPermission: vi.fn(),
504
- clearCache: vi.fn(),
505
- isCacheValid: vi.fn().mockReturnValue(true),
506
- },
507
- organisationSecurity: {
508
- canAccessOrganisation: vi.fn().mockReturnValue(true),
509
- canAccessEvent: vi.fn().mockReturnValue(true),
510
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
511
- isEventAdmin: vi.fn().mockReturnValue(false),
512
- isLoading: false,
513
- error: null,
514
- },
515
- });
516
-
517
- const { rerender } = render(
518
- <RBACProvider>
519
- <TestComponent />
520
- </RBACProvider>
521
- );
522
-
523
- // Rapid changes should be handled efficiently
524
- for (let i = 0; i < 10; i++) {
525
- rerender(
526
- <RBACProvider>
527
- <TestComponent />
528
- </RBACProvider>
529
- );
530
- }
531
-
532
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
533
- });
534
- });
535
-
536
- describe('Edge cases', () => {
537
- it('should handle empty children', () => {
538
- mockUseRBAC.mockReturnValue({
539
- permissions: {
540
- permissions: [],
541
- isLoading: false,
542
- error: null,
543
- refetch: vi.fn(),
544
- },
545
- can: {
546
- can: vi.fn(),
547
- canAny: vi.fn(),
548
- canAll: vi.fn(),
549
- isLoading: false,
550
- error: null,
551
- },
552
- organisationPermissions: {
553
- permissions: [],
554
- isLoading: false,
555
- error: null,
556
- refetch: vi.fn(),
557
- },
558
- permissionCache: {
559
- getCachedPermission: vi.fn(),
560
- setCachedPermission: vi.fn(),
561
- clearCache: vi.fn(),
562
- isCacheValid: vi.fn().mockReturnValue(false),
563
- },
564
- organisationSecurity: {
565
- canAccessOrganisation: vi.fn(),
566
- canAccessEvent: vi.fn(),
567
- isOrganisationAdmin: vi.fn(),
568
- isEventAdmin: vi.fn(),
569
- isLoading: false,
570
- error: null,
571
- },
572
- });
573
-
574
- const { container } = render(
575
- <RBACProvider>
576
- {null}
577
- </RBACProvider>
578
- );
579
-
580
- expect(container.firstChild).toBeNull();
581
- });
582
-
583
- it('should handle undefined children', () => {
584
- mockUseRBAC.mockReturnValue({
585
- permissions: {
586
- permissions: [],
587
- isLoading: false,
588
- error: null,
589
- refetch: vi.fn(),
590
- },
591
- can: {
592
- can: vi.fn(),
593
- canAny: vi.fn(),
594
- canAll: vi.fn(),
595
- isLoading: false,
596
- error: null,
597
- },
598
- organisationPermissions: {
599
- permissions: [],
600
- isLoading: false,
601
- error: null,
602
- refetch: vi.fn(),
603
- },
604
- permissionCache: {
605
- getCachedPermission: vi.fn(),
606
- setCachedPermission: vi.fn(),
607
- clearCache: vi.fn(),
608
- isCacheValid: vi.fn().mockReturnValue(false),
609
- },
610
- organisationSecurity: {
611
- canAccessOrganisation: vi.fn(),
612
- canAccessEvent: vi.fn(),
613
- isOrganisationAdmin: vi.fn(),
614
- isEventAdmin: vi.fn(),
615
- isLoading: false,
616
- error: null,
617
- },
618
- });
619
-
620
- const { container } = render(
621
- <RBACProvider>
622
- {undefined}
623
- </RBACProvider>
624
- );
625
-
626
- expect(container.firstChild).toBeNull();
627
- });
628
- });
629
-
630
- describe('Accessibility', () => {
631
- it('should maintain accessibility throughout context changes', () => {
632
- mockUseRBAC.mockReturnValue({
633
- permissions: {
634
- permissions: ['read:users'],
635
- isLoading: false,
636
- error: null,
637
- refetch: vi.fn(),
638
- },
639
- can: {
640
- can: vi.fn().mockReturnValue(true),
641
- canAny: vi.fn().mockReturnValue(true),
642
- canAll: vi.fn().mockReturnValue(true),
643
- isLoading: false,
644
- error: null,
645
- },
646
- organisationPermissions: {
647
- permissions: ['read:organisation'],
648
- isLoading: false,
649
- error: null,
650
- refetch: vi.fn(),
651
- },
652
- permissionCache: {
653
- getCachedPermission: vi.fn(),
654
- setCachedPermission: vi.fn(),
655
- clearCache: vi.fn(),
656
- isCacheValid: vi.fn().mockReturnValue(true),
657
- },
658
- organisationSecurity: {
659
- canAccessOrganisation: vi.fn().mockReturnValue(true),
660
- canAccessEvent: vi.fn().mockReturnValue(true),
661
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
662
- isEventAdmin: vi.fn().mockReturnValue(false),
663
- isLoading: false,
664
- error: null,
665
- },
666
- });
667
-
668
- render(
669
- <RBACProvider>
670
- <TestComponent />
671
- </RBACProvider>
672
- );
673
-
674
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
675
- expect(screen.getByTestId('permissions')).toBeInTheDocument();
676
- expect(screen.getByTestId('can-read-users')).toBeInTheDocument();
677
- });
678
- });
679
-
680
- describe('[integration] Provider Initialization', () => {
681
- it('initializes without errors', () => {
682
- mockUseRBAC.mockReturnValue({
683
- permissions: {
684
- permissions: ['read:users'],
685
- isLoading: false,
686
- error: null,
687
- refetch: vi.fn(),
688
- },
689
- can: {
690
- can: vi.fn().mockReturnValue(true),
691
- canAny: vi.fn().mockReturnValue(true),
692
- canAll: vi.fn().mockReturnValue(true),
693
- isLoading: false,
694
- error: null,
695
- },
696
- organisationPermissions: {
697
- permissions: ['read:organisation'],
698
- isLoading: false,
699
- error: null,
700
- refetch: vi.fn(),
701
- },
702
- permissionCache: {
703
- getCachedPermission: vi.fn(),
704
- setCachedPermission: vi.fn(),
705
- clearCache: vi.fn(),
706
- isCacheValid: vi.fn().mockReturnValue(true),
707
- },
708
- organisationSecurity: {
709
- canAccessOrganisation: vi.fn().mockReturnValue(true),
710
- canAccessEvent: vi.fn().mockReturnValue(true),
711
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
712
- isEventAdmin: vi.fn().mockReturnValue(false),
713
- isLoading: false,
714
- error: null,
715
- },
716
- });
717
-
718
- render(
719
- <RBACProvider>
720
- <TestComponent />
721
- </RBACProvider>
722
- );
723
-
724
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
725
- expect(screen.getByTestId('permissions')).toBeInTheDocument();
726
- });
727
-
728
- it('handles missing dependencies gracefully', () => {
729
- mockUseRBAC.mockReturnValue({
730
- permissions: {
731
- permissions: [],
732
- isLoading: true,
733
- error: null,
734
- refetch: vi.fn(),
735
- },
736
- can: {
737
- can: vi.fn().mockReturnValue(false),
738
- canAny: vi.fn().mockReturnValue(false),
739
- canAll: vi.fn().mockReturnValue(false),
740
- isLoading: true,
741
- error: null,
742
- },
743
- organisationPermissions: {
744
- permissions: [],
745
- isLoading: true,
746
- error: null,
747
- refetch: vi.fn(),
748
- },
749
- permissionCache: {
750
- getCachedPermission: vi.fn(),
751
- setCachedPermission: vi.fn(),
752
- clearCache: vi.fn(),
753
- isCacheValid: vi.fn().mockReturnValue(false),
754
- },
755
- organisationSecurity: {
756
- canAccessOrganisation: vi.fn().mockReturnValue(false),
757
- canAccessEvent: vi.fn().mockReturnValue(false),
758
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
759
- isEventAdmin: vi.fn().mockReturnValue(false),
760
- isLoading: true,
761
- error: null,
762
- },
763
- });
764
-
765
- render(
766
- <RBACProvider>
767
- <TestComponent />
768
- </RBACProvider>
769
- );
770
-
771
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
772
- });
773
- });
774
-
775
- describe('[integration] Concurrent Permission Checks', () => {
776
- it('handles multiple permission checks simultaneously', () => {
777
- const mockCan = vi.fn().mockReturnValue(true);
778
- mockUseRBAC.mockReturnValue({
779
- permissions: {
780
- permissions: ['read:users'],
781
- isLoading: false,
782
- error: null,
783
- refetch: vi.fn(),
784
- },
785
- can: {
786
- can: mockCan,
787
- canAny: vi.fn().mockReturnValue(true),
788
- canAll: vi.fn().mockReturnValue(true),
789
- isLoading: false,
790
- error: null,
791
- },
792
- organisationPermissions: {
793
- permissions: ['read:organisation'],
794
- isLoading: false,
795
- error: null,
796
- refetch: vi.fn(),
797
- },
798
- permissionCache: {
799
- getCachedPermission: vi.fn(),
800
- setCachedPermission: vi.fn(),
801
- clearCache: vi.fn(),
802
- isCacheValid: vi.fn().mockReturnValue(true),
803
- },
804
- organisationSecurity: {
805
- canAccessOrganisation: vi.fn().mockReturnValue(true),
806
- canAccessEvent: vi.fn().mockReturnValue(true),
807
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
808
- isEventAdmin: vi.fn().mockReturnValue(false),
809
- isLoading: false,
810
- error: null,
811
- },
812
- });
813
-
814
- render(
815
- <RBACProvider>
816
- <TestComponent />
817
- </RBACProvider>
818
- );
819
-
820
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
821
- });
822
-
823
- it('maintains performance under high permission check load', () => {
824
- const mockCan = vi.fn().mockReturnValue(true);
825
- let callCount = 0;
826
-
827
- mockUseRBAC.mockReturnValue({
828
- permissions: {
829
- permissions: ['read:users'],
830
- isLoading: false,
831
- error: null,
832
- refetch: vi.fn(),
833
- },
834
- can: {
835
- can: () => {
836
- callCount++;
837
- return mockCan();
838
- },
839
- canAny: vi.fn().mockReturnValue(true),
840
- canAll: vi.fn().mockReturnValue(true),
841
- isLoading: false,
842
- error: null,
843
- },
844
- organisationPermissions: {
845
- permissions: ['read:organisation'],
846
- isLoading: false,
847
- error: null,
848
- refetch: vi.fn(),
849
- },
850
- permissionCache: {
851
- getCachedPermission: vi.fn(),
852
- setCachedPermission: vi.fn(),
853
- clearCache: vi.fn(),
854
- isCacheValid: vi.fn().mockReturnValue(true),
855
- },
856
- organisationSecurity: {
857
- canAccessOrganisation: vi.fn().mockReturnValue(true),
858
- canAccessEvent: vi.fn().mockReturnValue(true),
859
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
860
- isEventAdmin: vi.fn().mockReturnValue(false),
861
- isLoading: false,
862
- error: null,
863
- },
864
- });
865
-
866
- render(
867
- <RBACProvider>
868
- <TestComponent />
869
- </RBACProvider>
870
- );
871
-
872
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
873
- });
874
- });
875
-
876
- describe('[integration] Permission Cache Management', () => {
877
- it('provides cache invalidation functionality', () => {
878
- const mockClearCache = vi.fn();
879
- mockUseRBAC.mockReturnValue({
880
- permissions: {
881
- permissions: ['read:users'],
882
- isLoading: false,
883
- error: null,
884
- refetch: vi.fn(),
885
- },
886
- can: {
887
- can: vi.fn().mockReturnValue(true),
888
- canAny: vi.fn().mockReturnValue(true),
889
- canAll: vi.fn().mockReturnValue(true),
890
- isLoading: false,
891
- error: null,
892
- },
893
- organisationPermissions: {
894
- permissions: ['read:organisation'],
895
- isLoading: false,
896
- error: null,
897
- refetch: vi.fn(),
898
- },
899
- permissionCache: {
900
- getCachedPermission: vi.fn(),
901
- setCachedPermission: vi.fn(),
902
- clearCache: mockClearCache,
903
- isCacheValid: vi.fn().mockReturnValue(true),
904
- },
905
- organisationSecurity: {
906
- canAccessOrganisation: vi.fn().mockReturnValue(true),
907
- canAccessEvent: vi.fn().mockReturnValue(true),
908
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
909
- isEventAdmin: vi.fn().mockReturnValue(false),
910
- isLoading: false,
911
- error: null,
912
- },
913
- });
914
-
915
- render(
916
- <RBACProvider>
917
- <TestComponent />
918
- </RBACProvider>
919
- );
920
-
921
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
922
- expect(mockClearCache).toBeDefined();
923
- });
924
-
925
- it('handles cache validation states', () => {
926
- let cacheValid = false;
927
- mockUseRBAC.mockReturnValue({
928
- permissions: {
929
- permissions: ['read:users'],
930
- isLoading: false,
931
- error: null,
932
- refetch: vi.fn(),
933
- },
934
- can: {
935
- can: vi.fn().mockReturnValue(true),
936
- canAny: vi.fn().mockReturnValue(true),
937
- canAll: vi.fn().mockReturnValue(true),
938
- isLoading: false,
939
- error: null,
940
- },
941
- organisationPermissions: {
942
- permissions: ['read:organisation'],
943
- isLoading: false,
944
- error: null,
945
- refetch: vi.fn(),
946
- },
947
- permissionCache: {
948
- getCachedPermission: vi.fn(),
949
- setCachedPermission: vi.fn(),
950
- clearCache: vi.fn(),
951
- isCacheValid: vi.fn(() => cacheValid),
952
- },
953
- organisationSecurity: {
954
- canAccessOrganisation: vi.fn().mockReturnValue(true),
955
- canAccessEvent: vi.fn().mockReturnValue(true),
956
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
957
- isEventAdmin: vi.fn().mockReturnValue(false),
958
- isLoading: false,
959
- error: null,
960
- },
961
- });
962
-
963
- const { rerender } = render(
964
- <RBACProvider>
965
- <TestComponent />
966
- </RBACProvider>
967
- );
968
-
969
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
970
-
971
- // Toggle cache validity
972
- cacheValid = true;
973
- rerender(
974
- <RBACProvider>
975
- <TestComponent />
976
- </RBACProvider>
977
- );
978
-
979
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
980
- });
981
- });
982
-
983
- describe('[integration] Security and Access Control', () => {
984
- it('validates organization access', () => {
985
- const mockCanAccessOrg = vi.fn().mockReturnValue(true);
986
- mockUseRBAC.mockReturnValue({
987
- permissions: {
988
- permissions: ['read:users'],
989
- isLoading: false,
990
- error: null,
991
- refetch: vi.fn(),
992
- },
993
- can: {
994
- can: vi.fn().mockReturnValue(true),
995
- canAny: vi.fn().mockReturnValue(true),
996
- canAll: vi.fn().mockReturnValue(true),
997
- isLoading: false,
998
- error: null,
999
- },
1000
- organisationPermissions: {
1001
- permissions: ['read:organisation'],
1002
- isLoading: false,
1003
- error: null,
1004
- refetch: vi.fn(),
1005
- },
1006
- permissionCache: {
1007
- getCachedPermission: vi.fn(),
1008
- setCachedPermission: vi.fn(),
1009
- clearCache: vi.fn(),
1010
- isCacheValid: vi.fn().mockReturnValue(true),
1011
- },
1012
- organisationSecurity: {
1013
- canAccessOrganisation: mockCanAccessOrg,
1014
- canAccessEvent: vi.fn().mockReturnValue(true),
1015
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
1016
- isEventAdmin: vi.fn().mockReturnValue(false),
1017
- isLoading: false,
1018
- error: null,
1019
- },
1020
- });
1021
-
1022
- render(
1023
- <RBACProvider>
1024
- <TestComponent />
1025
- </RBACProvider>
1026
- );
1027
-
1028
- expect(mockCanAccessOrg).toBeDefined();
1029
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
1030
- });
1031
-
1032
- it('validates event access', () => {
1033
- const mockCanAccessEvent = vi.fn().mockReturnValue(true);
1034
- mockUseRBAC.mockReturnValue({
1035
- permissions: {
1036
- permissions: ['read:users'],
1037
- isLoading: false,
1038
- error: null,
1039
- refetch: vi.fn(),
1040
- },
1041
- can: {
1042
- can: vi.fn().mockReturnValue(true),
1043
- canAny: vi.fn().mockReturnValue(true),
1044
- canAll: vi.fn().mockReturnValue(true),
1045
- isLoading: false,
1046
- error: null,
1047
- },
1048
- organisationPermissions: {
1049
- permissions: ['read:organisation'],
1050
- isLoading: false,
1051
- error: null,
1052
- refetch: vi.fn(),
1053
- },
1054
- permissionCache: {
1055
- getCachedPermission: vi.fn(),
1056
- setCachedPermission: vi.fn(),
1057
- clearCache: vi.fn(),
1058
- isCacheValid: vi.fn().mockReturnValue(true),
1059
- },
1060
- organisationSecurity: {
1061
- canAccessOrganisation: vi.fn().mockReturnValue(true),
1062
- canAccessEvent: mockCanAccessEvent,
1063
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
1064
- isEventAdmin: vi.fn().mockReturnValue(false),
1065
- isLoading: false,
1066
- error: null,
1067
- },
1068
- });
1069
-
1070
- render(
1071
- <RBACProvider>
1072
- <TestComponent />
1073
- </RBACProvider>
1074
- );
1075
-
1076
- expect(mockCanAccessEvent).toBeDefined();
1077
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
1078
- });
1079
-
1080
- it('checks admin roles correctly', () => {
1081
- const mockIsOrgAdmin = vi.fn().mockReturnValue(false);
1082
- const mockIsEventAdmin = vi.fn().mockReturnValue(false);
1083
-
1084
- mockUseRBAC.mockReturnValue({
1085
- permissions: {
1086
- permissions: ['read:users'],
1087
- isLoading: false,
1088
- error: null,
1089
- refetch: vi.fn(),
1090
- },
1091
- can: {
1092
- can: vi.fn().mockReturnValue(true),
1093
- canAny: vi.fn().mockReturnValue(true),
1094
- canAll: vi.fn().mockReturnValue(true),
1095
- isLoading: false,
1096
- error: null,
1097
- },
1098
- organisationPermissions: {
1099
- permissions: ['read:organisation'],
1100
- isLoading: false,
1101
- error: null,
1102
- refetch: vi.fn(),
1103
- },
1104
- permissionCache: {
1105
- getCachedPermission: vi.fn(),
1106
- setCachedPermission: vi.fn(),
1107
- clearCache: vi.fn(),
1108
- isCacheValid: vi.fn().mockReturnValue(true),
1109
- },
1110
- organisationSecurity: {
1111
- canAccessOrganisation: vi.fn().mockReturnValue(true),
1112
- canAccessEvent: vi.fn().mockReturnValue(true),
1113
- isOrganisationAdmin: mockIsOrgAdmin,
1114
- isEventAdmin: mockIsEventAdmin,
1115
- isLoading: false,
1116
- error: null,
1117
- },
1118
- });
1119
-
1120
- render(
1121
- <RBACProvider>
1122
- <TestComponent />
1123
- </RBACProvider>
1124
- );
1125
-
1126
- expect(mockIsOrgAdmin).toBeDefined();
1127
- expect(mockIsEventAdmin).toBeDefined();
1128
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
1129
- });
1130
- });
1131
-
1132
- describe('[integration] Rapid State Changes', () => {
1133
- it('handles rapid permission updates without errors', () => {
1134
- let permissionState = { permissions: ['read:users'], isLoading: false, error: null, refetch: vi.fn() };
1135
-
1136
- mockUseRBAC.mockReturnValue({
1137
- permissions: permissionState,
1138
- can: {
1139
- can: vi.fn().mockReturnValue(true),
1140
- canAny: vi.fn().mockReturnValue(true),
1141
- canAll: vi.fn().mockReturnValue(true),
1142
- isLoading: false,
1143
- error: null,
1144
- },
1145
- organisationPermissions: {
1146
- permissions: ['read:organisation'],
1147
- isLoading: false,
1148
- error: null,
1149
- refetch: vi.fn(),
1150
- },
1151
- permissionCache: {
1152
- getCachedPermission: vi.fn(),
1153
- setCachedPermission: vi.fn(),
1154
- clearCache: vi.fn(),
1155
- isCacheValid: vi.fn().mockReturnValue(true),
1156
- },
1157
- organisationSecurity: {
1158
- canAccessOrganisation: vi.fn().mockReturnValue(true),
1159
- canAccessEvent: vi.fn().mockReturnValue(true),
1160
- isOrganisationAdmin: vi.fn().mockReturnValue(false),
1161
- isEventAdmin: vi.fn().mockReturnValue(false),
1162
- isLoading: false,
1163
- error: null,
1164
- },
1165
- });
1166
-
1167
- const { rerender } = render(
1168
- <RBACProvider>
1169
- <TestComponent />
1170
- </RBACProvider>
1171
- );
1172
-
1173
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
1174
-
1175
- // Rapid updates
1176
- permissionState = { permissions: ['write:users'], isLoading: false, error: null, refetch: vi.fn() };
1177
- rerender(
1178
- <RBACProvider>
1179
- <TestComponent />
1180
- </RBACProvider>
1181
- );
1182
-
1183
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
1184
- });
1185
- });
1186
- });