@jmruthers/pace-core 0.5.13 → 0.5.15
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/dist/{DataTable-NNCMQSDG.js → DataTable-RICY7YDA.js} +3 -3
- package/dist/{chunk-AMOT5ZSZ.js → chunk-F6IHN3DC.js} +57 -17
- package/dist/chunk-F6IHN3DC.js.map +1 -0
- package/dist/{chunk-BUWLPWDA.js → chunk-JPXJGMOO.js} +2 -2
- package/dist/{chunk-PILT65PA.js → chunk-JZCNOXSG.js} +2 -2
- package/dist/{chunk-5E3YF7HA.js → chunk-MQGGT7FF.js} +35 -31
- package/dist/{chunk-5E3YF7HA.js.map → chunk-MQGGT7FF.js.map} +1 -1
- package/dist/components.js +3 -3
- package/dist/index.js +4 -4
- package/dist/rbac/index.js +2 -2
- package/dist/utils.js +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +1 -1
- 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/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +1 -1
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- 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/DataAccessRecord.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/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventContextType.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- package/docs/api/interfaces/EventProviderProps.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/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 +1 -1
- 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 +1 -1
- 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/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.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/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContextType.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACProviderProps.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- 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/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/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.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 +8 -8
- package/package.json +1 -1
- package/src/rbac/components/PagePermissionGuard.tsx +21 -13
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +478 -0
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +157 -0
- package/src/rbac/hooks/useCan.test.ts +1 -1
- package/src/rbac/hooks/usePermissions.test.ts +5 -8
- package/src/rbac/hooks/usePermissions.ts +74 -22
- package/dist/chunk-AMOT5ZSZ.js.map +0 -1
- /package/dist/{DataTable-NNCMQSDG.js.map → DataTable-RICY7YDA.js.map} +0 -0
- /package/dist/{chunk-BUWLPWDA.js.map → chunk-JPXJGMOO.js.map} +0 -0
- /package/dist/{chunk-PILT65PA.js.map → chunk-JZCNOXSG.js.map} +0 -0
package/docs/api/modules.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
[@jmruthers/pace-core - v0.5.
|
|
1
|
+
[@jmruthers/pace-core - v0.5.15](README.md) / Exports
|
|
2
2
|
|
|
3
|
-
# @jmruthers/pace-core - v0.5.
|
|
3
|
+
# @jmruthers/pace-core - v0.5.15
|
|
4
4
|
|
|
5
5
|
**`File`**
|
|
6
6
|
|
|
@@ -5434,7 +5434,7 @@ function MyComponent() {
|
|
|
5434
5434
|
|
|
5435
5435
|
#### Defined in
|
|
5436
5436
|
|
|
5437
|
-
[packages/core/src/rbac/hooks/usePermissions.ts:
|
|
5437
|
+
[packages/core/src/rbac/hooks/usePermissions.ts:175](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/rbac/hooks/usePermissions.ts#L175)
|
|
5438
5438
|
|
|
5439
5439
|
___
|
|
5440
5440
|
|
|
@@ -5484,7 +5484,7 @@ function MyComponent() {
|
|
|
5484
5484
|
|
|
5485
5485
|
#### Defined in
|
|
5486
5486
|
|
|
5487
|
-
[packages/core/src/rbac/hooks/usePermissions.ts:
|
|
5487
|
+
[packages/core/src/rbac/hooks/usePermissions.ts:254](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/rbac/hooks/usePermissions.ts#L254)
|
|
5488
5488
|
|
|
5489
5489
|
___
|
|
5490
5490
|
|
|
@@ -5541,7 +5541,7 @@ function MyComponent() {
|
|
|
5541
5541
|
|
|
5542
5542
|
#### Defined in
|
|
5543
5543
|
|
|
5544
|
-
[packages/core/src/rbac/hooks/usePermissions.ts:
|
|
5544
|
+
[packages/core/src/rbac/hooks/usePermissions.ts:328](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/rbac/hooks/usePermissions.ts#L328)
|
|
5545
5545
|
|
|
5546
5546
|
___
|
|
5547
5547
|
|
|
@@ -5592,7 +5592,7 @@ function MyComponent() {
|
|
|
5592
5592
|
|
|
5593
5593
|
#### Defined in
|
|
5594
5594
|
|
|
5595
|
-
[packages/core/src/rbac/hooks/usePermissions.ts:
|
|
5595
|
+
[packages/core/src/rbac/hooks/usePermissions.ts:410](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/rbac/hooks/usePermissions.ts#L410)
|
|
5596
5596
|
|
|
5597
5597
|
___
|
|
5598
5598
|
|
|
@@ -5643,7 +5643,7 @@ function MyComponent() {
|
|
|
5643
5643
|
|
|
5644
5644
|
#### Defined in
|
|
5645
5645
|
|
|
5646
|
-
[packages/core/src/rbac/hooks/usePermissions.ts:
|
|
5646
|
+
[packages/core/src/rbac/hooks/usePermissions.ts:495](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/rbac/hooks/usePermissions.ts#L495)
|
|
5647
5647
|
|
|
5648
5648
|
___
|
|
5649
5649
|
|
|
@@ -5694,7 +5694,7 @@ function MyComponent() {
|
|
|
5694
5694
|
|
|
5695
5695
|
#### Defined in
|
|
5696
5696
|
|
|
5697
|
-
[packages/core/src/rbac/hooks/usePermissions.ts:
|
|
5697
|
+
[packages/core/src/rbac/hooks/usePermissions.ts:579](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/rbac/hooks/usePermissions.ts#L579)
|
|
5698
5698
|
|
|
5699
5699
|
___
|
|
5700
5700
|
|
package/package.json
CHANGED
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
* - RBAC types - Type definitions
|
|
68
68
|
*/
|
|
69
69
|
|
|
70
|
-
import React, { useMemo, useCallback, useEffect, useState } from 'react';
|
|
70
|
+
import React, { useMemo, useCallback, useEffect, useState, useRef } from 'react';
|
|
71
71
|
import { useCan } from '../hooks';
|
|
72
72
|
import { useUnifiedAuth } from '../../providers/UnifiedAuthProvider';
|
|
73
73
|
import { UUID, Permission, Scope } from '../types';
|
|
@@ -132,6 +132,10 @@ export function PagePermissionGuard({
|
|
|
132
132
|
const [hasChecked, setHasChecked] = useState(false);
|
|
133
133
|
const [checkError, setCheckError] = useState<Error | null>(null);
|
|
134
134
|
const [resolvedScope, setResolvedScope] = useState<Scope | null>(null);
|
|
135
|
+
|
|
136
|
+
// Use ref to avoid infinite re-renders from supabase dependency
|
|
137
|
+
const supabaseRef = useRef(supabase);
|
|
138
|
+
supabaseRef.current = supabase;
|
|
135
139
|
|
|
136
140
|
// Resolve scope - either use provided scope or resolve from context
|
|
137
141
|
useEffect(() => {
|
|
@@ -145,12 +149,12 @@ export function PagePermissionGuard({
|
|
|
145
149
|
let appId: string | undefined = undefined;
|
|
146
150
|
|
|
147
151
|
// Try to resolve from database
|
|
148
|
-
if (
|
|
152
|
+
if (supabaseRef.current) {
|
|
149
153
|
const appName = getCurrentAppName();
|
|
150
154
|
if (appName) {
|
|
151
155
|
try {
|
|
152
156
|
console.log('[PagePermissionGuard] Resolving app name to ID:', appName);
|
|
153
|
-
const { data: app, error } = await
|
|
157
|
+
const { data: app, error } = await supabaseRef.current
|
|
154
158
|
.from('rbac_apps')
|
|
155
159
|
.select('id, name, is_active')
|
|
156
160
|
.eq('name', appName)
|
|
@@ -160,7 +164,7 @@ export function PagePermissionGuard({
|
|
|
160
164
|
if (error) {
|
|
161
165
|
console.error('[PagePermissionGuard] Database error resolving app ID:', error);
|
|
162
166
|
// Check if app exists but is inactive
|
|
163
|
-
const { data: inactiveApp } = await
|
|
167
|
+
const { data: inactiveApp } = await supabaseRef.current
|
|
164
168
|
.from('rbac_apps')
|
|
165
169
|
.select('id, name, is_active')
|
|
166
170
|
.eq('name', appName)
|
|
@@ -256,9 +260,9 @@ export function PagePermissionGuard({
|
|
|
256
260
|
}
|
|
257
261
|
|
|
258
262
|
// If we only have event, resolve organisation from event
|
|
259
|
-
if (selectedEventId &&
|
|
263
|
+
if (selectedEventId && supabaseRef.current) {
|
|
260
264
|
try {
|
|
261
|
-
const eventScope = await createScopeFromEvent(
|
|
265
|
+
const eventScope = await createScopeFromEvent(supabaseRef.current, selectedEventId);
|
|
262
266
|
if (!eventScope) {
|
|
263
267
|
setCheckError(new Error('Could not resolve organization from event context'));
|
|
264
268
|
setResolvedScope(null); // Ensure we don't proceed with incomplete scope
|
|
@@ -283,7 +287,7 @@ export function PagePermissionGuard({
|
|
|
283
287
|
};
|
|
284
288
|
|
|
285
289
|
resolveScope();
|
|
286
|
-
}, [scope, selectedOrganisationId, selectedEventId
|
|
290
|
+
}, [scope, selectedOrganisationId, selectedEventId]);
|
|
287
291
|
|
|
288
292
|
// Determine the page ID for permission checking
|
|
289
293
|
const effectivePageId = useMemo((): string => {
|
|
@@ -315,7 +319,7 @@ export function PagePermissionGuard({
|
|
|
315
319
|
|
|
316
320
|
// Use a stable scope object to prevent unnecessary re-renders
|
|
317
321
|
const scopeForUseCan = useMemo(() => {
|
|
318
|
-
return shouldCheckPermissions ? resolvedScope : { organisationId: '
|
|
322
|
+
return shouldCheckPermissions ? resolvedScope : { organisationId: '', appId: '', eventId: undefined };
|
|
319
323
|
}, [shouldCheckPermissions, resolvedScope]);
|
|
320
324
|
|
|
321
325
|
const { can, isLoading: canIsLoading, error: canError } = useCan(
|
|
@@ -392,27 +396,31 @@ export function PagePermissionGuard({
|
|
|
392
396
|
willShowLoading: isLoading || !resolvedScope,
|
|
393
397
|
willShowError: !!checkError,
|
|
394
398
|
willShowAccessDenied: !can,
|
|
395
|
-
willShowContent: !isLoading && !!resolvedScope && !checkError && can
|
|
399
|
+
willShowContent: !isLoading && !!resolvedScope && !checkError && can,
|
|
400
|
+
scopeKey: resolvedScope ? `${resolvedScope.organisationId}-${resolvedScope.eventId}-${resolvedScope.appId}` : 'no-scope'
|
|
396
401
|
});
|
|
397
402
|
|
|
403
|
+
// Create a key to force re-render when scope changes
|
|
404
|
+
const scopeKey = resolvedScope ? `${resolvedScope.organisationId}-${resolvedScope.eventId}-${resolvedScope.appId}` : 'no-scope';
|
|
405
|
+
|
|
398
406
|
// Show loading state
|
|
399
407
|
if (isLoading || !resolvedScope) {
|
|
400
|
-
return
|
|
408
|
+
return <div key={`loading-${scopeKey}`}>{loading}</div>;
|
|
401
409
|
}
|
|
402
410
|
|
|
403
411
|
// Show error state
|
|
404
412
|
if (checkError) {
|
|
405
413
|
console.error(`[PagePermissionGuard] Permission check failed for page ${pageName}:`, checkError);
|
|
406
|
-
return
|
|
414
|
+
return <div key={`error-${scopeKey}`}>{fallback}</div>;
|
|
407
415
|
}
|
|
408
416
|
|
|
409
417
|
// Show access denied
|
|
410
418
|
if (!can) {
|
|
411
|
-
return
|
|
419
|
+
return <div key={`denied-${scopeKey}`}>{fallback}</div>;
|
|
412
420
|
}
|
|
413
421
|
|
|
414
422
|
// Show protected content
|
|
415
|
-
return
|
|
423
|
+
return <div key={`content-${scopeKey}`}>{children}</div>;
|
|
416
424
|
}
|
|
417
425
|
|
|
418
426
|
/**
|