@jmruthers/pace-core 0.6.10 → 0.6.11
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/CHANGELOG.md +21 -0
- package/audit-tool/00-dependencies.cjs +46 -13
- package/audit-tool/audits/01-pace-core-compliance.cjs +96 -21
- package/audit-tool/audits/02-project-structure.cjs +13 -3
- package/audit-tool/audits/03-architecture.cjs +78 -4
- package/audit-tool/audits/04-code-quality.cjs +9 -2
- package/audit-tool/audits/05-styling.cjs +19 -7
- package/audit-tool/audits/06-security-rbac.cjs +105 -14
- package/audit-tool/audits/07-api-tech-stack.cjs +31 -15
- package/audit-tool/audits/08-testing-documentation.cjs +11 -3
- package/audit-tool/audits/09-operations.cjs +19 -7
- package/audit-tool/index.cjs +22 -11
- package/audit-tool/utils/report-utils.cjs +4 -0
- package/cursor-rules/01-pace-core-compliance.mdc +1 -0
- package/cursor-rules/02-project-structure.mdc +1 -0
- package/cursor-rules/03-architecture.mdc +3 -1
- package/cursor-rules/04-code-quality.mdc +1 -0
- package/cursor-rules/05-styling.mdc +41 -7
- package/cursor-rules/06-security-rbac.mdc +2 -1
- package/cursor-rules/07-api-tech-stack.mdc +1 -0
- package/cursor-rules/08-testing-documentation.mdc +1 -0
- package/cursor-rules/09-operations.mdc +1 -0
- package/dist/{DataTable-SAXFG4XI.js → DataTable-EFYP2QLE.js} +10 -7
- package/dist/{InactivityServiceProvider-DHryoh6K.d.ts → InactivityServiceProvider-BbxwwDz1.d.ts} +10 -1
- package/dist/{UnifiedAuthProvider-CiBAl9-s.d.ts → UnifiedAuthProvider-Bkt_tzdS.d.ts} +56 -24
- package/dist/{api-F47QJ7FX.js → api-BZR2CYXL.js} +3 -2
- package/dist/api-result-USV1Czr-.d.ts +51 -0
- package/dist/{audit-Z6ZZBWLU.js → audit-HI2DHUVU.js} +2 -1
- package/dist/{auth-BZOJqrdd.d.ts → auth-JvdRVaud.d.ts} +1 -1
- package/dist/{chunk-KSNLMI7N.js → chunk-2DL2WSOE.js} +1 -155
- package/dist/{chunk-MPY44PWB.js → chunk-2OEVOGGR.js} +4648 -3560
- package/dist/chunk-44CNXN4P.js +15 -0
- package/dist/{chunk-Y4PF6HIM.js → chunk-4R3T5ENU.js} +867 -786
- package/dist/{chunk-LNHFAF4X.js → chunk-7A6IMHH2.js} +289 -247
- package/dist/chunk-CU2BU2MQ.js +2 -0
- package/dist/{chunk-JJEYZ3DX.js → chunk-D6BMFMQZ.js} +37 -2
- package/dist/{chunk-BCTXBU6U.js → chunk-ENLXB7GP.js} +88 -71
- package/dist/{chunk-FBZ7U3ID.js → chunk-J2KQK6DG.js} +937 -987
- package/dist/{chunk-TFIPNIPE.js → chunk-KJXRL3XE.js} +3300 -2245
- package/dist/{chunk-3GWSPISD.js → chunk-L5LFKKLJ.js} +1 -1
- package/dist/{chunk-X5EAU5G7.js → chunk-PCSHBLPB.js} +132 -114
- package/dist/{chunk-NIU6DPQV.js → chunk-QRYSEPHB.js} +2 -0
- package/dist/{chunk-KYURMOQM.js → chunk-V7FTM2LU.js} +423 -320
- package/dist/chunk-WY6Y7KC3.js +264 -0
- package/dist/{chunk-FN52B75D.js → chunk-XOJME5T7.js} +176 -15
- package/dist/{chunk-7YDC7LMU.js → chunk-XPFVT3GN.js} +71 -66
- package/dist/{chunk-66R6RLUZ.js → chunk-YFTFFJIV.js} +3 -3
- package/dist/{chunk-W46INAVW.js → chunk-YYTWKVHO.js} +688 -570
- package/dist/components.d.ts +8 -7
- package/dist/components.js +17 -15
- package/dist/{database.generated-DT8JTZiP.d.ts → database.generated-qkdoiVrJ.d.ts} +45 -10
- package/dist/eslint-rules/index.cjs +3 -0
- package/dist/eslint-rules/rules/03-architecture.cjs +74 -0
- package/dist/eslint-rules/rules/06-security-rbac.cjs +74 -0
- package/dist/{event-WTAQuGcq.d.ts → event-BfCox3N2.d.ts} +36 -10
- package/dist/{file-reference-BavO2eQj.d.ts → file-reference-DU1hcawx.d.ts} +29 -13
- package/dist/hooks.d.ts +22 -9
- package/dist/hooks.js +34 -25
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/index.js +1 -0
- package/dist/index.d.ts +66 -177
- package/dist/index.js +316 -340
- package/dist/pagination-BW1mqywp.d.ts +201 -0
- package/dist/providers.d.ts +6 -5
- package/dist/providers.js +5 -3
- package/dist/rbac/index.d.ts +123 -138
- package/dist/rbac/index.js +10 -8
- package/dist/theming/runtime.d.ts +19 -2
- package/dist/theming/runtime.js +1 -1
- package/dist/{timezone-K-ptz3HO.d.ts → timezone-BTWWXKVY.d.ts} +1 -1
- package/dist/types.d.ts +17 -10
- package/dist/types.js +1 -0
- package/dist/{usePublicPageContext-vxBlEHO9.d.ts → usePublicPageContext-B91dGYW1.d.ts} +433 -356
- package/dist/{usePublicRouteParams-G3Ks53mk.d.ts → usePublicRouteParams-BgV6VhMi.d.ts} +73 -4
- package/dist/utils.d.ts +163 -145
- package/dist/utils.js +42 -25
- package/docs/api/modules.md +782 -643
- package/docs/api-reference/rpc-functions.md +12 -3
- package/docs/core-concepts/rbac-system.md +8 -0
- package/docs/getting-started/cursor-rules.md +17 -20
- package/docs/getting-started/dependencies.md +1 -1
- package/docs/getting-started/setup.md +235 -0
- package/docs/implementation-guides/authentication.md +27 -0
- package/docs/implementation-guides/data-tables.md +176 -3
- package/docs/migration/ApiResult-migration.md +25 -0
- package/docs/rbac/api-reference.md +33 -31
- package/docs/standards/0-standards-overview.md +50 -15
- package/docs/standards/1-pace-core-compliance-standards.md +62 -57
- package/docs/standards/2-project-structure-standards.md +33 -16
- package/docs/standards/3-architecture-standards.md +41 -1
- package/docs/standards/4-code-quality-standards.md +26 -6
- package/docs/standards/5-styling-standards.md +35 -1
- package/docs/standards/6-security-rbac-standards.md +66 -0
- package/docs/standards/7-api-tech-stack-standards.md +25 -14
- package/docs/standards/8-testing-documentation-standards.md +31 -0
- package/docs/standards/9-operations-standards.md +19 -0
- package/docs/standards/README.md +20 -201
- package/docs/testing/test-setup-for-consumers.md +2 -0
- package/docs/troubleshooting/common-issues.md +17 -1
- package/docs/troubleshooting/organisation-context-setup.md +8 -0
- package/docs/troubleshooting/print-event-name-css-variable-analysis.md +217 -0
- package/eslint-config-pace-core.cjs +20 -0
- package/package.json +14 -20
- package/scripts/{build-docs-incremental.js → build-docs.js} +3 -2
- package/scripts/setup.cjs +536 -0
- package/scripts/validate.cjs +480 -0
- package/src/__tests__/helpers/{__tests__/component-test-utils.test.tsx → component-test-utils.test.tsx} +3 -3
- package/src/__tests__/helpers/{__tests__/optimized-test-setup.test.ts → optimized-test-setup.test.ts} +2 -2
- package/src/__tests__/helpers/{__tests__/supabaseMock.test.ts → supabaseMock.test.ts} +2 -2
- package/src/__tests__/helpers/{__tests__/test-providers.test.tsx → test-providers.test.tsx} +1 -1
- package/src/__tests__/helpers/test-providers.tsx +37 -39
- package/src/__tests__/helpers/{__tests__/test-utils.test.tsx → test-utils.test.tsx} +4 -3
- package/src/__tests__/helpers/{__tests__/timer-utils.test.ts → timer-utils.test.ts} +2 -2
- package/src/assets/app-icons/index.test.ts +304 -0
- package/src/components/AddressField/AddressField.test.tsx +1 -1
- package/src/components/AddressField/AddressField.tsx +238 -212
- package/src/components/Button/Button.tsx +1 -1
- package/src/components/Card/Card.test.tsx +172 -17
- package/src/components/Card/Card.tsx +19 -10
- package/src/components/ContextSelector/ContextSelector.internals.tsx +204 -0
- package/src/components/ContextSelector/{__tests__/ContextSelector.test.tsx → ContextSelector.test.tsx} +6 -6
- package/src/components/ContextSelector/ContextSelector.tsx +66 -280
- package/src/components/ContextSelector/ContextSelector.types.ts +35 -0
- package/src/components/ContextSelector/useContextSelectorState.tsx +195 -0
- package/src/components/DataTable/AUDIT_REPORT.md +59 -44
- package/src/components/DataTable/{__tests__/DataTable.comprehensive.test.tsx → DataTable.comprehensive.test.tsx} +6 -6
- package/src/components/DataTable/{__tests__/DataTable.default-state.test.tsx → DataTable.default-state.test.tsx} +5 -5
- package/src/components/DataTable/{__tests__/DataTable.export.test.tsx → DataTable.export.test.tsx} +10 -10
- package/src/components/DataTable/{__tests__/DataTable.grouping-aggregation.test.tsx → DataTable.grouping-aggregation.test.tsx} +6 -6
- package/src/components/DataTable/{__tests__/DataTable.hooks.test.tsx → DataTable.hooks.test.tsx} +6 -6
- package/src/components/DataTable/{__tests__/DataTable.select-label-display.test.tsx → DataTable.select-label-display.test.tsx} +6 -6
- package/src/components/DataTable/DataTable.test.tsx +787 -416
- package/src/components/DataTable/DataTable.tsx +12 -12
- package/src/components/DataTable/DataTableCore.integration.test.tsx +458 -0
- package/src/components/DataTable/{__tests__/DataTableCore.test-setup.ts → DataTableCore.test-setup.ts} +10 -9
- package/src/components/DataTable/{__tests__/DataTableCore.test.tsx → DataTableCore.test.tsx} +8 -8
- package/src/components/DataTable/{__tests__/README.md → README.md} +17 -7
- package/src/components/DataTable/TESTING.md +101 -0
- package/src/components/DataTable/{__tests__/a11y.basic.test.tsx → a11y.basic.test.tsx} +34 -34
- package/src/components/DataTable/components/DataTableCore.tsx +104 -864
- package/src/components/DataTable/components/{__tests__/GroupingDropdown.test.tsx → GroupingDropdown.test.tsx} +17 -8
- package/src/components/DataTable/components/GroupingDropdown.tsx +2 -2
- package/src/components/DataTable/components/ImportModal.tsx +61 -559
- package/src/components/DataTable/components/ImportModalFileSection.tsx +148 -0
- package/src/components/DataTable/context/{__tests__/DataTableContext.test.tsx → DataTableContext.test.tsx} +2 -2
- package/src/components/DataTable/context/DataTableContext.tsx +7 -6
- package/src/components/DataTable/core/{__tests__/ColumnFactory.test.ts → ColumnFactory.test.ts} +2 -2
- package/src/components/DataTable/hooks/{__tests__/useColumnOrderPersistence.test.ts → useColumnOrderPersistence.test.ts} +2 -2
- package/src/components/DataTable/hooks/{__tests__/useColumnVisibilityPersistence.test.ts → useColumnVisibilityPersistence.test.ts} +2 -2
- package/src/components/DataTable/hooks/{__tests__/useDataTableConfiguration.test.ts → useDataTableConfiguration.test.ts} +3 -3
- package/src/components/DataTable/hooks/useDataTableConfiguration.ts +14 -2
- package/src/components/DataTable/hooks/{__tests__/useDataTableDataPipeline.test.ts → useDataTableDataPipeline.test.ts} +6 -6
- package/src/components/DataTable/hooks/useDataTableDeletionBatching.test.ts +127 -0
- package/src/components/DataTable/hooks/useDataTableDeletionBatching.ts +106 -0
- package/src/components/DataTable/hooks/useDataTableEffectiveActions.test.ts +461 -0
- package/src/components/DataTable/hooks/useDataTableEffectiveActions.ts +238 -0
- package/src/components/DataTable/hooks/useDataTableLayoutHandlers.test.ts +296 -0
- package/src/components/DataTable/hooks/useDataTableLayoutHandlers.ts +175 -0
- package/src/components/DataTable/hooks/useDataTablePaginationSync.test.ts +203 -0
- package/src/components/DataTable/hooks/useDataTablePaginationSync.ts +109 -0
- package/src/components/DataTable/hooks/{__tests__/useDataTablePermissions.test.ts → useDataTablePermissions.test.ts} +11 -11
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +79 -247
- package/src/components/DataTable/hooks/useDataTablePipeline.test.tsx +219 -0
- package/src/components/DataTable/hooks/useDataTablePipeline.tsx +239 -0
- package/src/components/DataTable/hooks/useDataTableRenderGuard.test.tsx +316 -0
- package/src/components/DataTable/hooks/useDataTableRenderGuard.tsx +195 -0
- package/src/components/DataTable/hooks/useDataTableScope.test.ts +110 -0
- package/src/components/DataTable/hooks/useDataTableScope.ts +123 -0
- package/src/components/DataTable/hooks/{__tests__/useDataTableState.test.ts → useDataTableState.test.ts} +47 -5
- package/src/components/DataTable/hooks/useDataTableState.ts +145 -94
- package/src/components/DataTable/hooks/useDataTableStateAndPersistence.test.ts +277 -0
- package/src/components/DataTable/hooks/useDataTableStateAndPersistence.ts +222 -0
- package/src/components/DataTable/hooks/useDataTableSuperAdmin.test.ts +93 -0
- package/src/components/DataTable/hooks/useDataTableSuperAdmin.ts +86 -0
- package/src/components/DataTable/hooks/useDataTableTableInstance.test.ts +185 -0
- package/src/components/DataTable/hooks/useDataTableTableInstance.ts +178 -0
- package/src/components/DataTable/hooks/{__tests__/useEffectiveColumnOrder.test.ts → useEffectiveColumnOrder.test.ts} +2 -2
- package/src/components/DataTable/hooks/{__tests__/useHierarchicalState.test.ts → useHierarchicalState.test.ts} +2 -2
- package/src/components/DataTable/{components/hooks → hooks}/useImportModalFocus.test.ts +3 -3
- package/src/components/DataTable/{components/hooks → hooks}/useImportModalFocus.ts +2 -2
- package/src/components/DataTable/hooks/useImportModalState.test.ts +390 -0
- package/src/components/DataTable/hooks/useImportModalState.ts +345 -0
- package/src/components/DataTable/hooks/{__tests__/useKeyboardNavigation.test.ts → useKeyboardNavigation.test.ts} +3 -3
- package/src/components/DataTable/hooks/useKeyboardNavigation.ts +309 -269
- package/src/components/DataTable/{components/hooks → hooks}/usePermissionTracking.test.ts +3 -3
- package/src/components/DataTable/{components/hooks → hooks}/usePermissionTracking.ts +3 -3
- package/src/components/DataTable/hooks/{__tests__/useServerSideDataEffect.test.ts → useServerSideDataEffect.test.ts} +2 -2
- package/src/components/DataTable/hooks/useServerSideDataEffect.ts +14 -3
- package/src/components/DataTable/hooks/{__tests__/useTableColumns.test.ts → useTableColumns.test.ts} +2 -2
- package/src/components/DataTable/hooks/{__tests__/useTableHandlers.test.ts → useTableHandlers.test.ts} +25 -4
- package/src/components/DataTable/hooks/useTableHandlers.ts +5 -2
- package/src/components/DataTable/index.ts +18 -17
- package/src/components/DataTable/{__tests__/keyboard.test.tsx → keyboard.test.tsx} +41 -63
- package/src/components/DataTable/{__tests__/mocks → mocks}/MockRBACProvider.tsx +1 -1
- package/src/components/DataTable/{__tests__/pagination.modes.test.tsx → pagination.modes.test.tsx} +6 -6
- package/src/components/DataTable/{__tests__/ssr.strict-mode.test.tsx → ssr.strict-mode.test.tsx} +2 -2
- package/src/components/DataTable/{__tests__/styles.test.ts → styles.test.ts} +1 -4
- package/src/components/DataTable/styles.ts +0 -1
- package/src/components/DataTable/test-utils/MockDataTableComponents.tsx +55 -0
- package/src/components/DataTable/{__tests__/test-utils → test-utils}/dataFactories.ts +2 -2
- package/src/components/DataTable/test-utils/featureConfig.ts +10 -0
- package/src/components/DataTable/{__tests__/test-utils/sharedTestUtils.tsx → test-utils/sharedTestUtils.ts} +97 -66
- package/src/components/DataTable/{__tests__/test-utils.ts → test-utils.ts} +1 -1
- package/src/components/DataTable/types/actions.ts +71 -0
- package/src/components/DataTable/types/base.ts +39 -0
- package/src/components/DataTable/types/columns.ts +125 -0
- package/src/components/DataTable/types/export.ts +32 -0
- package/src/components/DataTable/types/features.ts +81 -0
- package/src/components/DataTable/types/hierarchical.ts +44 -0
- package/src/components/DataTable/types/index.ts +43 -0
- package/src/components/DataTable/types/pagination.ts +85 -0
- package/src/components/DataTable/types/performance.ts +47 -0
- package/src/components/DataTable/types/props.ts +62 -0
- package/src/components/DataTable/types/rbac.ts +45 -0
- package/src/components/DataTable/{components/__tests__ → ui/layout}/DataTableCore.test.tsx +430 -28
- package/src/components/DataTable/ui/layout/DataTableCore.tsx +345 -0
- package/src/components/DataTable/{components/__tests__ → ui/layout}/DataTableErrorBoundary.test.tsx +4 -4
- package/src/components/DataTable/{components → ui/layout}/DataTableErrorBoundary.tsx +7 -7
- package/src/components/DataTable/ui/layout/DataTableLayout.test.tsx +1352 -0
- package/src/components/DataTable/ui/layout/DataTableLayout.tsx +661 -0
- package/src/components/DataTable/ui/modals/BulkDeleteConfirmDialog.test.tsx +91 -0
- package/src/components/DataTable/ui/modals/BulkDeleteConfirmDialog.tsx +43 -0
- package/src/components/DataTable/ui/modals/DataTableModals.test.tsx +749 -0
- package/src/components/DataTable/{components → ui/modals}/DataTableModals.tsx +36 -28
- package/src/components/DataTable/ui/modals/ImportModal.test.tsx +1834 -0
- package/src/components/DataTable/ui/modals/ImportModal.tsx +197 -0
- package/src/components/DataTable/ui/modals/ImportModalFailedRowsSection.tsx +60 -0
- package/src/components/DataTable/ui/modals/ImportModalFileSection.tsx +148 -0
- package/src/components/DataTable/ui/modals/ImportModalPreviewSection.tsx +60 -0
- package/src/components/DataTable/ui/modals/ImportModalSummarySection.tsx +59 -0
- package/src/components/DataTable/ui/modals/importModalPersistence.ts +73 -0
- package/src/components/DataTable/{components/__tests__ → ui/shared}/AccessDeniedPage.test.tsx +2 -2
- package/src/components/DataTable/{components → ui/shared}/AccessDeniedPage.tsx +2 -2
- package/src/components/DataTable/{components/__tests__ → ui/shared}/ActionButtons.test.tsx +6 -4
- package/src/components/DataTable/{components → ui/shared}/ActionButtons.tsx +4 -4
- package/src/components/DataTable/{components/__tests__ → ui/shared}/ColumnFilter.test.tsx +29 -16
- package/src/components/DataTable/{components → ui/shared}/ColumnFilter.tsx +4 -4
- package/src/components/DataTable/{components/__tests__ → ui/shared}/PaginationControls.test.tsx +38 -16
- package/src/components/DataTable/{components → ui/shared}/PaginationControls.tsx +21 -15
- package/src/components/DataTable/{components/__tests__ → ui/shared}/SortIndicator.test.tsx +2 -2
- package/src/components/DataTable/{components → ui/shared}/SortIndicator.tsx +1 -1
- package/src/components/DataTable/{components/__tests__ → ui/table}/EditFields.test.tsx +3 -3
- package/src/components/DataTable/{components → ui/table}/EditFields.tsx +138 -69
- package/src/components/DataTable/{components/__tests__ → ui/table}/EditableRow.test.tsx +36 -27
- package/src/components/DataTable/{components → ui/table}/EditableRow.tsx +86 -104
- package/src/components/DataTable/{components/__tests__ → ui/table}/EmptyState.test.tsx +2 -62
- package/src/components/DataTable/{components → ui/table}/EmptyState.tsx +7 -15
- package/src/components/DataTable/{components/__tests__ → ui/table}/FilterRow.test.tsx +5 -4
- package/src/components/DataTable/{components → ui/table}/FilterRow.tsx +3 -3
- package/src/components/DataTable/{components/__tests__ → ui/table}/LoadingState.test.tsx +6 -10
- package/src/components/DataTable/{components → ui/table}/LoadingState.tsx +4 -4
- package/src/components/DataTable/{components/__tests__ → ui/table}/RowComponent.test.tsx +412 -17
- package/src/components/DataTable/{components → ui/table}/RowComponent.tsx +183 -177
- package/src/components/DataTable/{components/__tests__ → ui/table}/UnifiedTableBody.test.tsx +425 -16
- package/src/components/DataTable/ui/table/UnifiedTableBody.tsx +440 -0
- package/src/components/DataTable/{components/__tests__ → ui/table}/cellValueUtils.test.ts +2 -2
- package/src/components/DataTable/{components → ui/table}/cellValueUtils.ts +1 -1
- package/src/components/DataTable/{components/__tests__ → ui/toolbar}/BulkOperationsDropdown.test.tsx +12 -5
- package/src/components/DataTable/{components → ui/toolbar}/BulkOperationsDropdown.tsx +3 -3
- package/src/components/DataTable/{components/__tests__ → ui/toolbar}/ColumnVisibilityDropdown.test.tsx +7 -4
- package/src/components/DataTable/{components → ui/toolbar}/ColumnVisibilityDropdown.tsx +7 -7
- package/src/components/DataTable/{components/__tests__ → ui/toolbar}/DataTableToolbar.test.tsx +4 -4
- package/src/components/DataTable/{components → ui/toolbar}/DataTableToolbar.tsx +4 -4
- package/src/components/DataTable/ui/toolbar/GroupingDropdown.test.tsx +621 -0
- package/src/components/DataTable/ui/toolbar/GroupingDropdown.tsx +107 -0
- package/src/components/DataTable/utils/{__tests__/a11yUtils.test.ts → a11yUtils.test.ts} +2 -2
- package/src/components/DataTable/utils/{__tests__/aggregationUtils.test.ts → aggregationUtils.test.ts} +3 -3
- package/src/components/DataTable/utils/{__tests__/columnUtils.test.ts → columnUtils.test.ts} +2 -2
- package/src/components/DataTable/utils/csvParse.test.ts +74 -0
- package/src/components/DataTable/utils/csvParse.ts +65 -0
- package/src/components/DataTable/utils/{__tests__/errorHandling.test.ts → errorHandling.test.ts} +2 -2
- package/src/components/DataTable/utils/{__tests__/exportUtils.test.ts → exportUtils.test.ts} +3 -3
- package/src/components/DataTable/utils/{__tests__/flexibleImport.test.ts → flexibleImport.test.ts} +2 -2
- package/src/components/DataTable/utils/flexibleImport.ts +3 -186
- package/src/components/DataTable/utils/{__tests__/hierarchicalSorting.test.ts → hierarchicalSorting.test.ts} +3 -3
- package/src/components/DataTable/utils/{__tests__/hierarchicalUtils.test.ts → hierarchicalUtils.test.ts} +3 -3
- package/src/components/DataTable/utils/importDateParser.test.ts +162 -0
- package/src/components/DataTable/utils/importDateParser.ts +114 -0
- package/src/components/DataTable/utils/importValueParser.test.ts +138 -0
- package/src/components/DataTable/utils/importValueParser.ts +91 -0
- package/src/components/DataTable/utils/{__tests__/paginationUtils.test.ts → paginationUtils.test.ts} +2 -2
- package/src/components/DataTable/utils/paginationUtils.ts +6 -3
- package/src/components/DataTable/utils/{__tests__/performanceUtils.test.ts → performanceUtils.test.ts} +3 -3
- package/src/components/DataTable/utils/{__tests__/rowUtils.test.ts → rowUtils.test.ts} +3 -3
- package/src/components/DataTable/utils/{__tests__/selectFieldUtils.test.ts → selectFieldUtils.test.ts} +66 -3
- package/src/components/DataTable/utils/selectFieldUtils.ts +97 -60
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +1 -1
- package/src/components/DateTimeField/DateTimeField.test.tsx +1 -1
- package/src/components/Dialog/Dialog.test-utils.ts +49 -0
- package/src/components/Dialog/Dialog.test.tsx +896 -89
- package/src/components/Dialog/Dialog.tsx +174 -882
- package/src/components/Dialog/dialogLock.test.ts +238 -0
- package/src/components/Dialog/dialogLock.ts +98 -0
- package/src/components/Dialog/index.ts +2 -0
- package/src/components/Dialog/useDialogDimensions.test.ts +163 -0
- package/src/components/Dialog/useDialogDimensions.ts +140 -0
- package/src/components/Dialog/useDialogLifecycle.test.ts +358 -0
- package/src/components/Dialog/useDialogLifecycle.ts +135 -0
- package/src/components/Dialog/useDialogPersistence.test.ts +381 -0
- package/src/components/Dialog/useDialogPersistence.ts +357 -0
- package/src/components/FileDisplay/FileDisplay.test.tsx +40 -40
- package/src/components/FileDisplay/FileDisplay.tsx +24 -656
- package/src/components/FileDisplay/FileDisplayContent.test.tsx +395 -0
- package/src/components/FileDisplay/FileDisplayContent.tsx +242 -0
- package/src/components/FileDisplay/FileDisplayDeleteConfirmDialog.test.tsx +74 -0
- package/src/components/FileDisplay/FileDisplayDeleteConfirmDialog.tsx +38 -0
- package/src/components/FileDisplay/FileDisplayEmptyView.test.tsx +33 -0
- package/src/components/FileDisplay/FileDisplayEmptyView.tsx +33 -0
- package/src/components/FileDisplay/FileDisplayErrorView.test.tsx +71 -0
- package/src/components/FileDisplay/FileDisplayErrorView.tsx +50 -0
- package/src/components/FileDisplay/FileDisplayLoadingFallbackView.test.tsx +22 -0
- package/src/components/FileDisplay/FileDisplayLoadingFallbackView.tsx +22 -0
- package/src/components/FileDisplay/FileDisplayLoadingView.test.tsx +21 -0
- package/src/components/FileDisplay/FileDisplayLoadingView.tsx +23 -0
- package/src/components/FileDisplay/FileDisplayMultipleFilesView.test.tsx +101 -0
- package/src/components/FileDisplay/FileDisplayMultipleFilesView.tsx +109 -0
- package/src/components/FileDisplay/FileDisplaySingleDocumentLinkView.test.tsx +58 -0
- package/src/components/FileDisplay/FileDisplaySingleDocumentLinkView.tsx +48 -0
- package/src/components/FileDisplay/FileDisplaySingleFileWithActionsView.test.tsx +111 -0
- package/src/components/FileDisplay/FileDisplaySingleFileWithActionsView.tsx +270 -0
- package/src/components/FileDisplay/FileDisplaySingleImageView.test.tsx +78 -0
- package/src/components/FileDisplay/FileDisplaySingleImageView.tsx +67 -0
- package/src/components/FileDisplay/fallbackUtils.test.ts +50 -0
- package/src/components/FileDisplay/fallbackUtils.ts +44 -0
- package/src/components/FileDisplay/fetchFileDisplayData.ts +24 -0
- package/src/components/FileDisplay/fetchFileDisplayData.unit.test.ts +183 -0
- package/src/components/FileDisplay/fileDisplayUtils.test.ts +58 -0
- package/src/components/FileDisplay/fileDisplayUtils.ts +24 -0
- package/src/{hooks/__tests__ → components/FileDisplay}/useFileDisplay.test.ts +40 -42
- package/src/components/FileDisplay/useFileDisplay.ts +515 -0
- package/src/{hooks/__tests__ → components/FileDisplay}/useFileDisplay.unit.test.ts +406 -77
- package/src/components/FileDisplay/useFileDisplayData.ts +126 -0
- package/src/{hooks/public → components/FileDisplay}/usePublicFileDisplay.test.ts +94 -88
- package/src/components/FileDisplay/usePublicFileDisplay.ts +579 -0
- package/src/components/FileUpload/FileUpload.test.tsx +16 -10
- package/src/components/FileUpload/FileUpload.tsx +107 -525
- package/src/components/FileUpload/FileUploadDropZone.tsx +112 -0
- package/src/components/FileUpload/FileUploadProgressItem.tsx +86 -0
- package/src/components/FileUpload/FileUploadProgressList.tsx +40 -0
- package/src/components/FileUpload/useFileUploadManager.test.ts +308 -0
- package/src/components/FileUpload/useFileUploadManager.ts +454 -0
- package/src/components/FileUpload/useResolvedAppId.test.ts +102 -0
- package/src/components/FileUpload/useResolvedAppId.ts +77 -0
- package/src/components/Footer/Footer.test.tsx +6 -292
- package/src/components/Footer/Footer.tsx +8 -125
- package/src/components/Form/Form.test.tsx +44 -27
- package/src/components/Form/Form.tsx +64 -287
- package/src/components/Form/useFormPersistence.ts +257 -0
- package/src/components/Header/Header.test.tsx +17 -18
- package/src/components/Header/Header.tsx +10 -1
- package/src/components/Input/Input.tsx +1 -1
- package/src/components/Label/Label.test.tsx +1 -1
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +1 -1
- package/src/components/NavigationMenu/HierarchicalNavItem.tsx +104 -0
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +1029 -26
- package/src/components/NavigationMenu/NavigationMenu.tsx +61 -361
- package/src/components/NavigationMenu/index.ts +6 -1
- package/src/components/NavigationMenu/navigationPermissionHelper.ts +188 -0
- package/src/components/NavigationMenu/{__tests__/useNavigationFiltering.test.ts → useNavigationFiltering.test.ts} +68 -53
- package/src/components/NavigationMenu/useNavigationFiltering.ts +197 -296
- package/src/components/NavigationMenu/useNavigationScope.ts +125 -0
- package/src/components/PaceAppLayout/PaceAppLayout.edge-cases.test.tsx +77 -62
- package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +3 -3
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +16 -19
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +529 -5
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +280 -756
- package/src/components/PaceAppLayout/useFilteredNavItems.ts +304 -0
- package/src/components/PaceAppLayout/usePaceAppLayoutConfig.ts +142 -0
- package/src/components/PaceAppLayout/usePaceAppLayoutGate.tsx +150 -0
- package/src/components/PaceAppLayout/usePaceAppLayoutPermissions.ts +162 -0
- package/src/components/PaceAppLayout/usePaceAppLayoutScope.ts +79 -0
- package/src/components/PaceAppLayout/useRoleBasedRouteAccess.ts +157 -0
- package/src/components/PaceAppLayout/useSuperAdminFallback.ts +58 -0
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +31 -25
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +31 -122
- package/src/components/PaceLoginPage/useLoginAppAccess.ts +153 -0
- package/src/components/Progress/Progress.tsx +1 -2
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +29 -235
- package/src/components/ProtectedRoute/useProtectedRouteState.ts +128 -0
- package/src/components/ProtectedRoute/useVisibilityRedirectGrace.ts +89 -0
- package/src/components/PublicLayout/PublicLayout.test.tsx +217 -36
- package/src/components/PublicLayout/PublicPageLayout.tsx +132 -73
- package/src/components/PublicLayout/PublicPageProvider.tsx +5 -1
- package/src/components/Select/Select.test.tsx +1 -1
- package/src/components/Select/Select.tsx +28 -18
- package/src/components/Select/{__tests__/context.test.tsx → context.test.tsx} +3 -3
- package/src/components/Select/{utils/__tests__/text.test.tsx → text.test.tsx} +2 -2
- package/src/components/Select/{utils/text.ts → text.ts} +1 -1
- package/src/components/Select/{hooks/__tests__/useSelectEvents.test.ts → useSelectEvents.test.ts} +5 -5
- package/src/components/Select/{hooks/useSelectEvents.ts → useSelectEvents.ts} +2 -2
- package/src/components/Select/{hooks/__tests__/useSelectSearch.test.tsx → useSelectSearch.test.tsx} +7 -7
- package/src/components/Select/{hooks/useSelectSearch.ts → useSelectSearch.ts} +2 -2
- package/src/components/Select/{hooks/__tests__/useSelectState.test.ts → useSelectState.test.ts} +16 -2
- package/src/components/Select/{hooks/useSelectState.ts → useSelectState.ts} +3 -3
- package/src/components/Table/Table.test.tsx +348 -0
- package/src/components/Tabs/Tabs.test.tsx +270 -0
- package/src/components/Tabs/Tabs.tsx +1 -1
- package/src/components/Toast/Toast.test.tsx +420 -0
- package/src/components/{__tests__/index.test.ts → index.test.ts} +2 -2
- package/src/constants/{__tests__/performance.test.ts → performance.test.ts} +2 -2
- package/src/hooks/{__tests__/ServiceHooks.test.tsx → ServiceHooks.test.tsx} +8 -8
- package/src/hooks/{__tests__/hooks.integration.test.tsx → hooks.integration.test.tsx} +11 -11
- package/src/hooks/index.ts +7 -4
- package/src/hooks/{__tests__/index.unit.test.ts → index.unit.test.ts} +2 -2
- package/src/hooks/public/usePublicEvent.test.ts +1 -1
- package/src/hooks/public/usePublicEventLogo.test.ts +1 -1
- package/src/hooks/public/usePublicRouteParams.test.ts +1 -1
- package/src/hooks/services/useAuth.ts +9 -7
- package/src/hooks/useAddressAutocomplete.test.ts +22 -22
- package/src/hooks/useAddressAutocomplete.ts +90 -75
- package/src/hooks/{__tests__/useAppConfig.unit.test.ts → useAppConfig.unit.test.ts} +328 -22
- package/src/hooks/{__tests__/useComponentPerformance.unit.test.tsx → useComponentPerformance.unit.test.tsx} +27 -41
- package/src/hooks/useDataTablePerformance.ts +100 -120
- package/src/hooks/{__tests__/useDataTablePerformance.unit.test.ts → useDataTablePerformance.unit.test.ts} +5 -5
- package/src/hooks/{__tests__/useDataTableState.test.ts → useDataTableState.test.ts} +2 -2
- package/src/hooks/{__tests__/useDebounce.unit.test.ts → useDebounce.unit.test.ts} +2 -2
- package/src/hooks/useEventTheme.test.ts +4 -1
- package/src/hooks/useEventTheme.ts +49 -21
- package/src/hooks/useEvents.ts +41 -1
- package/src/hooks/{__tests__/useEvents.unit.test.ts → useEvents.unit.test.ts} +5 -5
- package/src/hooks/useFileReference.test.ts +44 -41
- package/src/hooks/useFileReference.ts +182 -173
- package/src/hooks/useFileUrl.ts +1 -1
- package/src/hooks/{__tests__/useFileUrl.unit.test.ts → useFileUrl.unit.test.ts} +26 -36
- package/src/hooks/{__tests__/useFileUrlCache.test.ts → useFileUrlCache.test.ts} +8 -8
- package/src/hooks/useFileUrlCache.ts +1 -1
- package/src/hooks/{__tests__/useFocusManagement.unit.test.ts → useFocusManagement.unit.test.ts} +2 -2
- package/src/hooks/{__tests__/useFocusTrap.unit.test.tsx → useFocusTrap.unit.test.tsx} +2 -2
- package/src/hooks/{__tests__/useFormDialog.test.ts → useFormDialog.test.ts} +2 -2
- package/src/hooks/useInactivityTracker.ts +138 -131
- package/src/hooks/{__tests__/useInactivityTracker.unit.test.ts → useInactivityTracker.unit.test.ts} +3 -3
- package/src/hooks/{__tests__/useIsMobile.unit.test.ts → useIsMobile.unit.test.ts} +2 -2
- package/src/hooks/useIsPrint.ts +62 -0
- package/src/hooks/useIsPrint.unit.test.ts +545 -0
- package/src/hooks/{__tests__/useKeyboardShortcuts.unit.test.ts → useKeyboardShortcuts.unit.test.ts} +2 -2
- package/src/hooks/{__tests__/useOrganisationPermissions.unit.test.tsx → useOrganisationPermissions.unit.test.tsx} +4 -4
- package/src/hooks/useOrganisationSecurity.test.ts +3 -3
- package/src/hooks/useOrganisationSecurity.ts +190 -201
- package/src/hooks/{__tests__/useOrganisationSecurity.unit.test.tsx → useOrganisationSecurity.unit.test.tsx} +61 -63
- package/src/hooks/{__tests__/useOrganisations.unit.test.ts → useOrganisations.unit.test.ts} +5 -5
- package/src/hooks/{__tests__/usePerformanceMonitor.unit.test.ts → usePerformanceMonitor.unit.test.ts} +13 -14
- package/src/hooks/{__tests__/usePermissionCache.test.ts → usePermissionCache.test.ts} +26 -27
- package/src/hooks/usePermissionCache.ts +276 -271
- package/src/hooks/{__tests__/usePreventTabReload.test.ts → usePreventTabReload.test.ts} +2 -2
- package/src/hooks/{__tests__/usePublicEvent.simple.test.ts → usePublicEvent.simple.test.ts} +4 -4
- package/src/hooks/{__tests__/usePublicEvent.test.ts → usePublicEvent.test.ts} +4 -4
- package/src/hooks/{__tests__/usePublicEvent.unit.test.ts → usePublicEvent.unit.test.ts} +4 -4
- package/src/hooks/{__tests__/usePublicFileDisplay.test.ts → usePublicFileDisplay.test.ts} +12 -12
- package/src/hooks/{__tests__/usePublicRouteParams.unit.test.ts → usePublicRouteParams.unit.test.ts} +3 -3
- package/src/hooks/{__tests__/useQueryCache.test.ts → useQueryCache.test.ts} +2 -2
- package/src/hooks/useQueryCache.ts +0 -2
- package/src/hooks/{__tests__/useRBAC.unit.test.ts → useRBAC.unit.test.ts} +55 -38
- package/src/hooks/{__tests__/useSessionDraft.test.ts → useSessionDraft.test.ts} +2 -2
- package/src/hooks/{__tests__/useSessionRestoration.unit.test.tsx → useSessionRestoration.unit.test.tsx} +10 -19
- package/src/hooks/useStorage.ts +21 -16
- package/src/hooks/{__tests__/useStorage.unit.test.ts → useStorage.unit.test.ts} +38 -75
- package/src/hooks/{__tests__/useToast.test.ts → useToast.test.ts} +2 -2
- package/src/hooks/{__tests__/useToast.unit.test.tsx → useToast.unit.test.tsx} +2 -2
- package/src/hooks/{__tests__/useZodForm.unit.test.tsx → useZodForm.unit.test.tsx} +2 -2
- package/src/icons/{__tests__/index.test.ts → index.test.ts} +2 -2
- package/src/icons/index.ts +2 -0
- package/src/{__tests__/index.test.ts → index.test.ts} +3 -7
- package/src/index.ts +15 -7
- package/src/providers/{__tests__/AuthProvider.test.tsx → AuthProvider.test.tsx} +3 -3
- package/src/providers/{__tests__/EventProvider.test.tsx → EventProvider.test.tsx} +3 -3
- package/src/providers/InactivityProvider.test-helper.tsx +40 -0
- package/src/providers/{__tests__/InactivityProvider.test.tsx → InactivityProvider.test.tsx} +14 -21
- package/src/providers/{__tests__/ProviderLifecycle.test.tsx → ProviderLifecycle.test.tsx} +4 -4
- package/src/providers/{__tests__/UnifiedAuthProvider.test.tsx → UnifiedAuthProvider.test.tsx} +1 -1
- package/src/providers/{__tests__/index.test.ts → index.test.ts} +2 -2
- package/src/providers/services/{__tests__/AuthServiceProvider.integration.test.tsx → AuthServiceProvider.integration.test.tsx} +4 -4
- package/src/providers/services/{__tests__/AuthServiceProvider.test.tsx → AuthServiceProvider.test.tsx} +7 -7
- package/src/providers/services/{__tests__/EventServiceProvider.test.tsx → EventServiceProvider.test.tsx} +7 -7
- package/src/providers/services/{__tests__/InactivityServiceProvider.test.tsx → InactivityServiceProvider.test.tsx} +5 -5
- package/src/providers/services/{__tests__/OrganisationServiceProvider.test.tsx → OrganisationServiceProvider.test.tsx} +6 -6
- package/src/providers/services/UnifiedAuthContext.ts +30 -27
- package/src/providers/services/{__tests__/UnifiedAuthProvider.advanced.test.tsx → UnifiedAuthProvider.advanced.test.tsx} +8 -9
- package/src/providers/services/{__tests__/UnifiedAuthProvider.appId.test.tsx → UnifiedAuthProvider.appId.test.tsx} +25 -25
- package/src/providers/services/{__tests__/UnifiedAuthProvider.integration.test.tsx → UnifiedAuthProvider.integration.test.tsx} +14 -11
- package/src/providers/services/UnifiedAuthProvider.tsx +115 -360
- package/src/providers/services/{__tests__/contexts.test.tsx → contexts.test.tsx} +6 -6
- package/src/providers/services/{__tests__/useUnifiedAuth.test.tsx → useUnifiedAuth.test.tsx} +6 -6
- package/src/providers/services/useUnifiedAuthContextValue.ts +279 -0
- package/src/providers/useInactivity.test-helper.ts +27 -0
- package/src/rbac/{__tests__/adapters.comprehensive.test.tsx → adapters.comprehensive.test.tsx} +24 -24
- package/src/rbac/adapters.test.tsx +22 -22
- package/src/rbac/adapters.tsx +29 -29
- package/src/rbac/api.test.ts +973 -42
- package/src/rbac/api.ts +228 -253
- package/src/rbac/{__tests__/audit-batched.test.ts → audit-batched.test.ts} +6 -6
- package/src/rbac/audit.ts +4 -1
- package/src/rbac/{__tests__/auth-rbac-security.integration.test.tsx → auth-rbac-security.integration.test.tsx} +1 -1
- package/src/rbac/{__tests__/auth-rbac.e2e.test.tsx → auth-rbac.e2e.test.tsx} +27 -34
- package/src/rbac/cache-invalidation.test.ts +715 -0
- package/src/rbac/components/{__tests__/AccessDenied.test.tsx → AccessDenied.test.tsx} +3 -3
- package/src/rbac/components/{__tests__/NavigationGuard.test.tsx → NavigationGuard.test.tsx} +13 -11
- package/src/{__tests__/rbac/PagePermissionGuard.test.tsx → rbac/components/PagePermissionGuard.guard.test.tsx} +33 -19
- package/src/rbac/components/{__tests__/PagePermissionGuard.performance.test.tsx → PagePermissionGuard.performance.test.tsx} +30 -9
- package/src/rbac/components/{__tests__/PagePermissionGuard.race-condition.test.tsx → PagePermissionGuard.race-condition.test.tsx} +7 -7
- package/src/rbac/components/{__tests__/PagePermissionGuard.test.tsx → PagePermissionGuard.test.tsx} +10 -10
- package/src/rbac/components/PagePermissionGuard.tsx +177 -372
- package/src/rbac/components/{__tests__/PagePermissionGuard.verification.test.tsx → PagePermissionGuard.verification.test.tsx} +7 -7
- package/src/rbac/config.ts +58 -18
- package/src/rbac/{__tests__/engine.comprehensive.test.ts → engine.comprehensive.test.ts} +3 -3
- package/src/rbac/engine.test.ts +494 -0
- package/src/rbac/errors.ts +89 -55
- package/src/rbac/hooks/permissions/runPermissionCheck.ts +77 -0
- package/src/rbac/hooks/permissions/{__tests__/useAccessLevel.test.ts → useAccessLevel.test.ts} +40 -40
- package/src/rbac/hooks/permissions/useAccessLevel.ts +16 -6
- package/src/rbac/hooks/permissions/{__tests__/useCan.test.ts → useCan.test.ts} +41 -41
- package/src/rbac/hooks/permissions/useCan.ts +170 -252
- package/src/rbac/hooks/permissions/{__tests__/useMultiplePermissions.test.ts → useMultiplePermissions.test.ts} +49 -49
- package/src/rbac/hooks/permissions/useMultiplePermissions.ts +6 -2
- package/src/rbac/hooks/permissions/{__tests__/usePermissions.test.ts → usePermissions.test.ts} +10 -12
- package/src/rbac/hooks/permissions/usePermissions.ts +36 -65
- package/src/rbac/hooks/useCan.test.ts +42 -42
- package/src/rbac/hooks/usePageAccessLogging.ts +160 -0
- package/src/rbac/hooks/usePageGuardScope.ts +117 -0
- package/src/rbac/hooks/usePagePermissionCheck.ts +67 -0
- package/src/rbac/hooks/{__tests__/usePermissions.integration.test.ts → usePermissions.integration.test.ts} +9 -9
- package/src/{__tests__/hooks/usePermissions.test.ts → rbac/hooks/usePermissions.stability.test.ts} +18 -18
- package/src/rbac/hooks/usePermissions.test.ts +54 -54
- package/src/rbac/hooks/useRBAC.test.ts +313 -217
- package/src/rbac/hooks/useRBAC.ts +145 -81
- package/src/rbac/hooks/useResourcePermissions.test.ts +25 -25
- package/src/rbac/hooks/useResourcePermissions.ts +68 -134
- package/src/rbac/hooks/useResourcePermissionsSuperAdmin.ts +67 -0
- package/src/rbac/hooks/useRoleManagement.test.ts +27 -112
- package/src/rbac/hooks/useRoleManagement.ts +153 -585
- package/src/rbac/hooks/{__tests__/useSecureSupabase.test.ts → useSecureSupabase.test.ts} +17 -17
- package/src/rbac/hooks/useSecureSupabase.ts +10 -2
- package/src/rbac/hooks/useSuperAdminCheck.ts +80 -0
- package/src/rbac/{__tests__/performance.test.ts → performance.test.ts} +1 -1
- package/src/rbac/{__tests__/rbac-core.test.tsx → rbac-core.test.tsx} +3 -3
- package/src/rbac/{__tests__/rbac-engine-core-logic.test.ts → rbac-engine-core-logic.test.ts} +2 -2
- package/src/rbac/{__tests__/rbac-engine-simplified.test.ts → rbac-engine-simplified.test.ts} +3 -3
- package/src/rbac/{__tests__/rbac-functions.test.ts → rbac-functions.test.ts} +57 -0
- package/src/rbac/{__tests__/rbac-role-isolation.test.ts → rbac-role-isolation.test.ts} +2 -2
- package/src/rbac/request-deduplication.test.ts +14 -9
- package/src/rbac/request-deduplication.ts +5 -4
- package/src/rbac/{__tests__/scenarios.user-role.test.tsx → scenarios.user-role.test.tsx} +23 -23
- package/src/rbac/secureClient.test.ts +514 -83
- package/src/rbac/secureClient.ts +8 -2
- package/src/rbac/security.test.ts +323 -0
- package/src/rbac/types/roleManagement.ts +66 -0
- package/src/rbac/utils/{__tests__/clientSecurity.test.ts → clientSecurity.test.ts} +4 -4
- package/src/rbac/utils/{__tests__/contextValidator.test.ts → contextValidator.test.ts} +4 -4
- package/src/rbac/utils/contextValidator.ts +5 -1
- package/src/rbac/utils/{__tests__/deep-equal.test.ts → deep-equal.test.ts} +1 -1
- package/src/rbac/utils/{__tests__/eventContext.test.ts → eventContext.test.ts} +36 -21
- package/src/rbac/utils/eventContext.ts +37 -33
- package/src/rbac/utils/fetchPermissionMap.ts +13 -0
- package/src/rbac/utils/permissionMapHelpers.ts +34 -0
- package/src/rbac/utils/roleManagementRpc.ts +303 -0
- package/src/services/{__tests__/AuthService.edge-cases.test.ts → AuthService.edge-cases.test.ts} +19 -19
- package/src/services/{__tests__/AuthService.restoreSession.test.ts → AuthService.restoreSession.test.ts} +2 -2
- package/src/services/{__tests__/AuthService.test.ts → AuthService.test.ts} +89 -55
- package/src/services/AuthService.ts +184 -205
- package/src/services/{__tests__/BaseService.edge-cases.test.ts → BaseService.edge-cases.test.ts} +3 -3
- package/src/services/{__tests__/BaseService.test.ts → BaseService.test.ts} +2 -2
- package/src/services/{__tests__/EventService.edge-cases.test.ts → EventService.edge-cases.test.ts} +27 -24
- package/src/services/{__tests__/EventService.eventColours.test.ts → EventService.eventColours.test.ts} +1 -1
- package/src/services/{__tests__/EventService.test.ts → EventService.test.ts} +256 -24
- package/src/services/EventService.ts +242 -312
- package/src/services/{__tests__/InactivityService.edge-cases.test.ts → InactivityService.edge-cases.test.ts} +3 -3
- package/src/services/{__tests__/InactivityService.lifecycle.test.ts → InactivityService.lifecycle.test.ts} +2 -2
- package/src/services/{__tests__/InactivityService.test.ts → InactivityService.test.ts} +179 -4
- package/src/services/InactivityService.ts +172 -213
- package/src/services/{__tests__/OrganisationService.edge-cases.test.ts → OrganisationService.edge-cases.test.ts} +5 -5
- package/src/services/{__tests__/OrganisationService.pagination.test.ts → OrganisationService.pagination.test.ts} +4 -4
- package/src/services/{__tests__/OrganisationService.test.ts → OrganisationService.test.ts} +410 -7
- package/src/services/OrganisationService.ts +184 -238
- package/src/services/base/BaseService.test.ts +1 -1
- package/src/services/interfaces/{__tests__/IAuthService.test.ts → IAuthService.test.ts} +21 -27
- package/src/services/interfaces/IAuthService.ts +10 -9
- package/src/services/interfaces/{__tests__/IEventService.test.ts → IEventService.test.ts} +4 -4
- package/src/services/interfaces/{__tests__/IInactivityService.test.ts → IInactivityService.test.ts} +3 -3
- package/src/services/interfaces/{__tests__/IOrganisationService.test.ts → IOrganisationService.test.ts} +3 -3
- package/src/styles/core.css +243 -12
- package/src/theming/{__tests__/parseEventColours.test.ts → parseEventColours.test.ts} +1 -1
- package/src/theming/{__tests__/runtime.test.ts → runtime.test.ts} +8 -17
- package/src/theming/runtime.ts +71 -2
- package/src/types/api-result.ts +53 -0
- package/src/types/{__tests__/core.test.ts → core.test.ts} +2 -2
- package/src/types/{__tests__/database-generated.test.ts → database-generated.test.ts} +3 -3
- package/src/types/database.generated.ts +45 -10
- package/src/types/event.ts +38 -18
- package/src/types/{__tests__/file-reference.test.ts → file-reference.test.ts} +13 -13
- package/src/types/file-reference.ts +37 -12
- package/src/types/{__tests__/guards.test.ts → guards.test.ts} +2 -2
- package/src/types/{__tests__/index.test.ts → index.test.ts} +2 -2
- package/src/types/index.ts +3 -0
- package/src/types/{__tests__/organisation.roles.test.ts → organisation.roles.test.ts} +1 -1
- package/src/types/{__tests__/organisation.test.ts → organisation.test.ts} +3 -31
- package/src/types/organisation.ts +15 -15
- package/src/types/supabase.ts +13 -4
- package/src/types/{__tests__/theme.test.ts → theme.test.ts} +1 -1
- package/src/types/{__tests__/type-validation.test.ts → type-validation.test.ts} +1 -1
- package/src/types/{__tests__/validation.test.ts → validation.test.ts} +2 -2
- package/src/utils/app/appIdResolver.test.ts +98 -71
- package/src/utils/app/appIdResolver.ts +31 -20
- package/src/utils/{__tests__/appConfig.unit.test.ts → appConfig.unit.test.ts} +1 -1
- package/src/utils/{__tests__/audit.unit.test.ts → audit.unit.test.ts} +1 -1
- package/src/utils/{__tests__/auth-utils.unit.test.ts → auth-utils.unit.test.ts} +16 -17
- package/src/utils/{__tests__/bundleAnalysis.unit.test.ts → bundleAnalysis.unit.test.ts} +35 -35
- package/src/utils/{__tests__/cn.unit.test.ts → cn.unit.test.ts} +1 -1
- package/src/utils/context/organisationContext.test.ts +105 -91
- package/src/utils/context/organisationContext.ts +29 -40
- package/src/utils/core/{__tests__/cn.test.ts → cn.test.ts} +3 -3
- package/src/utils/core/{__tests__/debugLogger.test.ts → debugLogger.test.ts} +2 -2
- package/src/utils/core/{__tests__/logger.test.ts → logger.test.ts} +2 -2
- package/src/utils/core/mergeRefs.ts +24 -0
- package/src/utils/{__tests__/debugLogger.test.ts → debugLogger.test.ts} +1 -1
- package/src/utils/{__tests__/deviceFingerprint.unit.test.ts → deviceFingerprint.unit.test.ts} +1 -1
- package/src/utils/dynamic/createLazyComponent.tsx +9 -1
- package/src/utils/dynamic/{__tests__/dynamicUtils.test.ts → dynamicUtils.test.ts} +2 -2
- package/src/utils/dynamic/{__tests__/lazyLoad.test.tsx → lazyLoad.test.tsx} +2 -2
- package/src/utils/{__tests__/dynamicUtils.unit.test.ts → dynamicUtils.unit.test.ts} +1 -1
- package/src/utils/file-reference/{__tests__/file-reference.test.ts → file-reference.test.ts} +214 -289
- package/src/utils/file-reference/index.ts +330 -347
- package/src/utils/{__tests__/formatDate.unit.test.ts → formatDate.unit.test.ts} +2 -2
- package/src/utils/formatting/formatDateTimeTimezone.test.ts +1 -1
- package/src/utils/formatting/formatNumber.test.ts +1 -1
- package/src/utils/{__tests__/formatting.unit.test.ts → formatting.unit.test.ts} +1 -1
- package/src/utils/google-places/googlePlacesUtils.test.ts +70 -48
- package/src/utils/google-places/googlePlacesUtils.ts +67 -99
- package/src/utils/google-places/loadGoogleMapsScript.test.ts +25 -22
- package/src/utils/google-places/loadGoogleMapsScript.ts +138 -117
- package/src/utils/{__tests__/index.unit.test.ts → index.unit.test.ts} +1 -1
- package/src/utils/{__tests__/lazyLoad.unit.test.tsx → lazyLoad.unit.test.tsx} +13 -14
- package/src/utils/location/location.test.ts +1 -1
- package/src/utils/{__tests__/logger.unit.test.ts → logger.unit.test.ts} +1 -1
- package/src/utils/{__tests__/organisationContext.unit.test.ts → organisationContext.unit.test.ts} +37 -48
- package/src/utils/performance/{__tests__/bundleAnalysis.test.ts → bundleAnalysis.test.ts} +2 -2
- package/src/utils/performance/{__tests__/performanceBenchmark.test.ts → performanceBenchmark.test.ts} +2 -2
- package/src/utils/performance/{__tests__/performanceBudgets.test.ts → performanceBudgets.test.ts} +2 -2
- package/src/utils/{__tests__/performanceBenchmark.test.ts → performanceBenchmark.test.ts} +2 -2
- package/src/utils/{__tests__/performanceBudgets.unit.test.ts → performanceBudgets.unit.test.ts} +2 -2
- package/src/utils/{__tests__/permissionTypes.unit.test.ts → permissionTypes.unit.test.ts} +1 -1
- package/src/utils/{__tests__/permissionUtils.unit.test.ts → permissionUtils.unit.test.ts} +1 -1
- package/src/utils/permissions/{__tests__/permissionTypes.test.ts → permissionTypes.test.ts} +2 -2
- package/src/utils/persistence/{__tests__/keyDerivation.test.ts → keyDerivation.test.ts} +2 -2
- package/src/utils/persistence/{__tests__/sensitiveFieldDetection.test.ts → sensitiveFieldDetection.test.ts} +2 -2
- package/src/utils/{__tests__/request-deduplication.test.ts → request-deduplication.test.ts} +2 -2
- package/src/utils/{__tests__/sanitization.unit.test.ts → sanitization.unit.test.ts} +1 -1
- package/src/utils/{__tests__/schemaUtils.unit.test.ts → schemaUtils.unit.test.ts} +1 -1
- package/src/utils/{__tests__/secureDataAccess.unit.test.ts → secureDataAccess.unit.test.ts} +2 -2
- package/src/utils/{__tests__/secureErrors.unit.test.ts → secureErrors.unit.test.ts} +4 -4
- package/src/utils/{__tests__/secureStorage.unit.test.ts → secureStorage.unit.test.ts} +1 -1
- package/src/utils/security/auth-utils.ts +34 -23
- package/src/utils/security/secureDataAccess.ts +241 -281
- package/src/utils/security/secureErrors.test.ts +1 -1
- package/src/utils/security/secureStorage.test.ts +1 -1
- package/src/utils/security/security.test.ts +25 -17
- package/src/utils/security/security.ts +15 -18
- package/src/utils/security/securityMonitor.test.ts +1 -1
- package/src/utils/{__tests__/security.unit.test.ts → security.unit.test.ts} +21 -15
- package/src/utils/{__tests__/securityMonitor.unit.test.ts → securityMonitor.unit.test.ts} +1 -1
- package/src/utils/{__tests__/sessionTracking.unit.test.ts → sessionTracking.unit.test.ts} +12 -12
- package/src/utils/storage/{__tests__/config.unit.test.ts → config.unit.test.ts} +2 -2
- package/src/utils/storage/helpers.test.ts +88 -102
- package/src/utils/storage/helpers.ts +173 -251
- package/src/utils/storage/{__tests__/index.unit.test.ts → index.unit.test.ts} +3 -3
- package/src/utils/storage/types.ts +7 -0
- package/src/utils/supabase/createBaseClient.test.ts +1 -1
- package/src/utils/timezone/timezone.test.ts +1 -1
- package/src/utils/{__tests__/timezone.test.ts → timezone.test.ts} +2 -2
- package/src/utils/validation/{__tests__/common.test.ts → common.test.ts} +2 -2
- package/src/utils/validation/{__tests__/csrf.test.ts → csrf.test.ts} +56 -28
- package/src/utils/validation/csrf.ts +42 -41
- package/src/utils/validation/{__tests__/htmlSanitization.unit.test.ts → htmlSanitization.unit.test.ts} +2 -2
- package/src/utils/validation/{__tests__/passwordSchema.test.ts → passwordSchema.test.ts} +2 -2
- package/src/utils/validation/{__tests__/schema.test.ts → schema.test.ts} +2 -2
- package/src/utils/validation/{__tests__/sqlInjectionProtection.test.ts → sqlInjectionProtection.test.ts} +2 -2
- package/src/utils/validation/{__tests__/user.test.ts → user.test.ts} +2 -2
- package/src/utils/validation/{__tests__/validation.test.ts → validation.test.ts} +2 -2
- package/src/utils/validation/{__tests__/validationUtils.test.ts → validationUtils.test.ts} +2 -2
- package/src/utils/{__tests__/validation.unit.test.ts → validation.unit.test.ts} +1 -1
- package/src/utils/{__tests__/validationUtils.unit.test.ts → validationUtils.unit.test.ts} +5 -2
- package/dist/UnifiedAuthProvider-BBD2PS3Q.js +0 -7
- package/dist/chunk-KPYQWGFQ.js +0 -183
- package/dist/types-D05dCGma.d.ts +0 -521
- package/scripts/eslint-audit.cjs +0 -222
- package/scripts/generate-docs.js +0 -157
- package/scripts/install-cursor-rules.cjs +0 -255
- package/scripts/install-eslint-config.cjs +0 -349
- package/scripts/setup-build-cache.js +0 -73
- package/scripts/validate-pre-publish.js +0 -145
- package/src/__tests__/integration/UserProfile.test.tsx +0 -124
- package/src/__tests__/public-recipe-view.test.ts +0 -228
- package/src/__tests__/rls-policies.test.ts +0 -472
- package/src/components/DataTable/__tests__/DataTable.test.tsx +0 -876
- package/src/components/DataTable/components/DataTableLayout.tsx +0 -584
- package/src/components/DataTable/components/UnifiedTableBody.tsx +0 -395
- package/src/components/DataTable/components/__tests__/DataTableLayout.test.tsx +0 -467
- package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +0 -358
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +0 -957
- package/src/components/DataTable/core/ActionManager.ts +0 -235
- package/src/components/DataTable/core/ColumnManager.ts +0 -204
- package/src/components/DataTable/core/DataManager.ts +0 -190
- package/src/components/DataTable/core/LocalDataAdapter.ts +0 -274
- package/src/components/DataTable/core/PluginRegistry.ts +0 -229
- package/src/components/DataTable/core/StateManager.ts +0 -312
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +0 -235
- package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +0 -141
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +0 -178
- package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +0 -133
- package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +0 -142
- package/src/components/DataTable/core/__tests__/StateManager.test.ts +0 -158
- package/src/components/DataTable/core/interfaces.ts +0 -338
- package/src/components/DataTable/types.ts +0 -764
- package/src/hooks/public/usePublicFileDisplay.ts +0 -534
- package/src/hooks/useFileDisplay.ts +0 -748
- package/src/providers/OrganisationProvider.test.tsx +0 -40
- package/src/providers/OrganisationProvider.tsx +0 -92
- package/src/providers/__tests__/InactivityProvider.test-helper.tsx +0 -65
- package/src/providers/__tests__/OrganisationProvider.test.tsx +0 -616
- package/src/providers/__tests__/OrganisationProvider.wrapper.test.tsx +0 -591
- package/src/rbac/__tests__/cache-invalidation.test.ts +0 -393
- /package/src/components/DataTable/{components/__tests__ → ui}/COVERAGE_NOTE.md +0 -0
- /package/src/components/DataTable/utils/{__tests__/COVERAGE_NOTE.md → COVERAGE_NOTE.md} +0 -0
- /package/src/hooks/{__tests__/useApiFetch.unit.test.ts → useApiFetch.unit.test.ts} +0 -0
- /package/src/providers/{__tests__/README.md → README.md} +0 -0
- /package/src/rbac/{__tests__/index.test.ts → index.test.ts} +0 -0
- /package/src/rbac/{__tests__/rbac-integration.test.ts → rbac-integration.test.ts} +0 -0
- /package/src/types/{__tests__/README.md → README.md} +0 -0
package/src/rbac/api.ts
CHANGED
|
@@ -30,9 +30,21 @@ import { createLogger } from '../utils/core/logger';
|
|
|
30
30
|
import { enablePerformanceMonitoring } from './performance';
|
|
31
31
|
import { getOrCreateRequest } from './request-deduplication';
|
|
32
32
|
import { ContextValidator } from './utils/contextValidator';
|
|
33
|
+
import { ok, err, type ApiResult, type ApiError } from '../types/api-result';
|
|
33
34
|
|
|
34
35
|
const log = createLogger('RBACAPI');
|
|
35
36
|
|
|
37
|
+
function toApiError(error: unknown): ApiError {
|
|
38
|
+
if (error instanceof RBACNotInitializedError) {
|
|
39
|
+
return { code: 'RBAC_NOT_INITIALIZED', message: error.message };
|
|
40
|
+
}
|
|
41
|
+
if (error instanceof OrganisationContextRequiredError) {
|
|
42
|
+
return { code: 'ORGANISATION_CONTEXT_REQUIRED', message: error.message };
|
|
43
|
+
}
|
|
44
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
45
|
+
return { code: 'RBAC_ERROR', message };
|
|
46
|
+
}
|
|
47
|
+
|
|
36
48
|
// Global engine instance
|
|
37
49
|
let globalEngine: RBACEngine | null = null;
|
|
38
50
|
|
|
@@ -134,14 +146,14 @@ export async function getAccessLevel(
|
|
|
134
146
|
scope: Scope;
|
|
135
147
|
},
|
|
136
148
|
appName?: string
|
|
137
|
-
): Promise<AccessLevel
|
|
149
|
+
): Promise<ApiResult<AccessLevel>> {
|
|
138
150
|
try {
|
|
139
151
|
const engine = getEngine();
|
|
140
152
|
|
|
141
153
|
// Check super admin status first - super admins bypass context requirements
|
|
142
154
|
const isSuperAdminUser = await engine['checkSuperAdmin'](input.userId);
|
|
143
155
|
if (isSuperAdminUser) {
|
|
144
|
-
return 'super';
|
|
156
|
+
return ok('super');
|
|
145
157
|
}
|
|
146
158
|
|
|
147
159
|
// For functions without pageId, default to organisation scope validation
|
|
@@ -158,13 +170,13 @@ export async function getAccessLevel(
|
|
|
158
170
|
}
|
|
159
171
|
|
|
160
172
|
// Use resolved scope
|
|
161
|
-
|
|
173
|
+
const accessLevel = await engine.getAccessLevel({
|
|
162
174
|
...input,
|
|
163
175
|
scope: validation.resolvedScope
|
|
164
176
|
});
|
|
177
|
+
return ok(accessLevel);
|
|
165
178
|
} catch (error) {
|
|
166
|
-
|
|
167
|
-
throw error;
|
|
179
|
+
return err(toApiError(error));
|
|
168
180
|
}
|
|
169
181
|
}
|
|
170
182
|
|
|
@@ -194,7 +206,7 @@ export async function getPermissionMap(
|
|
|
194
206
|
scope: Scope;
|
|
195
207
|
},
|
|
196
208
|
appName?: string
|
|
197
|
-
): Promise<PermissionMap
|
|
209
|
+
): Promise<ApiResult<PermissionMap>> {
|
|
198
210
|
try {
|
|
199
211
|
const engine = getEngine();
|
|
200
212
|
|
|
@@ -212,26 +224,26 @@ export async function getPermissionMap(
|
|
|
212
224
|
}
|
|
213
225
|
|
|
214
226
|
// Use resolved scope
|
|
215
|
-
|
|
227
|
+
const permissionMap = await engine.getPermissionMap({
|
|
216
228
|
...input,
|
|
217
229
|
scope: validation.resolvedScope
|
|
218
230
|
});
|
|
231
|
+
return ok(permissionMap);
|
|
219
232
|
} catch (error) {
|
|
220
|
-
|
|
221
|
-
throw error;
|
|
233
|
+
return err(toApiError(error));
|
|
222
234
|
}
|
|
223
235
|
}
|
|
224
236
|
|
|
225
237
|
export async function resolveAppContext(input: {
|
|
226
238
|
userId: UUID;
|
|
227
239
|
appName: string;
|
|
228
|
-
}): Promise<RBACAppContext | null
|
|
240
|
+
}): Promise<ApiResult<RBACAppContext | null>> {
|
|
229
241
|
try {
|
|
230
242
|
const engine = getEngine();
|
|
231
|
-
|
|
243
|
+
const context = await engine.resolveAppContext(input);
|
|
244
|
+
return ok(context);
|
|
232
245
|
} catch (error) {
|
|
233
|
-
|
|
234
|
-
throw error;
|
|
246
|
+
return err(toApiError(error));
|
|
235
247
|
}
|
|
236
248
|
}
|
|
237
249
|
|
|
@@ -241,26 +253,31 @@ export async function getRoleContext(
|
|
|
241
253
|
scope: Scope;
|
|
242
254
|
},
|
|
243
255
|
appName?: string
|
|
244
|
-
): Promise<RBACRoleContext
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
256
|
+
): Promise<ApiResult<RBACRoleContext>> {
|
|
257
|
+
try {
|
|
258
|
+
const engine = getEngine();
|
|
259
|
+
|
|
260
|
+
// For functions without pageId, default to organisation scope validation
|
|
261
|
+
const validation = await ContextValidator.resolveScopeForPage(
|
|
262
|
+
input.scope,
|
|
263
|
+
'organisation', // Default to organisation scope when no page context
|
|
264
|
+
appName,
|
|
265
|
+
engine['supabase']
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
if (!validation.isValid || !validation.resolvedScope) {
|
|
269
|
+
throw validation.error || new OrganisationContextRequiredError();
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Use resolved scope
|
|
273
|
+
const roleContext = await engine.getRoleContext({
|
|
274
|
+
...input,
|
|
275
|
+
scope: validation.resolvedScope
|
|
276
|
+
});
|
|
277
|
+
return ok(roleContext);
|
|
278
|
+
} catch (error) {
|
|
279
|
+
return err(toApiError(error));
|
|
257
280
|
}
|
|
258
|
-
|
|
259
|
-
// Use resolved scope
|
|
260
|
-
return engine.getRoleContext({
|
|
261
|
-
...input,
|
|
262
|
-
scope: validation.resolvedScope
|
|
263
|
-
});
|
|
264
281
|
}
|
|
265
282
|
|
|
266
283
|
/**
|
|
@@ -291,154 +308,148 @@ export async function isPermitted(
|
|
|
291
308
|
* @default null
|
|
292
309
|
*/
|
|
293
310
|
precomputedSuperAdmin: boolean | null = null
|
|
294
|
-
): Promise<boolean
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
// If null, check super admin status
|
|
305
|
-
if (precomputedSuperAdmin === null) {
|
|
306
|
-
const isSuperAdminUser = await engine['checkSuperAdmin'](input.userId);
|
|
307
|
-
if (isSuperAdminUser) {
|
|
308
|
-
return true;
|
|
311
|
+
): Promise<ApiResult<boolean>> {
|
|
312
|
+
try {
|
|
313
|
+
const engine = getEngine();
|
|
314
|
+
|
|
315
|
+
// Check super admin status first - super admins bypass context requirements
|
|
316
|
+
// Super admins have access to all permissions regardless of organisation context
|
|
317
|
+
// PERFORMANCE: Use precomputed value if provided to avoid duplicate checks
|
|
318
|
+
if (precomputedSuperAdmin === true) {
|
|
319
|
+
return ok(true);
|
|
309
320
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
try {
|
|
317
|
-
const { data } = await engine['supabase']
|
|
318
|
-
.from('rbac_apps')
|
|
319
|
-
.select('name')
|
|
320
|
-
.eq('id', input.scope.appId)
|
|
321
|
-
.eq('is_active', true)
|
|
322
|
-
.single() as { data: { name: string } | null };
|
|
323
|
-
if (data) {
|
|
324
|
-
resolvedAppName = data.name;
|
|
321
|
+
|
|
322
|
+
// If null, check super admin status
|
|
323
|
+
if (precomputedSuperAdmin === null) {
|
|
324
|
+
const isSuperAdminUser = await engine['checkSuperAdmin'](input.userId);
|
|
325
|
+
if (isSuperAdminUser) {
|
|
326
|
+
return ok(true);
|
|
325
327
|
}
|
|
326
|
-
} catch (_err) {
|
|
327
|
-
// Ignore errors - appName is optional
|
|
328
328
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
329
|
+
// If precomputedSuperAdmin === false, skip check and proceed with permission check
|
|
330
|
+
|
|
331
|
+
// Get app name if not provided (for PORTAL/ADMIN special case)
|
|
332
|
+
let resolvedAppName = appName;
|
|
333
|
+
if (!resolvedAppName && input.scope.appId) {
|
|
334
|
+
try {
|
|
335
|
+
const { data } = await engine['supabase']
|
|
336
|
+
.from('rbac_apps')
|
|
337
|
+
.select('name')
|
|
338
|
+
.eq('id', input.scope.appId)
|
|
339
|
+
.eq('is_active', true)
|
|
340
|
+
.single() as { data: { name: string } | null };
|
|
341
|
+
if (data) {
|
|
342
|
+
resolvedAppName = data.name;
|
|
343
|
+
}
|
|
344
|
+
} catch (_err) {
|
|
345
|
+
// Ignore errors - appName is optional
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Get page scope type (required for all permission checks)
|
|
350
|
+
// All pages must have scope_type set - this is the single source of truth
|
|
351
|
+
let pageScopeType: 'event' | 'organisation' | 'both';
|
|
352
|
+
if (input.pageId) {
|
|
353
|
+
const scopeResult = await getPageScopeType(
|
|
337
354
|
input.pageId,
|
|
338
355
|
input.scope.appId,
|
|
339
356
|
resolvedAppName
|
|
340
357
|
);
|
|
341
|
-
if (!
|
|
342
|
-
|
|
358
|
+
if (!scopeResult.ok) {
|
|
359
|
+
log.error('Failed to get page scope type:', scopeResult.error);
|
|
360
|
+
return err(scopeResult.error);
|
|
343
361
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
362
|
+
if (!scopeResult.data) {
|
|
363
|
+
return err({ code: 'PAGE_SCOPE_TYPE_MISSING', message: `Page ${input.pageId} does not have scope_type set` });
|
|
364
|
+
}
|
|
365
|
+
pageScopeType = scopeResult.data;
|
|
366
|
+
} else {
|
|
367
|
+
// No pageId provided - default to organisation scope
|
|
368
|
+
// This should rarely happen, but provides a safe fallback
|
|
369
|
+
pageScopeType = 'organisation';
|
|
348
370
|
}
|
|
349
|
-
} else {
|
|
350
|
-
// No pageId provided - default to organisation scope
|
|
351
|
-
// This should rarely happen, but provides a safe fallback
|
|
352
|
-
pageScopeType = 'organisation';
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
// Validate context using page-level scope (single source of truth)
|
|
356
|
-
const validation = await ContextValidator.resolveScopeForPage(
|
|
357
|
-
input.scope,
|
|
358
|
-
pageScopeType,
|
|
359
|
-
resolvedAppName,
|
|
360
|
-
engine['supabase']
|
|
361
|
-
);
|
|
362
|
-
|
|
363
|
-
if (!validation.isValid || !validation.resolvedScope) {
|
|
364
|
-
throw validation.error || new OrganisationContextRequiredError();
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// Use resolved scope for permission check
|
|
368
|
-
const validatedScope = validation.resolvedScope;
|
|
369
|
-
|
|
370
|
-
// Handle 'both' scope pages - check both scopes and return union
|
|
371
|
-
if (pageScopeType === 'both' && input.pageId) {
|
|
372
|
-
// Check permission with event scope
|
|
373
|
-
const eventScope: Scope = {
|
|
374
|
-
organisationId: validatedScope.organisationId, // Org derived from event
|
|
375
|
-
eventId: validatedScope.eventId,
|
|
376
|
-
appId: validatedScope.appId
|
|
377
|
-
};
|
|
378
|
-
|
|
379
|
-
// Check permission with organisation scope (if org is available separately)
|
|
380
|
-
// For 'both' pages, we check the permission in both contexts and return the union
|
|
381
|
-
// Higher permission wins (true > false, admin > user, etc.)
|
|
382
371
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
372
|
+
// Validate context using page-level scope (single source of truth)
|
|
373
|
+
const validation = await ContextValidator.resolveScopeForPage(
|
|
374
|
+
input.scope,
|
|
375
|
+
pageScopeType,
|
|
376
|
+
resolvedAppName,
|
|
377
|
+
engine['supabase']
|
|
378
|
+
);
|
|
388
379
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
};
|
|
380
|
+
if (!validation.isValid || !validation.resolvedScope) {
|
|
381
|
+
throw validation.error || new OrganisationContextRequiredError();
|
|
382
|
+
}
|
|
393
383
|
|
|
394
|
-
|
|
384
|
+
// Use resolved scope for permission check
|
|
385
|
+
const validatedScope = validation.resolvedScope;
|
|
395
386
|
|
|
396
|
-
//
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
const
|
|
400
|
-
organisationId: validatedScope.organisationId,
|
|
401
|
-
eventId:
|
|
387
|
+
// Handle 'both' scope pages - check both scopes and return union
|
|
388
|
+
if (pageScopeType === 'both' && input.pageId) {
|
|
389
|
+
// Check permission with event scope
|
|
390
|
+
const eventScope: Scope = {
|
|
391
|
+
organisationId: validatedScope.organisationId, // Org derived from event
|
|
392
|
+
eventId: validatedScope.eventId,
|
|
402
393
|
appId: validatedScope.appId
|
|
403
394
|
};
|
|
404
395
|
|
|
405
|
-
const
|
|
396
|
+
const eventSecurityContext: SecurityContext = {
|
|
406
397
|
userId: input.userId,
|
|
407
|
-
organisationId:
|
|
398
|
+
organisationId: eventScope.organisationId || null,
|
|
408
399
|
timestamp: new Date(),
|
|
409
400
|
};
|
|
410
401
|
|
|
411
|
-
const
|
|
402
|
+
const eventInput: PermissionCheck = {
|
|
412
403
|
...input,
|
|
413
|
-
scope:
|
|
404
|
+
scope: eventScope
|
|
414
405
|
};
|
|
415
406
|
|
|
416
|
-
const
|
|
407
|
+
const hasEventPermission = await engine.isPermitted(eventInput, eventSecurityContext);
|
|
417
408
|
|
|
418
|
-
//
|
|
419
|
-
|
|
420
|
-
|
|
409
|
+
// Also check with organisation scope if we have a separate org context
|
|
410
|
+
if (validatedScope.organisationId && validatedScope.eventId) {
|
|
411
|
+
const orgScope: Scope = {
|
|
412
|
+
organisationId: validatedScope.organisationId,
|
|
413
|
+
eventId: undefined, // Clear event for org-only check
|
|
414
|
+
appId: validatedScope.appId
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
const orgSecurityContext: SecurityContext = {
|
|
418
|
+
userId: input.userId,
|
|
419
|
+
organisationId: orgScope.organisationId || null,
|
|
420
|
+
timestamp: new Date(),
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
const orgInput: PermissionCheck = {
|
|
424
|
+
...input,
|
|
425
|
+
scope: orgScope
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
const hasOrgPermission = await engine.isPermitted(orgInput, orgSecurityContext);
|
|
429
|
+
|
|
430
|
+
return ok(hasEventPermission || hasOrgPermission);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
return ok(hasEventPermission);
|
|
421
434
|
}
|
|
422
435
|
|
|
423
|
-
//
|
|
424
|
-
|
|
436
|
+
// Standard permission check for single-scope pages
|
|
437
|
+
const securityContext: SecurityContext = {
|
|
438
|
+
userId: input.userId,
|
|
439
|
+
organisationId: validatedScope.organisationId || null,
|
|
440
|
+
timestamp: new Date(),
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
const validatedInput: PermissionCheck = {
|
|
444
|
+
...input,
|
|
445
|
+
scope: validatedScope
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
const permitted = await engine.isPermitted(validatedInput, securityContext);
|
|
449
|
+
return ok(permitted);
|
|
450
|
+
} catch (error) {
|
|
451
|
+
return err(toApiError(error));
|
|
425
452
|
}
|
|
426
|
-
|
|
427
|
-
// Standard permission check for single-scope pages
|
|
428
|
-
const securityContext: SecurityContext = {
|
|
429
|
-
userId: input.userId,
|
|
430
|
-
organisationId: validatedScope.organisationId || null,
|
|
431
|
-
timestamp: new Date(),
|
|
432
|
-
// Optional fields can be omitted
|
|
433
|
-
};
|
|
434
|
-
|
|
435
|
-
// Create new input with validated scope
|
|
436
|
-
const validatedInput: PermissionCheck = {
|
|
437
|
-
...input,
|
|
438
|
-
scope: validatedScope
|
|
439
|
-
};
|
|
440
|
-
|
|
441
|
-
return engine.isPermitted(validatedInput, securityContext);
|
|
442
453
|
}
|
|
443
454
|
|
|
444
455
|
/**
|
|
@@ -454,7 +465,7 @@ export async function isPermitted(
|
|
|
454
465
|
export async function isPermittedCached(
|
|
455
466
|
input: PermissionCheck,
|
|
456
467
|
appName?: string
|
|
457
|
-
): Promise<boolean
|
|
468
|
+
): Promise<ApiResult<boolean>> {
|
|
458
469
|
const { userId, scope, permission, pageId } = input;
|
|
459
470
|
|
|
460
471
|
// Check cache first (checks both short-term and session cache)
|
|
@@ -469,23 +480,20 @@ export async function isPermittedCached(
|
|
|
469
480
|
|
|
470
481
|
const cached = rbacCache.get<boolean>(cacheKey, true);
|
|
471
482
|
if (cached !== null) {
|
|
472
|
-
return cached;
|
|
483
|
+
return ok(cached);
|
|
473
484
|
}
|
|
474
485
|
|
|
475
486
|
// Use request deduplication - if same request is in-flight, share the promise
|
|
476
487
|
return getOrCreateRequest(input, async (checkInput) => {
|
|
477
|
-
// Check permission with context validation
|
|
478
|
-
// Note: We can't pass precomputedSuperAdmin here because getOrCreateRequest doesn't support it
|
|
479
|
-
// The super admin check in isPermitted will be cached, so it's not a huge performance hit
|
|
480
488
|
const result = await isPermitted(checkInput, appName, null);
|
|
481
|
-
|
|
489
|
+
if (!result.ok) {
|
|
490
|
+
return result;
|
|
491
|
+
}
|
|
482
492
|
// Determine if this is a page-level check (has pageId or permission contains 'page.')
|
|
483
493
|
const isPageLevelCheck = !!pageId || permission.includes('page.');
|
|
484
|
-
|
|
485
494
|
// Cache result - use session cache for page-level checks
|
|
486
|
-
rbacCache.set(cacheKey, result, undefined, isPageLevelCheck);
|
|
487
|
-
|
|
488
|
-
return result;
|
|
495
|
+
rbacCache.set(cacheKey, result.data, undefined, isPageLevelCheck);
|
|
496
|
+
return ok(result.data);
|
|
489
497
|
});
|
|
490
498
|
}
|
|
491
499
|
|
|
@@ -500,21 +508,23 @@ export async function hasAnyPermission(input: {
|
|
|
500
508
|
scope: Scope;
|
|
501
509
|
permissions: Permission[];
|
|
502
510
|
pageId?: UUID;
|
|
503
|
-
}): Promise<boolean
|
|
511
|
+
}): Promise<ApiResult<boolean>> {
|
|
504
512
|
const { permissions, ...baseInput } = input;
|
|
505
513
|
|
|
506
514
|
for (const permission of permissions) {
|
|
507
|
-
const
|
|
515
|
+
const result = await isPermitted({
|
|
508
516
|
...baseInput,
|
|
509
517
|
permission,
|
|
510
518
|
});
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
519
|
+
if (!result.ok) {
|
|
520
|
+
return result;
|
|
521
|
+
}
|
|
522
|
+
if (result.data) {
|
|
523
|
+
return ok(true);
|
|
514
524
|
}
|
|
515
525
|
}
|
|
516
526
|
|
|
517
|
-
return false;
|
|
527
|
+
return ok(false);
|
|
518
528
|
}
|
|
519
529
|
|
|
520
530
|
/**
|
|
@@ -528,21 +538,23 @@ export async function hasAllPermissions(input: {
|
|
|
528
538
|
scope: Scope;
|
|
529
539
|
permissions: Permission[];
|
|
530
540
|
pageId?: UUID;
|
|
531
|
-
}): Promise<boolean
|
|
541
|
+
}): Promise<ApiResult<boolean>> {
|
|
532
542
|
const { permissions, ...baseInput } = input;
|
|
533
543
|
|
|
534
544
|
for (const permission of permissions) {
|
|
535
|
-
const
|
|
545
|
+
const result = await isPermitted({
|
|
536
546
|
...baseInput,
|
|
537
547
|
permission,
|
|
538
548
|
});
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
549
|
+
if (!result.ok) {
|
|
550
|
+
return result;
|
|
551
|
+
}
|
|
552
|
+
if (!result.data) {
|
|
553
|
+
return ok(false);
|
|
542
554
|
}
|
|
543
555
|
}
|
|
544
556
|
|
|
545
|
-
return true;
|
|
557
|
+
return ok(true);
|
|
546
558
|
}
|
|
547
559
|
|
|
548
560
|
/**
|
|
@@ -551,9 +563,14 @@ export async function hasAllPermissions(input: {
|
|
|
551
563
|
* @param userId - User ID
|
|
552
564
|
* @returns Promise resolving to super admin status
|
|
553
565
|
*/
|
|
554
|
-
export async function isSuperAdmin(userId: UUID): Promise<boolean
|
|
555
|
-
|
|
556
|
-
|
|
566
|
+
export async function isSuperAdmin(userId: UUID): Promise<ApiResult<boolean>> {
|
|
567
|
+
try {
|
|
568
|
+
const engine = getEngine();
|
|
569
|
+
const value = await engine['checkSuperAdmin'](userId);
|
|
570
|
+
return ok(value);
|
|
571
|
+
} catch (error) {
|
|
572
|
+
return err(toApiError(error));
|
|
573
|
+
}
|
|
557
574
|
}
|
|
558
575
|
|
|
559
576
|
|
|
@@ -572,14 +589,13 @@ export async function getPageScopeType(
|
|
|
572
589
|
pageId: UUID | string,
|
|
573
590
|
appId?: UUID,
|
|
574
591
|
appName?: string
|
|
575
|
-
): Promise<'event' | 'organisation' | 'both'
|
|
576
|
-
const engine = getEngine();
|
|
577
|
-
|
|
592
|
+
): Promise<ApiResult<'event' | 'organisation' | 'both'>> {
|
|
578
593
|
try {
|
|
594
|
+
const engine = getEngine();
|
|
595
|
+
|
|
579
596
|
// Resolve appId if not provided
|
|
580
597
|
let resolvedAppId = appId;
|
|
581
598
|
if (!resolvedAppId && appName) {
|
|
582
|
-
// Get appId directly from app name
|
|
583
599
|
const { data: app, error: appError } = await engine['supabase']
|
|
584
600
|
.from('rbac_apps')
|
|
585
601
|
.select('id, name, is_active')
|
|
@@ -594,12 +610,12 @@ export async function getPageScopeType(
|
|
|
594
610
|
error: appError,
|
|
595
611
|
errorMessage: appError instanceof Error ? appError.message : String(appError)
|
|
596
612
|
});
|
|
597
|
-
|
|
613
|
+
return err({ code: 'APP_RESOLVE_FAILED', message: `Failed to resolve appId from appName "${appName}": ${appError instanceof Error ? appError.message : String(appError)}` });
|
|
598
614
|
}
|
|
599
615
|
|
|
600
616
|
if (!app) {
|
|
601
617
|
log.error('App not found or inactive', { appName, pageId });
|
|
602
|
-
|
|
618
|
+
return err({ code: 'APP_NOT_FOUND', message: `Could not resolve appId for appName "${appName}" - app not found or not active` });
|
|
603
619
|
}
|
|
604
620
|
|
|
605
621
|
resolvedAppId = app.id;
|
|
@@ -607,14 +623,12 @@ export async function getPageScopeType(
|
|
|
607
623
|
|
|
608
624
|
if (!resolvedAppId) {
|
|
609
625
|
log.error('No appId resolved', { pageId, appId, appName });
|
|
610
|
-
|
|
626
|
+
return err({ code: 'APP_ID_REQUIRED', message: `Could not resolve appId for page ${pageId} - appId and appName both missing or invalid` });
|
|
611
627
|
}
|
|
612
628
|
|
|
613
|
-
// Resolve pageId if it's a page name
|
|
614
629
|
let resolvedPageId: UUID | string = pageId;
|
|
615
630
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
616
631
|
if (!uuidRegex.test(pageId)) {
|
|
617
|
-
// It's a page name, resolve to UUID
|
|
618
632
|
const { data: page, error: pageError } = await engine['supabase']
|
|
619
633
|
.from('rbac_app_pages')
|
|
620
634
|
.select('id, page_name, app_id')
|
|
@@ -623,42 +637,23 @@ export async function getPageScopeType(
|
|
|
623
637
|
.maybeSingle() as { data: { id: UUID; page_name: string; app_id: UUID } | null; error: unknown | null };
|
|
624
638
|
|
|
625
639
|
if (pageError) {
|
|
626
|
-
log.error('Error resolving pageId from page_name', {
|
|
627
|
-
|
|
628
|
-
appId: resolvedAppId,
|
|
629
|
-
appName,
|
|
630
|
-
error: pageError,
|
|
631
|
-
errorMessage: pageError instanceof Error ? pageError.message : String(pageError),
|
|
632
|
-
errorCode: (pageError as { code?: string })?.code
|
|
633
|
-
});
|
|
634
|
-
throw new Error(`Failed to resolve pageId "${pageId}" for appId ${resolvedAppId}: ${pageError instanceof Error ? pageError.message : String(pageError)}`);
|
|
640
|
+
log.error('Error resolving pageId from page_name', { pageId, appId: resolvedAppId, appName, error: pageError });
|
|
641
|
+
return err({ code: 'PAGE_RESOLVE_FAILED', message: `Failed to resolve pageId "${pageId}" for appId ${resolvedAppId}: ${pageError instanceof Error ? pageError.message : String(pageError)}` });
|
|
635
642
|
}
|
|
636
643
|
|
|
637
644
|
if (!page) {
|
|
638
|
-
log.error('Page not found in database', {
|
|
639
|
-
|
|
640
|
-
appId: resolvedAppId,
|
|
641
|
-
appName,
|
|
642
|
-
note: 'Page may not exist in rbac_app_pages table or may be for a different app'
|
|
643
|
-
});
|
|
644
|
-
throw new Error(`Could not resolve pageId "${pageId}" to a valid UUID - page not found for appId ${resolvedAppId}`);
|
|
645
|
+
log.error('Page not found in database', { pageId, appId: resolvedAppId, appName });
|
|
646
|
+
return err({ code: 'PAGE_NOT_FOUND', message: `Could not resolve pageId "${pageId}" to a valid UUID - page not found for appId ${resolvedAppId}` });
|
|
645
647
|
}
|
|
646
648
|
|
|
647
649
|
resolvedPageId = page.id;
|
|
648
650
|
}
|
|
649
651
|
|
|
650
|
-
// If still not a UUID, can't proceed
|
|
651
652
|
if (!uuidRegex.test(resolvedPageId)) {
|
|
652
|
-
log.error('PageId resolution failed - not a valid UUID', {
|
|
653
|
-
|
|
654
|
-
resolvedPageId,
|
|
655
|
-
appId: resolvedAppId,
|
|
656
|
-
appName
|
|
657
|
-
});
|
|
658
|
-
throw new Error(`Could not resolve pageId ${pageId} to a valid UUID`);
|
|
653
|
+
log.error('PageId resolution failed - not a valid UUID', { originalPageId: pageId, resolvedPageId, appId: resolvedAppId, appName });
|
|
654
|
+
return err({ code: 'PAGE_ID_INVALID', message: `Could not resolve pageId ${pageId} to a valid UUID` });
|
|
659
655
|
}
|
|
660
656
|
|
|
661
|
-
// Query scope type directly from rbac_app_pages (removed legacy RPC get_page_scope_type)
|
|
662
657
|
const { data: pageData, error } = await engine['supabase']
|
|
663
658
|
.from('rbac_app_pages')
|
|
664
659
|
.select('scope_type, page_name, app_id')
|
|
@@ -666,44 +661,19 @@ export async function getPageScopeType(
|
|
|
666
661
|
.single();
|
|
667
662
|
|
|
668
663
|
if (error) {
|
|
669
|
-
log.error('Error fetching page scope type from database', {
|
|
670
|
-
|
|
671
|
-
originalPageId: pageId,
|
|
672
|
-
appId: resolvedAppId,
|
|
673
|
-
appName,
|
|
674
|
-
error,
|
|
675
|
-
errorMessage: error instanceof Error ? error.message : String(error),
|
|
676
|
-
errorCode: (error as { code?: string })?.code,
|
|
677
|
-
errorDetails: (error as { details?: string })?.details,
|
|
678
|
-
errorHint: (error as { hint?: string })?.hint
|
|
679
|
-
});
|
|
680
|
-
throw new Error(`Failed to get page scope type: ${error instanceof Error ? error.message : String(error)}`);
|
|
664
|
+
log.error('Error fetching page scope type from database', { pageId: resolvedPageId, originalPageId: pageId, appId: resolvedAppId, appName, error });
|
|
665
|
+
return err({ code: 'PAGE_SCOPE_FETCH_FAILED', message: `Failed to get page scope type: ${error instanceof Error ? error.message : String(error)}` });
|
|
681
666
|
}
|
|
682
667
|
|
|
683
668
|
if (!pageData || !pageData.scope_type) {
|
|
684
|
-
log.error('Page found but scope_type is missing', {
|
|
685
|
-
|
|
686
|
-
originalPageId: pageId,
|
|
687
|
-
appId: resolvedAppId,
|
|
688
|
-
appName,
|
|
689
|
-
pageData
|
|
690
|
-
});
|
|
691
|
-
throw new Error(`Page ${resolvedPageId} does not have scope_type set`);
|
|
669
|
+
log.error('Page found but scope_type is missing', { pageId: resolvedPageId, originalPageId: pageId, appId: resolvedAppId, appName, pageData });
|
|
670
|
+
return err({ code: 'PAGE_SCOPE_TYPE_MISSING', message: `Page ${resolvedPageId} does not have scope_type set` });
|
|
692
671
|
}
|
|
693
672
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
log.error('Error fetching page scope type (catch block)', {
|
|
699
|
-
pageId,
|
|
700
|
-
appId,
|
|
701
|
-
appName,
|
|
702
|
-
error: err,
|
|
703
|
-
errorMessage: err instanceof Error ? err.message : String(err),
|
|
704
|
-
errorStack: err instanceof Error ? err.stack : undefined
|
|
705
|
-
});
|
|
706
|
-
throw err instanceof Error ? err : new Error(`Failed to get page scope type: ${String(err)}`);
|
|
673
|
+
return ok(pageData.scope_type as 'event' | 'organisation' | 'both');
|
|
674
|
+
} catch (error) {
|
|
675
|
+
log.error('Error fetching page scope type (catch block)', { pageId, appId, appName, error });
|
|
676
|
+
return err(toApiError(error));
|
|
707
677
|
}
|
|
708
678
|
}
|
|
709
679
|
|
|
@@ -714,13 +684,15 @@ export async function getPageScopeType(
|
|
|
714
684
|
* @param organisationId - Organisation ID
|
|
715
685
|
* @returns Promise resolving to organisation admin status
|
|
716
686
|
*/
|
|
717
|
-
export async function isOrganisationAdmin(userId: UUID, organisationId: UUID): Promise<boolean
|
|
718
|
-
const
|
|
687
|
+
export async function isOrganisationAdmin(userId: UUID, organisationId: UUID): Promise<ApiResult<boolean>> {
|
|
688
|
+
const result = await getAccessLevel({
|
|
719
689
|
userId,
|
|
720
690
|
scope: { organisationId },
|
|
721
691
|
});
|
|
722
|
-
|
|
723
|
-
|
|
692
|
+
if (!result.ok) {
|
|
693
|
+
return result;
|
|
694
|
+
}
|
|
695
|
+
return ok(result.data === 'admin' || result.data === 'super');
|
|
724
696
|
}
|
|
725
697
|
|
|
726
698
|
/**
|
|
@@ -730,13 +702,16 @@ export async function isOrganisationAdmin(userId: UUID, organisationId: UUID): P
|
|
|
730
702
|
* @param scope - Permission scope with eventId and appId
|
|
731
703
|
* @returns Promise resolving to event admin status
|
|
732
704
|
*/
|
|
733
|
-
export async function isEventAdmin(userId: UUID, scope: Scope): Promise<boolean
|
|
705
|
+
export async function isEventAdmin(userId: UUID, scope: Scope): Promise<ApiResult<boolean>> {
|
|
734
706
|
if (!scope.eventId || !scope.appId) {
|
|
735
|
-
return false;
|
|
707
|
+
return ok(false);
|
|
736
708
|
}
|
|
737
709
|
|
|
738
|
-
const
|
|
739
|
-
|
|
710
|
+
const result = await getAccessLevel({ userId, scope });
|
|
711
|
+
if (!result.ok) {
|
|
712
|
+
return result;
|
|
713
|
+
}
|
|
714
|
+
return ok(result.data === 'admin' || result.data === 'super');
|
|
740
715
|
}
|
|
741
716
|
|
|
742
717
|
/**
|