@jmruthers/pace-core 0.5.183 → 0.5.185
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 +38 -0
- package/README.md +60 -1
- package/core-usage-manifest.json +312 -0
- package/dist/{DataTable-QAB34V6K.js → DataTable-IX2NBUTP.js} +6 -6
- package/dist/{DataTable-Bz8ffqyA.d.ts → DataTable-Z9NLVJh0.d.ts} +1 -1
- package/dist/{index-Bl--n7-T.d.ts → PublicPageProvider-BABf6JCh.d.ts} +21 -10
- package/dist/{UnifiedAuthProvider-7F6T4B6K.js → UnifiedAuthProvider-A4BCQRJY.js} +4 -2
- package/dist/{UnifiedAuthProvider-F86d7dSi.d.ts → UnifiedAuthProvider-BG0AL5eE.d.ts} +2 -1
- package/dist/{api-ROMBCNKU.js → api-BMFCXVQX.js} +2 -2
- package/dist/{chunk-RA3JUFMW.js → chunk-445GEP27.js} +154 -4
- package/dist/{chunk-RA3JUFMW.js.map → chunk-445GEP27.js.map} +1 -1
- package/dist/{chunk-CSOFYHAG.js → chunk-AISXLWGZ.js} +374 -60
- package/dist/chunk-AISXLWGZ.js.map +1 -0
- package/dist/{chunk-FUEYYMX5.js → chunk-FXFJRTKI.js} +24 -3
- package/dist/chunk-FXFJRTKI.js.map +1 -0
- package/dist/{chunk-QETLRQI6.js → chunk-HC67NW5K.js} +380 -360
- package/dist/chunk-HC67NW5K.js.map +1 -0
- package/dist/chunk-HESYZWZW.js +388 -0
- package/dist/chunk-HESYZWZW.js.map +1 -0
- package/dist/{chunk-QUVSNGIP.js → chunk-HGPQUCBC.js} +34 -9
- package/dist/{chunk-QUVSNGIP.js.map → chunk-HGPQUCBC.js.map} +1 -1
- package/dist/{chunk-UHNYIBXL.js → chunk-IXSNYUCT.js} +1 -1
- package/dist/chunk-IXSNYUCT.js.map +1 -0
- package/dist/{chunk-MI7HBHN3.js → chunk-MX3EIJGQ.js} +4 -3
- package/dist/{chunk-MI7HBHN3.js.map → chunk-MX3EIJGQ.js.map} +1 -1
- package/dist/{chunk-PWAHJW4G.js → chunk-OKI34GZD.js} +86 -33
- package/dist/chunk-OKI34GZD.js.map +1 -0
- package/dist/{chunk-W22JP75J.js → chunk-STTZQK2I.js} +3 -3
- package/dist/chunk-THRPYOFK.js +215 -0
- package/dist/chunk-THRPYOFK.js.map +1 -0
- package/dist/{chunk-M7W4CP3M.js → chunk-U6WNSFX5.js} +2 -1
- package/dist/chunk-U6WNSFX5.js.map +1 -0
- package/dist/{chunk-QCDXODCA.js → chunk-XAUHJD3L.js} +2 -2
- package/dist/components.d.ts +182 -6
- package/dist/components.js +157 -11
- package/dist/components.js.map +1 -1
- package/dist/eslint-rules/pace-core-compliance.cjs +406 -0
- package/dist/{file-reference-D06mEEWW.d.ts → file-reference-BjR39ktt.d.ts} +7 -1
- package/dist/hooks.d.ts +7 -14
- package/dist/hooks.js +10 -22
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +11 -11
- package/dist/index.js +79 -16
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +3 -1
- package/dist/rbac/index.d.ts +205 -14
- package/dist/rbac/index.js +28 -6
- package/dist/timezone-_pgH8qrY.d.ts +530 -0
- package/dist/{types-_x1f4QBF.d.ts → types-DUyCRSTj.d.ts} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/{usePublicRouteParams-JJczomYq.d.ts → usePublicRouteParams-CvnC3d-e.d.ts} +113 -2
- package/dist/utils.d.ts +109 -151
- package/dist/utils.js +128 -138
- package/dist/utils.js.map +1 -1
- package/docs/api/README.md +60 -1
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/Logger.md +178 -0
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +2 -2
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +2 -2
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +5 -5
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/enums/LogLevel.md +54 -0
- package/docs/api/enums/RBACErrorCode.md +1 -1
- package/docs/api/enums/RPCFunction.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CalendarProps.md +18 -2
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/ComplianceResult.md +30 -0
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/DatabaseComplianceResult.md +85 -0
- package/docs/api/interfaces/DatabaseIssue.md +41 -0
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventAppRoleData.md +6 -6
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +1 -1
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +24 -8
- package/docs/api/interfaces/FileUploadProps.md +24 -13
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/FormFieldProps.md +1 -1
- package/docs/api/interfaces/FormProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.md +9 -9
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoggerConfig.md +62 -0
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +36 -23
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +11 -11
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProgressProps.md +1 -1
- package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/QuickFix.md +52 -0
- package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
- package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
- package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +4 -4
- package/docs/api/interfaces/RBACContext.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
- package/docs/api/interfaces/RBACResult.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
- package/docs/api/interfaces/RBACRolesListParams.md +1 -1
- package/docs/api/interfaces/RBACRolesListResult.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
- package/docs/api/interfaces/ResourcePermissions.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +7 -7
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RoleManagementResult.md +5 -5
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/RuntimeComplianceResult.md +55 -0
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
- package/docs/api/interfaces/SetupIssue.md +41 -0
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/TabsContentProps.md +1 -1
- package/docs/api/interfaces/TabsListProps.md +1 -1
- package/docs/api/interfaces/TabsProps.md +1 -1
- package/docs/api/interfaces/TabsTriggerProps.md +1 -1
- package/docs/api/interfaces/TextareaProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
- package/docs/api/interfaces/UseFormDialogOptions.md +62 -0
- package/docs/api/interfaces/UseFormDialogReturn.md +117 -0
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +2 -2
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +2 -2
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +2 -2
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +738 -42
- package/docs/api-reference/hooks.md +111 -0
- package/docs/api-reference/rpc-functions.md +1 -1
- package/docs/api-reference/utilities.md +184 -0
- package/docs/getting-started/installation-guide.md +75 -16
- package/docs/getting-started/quick-start.md +61 -11
- package/docs/implementation-guides/authentication.md +88 -12
- package/docs/implementation-guides/file-reference-system.md +2 -1
- package/docs/implementation-guides/file-upload-storage.md +21 -0
- package/docs/rbac/README.md +1 -0
- package/docs/rbac/compliance/compliance-guide.md +544 -0
- package/docs/rbac/getting-started.md +158 -33
- package/docs/standards/pace-core-compliance.md +432 -0
- package/eslint-config-pace-core.cjs +93 -0
- package/package.json +15 -3
- package/scripts/analyze-bundle.js +232 -0
- package/scripts/build-css.js +56 -0
- package/scripts/build-docs-incremental.js +1015 -0
- package/scripts/check-pace-core-compliance.cjs +2353 -0
- package/scripts/generate-docs.js +157 -0
- package/scripts/setup-build-cache.js +73 -0
- package/scripts/utils/command-runner.js +131 -0
- package/scripts/utils/env.js +33 -0
- package/scripts/utils/index.js +10 -0
- package/scripts/utils/logger.js +88 -0
- package/scripts/utils/path-helpers.js +37 -0
- package/scripts/validate-formats.js +133 -0
- package/scripts/validate-master.js +155 -0
- package/scripts/validate-pre-publish.js +140 -0
- package/scripts/validate-theme.js +142 -0
- package/src/components/Calendar/Calendar.tsx +8 -1
- package/src/components/Card/Card.tsx +47 -8
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +314 -0
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +126 -0
- package/src/components/DatePickerWithTimezone/README.md +135 -0
- package/src/components/DatePickerWithTimezone/index.ts +10 -0
- package/src/components/DateTimeField/DateTimeField.test.tsx +358 -0
- package/src/components/DateTimeField/DateTimeField.tsx +232 -0
- package/src/components/DateTimeField/README.md +148 -0
- package/src/components/DateTimeField/index.ts +10 -0
- package/src/components/FileUpload/FileUpload.tsx +3 -0
- package/src/components/Header/Header.test.tsx +47 -18
- package/src/components/Header/Header.tsx +24 -6
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +29 -20
- package/src/components/PaceAppLayout/README.md +9 -0
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +1 -1
- package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +37 -8
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +12 -4
- package/src/components/index.ts +8 -0
- package/src/eslint-rules/pace-core-compliance.cjs +406 -0
- package/src/eslint-rules/pace-core-compliance.js +640 -0
- package/src/hooks/__tests__/useFormDialog.test.ts +478 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useFileReference.test.ts +1 -0
- package/src/hooks/useFormDialog.ts +147 -0
- package/src/index.ts +27 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +6 -5
- package/src/providers/services/UnifiedAuthProvider.tsx +24 -3
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +3 -0
- package/src/rbac/compliance/database-validator.ts +165 -0
- package/src/rbac/compliance/index.ts +38 -0
- package/src/rbac/compliance/quick-fix-suggestions.ts +209 -0
- package/src/rbac/compliance/runtime-compliance.ts +77 -0
- package/src/rbac/compliance/setup-validator.ts +131 -0
- package/src/rbac/components/PagePermissionGuard.tsx +8 -64
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +35 -21
- package/src/rbac/docs/event-based-apps.md +285 -0
- package/src/rbac/errors.ts +11 -0
- package/src/rbac/hooks/useRoleManagement.ts +292 -12
- package/src/rbac/index.ts +30 -0
- package/src/services/OrganisationService.ts +4 -0
- package/src/types/file-reference.ts +6 -0
- package/src/utils/__tests__/timezone.test.ts +345 -0
- package/src/utils/file-reference/__tests__/file-reference.test.ts +2 -0
- package/src/utils/file-reference/index.ts +1 -0
- package/src/utils/formatting/formatDateTimeTimezone.test.ts +167 -0
- package/src/utils/formatting/formatting.ts +179 -0
- package/src/utils/index.ts +27 -1
- package/src/utils/location/index.ts +16 -0
- package/src/utils/location/location.test.ts +286 -0
- package/src/utils/location/location.ts +175 -0
- package/src/utils/timezone/index.ts +17 -0
- package/src/utils/timezone/timezone.test.ts +349 -0
- package/src/utils/timezone/timezone.ts +281 -0
- package/dist/chunk-CSOFYHAG.js.map +0 -1
- package/dist/chunk-FUEYYMX5.js.map +0 -1
- package/dist/chunk-HKIT6O7W.js +0 -198
- package/dist/chunk-HKIT6O7W.js.map +0 -1
- package/dist/chunk-KUEN3HFB.js +0 -94
- package/dist/chunk-KUEN3HFB.js.map +0 -1
- package/dist/chunk-M7W4CP3M.js.map +0 -1
- package/dist/chunk-PWAHJW4G.js.map +0 -1
- package/dist/chunk-QETLRQI6.js.map +0 -1
- package/dist/chunk-UHNYIBXL.js.map +0 -1
- package/dist/formatting-5wETwiGF.d.ts +0 -162
- /package/dist/{DataTable-QAB34V6K.js.map → DataTable-IX2NBUTP.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-7F6T4B6K.js.map → UnifiedAuthProvider-A4BCQRJY.js.map} +0 -0
- /package/dist/{api-ROMBCNKU.js.map → api-BMFCXVQX.js.map} +0 -0
- /package/dist/{chunk-W22JP75J.js.map → chunk-STTZQK2I.js.map} +0 -0
- /package/dist/{chunk-QCDXODCA.js.map → chunk-XAUHJD3L.js.map} +0 -0
|
@@ -475,14 +475,15 @@ const files = await service.listFileReferences('pace_person', personId, orgId);
|
|
|
475
475
|
|
|
476
476
|
```sql
|
|
477
477
|
-- Create file reference (replaces insert_file_reference)
|
|
478
|
+
-- Requires page context for context-aware permission checks
|
|
478
479
|
SELECT data_file_reference_create(
|
|
479
480
|
p_table_name := 'pace_person',
|
|
480
481
|
p_record_id := 'person-uuid',
|
|
481
482
|
p_file_path := 'org-123/profile_photos/file.jpg',
|
|
482
483
|
p_organisation_id := 'org-uuid',
|
|
483
484
|
p_app_id := 'app-uuid',
|
|
485
|
+
p_page_context := 'configuration',
|
|
484
486
|
p_file_metadata := '{"fileName": "photo.jpg"}'::jsonb,
|
|
485
|
-
p_category := 'profile_photos',
|
|
486
487
|
p_is_public := false
|
|
487
488
|
);
|
|
488
489
|
|
|
@@ -48,6 +48,7 @@ function MyFileUpload() {
|
|
|
48
48
|
organisation_id="org-123"
|
|
49
49
|
// app_id auto-resolved from app name
|
|
50
50
|
category={FileCategory.GENERAL_DOCUMENTS}
|
|
51
|
+
pageContext="configuration"
|
|
51
52
|
accept=".pdf,.doc,.docx"
|
|
52
53
|
maxSize={5 * 1024 * 1024} // 5MB
|
|
53
54
|
showProgress={true}
|
|
@@ -127,6 +128,7 @@ interface FileUploadProps {
|
|
|
127
128
|
organisation_id: string;
|
|
128
129
|
app_id?: string; // Optional - will be resolved from app name if not provided
|
|
129
130
|
category: FileCategory;
|
|
131
|
+
pageContext: string; // The page context where the file upload occurs (e.g., 'configuration', 'forms', 'applications')
|
|
130
132
|
accept?: string;
|
|
131
133
|
maxSize?: number;
|
|
132
134
|
multiple?: boolean;
|
|
@@ -152,6 +154,7 @@ interface FileUploadProps {
|
|
|
152
154
|
record_id="person-123"
|
|
153
155
|
organisation_id={organisationId}
|
|
154
156
|
category={FileCategory.PROFILE_PHOTOS}
|
|
157
|
+
pageContext="configuration"
|
|
155
158
|
accept="image/*"
|
|
156
159
|
maxSize={2 * 1024 * 1024} // 2MB
|
|
157
160
|
onUploadSuccess={(result) => console.log('Uploaded:', result.file_reference)}
|
|
@@ -168,6 +171,7 @@ interface FileUploadProps {
|
|
|
168
171
|
record_id="person-123"
|
|
169
172
|
organisation_id={organisationId}
|
|
170
173
|
category={FileCategory.GENERAL_DOCUMENTS}
|
|
174
|
+
pageContext="forms"
|
|
171
175
|
multiple={true}
|
|
172
176
|
accept=".pdf,.doc,.docx"
|
|
173
177
|
showProgress={true}
|
|
@@ -197,6 +201,23 @@ interface FileUploadProps {
|
|
|
197
201
|
</FileUpload>
|
|
198
202
|
```
|
|
199
203
|
|
|
204
|
+
#### Page Context and Permissions
|
|
205
|
+
|
|
206
|
+
The `pageContext` parameter enables context-aware permission checks for file uploads. Instead of requiring a generic `'create:files'` permission on a `'files'` page, the system checks permissions based on the actual page where the upload occurs.
|
|
207
|
+
|
|
208
|
+
**Permission Check Behavior:**
|
|
209
|
+
- The system checks for `'create:page.{pageContext}'` permission first
|
|
210
|
+
- If that permission doesn't exist, it checks for `'update:page.{pageContext}'` permission
|
|
211
|
+
- The user needs at least one of these permissions to upload files
|
|
212
|
+
- This ensures file uploads are controlled by the same permissions as the page where they occur
|
|
213
|
+
|
|
214
|
+
**Example Use Cases:**
|
|
215
|
+
- Event logo uploads on the `'configuration'` page require `'create:page.configuration'` or `'update:page.configuration'` permission
|
|
216
|
+
- Form document uploads on the `'forms'` page require `'create:page.forms'` or `'update:page.forms'` permission
|
|
217
|
+
- Application file uploads on the `'applications'` page require `'create:page.applications'` or `'update:page.applications'` permission
|
|
218
|
+
|
|
219
|
+
**Important:** The `pageContext` must match a page defined in your RBAC system (`rbac_app_pages` table) for the permission checks to work correctly.
|
|
220
|
+
|
|
200
221
|
### FileDisplay
|
|
201
222
|
|
|
202
223
|
A component for displaying and managing files associated with database records.
|
package/docs/rbac/README.md
CHANGED
|
@@ -66,6 +66,7 @@ function MyComponent() {
|
|
|
66
66
|
- **[Event-Based Apps](./event-based-apps.md)** - Get up and running in 10 minutes (foolproof guide for event-based apps)
|
|
67
67
|
- **[API Reference](./api-reference.md)** - Complete API documentation
|
|
68
68
|
- **[Troubleshooting](./troubleshooting.md)** - Common issues and solutions
|
|
69
|
+
- **[Compliance Guide](./compliance/compliance-guide.md)** - Ensuring proper RBAC/auth setup and usage
|
|
69
70
|
- **[Examples](./examples.md)** - Practical usage examples
|
|
70
71
|
- **[Advanced Patterns](./advanced-patterns.md)** - Complex scenarios and optimizations
|
|
71
72
|
|
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
# RBAC/Auth Compliance Guide
|
|
2
|
+
|
|
3
|
+
> **📚 RBAC Compliance** | [← Back to RBAC Documentation](../README.md) | [Troubleshooting](./troubleshooting-compliance.md) | [Migrating Custom Auth](./migrating-custom-auth.md)
|
|
4
|
+
|
|
5
|
+
This guide explains how to achieve RBAC/auth compliance in your pace app to ensure proper security and consistent usage of pace-core.
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
The RBAC/auth compliance system ensures that:
|
|
10
|
+
- All auth/rbac/permission functionality uses pace-core exclusively
|
|
11
|
+
- RBAC system is properly initialized
|
|
12
|
+
- All pages are protected with PagePermissionGuard
|
|
13
|
+
- Supabase configuration is centralized
|
|
14
|
+
- No custom auth/rbac code exists
|
|
15
|
+
|
|
16
|
+
## Compliance Checks
|
|
17
|
+
|
|
18
|
+
The compliance system checks for:
|
|
19
|
+
|
|
20
|
+
### 1. Custom Auth/RBAC Code
|
|
21
|
+
|
|
22
|
+
**What it checks:**
|
|
23
|
+
- Custom auth hooks (useAuth, useLogin, useLogout, etc.)
|
|
24
|
+
- Custom RBAC components (PermissionGuard, AuthGuard, etc.)
|
|
25
|
+
- Custom permission utilities (checkPermission, hasAccess, etc.)
|
|
26
|
+
|
|
27
|
+
**How to fix:**
|
|
28
|
+
- Remove custom implementations
|
|
29
|
+
- Import equivalent from `@jmruthers/pace-core` or `@jmruthers/pace-core/rbac`
|
|
30
|
+
- Update all usages
|
|
31
|
+
|
|
32
|
+
See [Migrating Custom Auth](./migrating-custom-auth.md) for detailed migration steps.
|
|
33
|
+
|
|
34
|
+
### 2. Duplicate Supabase Configuration
|
|
35
|
+
|
|
36
|
+
**What it checks:**
|
|
37
|
+
- Multiple `createClient` calls
|
|
38
|
+
- Supabase environment variables in multiple files
|
|
39
|
+
|
|
40
|
+
**How to fix:**
|
|
41
|
+
- Create a single `supabase.ts` file
|
|
42
|
+
- Export the client instance
|
|
43
|
+
- Import from the shared location everywhere
|
|
44
|
+
|
|
45
|
+
### 3. Unprotected Pages
|
|
46
|
+
|
|
47
|
+
**What it checks:**
|
|
48
|
+
- Routes without PagePermissionGuard
|
|
49
|
+
- Pages without permission checks
|
|
50
|
+
|
|
51
|
+
**How to fix:**
|
|
52
|
+
- Wrap all routes with PagePermissionGuard
|
|
53
|
+
- Set `pageName` and `operation` props
|
|
54
|
+
- Ensure pages exist in `rbac_app_pages` table
|
|
55
|
+
|
|
56
|
+
### 4. Direct Supabase Auth Usage
|
|
57
|
+
|
|
58
|
+
**What it checks:**
|
|
59
|
+
- Direct calls to `supabase.auth.signIn`, `supabase.auth.signUp`, etc.
|
|
60
|
+
|
|
61
|
+
**How to fix:**
|
|
62
|
+
- Use `useUnifiedAuth` hook from pace-core
|
|
63
|
+
- Use `UnifiedAuthProvider` to wrap your app
|
|
64
|
+
- Replace all direct auth calls with pace-core methods
|
|
65
|
+
|
|
66
|
+
### 5. Provider Setup Issues
|
|
67
|
+
|
|
68
|
+
**What it checks:**
|
|
69
|
+
- Missing `UnifiedAuthProvider` or `OrganisationProvider`
|
|
70
|
+
- Incorrect provider nesting order
|
|
71
|
+
- Providers placed in wrong locations
|
|
72
|
+
|
|
73
|
+
**How to fix:**
|
|
74
|
+
- Ensure correct nesting: `QueryClientProvider` → `BrowserRouter` → `UnifiedAuthProvider` → `OrganisationProvider` → `App`
|
|
75
|
+
- Place providers in `main.tsx` or `App.tsx` entry file
|
|
76
|
+
- See [Provider Setup](#provider-setup) section below
|
|
77
|
+
|
|
78
|
+
### 6. Vite Configuration Issues
|
|
79
|
+
|
|
80
|
+
**What it checks:**
|
|
81
|
+
- `@jmruthers/pace-core` in `optimizeDeps.include` (should be excluded)
|
|
82
|
+
- Missing `@jmruthers/pace-core` in `optimizeDeps.exclude`
|
|
83
|
+
- Missing `react-router-dom` in `resolve.dedupe`
|
|
84
|
+
|
|
85
|
+
**How to fix:**
|
|
86
|
+
- Add `@jmruthers/pace-core` to `optimizeDeps.exclude`
|
|
87
|
+
- Remove `@jmruthers/pace-core` from `optimizeDeps.include`
|
|
88
|
+
- Add `react-router-dom` to `resolve.dedupe`
|
|
89
|
+
- See [Vite Configuration](#vite-configuration) section below
|
|
90
|
+
|
|
91
|
+
### 7. Router Setup Issues
|
|
92
|
+
|
|
93
|
+
**What it checks:**
|
|
94
|
+
- Missing `BrowserRouter`
|
|
95
|
+
- `BrowserRouter` placed incorrectly (inside `UnifiedAuthProvider` instead of wrapping it)
|
|
96
|
+
- `Routes` used without `BrowserRouter`
|
|
97
|
+
|
|
98
|
+
**How to fix:**
|
|
99
|
+
- Wrap app with `BrowserRouter` from `react-router-dom`
|
|
100
|
+
- Ensure `BrowserRouter` wraps `UnifiedAuthProvider` (not the other way around)
|
|
101
|
+
- See [Router Setup](#router-setup) section below
|
|
102
|
+
|
|
103
|
+
## Running Compliance Checks
|
|
104
|
+
|
|
105
|
+
### Static Analysis
|
|
106
|
+
|
|
107
|
+
Run the compliance check script:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
npm run check:pace-core
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
This will scan your codebase and report:
|
|
114
|
+
- Custom auth/rbac code
|
|
115
|
+
- Duplicate configurations
|
|
116
|
+
- Unprotected pages
|
|
117
|
+
- Direct Supabase auth usage
|
|
118
|
+
- Provider setup issues
|
|
119
|
+
- Vite configuration problems
|
|
120
|
+
- Router setup issues
|
|
121
|
+
|
|
122
|
+
### ESLint Rules
|
|
123
|
+
|
|
124
|
+
The compliance system includes ESLint rules that run during development:
|
|
125
|
+
|
|
126
|
+
- `no-custom-auth-code` - Disallows custom auth/rbac implementations
|
|
127
|
+
- `no-duplicate-supabase-config` - Disallows multiple Supabase configurations
|
|
128
|
+
- `require-page-permission-guard` - Requires PagePermissionGuard on routes
|
|
129
|
+
- `no-direct-supabase-auth` - Disallows direct Supabase auth usage
|
|
130
|
+
|
|
131
|
+
### Runtime Validation
|
|
132
|
+
|
|
133
|
+
Check runtime compliance programmatically:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { checkRuntimeCompliance } from '@jmruthers/pace-core/rbac';
|
|
137
|
+
|
|
138
|
+
const result = checkRuntimeCompliance();
|
|
139
|
+
if (!result.setup.isCompliant) {
|
|
140
|
+
console.warn('RBAC setup issues:', result.setup.issues);
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Achieving Compliance
|
|
145
|
+
|
|
146
|
+
### Step 1: Initialize RBAC
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
// main.tsx or App.tsx
|
|
150
|
+
import { setupRBAC } from '@jmruthers/pace-core/rbac';
|
|
151
|
+
import { createClient } from '@supabase/supabase-js';
|
|
152
|
+
|
|
153
|
+
const supabase = createClient(
|
|
154
|
+
import.meta.env.VITE_SUPABASE_URL,
|
|
155
|
+
import.meta.env.VITE_SUPABASE_ANON_KEY
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
// ⚠️ REQUIRED: Call setupRBAC before rendering
|
|
159
|
+
setupRBAC(supabase);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Step 2: Set Up Providers
|
|
163
|
+
|
|
164
|
+
**⚠️ CRITICAL: Provider nesting order matters!**
|
|
165
|
+
|
|
166
|
+
The correct nesting order is:
|
|
167
|
+
1. `QueryClientProvider` (outermost)
|
|
168
|
+
2. `BrowserRouter`
|
|
169
|
+
3. `UnifiedAuthProvider`
|
|
170
|
+
4. `OrganisationProvider`
|
|
171
|
+
5. `App` (innermost)
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
// main.tsx - Correct setup
|
|
175
|
+
import { BrowserRouter } from 'react-router-dom';
|
|
176
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
177
|
+
import { UnifiedAuthProvider, OrganisationProvider } from '@jmruthers/pace-core';
|
|
178
|
+
|
|
179
|
+
const queryClient = new QueryClient();
|
|
180
|
+
|
|
181
|
+
createRoot(document.getElementById("root")!).render(
|
|
182
|
+
<QueryClientProvider client={queryClient}>
|
|
183
|
+
<BrowserRouter>
|
|
184
|
+
<UnifiedAuthProvider supabaseClient={supabase} appName={APP_NAME}>
|
|
185
|
+
<OrganisationProvider>
|
|
186
|
+
<App />
|
|
187
|
+
</OrganisationProvider>
|
|
188
|
+
</UnifiedAuthProvider>
|
|
189
|
+
</BrowserRouter>
|
|
190
|
+
</QueryClientProvider>
|
|
191
|
+
);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Common mistakes to avoid:**
|
|
195
|
+
- ❌ `BrowserRouter` inside `UnifiedAuthProvider` (causes Router context errors)
|
|
196
|
+
- ❌ `UnifiedAuthProvider` wrapping `BrowserRouter` (causes context errors)
|
|
197
|
+
- ❌ Missing `BrowserRouter` (causes `useNavigate` errors)
|
|
198
|
+
|
|
199
|
+
### Step 3: Protect All Pages
|
|
200
|
+
|
|
201
|
+
```tsx
|
|
202
|
+
// pages/Dashboard.tsx
|
|
203
|
+
import { PagePermissionGuard } from '@jmruthers/pace-core/rbac';
|
|
204
|
+
|
|
205
|
+
function Dashboard() {
|
|
206
|
+
return (
|
|
207
|
+
<PagePermissionGuard pageName="dashboard" operation="read">
|
|
208
|
+
<DashboardContent />
|
|
209
|
+
</PagePermissionGuard>
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Step 4: Use pace-core Auth
|
|
215
|
+
|
|
216
|
+
```tsx
|
|
217
|
+
// components/Login.tsx
|
|
218
|
+
import { useUnifiedAuth } from '@jmruthers/pace-core';
|
|
219
|
+
|
|
220
|
+
function Login() {
|
|
221
|
+
const { signIn } = useUnifiedAuth();
|
|
222
|
+
|
|
223
|
+
const handleLogin = async () => {
|
|
224
|
+
await signIn({ email, password });
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
return <button onClick={handleLogin}>Login</button>;
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Step 5: Configure Vite
|
|
232
|
+
|
|
233
|
+
**⚠️ CRITICAL: Vite configuration prevents React context mismatches!**
|
|
234
|
+
|
|
235
|
+
Add to your `vite.config.ts`:
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
import { defineConfig } from 'vite';
|
|
239
|
+
|
|
240
|
+
export default defineConfig({
|
|
241
|
+
resolve: {
|
|
242
|
+
dedupe: ['react', 'react-dom', 'react-router-dom']
|
|
243
|
+
},
|
|
244
|
+
optimizeDeps: {
|
|
245
|
+
include: [
|
|
246
|
+
'react',
|
|
247
|
+
'react-dom',
|
|
248
|
+
'react/jsx-runtime'
|
|
249
|
+
],
|
|
250
|
+
// CRITICAL: Exclude pace-core to prevent React context mismatches
|
|
251
|
+
exclude: ['@jmruthers/pace-core', 'react-router-dom']
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Why this matters:**
|
|
257
|
+
- Pre-bundling `@jmruthers/pace-core` creates separate React instances
|
|
258
|
+
- This causes "useUnifiedAuth must be used within a UnifiedAuthProvider" errors
|
|
259
|
+
- Excluding it ensures pace-core uses the same React instance as your app
|
|
260
|
+
|
|
261
|
+
### Step 6: Centralize Supabase Config
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
// src/lib/supabase.ts
|
|
265
|
+
import { createClient } from '@supabase/supabase-js';
|
|
266
|
+
|
|
267
|
+
export const supabase = createClient(
|
|
268
|
+
import.meta.env.VITE_SUPABASE_URL,
|
|
269
|
+
import.meta.env.VITE_SUPABASE_ANON_KEY
|
|
270
|
+
);
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Database Configuration
|
|
274
|
+
|
|
275
|
+
Ensure your database is properly configured:
|
|
276
|
+
|
|
277
|
+
1. **App Registration**: App must exist in `rbac_apps` table
|
|
278
|
+
2. **Pages**: All pages must be registered in `rbac_app_pages` table
|
|
279
|
+
3. **Permissions**: Permissions must be configured in `rbac_page_permissions` table
|
|
280
|
+
4. **User Roles**: Users must have roles in `rbac_organisation_roles` table
|
|
281
|
+
|
|
282
|
+
See [RBAC Quick Start](../quick-start.md) for database setup instructions.
|
|
283
|
+
|
|
284
|
+
## Quick Fixes
|
|
285
|
+
|
|
286
|
+
The compliance system provides quick fix suggestions:
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
import { getQuickFixes } from '@jmruthers/pace-core/rbac';
|
|
290
|
+
|
|
291
|
+
const fixes = getQuickFixes('custom-auth-code', { name: 'useAuth', type: 'hook' });
|
|
292
|
+
fixes.forEach(fix => {
|
|
293
|
+
console.log(fix.suggestion);
|
|
294
|
+
console.log(fix.codeExample);
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## CI/CD Integration
|
|
299
|
+
|
|
300
|
+
Add compliance checks to your CI/CD pipeline:
|
|
301
|
+
|
|
302
|
+
```yaml
|
|
303
|
+
# .github/workflows/compliance.yml
|
|
304
|
+
- name: Check pace-core compliance
|
|
305
|
+
run: npm run check:pace-core
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
The script exits with code 1 if compliance issues are found, causing the build to fail.
|
|
309
|
+
|
|
310
|
+
## Troubleshooting Common Issues
|
|
311
|
+
|
|
312
|
+
### Provider Setup Issues
|
|
313
|
+
|
|
314
|
+
**Issue:** "useUnifiedAuth must be used within a UnifiedAuthProvider" error
|
|
315
|
+
|
|
316
|
+
**Possible causes:**
|
|
317
|
+
1. `UnifiedAuthProvider` is missing or not wrapping your app
|
|
318
|
+
2. `BrowserRouter` is inside `UnifiedAuthProvider` (wrong nesting)
|
|
319
|
+
3. Vite is pre-bundling `@jmruthers/pace-core` (React context mismatch)
|
|
320
|
+
|
|
321
|
+
**Solution:**
|
|
322
|
+
1. **Check provider nesting** in `main.tsx`:
|
|
323
|
+
```tsx
|
|
324
|
+
// ✅ CORRECT
|
|
325
|
+
<QueryClientProvider>
|
|
326
|
+
<BrowserRouter>
|
|
327
|
+
<UnifiedAuthProvider>
|
|
328
|
+
<OrganisationProvider>
|
|
329
|
+
<App />
|
|
330
|
+
</OrganisationProvider>
|
|
331
|
+
</UnifiedAuthProvider>
|
|
332
|
+
</BrowserRouter>
|
|
333
|
+
</QueryClientProvider>
|
|
334
|
+
|
|
335
|
+
// ❌ WRONG - BrowserRouter inside UnifiedAuthProvider
|
|
336
|
+
<UnifiedAuthProvider>
|
|
337
|
+
<BrowserRouter>
|
|
338
|
+
<App />
|
|
339
|
+
</BrowserRouter>
|
|
340
|
+
</UnifiedAuthProvider>
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
2. **Check Vite config** - ensure `@jmruthers/pace-core` is in `optimizeDeps.exclude`:
|
|
344
|
+
```typescript
|
|
345
|
+
optimizeDeps: {
|
|
346
|
+
exclude: ['@jmruthers/pace-core', 'react-router-dom']
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
3. **Clear Vite cache** and restart dev server:
|
|
351
|
+
```bash
|
|
352
|
+
rm -rf node_modules/.vite
|
|
353
|
+
npm run dev
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Router Context Issues
|
|
357
|
+
|
|
358
|
+
**Issue:** "useNavigate() may be used only in the context of a <Router> component" error
|
|
359
|
+
|
|
360
|
+
**Possible causes:**
|
|
361
|
+
1. Missing `BrowserRouter`
|
|
362
|
+
2. `BrowserRouter` placed incorrectly
|
|
363
|
+
3. `react-router-dom` being pre-bundled by Vite
|
|
364
|
+
|
|
365
|
+
**Solution:**
|
|
366
|
+
1. **Add BrowserRouter** wrapping your app:
|
|
367
|
+
```tsx
|
|
368
|
+
import { BrowserRouter } from 'react-router-dom';
|
|
369
|
+
|
|
370
|
+
<BrowserRouter>
|
|
371
|
+
<UnifiedAuthProvider>
|
|
372
|
+
<App />
|
|
373
|
+
</UnifiedAuthProvider>
|
|
374
|
+
</BrowserRouter>
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
2. **Update Vite config**:
|
|
378
|
+
```typescript
|
|
379
|
+
resolve: {
|
|
380
|
+
dedupe: ['react', 'react-dom', 'react-router-dom']
|
|
381
|
+
},
|
|
382
|
+
optimizeDeps: {
|
|
383
|
+
exclude: ['react-router-dom']
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
3. **Clear Vite cache** and restart
|
|
388
|
+
|
|
389
|
+
### Vite Configuration Issues
|
|
390
|
+
|
|
391
|
+
**Issue:** React context mismatch errors, components can't find providers
|
|
392
|
+
|
|
393
|
+
**Possible causes:**
|
|
394
|
+
1. `@jmruthers/pace-core` is being pre-bundled by Vite
|
|
395
|
+
2. Multiple React instances in the bundle
|
|
396
|
+
|
|
397
|
+
**Solution:**
|
|
398
|
+
1. **Exclude pace-core from pre-bundling**:
|
|
399
|
+
```typescript
|
|
400
|
+
optimizeDeps: {
|
|
401
|
+
exclude: ['@jmruthers/pace-core']
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
2. **Dedupe React dependencies**:
|
|
406
|
+
```typescript
|
|
407
|
+
resolve: {
|
|
408
|
+
dedupe: ['react', 'react-dom', 'react-router-dom']
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
3. **Clear Vite cache**:
|
|
413
|
+
```bash
|
|
414
|
+
rm -rf node_modules/.vite
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Custom Auth/RBAC Code Detected
|
|
418
|
+
|
|
419
|
+
**Issue:** Custom `useAuth` hook or `PermissionGuard` component found
|
|
420
|
+
|
|
421
|
+
**Solution:**
|
|
422
|
+
1. Remove your custom implementation
|
|
423
|
+
2. Import from pace-core:
|
|
424
|
+
```typescript
|
|
425
|
+
import { useUnifiedAuth } from '@jmruthers/pace-core';
|
|
426
|
+
import { PagePermissionGuard } from '@jmruthers/pace-core/rbac';
|
|
427
|
+
```
|
|
428
|
+
3. Update all usages - see [Migration Examples](#migrating-from-custom-code) below
|
|
429
|
+
|
|
430
|
+
### Duplicate Supabase Configuration
|
|
431
|
+
|
|
432
|
+
**Issue:** Multiple `createClient` calls found
|
|
433
|
+
|
|
434
|
+
**Solution:**
|
|
435
|
+
1. Create a single `supabase.ts` file:
|
|
436
|
+
```typescript
|
|
437
|
+
// src/lib/supabase.ts
|
|
438
|
+
export const supabase = createClient(url, key);
|
|
439
|
+
```
|
|
440
|
+
2. Remove all other `createClient` calls
|
|
441
|
+
3. Import from the shared location everywhere
|
|
442
|
+
|
|
443
|
+
### Unprotected Pages
|
|
444
|
+
|
|
445
|
+
**Issue:** Route without PagePermissionGuard
|
|
446
|
+
|
|
447
|
+
**Solution:**
|
|
448
|
+
1. Wrap all routes with PagePermissionGuard:
|
|
449
|
+
```tsx
|
|
450
|
+
<PagePermissionGuard pageName="dashboard" operation="read">
|
|
451
|
+
<Dashboard />
|
|
452
|
+
</PagePermissionGuard>
|
|
453
|
+
```
|
|
454
|
+
2. Ensure pages exist in `rbac_app_pages` table
|
|
455
|
+
|
|
456
|
+
### Direct Supabase Auth Usage
|
|
457
|
+
|
|
458
|
+
**Issue:** Direct `supabase.auth` calls detected
|
|
459
|
+
|
|
460
|
+
**Solution:**
|
|
461
|
+
1. Use `useUnifiedAuth` hook instead:
|
|
462
|
+
```typescript
|
|
463
|
+
const { signIn } = useUnifiedAuth();
|
|
464
|
+
await signIn({ email, password });
|
|
465
|
+
```
|
|
466
|
+
2. Ensure `UnifiedAuthProvider` wraps your app
|
|
467
|
+
|
|
468
|
+
### RBAC Not Initialized
|
|
469
|
+
|
|
470
|
+
**Issue:** `setupRBAC()` not called
|
|
471
|
+
|
|
472
|
+
**Solution:**
|
|
473
|
+
```typescript
|
|
474
|
+
// main.tsx - Must be called before rendering
|
|
475
|
+
import { setupRBAC } from '@jmruthers/pace-core/rbac';
|
|
476
|
+
setupRBAC(supabase);
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
## Migrating from Custom Code
|
|
480
|
+
|
|
481
|
+
### Migrating `useAuth` Hook
|
|
482
|
+
|
|
483
|
+
**Before:**
|
|
484
|
+
```typescript
|
|
485
|
+
// src/hooks/useAuth.ts
|
|
486
|
+
export function useAuth() {
|
|
487
|
+
const [user, setUser] = useState(null);
|
|
488
|
+
// ... custom logic
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
**After:**
|
|
493
|
+
```typescript
|
|
494
|
+
import { useUnifiedAuth } from '@jmruthers/pace-core';
|
|
495
|
+
const { user } = useUnifiedAuth();
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
### Migrating `PermissionGuard` Component
|
|
499
|
+
|
|
500
|
+
**Before:**
|
|
501
|
+
```tsx
|
|
502
|
+
<PermissionGuard permission="read:users">
|
|
503
|
+
<UsersPage />
|
|
504
|
+
</PermissionGuard>
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
**After:**
|
|
508
|
+
```tsx
|
|
509
|
+
<PagePermissionGuard pageName="users" operation="read">
|
|
510
|
+
<UsersPage />
|
|
511
|
+
</PagePermissionGuard>
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
### Migrating `checkPermission` Utility
|
|
515
|
+
|
|
516
|
+
**Before:**
|
|
517
|
+
```typescript
|
|
518
|
+
const hasAccess = checkPermission(user, 'read:users');
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
**After:**
|
|
522
|
+
```typescript
|
|
523
|
+
import { isPermitted } from '@jmruthers/pace-core/rbac';
|
|
524
|
+
const hasAccess = await isPermitted({
|
|
525
|
+
userId: user.id,
|
|
526
|
+
scope: { organisationId: org.id },
|
|
527
|
+
permission: 'read:page.users'
|
|
528
|
+
});
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### Step-by-Step Migration Process
|
|
532
|
+
|
|
533
|
+
1. **Audit:** Run `npm run check:pace-core` to find all custom code
|
|
534
|
+
2. **Setup:** Ensure `setupRBAC()` is called and providers are configured
|
|
535
|
+
3. **Migrate:** Replace custom code with pace-core equivalents one component at a time
|
|
536
|
+
4. **Test:** Verify all auth flows and permission checks work
|
|
537
|
+
5. **Clean:** Remove custom files and update all imports
|
|
538
|
+
|
|
539
|
+
## Next Steps
|
|
540
|
+
|
|
541
|
+
- [RBAC Troubleshooting](../troubleshooting.md) - General RBAC issues
|
|
542
|
+
- [RBAC Quick Start](../quick-start.md) - Getting started with RBAC
|
|
543
|
+
- [RBAC API Reference](../api-reference.md) - Complete API documentation
|
|
544
|
+
|