@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
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Note: RBAC functionality is available via useRBAC() hook from '@jmruthers/pace-core/rbac'
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import React, { createContext, useContext, useMemo, useCallback, useRef, useEffect, useState } from 'react';
|
|
11
|
+
import React, { createContext, useContext, useMemo, useCallback, useRef, useEffect, useState, useReducer } from 'react';
|
|
12
12
|
import { type SupabaseClient, type User, type Session } from '@supabase/supabase-js';
|
|
13
13
|
import { AuthServiceProvider } from './AuthServiceProvider';
|
|
14
14
|
import { OrganisationServiceProvider } from './OrganisationServiceProvider';
|
|
@@ -114,7 +114,7 @@ export interface UnifiedAuthContextType {
|
|
|
114
114
|
sessionRestorationTimeoutMs: number;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
const UnifiedAuthContext = createContext<UnifiedAuthContextType | undefined>(undefined);
|
|
117
|
+
export const UnifiedAuthContext = createContext<UnifiedAuthContextType | undefined>(undefined);
|
|
118
118
|
|
|
119
119
|
export const useUnifiedAuth = () => {
|
|
120
120
|
const context = useContext(UnifiedAuthContext);
|
|
@@ -179,13 +179,15 @@ function UnifiedAuthContextProvider({
|
|
|
179
179
|
eventService = useEventService();
|
|
180
180
|
} catch (error) {
|
|
181
181
|
// EventService not available - provide fallback implementation
|
|
182
|
+
// Include subscribe method to match BaseService interface
|
|
182
183
|
eventService = {
|
|
183
184
|
getEvents: () => [],
|
|
184
185
|
getSelectedEvent: () => null,
|
|
185
186
|
isLoading: () => false,
|
|
186
187
|
getError: () => null,
|
|
187
188
|
setSelectedEvent: () => {},
|
|
188
|
-
refreshEvents: async () => {}
|
|
189
|
+
refreshEvents: async () => {},
|
|
190
|
+
subscribe: () => () => {} // No-op subscribe/unsubscribe for fallback
|
|
189
191
|
};
|
|
190
192
|
}
|
|
191
193
|
|
|
@@ -256,6 +258,25 @@ function UnifiedAuthContextProvider({
|
|
|
256
258
|
}
|
|
257
259
|
}, [isAuth, currentUser?.id, supabase, appName, appId]);
|
|
258
260
|
|
|
261
|
+
// Subscribe to service state changes to trigger re-renders
|
|
262
|
+
// Use useReducer to force updates when services notify
|
|
263
|
+
const [, forceUpdate] = useReducer(x => x + 1, 0);
|
|
264
|
+
|
|
265
|
+
useEffect(() => {
|
|
266
|
+
// Subscribe to all service changes
|
|
267
|
+
const unsubscribeAuth = authService.subscribe(() => forceUpdate());
|
|
268
|
+
const unsubscribeOrg = organisationService.subscribe(() => forceUpdate());
|
|
269
|
+
const unsubscribeEvent = eventService.subscribe(() => forceUpdate());
|
|
270
|
+
const unsubscribeInactivity = inactivityService.subscribe(() => forceUpdate());
|
|
271
|
+
|
|
272
|
+
return () => {
|
|
273
|
+
unsubscribeAuth();
|
|
274
|
+
unsubscribeOrg();
|
|
275
|
+
unsubscribeEvent();
|
|
276
|
+
unsubscribeInactivity();
|
|
277
|
+
};
|
|
278
|
+
}, [authService, organisationService, eventService, inactivityService]);
|
|
279
|
+
|
|
259
280
|
// Get loading states - these will trigger re-renders when services change
|
|
260
281
|
const authLoading = authService.isLoading();
|
|
261
282
|
const orgLoading = organisationService.isLoading();
|
|
@@ -30,6 +30,7 @@ vi.mock('../../hooks/services/useAuthService', () => ({
|
|
|
30
30
|
resetPassword: vi.fn(),
|
|
31
31
|
updatePassword: vi.fn(),
|
|
32
32
|
refreshSession: vi.fn(),
|
|
33
|
+
subscribe: vi.fn(() => () => {}), // Subscribe method that returns unsubscribe function
|
|
33
34
|
}),
|
|
34
35
|
}));
|
|
35
36
|
|
|
@@ -41,6 +42,7 @@ vi.mock('../../hooks/services/useEventService', () => ({
|
|
|
41
42
|
getError: vi.fn(() => null),
|
|
42
43
|
setSelectedEvent: vi.fn(),
|
|
43
44
|
refreshEvents: vi.fn(),
|
|
45
|
+
subscribe: vi.fn(() => () => {}), // Subscribe method that returns unsubscribe function
|
|
44
46
|
}),
|
|
45
47
|
}));
|
|
46
48
|
|
|
@@ -56,6 +58,7 @@ vi.mock('../../hooks/services/useInactivityService', () => ({
|
|
|
56
58
|
startTracking: vi.fn(),
|
|
57
59
|
stopTracking: vi.fn(),
|
|
58
60
|
handleIdleLogout: vi.fn(),
|
|
61
|
+
subscribe: vi.fn(() => () => {}), // Subscribe method that returns unsubscribe function
|
|
59
62
|
}),
|
|
60
63
|
}));
|
|
61
64
|
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Configuration Validator
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module RBAC/Compliance/DatabaseValidator
|
|
5
|
+
* @since 1.0.0
|
|
6
|
+
*
|
|
7
|
+
* This module provides utilities to validate database configuration for RBAC.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { SupabaseClient } from '@supabase/supabase-js';
|
|
11
|
+
import { Database } from '../../types/database';
|
|
12
|
+
|
|
13
|
+
export interface DatabaseIssue {
|
|
14
|
+
type: 'app-not-configured' | 'app-name-mismatch' | 'pages-not-configured' | 'permissions-not-configured' | 'rls-not-active' | 'roles-not-configured';
|
|
15
|
+
message: string;
|
|
16
|
+
recommendation: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface DatabaseComplianceResult {
|
|
20
|
+
appConfigured: boolean;
|
|
21
|
+
pagesConfigured: boolean;
|
|
22
|
+
permissionsConfigured: boolean;
|
|
23
|
+
rlsPoliciesActive: boolean;
|
|
24
|
+
rolesConfigured: boolean;
|
|
25
|
+
issues: DatabaseIssue[];
|
|
26
|
+
recommendations: string[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Validate database configuration
|
|
31
|
+
*
|
|
32
|
+
* @param supabase - Supabase client
|
|
33
|
+
* @param appName - Application name to validate
|
|
34
|
+
* @returns Database compliance result
|
|
35
|
+
*/
|
|
36
|
+
export async function validateDatabaseConfiguration(
|
|
37
|
+
supabase: SupabaseClient<Database>,
|
|
38
|
+
appName: string
|
|
39
|
+
): Promise<DatabaseComplianceResult> {
|
|
40
|
+
const issues: DatabaseIssue[] = [];
|
|
41
|
+
const recommendations: string[] = [];
|
|
42
|
+
|
|
43
|
+
let appConfigured = false;
|
|
44
|
+
let pagesConfigured = false;
|
|
45
|
+
let permissionsConfigured = false;
|
|
46
|
+
let rlsPoliciesActive = false;
|
|
47
|
+
let rolesConfigured = false;
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
// Check if app exists in rbac_apps
|
|
51
|
+
const { data: app, error: appError } = await supabase
|
|
52
|
+
.from('rbac_apps')
|
|
53
|
+
.select('id, name')
|
|
54
|
+
.eq('name', appName)
|
|
55
|
+
.single();
|
|
56
|
+
|
|
57
|
+
if (appError || !app) {
|
|
58
|
+
issues.push({
|
|
59
|
+
type: 'app-not-configured',
|
|
60
|
+
message: `App '${appName}' not found in rbac_apps table.`,
|
|
61
|
+
recommendation: `Register your app in the rbac_apps table with name '${appName}' (case-sensitive).`
|
|
62
|
+
});
|
|
63
|
+
} else {
|
|
64
|
+
appConfigured = true;
|
|
65
|
+
|
|
66
|
+
// Check if app name matches exactly
|
|
67
|
+
if (app.name !== appName) {
|
|
68
|
+
issues.push({
|
|
69
|
+
type: 'app-name-mismatch',
|
|
70
|
+
message: `App name mismatch. Database has '${app.name}', but environment variable has '${appName}'.`,
|
|
71
|
+
recommendation: `Ensure VITE_APP_NAME (or NEXT_PUBLIC_APP_NAME) matches the app name in rbac_apps table exactly (case-sensitive).`
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Check if pages are configured
|
|
76
|
+
const { data: pages, error: pagesError } = await supabase
|
|
77
|
+
.from('rbac_app_pages')
|
|
78
|
+
.select('id')
|
|
79
|
+
.eq('app_id', app.id)
|
|
80
|
+
.limit(1);
|
|
81
|
+
|
|
82
|
+
if (pagesError || !pages || pages.length === 0) {
|
|
83
|
+
issues.push({
|
|
84
|
+
type: 'pages-not-configured',
|
|
85
|
+
message: `No pages found for app '${appName}' in rbac_app_pages table.`,
|
|
86
|
+
recommendation: 'Register your app pages in the rbac_app_pages table. Each route/page should have an entry.'
|
|
87
|
+
});
|
|
88
|
+
} else {
|
|
89
|
+
pagesConfigured = true;
|
|
90
|
+
|
|
91
|
+
// Check if permissions are configured for pages
|
|
92
|
+
const { data: permissions, error: permissionsError } = await supabase
|
|
93
|
+
.from('rbac_page_permissions')
|
|
94
|
+
.select('id')
|
|
95
|
+
.in('page_id', pages.map(p => p.id))
|
|
96
|
+
.limit(1);
|
|
97
|
+
|
|
98
|
+
if (permissionsError || !permissions || permissions.length === 0) {
|
|
99
|
+
issues.push({
|
|
100
|
+
type: 'permissions-not-configured',
|
|
101
|
+
message: `No permissions found for app '${appName}' pages in rbac_page_permissions table.`,
|
|
102
|
+
recommendation: 'Configure permissions for your app pages in the rbac_page_permissions table. Each page should have permissions for different operations (read, create, update, delete).'
|
|
103
|
+
});
|
|
104
|
+
} else {
|
|
105
|
+
permissionsConfigured = true;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Check if RLS is enabled on RBAC tables (basic check)
|
|
111
|
+
// Note: This is a simplified check - full RLS validation would require more complex queries
|
|
112
|
+
try {
|
|
113
|
+
// Type assertion needed because rbac_check_rls_status may not be in generated types yet
|
|
114
|
+
const { data: rbacTables, error: rlsError } = await (supabase.rpc as any)('rbac_check_rls_status');
|
|
115
|
+
|
|
116
|
+
if (rlsError) {
|
|
117
|
+
// RLS check function might not exist, which is okay
|
|
118
|
+
// We'll assume RLS is active if we can query the tables
|
|
119
|
+
rlsPoliciesActive = true;
|
|
120
|
+
recommendations.push('Consider adding an RLS status check function to validate RLS policies are active.');
|
|
121
|
+
} else {
|
|
122
|
+
rlsPoliciesActive = true;
|
|
123
|
+
}
|
|
124
|
+
} catch (error) {
|
|
125
|
+
// RLS check function might not exist or be available
|
|
126
|
+
// We'll assume RLS is active if we can query the tables
|
|
127
|
+
rlsPoliciesActive = true;
|
|
128
|
+
recommendations.push('Consider adding an RLS status check function to validate RLS policies are active.');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Check if organisation roles exist (sample check)
|
|
132
|
+
const { data: orgRoles, error: rolesError } = await supabase
|
|
133
|
+
.from('rbac_organisation_roles')
|
|
134
|
+
.select('id')
|
|
135
|
+
.limit(1);
|
|
136
|
+
|
|
137
|
+
if (rolesError) {
|
|
138
|
+
issues.push({
|
|
139
|
+
type: 'roles-not-configured',
|
|
140
|
+
message: 'Unable to query rbac_organisation_roles table. RLS might be blocking access or table might not exist.',
|
|
141
|
+
recommendation: 'Ensure rbac_organisation_roles table exists and RLS policies allow read access for authenticated users.'
|
|
142
|
+
});
|
|
143
|
+
} else {
|
|
144
|
+
rolesConfigured = true;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
} catch (error) {
|
|
148
|
+
issues.push({
|
|
149
|
+
type: 'app-not-configured',
|
|
150
|
+
message: `Error validating database configuration: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
151
|
+
recommendation: 'Check your Supabase connection and ensure you have the necessary permissions to query RBAC tables.'
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
appConfigured,
|
|
157
|
+
pagesConfigured,
|
|
158
|
+
permissionsConfigured,
|
|
159
|
+
rlsPoliciesActive,
|
|
160
|
+
rolesConfigured,
|
|
161
|
+
issues,
|
|
162
|
+
recommendations
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RBAC Compliance Module
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module RBAC/Compliance
|
|
5
|
+
* @since 1.0.0
|
|
6
|
+
*
|
|
7
|
+
* This module provides compliance checking utilities for RBAC/auth setup.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
isRBACInitialized,
|
|
12
|
+
validateRBACSetup,
|
|
13
|
+
getSetupIssues,
|
|
14
|
+
type SetupIssue,
|
|
15
|
+
type ComplianceResult,
|
|
16
|
+
} from './setup-validator';
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
checkRuntimeCompliance,
|
|
20
|
+
validateAndWarn,
|
|
21
|
+
type RuntimeComplianceResult,
|
|
22
|
+
} from './runtime-compliance';
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
validateDatabaseConfiguration,
|
|
26
|
+
type DatabaseComplianceResult,
|
|
27
|
+
type DatabaseIssue,
|
|
28
|
+
} from './database-validator';
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
getQuickFixes,
|
|
32
|
+
getCustomAuthCodeFixes,
|
|
33
|
+
getDuplicateConfigFixes,
|
|
34
|
+
getUnprotectedPageFixes,
|
|
35
|
+
getDirectSupabaseAuthFixes,
|
|
36
|
+
type QuickFix,
|
|
37
|
+
} from './quick-fix-suggestions';
|
|
38
|
+
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quick Fix Suggestions for RBAC/Auth Compliance
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module RBAC/Compliance/QuickFixSuggestions
|
|
5
|
+
* @since 1.0.0
|
|
6
|
+
*
|
|
7
|
+
* This module provides auto-suggest fixes for common RBAC/auth compliance issues.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export interface QuickFix {
|
|
11
|
+
issue: string;
|
|
12
|
+
suggestion: string;
|
|
13
|
+
codeExample?: string;
|
|
14
|
+
migrationSteps?: string[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get quick fix suggestions for custom auth code
|
|
19
|
+
*/
|
|
20
|
+
export function getCustomAuthCodeFixes(customCodeName: string, type: 'hook' | 'component' | 'util'): QuickFix {
|
|
21
|
+
const fixes: Record<string, QuickFix> = {
|
|
22
|
+
'useAuth': {
|
|
23
|
+
issue: `Custom ${type} '${customCodeName}' detected`,
|
|
24
|
+
suggestion: `Replace with useUnifiedAuth from pace-core`,
|
|
25
|
+
codeExample: `// Before
|
|
26
|
+
import { useAuth } from './hooks/useAuth';
|
|
27
|
+
|
|
28
|
+
// After
|
|
29
|
+
import { useUnifiedAuth } from '@jmruthers/pace-core';`,
|
|
30
|
+
migrationSteps: [
|
|
31
|
+
'Remove custom useAuth hook',
|
|
32
|
+
'Import useUnifiedAuth from @jmruthers/pace-core',
|
|
33
|
+
'Update all usages to use useUnifiedAuth',
|
|
34
|
+
'Ensure UnifiedAuthProvider wraps your app'
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
'usePermissions': {
|
|
38
|
+
issue: `Custom ${type} '${customCodeName}' detected`,
|
|
39
|
+
suggestion: `Replace with usePermissions from pace-core`,
|
|
40
|
+
codeExample: `// Before
|
|
41
|
+
import { usePermissions } from './hooks/usePermissions';
|
|
42
|
+
|
|
43
|
+
// After
|
|
44
|
+
import { usePermissions } from '@jmruthers/pace-core/rbac';`,
|
|
45
|
+
migrationSteps: [
|
|
46
|
+
'Remove custom usePermissions hook',
|
|
47
|
+
'Import usePermissions from @jmruthers/pace-core/rbac',
|
|
48
|
+
'Update all usages - ensure setupRBAC() has been called',
|
|
49
|
+
'Verify provider hierarchy is correct'
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
'PermissionGuard': {
|
|
53
|
+
issue: `Custom ${type} '${customCodeName}' detected`,
|
|
54
|
+
suggestion: `Replace with PagePermissionGuard from pace-core`,
|
|
55
|
+
codeExample: `// Before
|
|
56
|
+
import { PermissionGuard } from './components/PermissionGuard';
|
|
57
|
+
|
|
58
|
+
// After
|
|
59
|
+
import { PagePermissionGuard } from '@jmruthers/pace-core/rbac';`,
|
|
60
|
+
migrationSteps: [
|
|
61
|
+
'Remove custom PermissionGuard component',
|
|
62
|
+
'Import PagePermissionGuard from @jmruthers/pace-core/rbac',
|
|
63
|
+
'Wrap pages with PagePermissionGuard',
|
|
64
|
+
'Use pageName and operation props instead of custom permission strings'
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
'checkPermission': {
|
|
68
|
+
issue: `Custom ${type} '${customCodeName}' detected`,
|
|
69
|
+
suggestion: `Replace with isPermitted from pace-core`,
|
|
70
|
+
codeExample: `// Before
|
|
71
|
+
import { checkPermission } from './utils/permissions';
|
|
72
|
+
|
|
73
|
+
// After
|
|
74
|
+
import { isPermitted } from '@jmruthers/pace-core/rbac';`,
|
|
75
|
+
migrationSteps: [
|
|
76
|
+
'Remove custom checkPermission utility',
|
|
77
|
+
'Import isPermitted from @jmruthers/pace-core/rbac',
|
|
78
|
+
'Update all usages to use isPermitted with proper scope',
|
|
79
|
+
'Ensure setupRBAC() has been called'
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
return fixes[customCodeName] || {
|
|
85
|
+
issue: `Custom ${type} '${customCodeName}' detected`,
|
|
86
|
+
suggestion: `Use pace-core's equivalent instead. Check @jmruthers/pace-core documentation for the correct import.`,
|
|
87
|
+
migrationSteps: [
|
|
88
|
+
`Remove custom ${customCodeName} ${type}`,
|
|
89
|
+
'Find equivalent in pace-core',
|
|
90
|
+
'Import from @jmruthers/pace-core or @jmruthers/pace-core/rbac',
|
|
91
|
+
'Update all usages'
|
|
92
|
+
]
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Get quick fix suggestions for duplicate Supabase config
|
|
98
|
+
*/
|
|
99
|
+
export function getDuplicateConfigFixes(): QuickFix {
|
|
100
|
+
return {
|
|
101
|
+
issue: 'Multiple Supabase client instantiations found',
|
|
102
|
+
suggestion: 'Consolidate to a single Supabase client configuration',
|
|
103
|
+
codeExample: `// Before - Multiple createClient calls
|
|
104
|
+
// src/lib/supabase.ts
|
|
105
|
+
export const supabase = createClient(url, key);
|
|
106
|
+
|
|
107
|
+
// src/utils/api.ts
|
|
108
|
+
export const supabase = createClient(url, key);
|
|
109
|
+
|
|
110
|
+
// After - Single configuration
|
|
111
|
+
// src/lib/supabase.ts
|
|
112
|
+
export const supabase = createClient(
|
|
113
|
+
import.meta.env.VITE_SUPABASE_URL,
|
|
114
|
+
import.meta.env.VITE_SUPABASE_ANON_KEY
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
// src/utils/api.ts
|
|
118
|
+
import { supabase } from '../lib/supabase';`,
|
|
119
|
+
migrationSteps: [
|
|
120
|
+
'Create a single supabase.ts file in a shared location (e.g., src/lib/supabase.ts)',
|
|
121
|
+
'Move all Supabase client creation to this file',
|
|
122
|
+
'Export the client instance',
|
|
123
|
+
'Update all files to import from the shared location',
|
|
124
|
+
'Remove duplicate createClient calls'
|
|
125
|
+
]
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Get quick fix suggestions for unprotected pages
|
|
131
|
+
*/
|
|
132
|
+
export function getUnprotectedPageFixes(): QuickFix {
|
|
133
|
+
return {
|
|
134
|
+
issue: 'Route/page found without PagePermissionGuard',
|
|
135
|
+
suggestion: 'Wrap all routes with PagePermissionGuard',
|
|
136
|
+
codeExample: `// Before
|
|
137
|
+
<Route path="/dashboard" element={<Dashboard />} />
|
|
138
|
+
|
|
139
|
+
// After
|
|
140
|
+
<Route
|
|
141
|
+
path="/dashboard"
|
|
142
|
+
element={
|
|
143
|
+
<PagePermissionGuard pageName="dashboard" operation="read">
|
|
144
|
+
<Dashboard />
|
|
145
|
+
</PagePermissionGuard>
|
|
146
|
+
}
|
|
147
|
+
/>`,
|
|
148
|
+
migrationSteps: [
|
|
149
|
+
'Import PagePermissionGuard from @jmruthers/pace-core/rbac',
|
|
150
|
+
'Wrap each route/page component with PagePermissionGuard',
|
|
151
|
+
'Set pageName prop to match your page name in rbac_app_pages table',
|
|
152
|
+
'Set operation prop (read, create, update, or delete)',
|
|
153
|
+
'Ensure setupRBAC() has been called and providers are set up correctly'
|
|
154
|
+
]
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get quick fix suggestions for direct Supabase auth usage
|
|
160
|
+
*/
|
|
161
|
+
export function getDirectSupabaseAuthFixes(): QuickFix {
|
|
162
|
+
return {
|
|
163
|
+
issue: 'Direct Supabase auth usage detected',
|
|
164
|
+
suggestion: 'Use UnifiedAuthProvider and useUnifiedAuth from pace-core',
|
|
165
|
+
codeExample: `// Before
|
|
166
|
+
import { createClient } from '@supabase/supabase-js';
|
|
167
|
+
const supabase = createClient(url, key);
|
|
168
|
+
await supabase.auth.signInWithPassword({ email, password });
|
|
169
|
+
|
|
170
|
+
// After
|
|
171
|
+
import { useUnifiedAuth } from '@jmruthers/pace-core';
|
|
172
|
+
const { signIn } = useUnifiedAuth();
|
|
173
|
+
await signIn({ email, password });`,
|
|
174
|
+
migrationSteps: [
|
|
175
|
+
'Remove direct Supabase auth calls',
|
|
176
|
+
'Import useUnifiedAuth from @jmruthers/pace-core',
|
|
177
|
+
'Use the auth methods from useUnifiedAuth hook',
|
|
178
|
+
'Ensure UnifiedAuthProvider wraps your app',
|
|
179
|
+
'Update all auth-related code to use pace-core hooks'
|
|
180
|
+
]
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Get all quick fix suggestions for a compliance issue
|
|
186
|
+
*/
|
|
187
|
+
export function getQuickFixes(issueType: string, details?: Record<string, any>): QuickFix[] {
|
|
188
|
+
const fixes: QuickFix[] = [];
|
|
189
|
+
|
|
190
|
+
switch (issueType) {
|
|
191
|
+
case 'custom-auth-code':
|
|
192
|
+
if (details?.name && details?.type) {
|
|
193
|
+
fixes.push(getCustomAuthCodeFixes(details.name, details.type));
|
|
194
|
+
}
|
|
195
|
+
break;
|
|
196
|
+
case 'duplicate-config':
|
|
197
|
+
fixes.push(getDuplicateConfigFixes());
|
|
198
|
+
break;
|
|
199
|
+
case 'unprotected-pages':
|
|
200
|
+
fixes.push(getUnprotectedPageFixes());
|
|
201
|
+
break;
|
|
202
|
+
case 'direct-supabase-auth':
|
|
203
|
+
fixes.push(getDirectSupabaseAuthFixes());
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return fixes;
|
|
208
|
+
}
|
|
209
|
+
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime Compliance Checking
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module RBAC/Compliance/RuntimeCompliance
|
|
5
|
+
* @since 1.0.0
|
|
6
|
+
*
|
|
7
|
+
* This module provides runtime compliance checking utilities.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { validateRBACSetup, SetupIssue } from './setup-validator';
|
|
11
|
+
import { getRBACLogger } from '../config';
|
|
12
|
+
|
|
13
|
+
export interface RuntimeComplianceResult {
|
|
14
|
+
setup: {
|
|
15
|
+
isCompliant: boolean;
|
|
16
|
+
issues: SetupIssue[];
|
|
17
|
+
};
|
|
18
|
+
warnings: string[];
|
|
19
|
+
providerContext?: {
|
|
20
|
+
available: boolean;
|
|
21
|
+
message?: string;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Check runtime compliance
|
|
27
|
+
*
|
|
28
|
+
* This function checks if the RBAC system is properly set up and logs warnings
|
|
29
|
+
* to the console if issues are found. This is intended for development-time
|
|
30
|
+
* validation only.
|
|
31
|
+
*
|
|
32
|
+
* @returns Runtime compliance result
|
|
33
|
+
*/
|
|
34
|
+
export function checkRuntimeCompliance(): RuntimeComplianceResult {
|
|
35
|
+
const logger = getRBACLogger();
|
|
36
|
+
const setupValidation = validateRBACSetup();
|
|
37
|
+
const warnings: string[] = [];
|
|
38
|
+
|
|
39
|
+
if (!setupValidation.isCompliant) {
|
|
40
|
+
setupValidation.issues.forEach(issue => {
|
|
41
|
+
const warning = `[RBAC Compliance] ${issue.message}\n Recommendation: ${issue.recommendation}`;
|
|
42
|
+
warnings.push(warning);
|
|
43
|
+
logger.warn(warning);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Check for provider context issues
|
|
48
|
+
const providerContextIssues = setupValidation.issues.filter(
|
|
49
|
+
issue => issue.type === 'missing-provider-context' || issue.type === 'not-initialized'
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const providerContext = providerContextIssues.length > 0 ? {
|
|
53
|
+
available: false,
|
|
54
|
+
message: 'UnifiedAuthProvider context may not be available. Ensure your app is wrapped with UnifiedAuthProvider from @jmruthers/pace-core.'
|
|
55
|
+
} : {
|
|
56
|
+
available: true
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
setup: setupValidation,
|
|
61
|
+
warnings,
|
|
62
|
+
providerContext
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Validate and warn about RBAC setup issues
|
|
68
|
+
*
|
|
69
|
+
* This is a convenience function that checks compliance and logs warnings.
|
|
70
|
+
* Call this in development mode to get early warnings about setup issues.
|
|
71
|
+
*/
|
|
72
|
+
export function validateAndWarn(): void {
|
|
73
|
+
if (import.meta.env.MODE === 'development' || import.meta.env.DEV) {
|
|
74
|
+
checkRuntimeCompliance();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|