@jmruthers/pace-core 0.5.143 → 0.5.144
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/{chunk-VP44VQJ6.js → chunk-FC46D3KC.js} +33 -15
- package/dist/chunk-FC46D3KC.js.map +1 -0
- package/dist/components.js +1 -1
- package/dist/index.js +1 -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/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/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.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 +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/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/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- 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 +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.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/ProtectedRouteProps.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/RBACLogger.md +1 -1
- package/docs/api/interfaces/ResourcePermissions.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RoleManagementResult.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/SessionRestorationLoaderProps.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/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/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.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 +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
- 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 +2 -2
- package/package.json +1 -1
- package/src/components/NavigationMenu/NavigationMenu.tsx +51 -15
- package/dist/chunk-VP44VQJ6.js.map +0 -1
package/docs/api/modules.md
CHANGED
package/package.json
CHANGED
|
@@ -451,7 +451,7 @@ export const NavigationMenu = React.forwardRef<
|
|
|
451
451
|
// When filterByPermissions is false, we'll simply ignore the resolved scope
|
|
452
452
|
const { supabase } = authContext || {};
|
|
453
453
|
const { selectedOrganisation } = authContext || {};
|
|
454
|
-
const { resolvedScope, isLoading: scopeLoading } = useResolvedScope({
|
|
454
|
+
const { resolvedScope, isLoading: scopeLoading, error: scopeError } = useResolvedScope({
|
|
455
455
|
supabase: filterByPermissions ? (supabase || null) : null,
|
|
456
456
|
selectedOrganisationId: filterByPermissions ? (selectedOrganisation?.id || null) : null,
|
|
457
457
|
selectedEventId: filterByPermissions ? (selectedEvent?.event_id || null) : null
|
|
@@ -467,12 +467,30 @@ export const NavigationMenu = React.forwardRef<
|
|
|
467
467
|
appId: undefined
|
|
468
468
|
});
|
|
469
469
|
|
|
470
|
-
//
|
|
470
|
+
// Build scope from resolvedScope if available, otherwise fall back to context values
|
|
471
|
+
// This handles the case where useResolvedScope errored initially but context is now ready
|
|
472
|
+
const effectiveScope = React.useMemo(() => {
|
|
473
|
+
if (!scopeLoading && resolvedScope?.organisationId) {
|
|
474
|
+
// Use resolved scope if available
|
|
475
|
+
return resolvedScope;
|
|
476
|
+
} else if (!scopeLoading && selectedOrganisation?.id) {
|
|
477
|
+
// Fall back to building scope from context if resolvedScope is null but context is ready
|
|
478
|
+
// This handles the case where useResolvedScope errored but context is now available
|
|
479
|
+
return {
|
|
480
|
+
organisationId: selectedOrganisation.id,
|
|
481
|
+
eventId: selectedEvent?.event_id || undefined,
|
|
482
|
+
appId: undefined // App ID will be resolved by usePermissions if needed
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
return null;
|
|
486
|
+
}, [scopeLoading, resolvedScope, selectedOrganisation?.id, selectedEvent?.event_id]);
|
|
487
|
+
|
|
488
|
+
// Only update stable scope when effective scope is available AND values actually changed
|
|
471
489
|
// This prevents triggering permission refetches during scope transitions
|
|
472
|
-
if (
|
|
473
|
-
const newOrgId =
|
|
474
|
-
const newEventId =
|
|
475
|
-
const newAppId =
|
|
490
|
+
if (effectiveScope?.organisationId) {
|
|
491
|
+
const newOrgId = effectiveScope.organisationId;
|
|
492
|
+
const newEventId = effectiveScope.eventId;
|
|
493
|
+
const newAppId = effectiveScope.appId;
|
|
476
494
|
|
|
477
495
|
// Only update if values actually changed
|
|
478
496
|
if (stableScopeRef.current.organisationId !== newOrgId ||
|
|
@@ -484,7 +502,7 @@ export const NavigationMenu = React.forwardRef<
|
|
|
484
502
|
appId: newAppId
|
|
485
503
|
};
|
|
486
504
|
}
|
|
487
|
-
} else if (!scopeLoading && !
|
|
505
|
+
} else if (!scopeLoading && !effectiveScope) {
|
|
488
506
|
// Only reset if we had a previous value and scope is resolved - don't clear during loading
|
|
489
507
|
if (stableScopeRef.current.organisationId !== '') {
|
|
490
508
|
stableScopeRef.current = {
|
|
@@ -522,13 +540,28 @@ export const NavigationMenu = React.forwardRef<
|
|
|
522
540
|
// Only wait for event context if we're actually loading events
|
|
523
541
|
const isEventContextReady = eventLoadingRaw === undefined ? true : !eventLoading;
|
|
524
542
|
|
|
543
|
+
// Check if we have valid context for permission checking
|
|
544
|
+
// Use actual context values, not just resolvedScope, because resolvedScope might be null
|
|
545
|
+
// if useResolvedScope errored initially but context is now ready
|
|
546
|
+
const hasValidContext = isOrgContextReady && isEventContextReady;
|
|
547
|
+
|
|
548
|
+
// If scope is still loading or we don't have valid context yet, show nothing
|
|
549
|
+
// BUT: If scope errored but context is now ready, retry (don't block forever)
|
|
550
|
+
const shouldWaitForScope = scopeLoading || (!hasValidContext);
|
|
551
|
+
const shouldRetryAfterError = scopeError && hasValidContext && !scopeLoading;
|
|
552
|
+
|
|
525
553
|
// During initial load or when scope/context is loading, show nothing
|
|
526
|
-
if (!authContext || !rbacContext ||
|
|
554
|
+
if (!authContext || !rbacContext || (shouldWaitForScope && !shouldRetryAfterError)) {
|
|
527
555
|
// Still loading - show nothing to prevent security risk
|
|
528
556
|
// Note: We check both org and event context readiness to prevent premature permission checks
|
|
557
|
+
// Exception: If scope errored but context is now ready, we'll retry below
|
|
529
558
|
return [];
|
|
530
559
|
}
|
|
531
560
|
|
|
561
|
+
// If scope errored but context is now ready, we can proceed with permission checks
|
|
562
|
+
// The resolvedScope might be null, but we'll use the actual context values
|
|
563
|
+
// usePermissions will handle the scope resolution internally
|
|
564
|
+
|
|
532
565
|
// During permission refetch (after initial load), preserve previous items if we have them
|
|
533
566
|
// This prevents navigation from disappearing when switching events
|
|
534
567
|
if (permissionsLoading) {
|
|
@@ -728,8 +761,10 @@ export const NavigationMenu = React.forwardRef<
|
|
|
728
761
|
permissionMap,
|
|
729
762
|
hasAnyPermission,
|
|
730
763
|
scopeLoading,
|
|
764
|
+
scopeError,
|
|
731
765
|
permissionsLoading,
|
|
732
766
|
resolvedScope,
|
|
767
|
+
effectiveScope,
|
|
733
768
|
auditLog,
|
|
734
769
|
// Add event context state to dependencies so we re-check permissions when event context becomes available
|
|
735
770
|
eventLoadingRaw,
|
|
@@ -742,18 +777,19 @@ export const NavigationMenu = React.forwardRef<
|
|
|
742
777
|
// Log navigation access attempts for debugging
|
|
743
778
|
React.useEffect(() => {
|
|
744
779
|
if (auditLog && authContext) {
|
|
780
|
+
// Find the current navigation item to log its actual permissions
|
|
781
|
+
const currentItem = items?.find(item => item.href === currentPath || item.id === 'navigation-menu');
|
|
745
782
|
logger.debug('NavigationMenu', 'Navigation access attempt:', {
|
|
746
|
-
itemId: 'navigation-menu',
|
|
747
|
-
label: 'Navigation Menu',
|
|
783
|
+
itemId: currentItem?.id || 'navigation-menu',
|
|
784
|
+
label: currentItem?.label || 'Navigation Menu',
|
|
748
785
|
href: currentPath,
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
accessLevel: null,
|
|
786
|
+
permissions: currentItem?.permissions || null,
|
|
787
|
+
roles: currentItem?.roles || null,
|
|
788
|
+
accessLevel: currentItem?.accessLevel || null,
|
|
753
789
|
timestamp: new Date().toISOString()
|
|
754
790
|
});
|
|
755
791
|
}
|
|
756
|
-
}, [auditLog, authContext, currentPath]);
|
|
792
|
+
}, [auditLog, authContext, currentPath, items]);
|
|
757
793
|
|
|
758
794
|
|
|
759
795
|
// Handle keyboard navigation for hierarchical mode
|