@jmruthers/pace-core 0.6.2 → 0.6.3
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 +45 -0
- package/cursor-rules/00-pace-core-compliance.mdc +34 -2
- package/dist/{AuthService-BPvc3Ka0.d.ts → AuthService-Cb34EQs3.d.ts} +9 -1
- package/dist/{DataTable-TPTKCX4D.js → DataTable-THFPBKTP.js} +9 -8
- package/dist/{PublicPageProvider-DC6kCaqf.d.ts → PublicPageProvider-DEMpysFR.d.ts} +45 -67
- package/dist/{UnifiedAuthProvider-CVcTjx-d.d.ts → UnifiedAuthProvider-CKvHP1MK.d.ts} +1 -8
- package/dist/{UnifiedAuthProvider-CH6Z342H.js → UnifiedAuthProvider-KAGUYQ4J.js} +5 -4
- package/dist/{api-MVVQZLJI.js → api-IAGWF3ZG.js} +10 -10
- package/dist/{audit-B5P6FFIR.js → audit-V53FV5AG.js} +2 -2
- package/dist/{chunk-SFZUDBL5.js → chunk-2T2IG7T7.js} +70 -56
- package/dist/chunk-2T2IG7T7.js.map +1 -0
- package/dist/{chunk-MMZ7JXPU.js → chunk-6Z7LTB3D.js} +13 -21
- package/dist/{chunk-MMZ7JXPU.js.map → chunk-6Z7LTB3D.js.map} +1 -1
- package/dist/{chunk-6J4GEEJR.js → chunk-CNCQDFLN.js} +53 -27
- package/dist/chunk-CNCQDFLN.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/{chunk-EHMR7VYL.js → chunk-DWUBLJJM.js} +361 -187
- package/dist/chunk-DWUBLJJM.js.map +1 -0
- package/dist/{chunk-2UOI2FG5.js → chunk-HFZBI76P.js} +4 -4
- package/dist/{chunk-F2IMUDXZ.js → chunk-M7MPQISP.js} +2 -2
- package/dist/{chunk-3XC4CPTD.js → chunk-PQBSKX33.js} +244 -5727
- package/dist/chunk-PQBSKX33.js.map +1 -0
- package/dist/chunk-QRPVRXYT.js +226 -0
- package/dist/chunk-QRPVRXYT.js.map +1 -0
- package/dist/{chunk-24UVZUZG.js → chunk-RWEBCB47.js} +129 -387
- package/dist/chunk-RWEBCB47.js.map +1 -0
- package/dist/{chunk-XWQCNGTQ.js → chunk-YDQHOZNA.js} +173 -79
- package/dist/chunk-YDQHOZNA.js.map +1 -0
- package/dist/{chunk-NECFR5MM.js → chunk-ZNIWI3UC.js} +562 -644
- package/dist/chunk-ZNIWI3UC.js.map +1 -0
- package/dist/components.d.ts +2 -2
- package/dist/components.js +12 -13
- package/dist/contextValidator-3JNZKUTX.js +9 -0
- package/dist/contextValidator-3JNZKUTX.js.map +1 -0
- package/dist/eslint-rules/pace-core-compliance.cjs +106 -0
- package/dist/hooks.d.ts +2 -2
- package/dist/hooks.js +7 -6
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.js +21 -16
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +3 -3
- package/dist/providers.js +4 -3
- package/dist/rbac/index.d.ts +67 -27
- package/dist/rbac/index.js +15 -8
- package/dist/styles/index.js +1 -1
- package/dist/theming/runtime.js +1 -1
- package/dist/types.js +1 -1
- package/dist/{usePublicRouteParams-1oMokgLF.d.ts → usePublicRouteParams-i3qtoBgg.d.ts} +7 -16
- package/dist/utils.js +5 -7
- package/dist/utils.js.map +1 -1
- package/docs/api/README.md +14 -16
- package/docs/api/modules.md +3796 -2513
- package/docs/components/context-selector.md +126 -0
- package/docs/migration/RBAC_SCOPE_MIGRATION.md +385 -0
- package/docs/pace-mint-fix-auto-selection.md +218 -0
- package/docs/pace-mint-rbac-setup.md +391 -0
- package/docs/rbac/secure-client-protection.md +330 -0
- package/package.json +3 -3
- package/scripts/audit/core/checks/compliance.cjs +72 -0
- package/scripts/audit/core/checks/dependencies.cjs +559 -28
- package/scripts/audit/core/checks/documentation.cjs +68 -3
- package/scripts/audit/core/checks/environment.cjs +2 -14
- package/scripts/audit/core/checks/error-handling.cjs +47 -6
- package/src/components/ContextSelector/ContextSelector.tsx +384 -0
- package/src/components/ContextSelector/index.ts +3 -0
- package/src/components/DataTable/components/RowComponent.tsx +19 -19
- package/src/components/DataTable/components/UnifiedTableBody.tsx +2 -2
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +8 -6
- package/src/components/Dialog/Dialog.tsx +29 -1
- package/src/components/FileDisplay/FileDisplay.tsx +42 -10
- package/src/components/Header/Header.test.tsx +43 -73
- package/src/components/Header/Header.tsx +44 -45
- package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +10 -19
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +2 -2
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +5 -5
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +9 -9
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +135 -33
- package/src/components/PaceAppLayout/README.md +14 -17
- package/src/components/PaceAppLayout/test-setup.tsx +2 -2
- package/src/components/index.ts +5 -5
- package/src/eslint-rules/pace-core-compliance.cjs +106 -0
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +4 -98
- package/src/hooks/useAppConfig.ts +15 -30
- package/src/hooks/useFileDisplay.ts +77 -50
- package/src/index.ts +4 -5
- package/src/providers/services/AuthServiceProvider.tsx +17 -7
- package/src/providers/services/EventServiceProvider.tsx +33 -5
- package/src/providers/services/UnifiedAuthProvider.tsx +90 -134
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +1 -1
- package/src/rbac/adapters.tsx +2 -2
- package/src/rbac/api.test.ts +59 -51
- package/src/rbac/api.ts +178 -132
- package/src/rbac/components/PagePermissionGuard.tsx +38 -10
- package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +32 -21
- package/src/rbac/hooks/permissions/useAccessLevel.ts +1 -1
- package/src/rbac/hooks/permissions/useCan.ts +41 -11
- package/src/rbac/hooks/permissions/useHasAllPermissions.ts +1 -1
- package/src/rbac/hooks/permissions/useHasAnyPermission.ts +1 -1
- package/src/rbac/hooks/permissions/useMultiplePermissions.ts +1 -1
- package/src/rbac/hooks/useCan.test.ts +0 -9
- package/src/rbac/hooks/useRBAC.test.ts +1 -5
- package/src/rbac/hooks/useRBAC.ts +36 -37
- package/src/rbac/hooks/useResolvedScope.test.ts +120 -35
- package/src/rbac/hooks/useResolvedScope.ts +35 -40
- package/src/rbac/hooks/useSecureSupabase.ts +7 -7
- package/src/rbac/index.ts +7 -0
- package/src/rbac/secureClient.test.ts +22 -18
- package/src/rbac/secureClient.ts +103 -16
- package/src/rbac/security.ts +0 -17
- package/src/rbac/types.ts +1 -0
- package/src/rbac/utils/__tests__/contextValidator.test.ts +64 -86
- package/src/rbac/utils/clientSecurity.ts +93 -0
- package/src/rbac/utils/contextValidator.ts +77 -168
- package/src/services/AuthService.ts +39 -7
- package/src/services/EventService.ts +186 -54
- package/src/services/OrganisationService.ts +81 -14
- package/src/services/__tests__/EventService.test.ts +1 -2
- package/src/services/base/BaseService.ts +3 -0
- package/src/utils/dynamic/dynamicUtils.ts +7 -4
- package/dist/chunk-24UVZUZG.js.map +0 -1
- package/dist/chunk-3XC4CPTD.js.map +0 -1
- package/dist/chunk-6J4GEEJR.js.map +0 -1
- package/dist/chunk-7D4SUZUM.js +0 -38
- package/dist/chunk-EHMR7VYL.js.map +0 -1
- package/dist/chunk-NECFR5MM.js.map +0 -1
- package/dist/chunk-SFZUDBL5.js.map +0 -1
- package/dist/chunk-XWQCNGTQ.js.map +0 -1
- package/docs/api/classes/ColumnFactory.md +0 -243
- package/docs/api/classes/InvalidScopeError.md +0 -73
- package/docs/api/classes/Logger.md +0 -178
- package/docs/api/classes/MissingUserContextError.md +0 -66
- package/docs/api/classes/OrganisationContextRequiredError.md +0 -66
- package/docs/api/classes/PermissionDeniedError.md +0 -73
- package/docs/api/classes/RBACAuditManager.md +0 -297
- package/docs/api/classes/RBACCache.md +0 -322
- package/docs/api/classes/RBACEngine.md +0 -171
- package/docs/api/classes/RBACError.md +0 -76
- package/docs/api/classes/RBACNotInitializedError.md +0 -66
- package/docs/api/classes/SecureSupabaseClient.md +0 -163
- package/docs/api/classes/StorageUtils.md +0 -328
- package/docs/api/enums/FileCategory.md +0 -184
- package/docs/api/enums/LogLevel.md +0 -54
- package/docs/api/enums/RBACErrorCode.md +0 -228
- package/docs/api/enums/RPCFunction.md +0 -118
- package/docs/api/interfaces/AddressFieldProps.md +0 -241
- package/docs/api/interfaces/AddressFieldRef.md +0 -94
- package/docs/api/interfaces/AggregateConfig.md +0 -43
- package/docs/api/interfaces/AutocompleteOptions.md +0 -75
- package/docs/api/interfaces/AvatarProps.md +0 -128
- package/docs/api/interfaces/BadgeProps.md +0 -34
- package/docs/api/interfaces/ButtonProps.md +0 -56
- package/docs/api/interfaces/CalendarProps.md +0 -73
- package/docs/api/interfaces/CardProps.md +0 -69
- package/docs/api/interfaces/ColorPalette.md +0 -7
- package/docs/api/interfaces/ColorShade.md +0 -66
- package/docs/api/interfaces/ComplianceResult.md +0 -30
- package/docs/api/interfaces/DataAccessRecord.md +0 -96
- package/docs/api/interfaces/DataRecord.md +0 -11
- package/docs/api/interfaces/DataTableAction.md +0 -252
- package/docs/api/interfaces/DataTableColumn.md +0 -504
- package/docs/api/interfaces/DataTableProps.md +0 -625
- package/docs/api/interfaces/DataTableToolbarButton.md +0 -96
- package/docs/api/interfaces/DatabaseComplianceResult.md +0 -85
- package/docs/api/interfaces/DatabaseIssue.md +0 -41
- package/docs/api/interfaces/EmptyStateConfig.md +0 -61
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +0 -235
- package/docs/api/interfaces/ErrorBoundaryProps.md +0 -147
- package/docs/api/interfaces/ErrorBoundaryProviderProps.md +0 -36
- package/docs/api/interfaces/ErrorBoundaryState.md +0 -75
- package/docs/api/interfaces/EventAppRoleData.md +0 -71
- package/docs/api/interfaces/ExportColumn.md +0 -90
- package/docs/api/interfaces/ExportOptions.md +0 -126
- package/docs/api/interfaces/FileDisplayProps.md +0 -249
- package/docs/api/interfaces/FileMetadata.md +0 -129
- package/docs/api/interfaces/FileReference.md +0 -118
- package/docs/api/interfaces/FileSizeLimits.md +0 -7
- package/docs/api/interfaces/FileUploadOptions.md +0 -139
- package/docs/api/interfaces/FileUploadProps.md +0 -296
- package/docs/api/interfaces/FooterProps.md +0 -107
- package/docs/api/interfaces/FormFieldProps.md +0 -166
- package/docs/api/interfaces/FormProps.md +0 -113
- package/docs/api/interfaces/GrantEventAppRoleParams.md +0 -122
- package/docs/api/interfaces/InactivityWarningModalProps.md +0 -115
- package/docs/api/interfaces/InputProps.md +0 -56
- package/docs/api/interfaces/LabelProps.md +0 -107
- package/docs/api/interfaces/LoggerConfig.md +0 -62
- package/docs/api/interfaces/LoginFormProps.md +0 -187
- package/docs/api/interfaces/NavigationAccessRecord.md +0 -107
- package/docs/api/interfaces/NavigationContextType.md +0 -164
- package/docs/api/interfaces/NavigationGuardProps.md +0 -139
- package/docs/api/interfaces/NavigationItem.md +0 -120
- package/docs/api/interfaces/NavigationMenuProps.md +0 -221
- package/docs/api/interfaces/NavigationProviderProps.md +0 -117
- package/docs/api/interfaces/Organisation.md +0 -140
- package/docs/api/interfaces/OrganisationContextType.md +0 -388
- package/docs/api/interfaces/OrganisationMembership.md +0 -140
- package/docs/api/interfaces/OrganisationProviderProps.md +0 -76
- package/docs/api/interfaces/OrganisationSecurityError.md +0 -62
- package/docs/api/interfaces/PaceAppLayoutProps.md +0 -409
- package/docs/api/interfaces/PaceLoginPageProps.md +0 -49
- package/docs/api/interfaces/PageAccessRecord.md +0 -85
- package/docs/api/interfaces/PagePermissionContextType.md +0 -140
- package/docs/api/interfaces/PagePermissionGuardProps.md +0 -153
- package/docs/api/interfaces/PagePermissionProviderProps.md +0 -119
- package/docs/api/interfaces/PaletteData.md +0 -41
- package/docs/api/interfaces/ParsedAddress.md +0 -120
- package/docs/api/interfaces/PermissionEnforcerProps.md +0 -153
- package/docs/api/interfaces/ProgressProps.md +0 -42
- package/docs/api/interfaces/ProtectedRouteProps.md +0 -78
- package/docs/api/interfaces/PublicPageFooterProps.md +0 -112
- package/docs/api/interfaces/PublicPageHeaderProps.md +0 -125
- package/docs/api/interfaces/PublicPageLayoutProps.md +0 -185
- package/docs/api/interfaces/QuickFix.md +0 -52
- package/docs/api/interfaces/RBACAccessValidateParams.md +0 -52
- package/docs/api/interfaces/RBACAccessValidateResult.md +0 -41
- package/docs/api/interfaces/RBACAuditLogParams.md +0 -85
- package/docs/api/interfaces/RBACAuditLogResult.md +0 -52
- package/docs/api/interfaces/RBACConfig.md +0 -133
- package/docs/api/interfaces/RBACContext.md +0 -52
- package/docs/api/interfaces/RBACLogger.md +0 -112
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +0 -74
- package/docs/api/interfaces/RBACPerformanceMetrics.md +0 -138
- package/docs/api/interfaces/RBACPermissionCheckParams.md +0 -74
- package/docs/api/interfaces/RBACPermissionCheckResult.md +0 -52
- package/docs/api/interfaces/RBACPermissionsGetParams.md +0 -63
- package/docs/api/interfaces/RBACPermissionsGetResult.md +0 -63
- package/docs/api/interfaces/RBACResult.md +0 -58
- package/docs/api/interfaces/RBACRoleGrantParams.md +0 -63
- package/docs/api/interfaces/RBACRoleGrantResult.md +0 -52
- package/docs/api/interfaces/RBACRoleRevokeParams.md +0 -63
- package/docs/api/interfaces/RBACRoleRevokeResult.md +0 -52
- package/docs/api/interfaces/RBACRoleValidateParams.md +0 -52
- package/docs/api/interfaces/RBACRoleValidateResult.md +0 -63
- package/docs/api/interfaces/RBACRolesListParams.md +0 -52
- package/docs/api/interfaces/RBACRolesListResult.md +0 -74
- package/docs/api/interfaces/RBACSessionTrackParams.md +0 -74
- package/docs/api/interfaces/RBACSessionTrackResult.md +0 -52
- package/docs/api/interfaces/ResourcePermissions.md +0 -155
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +0 -100
- package/docs/api/interfaces/RoleBasedRouterContextType.md +0 -151
- package/docs/api/interfaces/RoleBasedRouterProps.md +0 -156
- package/docs/api/interfaces/RoleManagementResult.md +0 -52
- package/docs/api/interfaces/RouteAccessRecord.md +0 -107
- package/docs/api/interfaces/RouteConfig.md +0 -134
- package/docs/api/interfaces/RuntimeComplianceResult.md +0 -55
- package/docs/api/interfaces/SecureDataContextType.md +0 -168
- package/docs/api/interfaces/SecureDataProviderProps.md +0 -132
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +0 -34
- package/docs/api/interfaces/SetupIssue.md +0 -41
- package/docs/api/interfaces/StorageConfig.md +0 -41
- package/docs/api/interfaces/StorageFileInfo.md +0 -74
- package/docs/api/interfaces/StorageFileMetadata.md +0 -151
- package/docs/api/interfaces/StorageListOptions.md +0 -99
- package/docs/api/interfaces/StorageListResult.md +0 -41
- package/docs/api/interfaces/StorageUploadOptions.md +0 -101
- package/docs/api/interfaces/StorageUploadResult.md +0 -63
- package/docs/api/interfaces/StorageUrlOptions.md +0 -60
- package/docs/api/interfaces/StyleImport.md +0 -19
- package/docs/api/interfaces/SwitchProps.md +0 -34
- package/docs/api/interfaces/TabsContentProps.md +0 -9
- package/docs/api/interfaces/TabsListProps.md +0 -9
- package/docs/api/interfaces/TabsProps.md +0 -9
- package/docs/api/interfaces/TabsTriggerProps.md +0 -50
- package/docs/api/interfaces/TextareaProps.md +0 -53
- package/docs/api/interfaces/ToastActionElement.md +0 -12
- package/docs/api/interfaces/ToastProps.md +0 -9
- package/docs/api/interfaces/UnifiedAuthContextType.md +0 -823
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +0 -173
- package/docs/api/interfaces/UseFormDialogOptions.md +0 -62
- package/docs/api/interfaces/UseFormDialogReturn.md +0 -117
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +0 -138
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +0 -123
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +0 -87
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +0 -84
- package/docs/api/interfaces/UsePublicEventOptions.md +0 -34
- package/docs/api/interfaces/UsePublicEventReturn.md +0 -71
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +0 -47
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +0 -123
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +0 -97
- package/docs/api/interfaces/UseResolvedScopeOptions.md +0 -47
- package/docs/api/interfaces/UseResolvedScopeReturn.md +0 -47
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +0 -34
- package/docs/api/interfaces/UserEventAccess.md +0 -121
- package/docs/api/interfaces/UserMenuProps.md +0 -88
- package/docs/api/interfaces/UserProfile.md +0 -63
- package/src/components/EventSelector/EventSelector.test.tsx +0 -720
- package/src/components/EventSelector/EventSelector.tsx +0 -423
- package/src/components/EventSelector/index.ts +0 -3
- package/src/components/OrganisationSelector/OrganisationSelector.test.tsx +0 -784
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +0 -327
- package/src/components/OrganisationSelector/index.ts +0 -9
- /package/dist/{DataTable-TPTKCX4D.js.map → DataTable-THFPBKTP.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-CH6Z342H.js.map → UnifiedAuthProvider-KAGUYQ4J.js.map} +0 -0
- /package/dist/{api-MVVQZLJI.js.map → api-IAGWF3ZG.js.map} +0 -0
- /package/dist/{audit-B5P6FFIR.js.map → audit-V53FV5AG.js.map} +0 -0
- /package/dist/{chunk-7D4SUZUM.js.map → chunk-DGUM43GV.js.map} +0 -0
- /package/dist/{chunk-2UOI2FG5.js.map → chunk-HFZBI76P.js.map} +0 -0
- /package/dist/{chunk-F2IMUDXZ.js.map → chunk-M7MPQISP.js.map} +0 -0
|
@@ -2,30 +2,66 @@ import {
|
|
|
2
2
|
useAppConfig,
|
|
3
3
|
useEvents,
|
|
4
4
|
useOrganisationSecurity
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-6Z7LTB3D.js";
|
|
6
6
|
import {
|
|
7
7
|
useOrganisations,
|
|
8
8
|
useUnifiedAuth
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-DWUBLJJM.js";
|
|
10
10
|
import {
|
|
11
|
-
ContextValidator,
|
|
12
|
-
OrganisationContextRequiredError,
|
|
13
11
|
getAccessLevel,
|
|
12
|
+
getPageScopeType,
|
|
14
13
|
getPermissionMap,
|
|
15
14
|
getRBACLogger,
|
|
16
15
|
getRoleContext,
|
|
17
16
|
isPermitted,
|
|
18
17
|
isPermittedCached,
|
|
19
18
|
resolveAppContext
|
|
20
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-RWEBCB47.js";
|
|
20
|
+
import {
|
|
21
|
+
ContextValidator,
|
|
22
|
+
OrganisationContextRequiredError
|
|
23
|
+
} from "./chunk-QRPVRXYT.js";
|
|
21
24
|
import {
|
|
22
25
|
getCurrentAppName
|
|
23
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-M7MPQISP.js";
|
|
24
27
|
import {
|
|
25
28
|
createLogger,
|
|
26
29
|
logger
|
|
27
30
|
} from "./chunk-PWLANIRT.js";
|
|
28
31
|
|
|
32
|
+
// src/rbac/utils/clientSecurity.ts
|
|
33
|
+
var SECURE_CLIENT_SYMBOL = Symbol("pace-core-secure-client");
|
|
34
|
+
function isSecureClient(client) {
|
|
35
|
+
if (!client) return false;
|
|
36
|
+
return client[SECURE_CLIENT_SYMBOL] === true;
|
|
37
|
+
}
|
|
38
|
+
function warnIfInsecureClient(client, context) {
|
|
39
|
+
if (typeof process !== "undefined" && true) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (!client) return;
|
|
43
|
+
if (!isSecureClient(client)) {
|
|
44
|
+
const contextMsg = context ? ` in ${context}` : "";
|
|
45
|
+
console.warn(
|
|
46
|
+
`[pace-core Security Warning] Non-secure Supabase client detected${contextMsg}.
|
|
47
|
+
You are using a Supabase client created with createClient() instead of useSecureSupabase().
|
|
48
|
+
This bypasses organisation context enforcement and RLS policies, which can lead to:
|
|
49
|
+
- Cross-organisation data access
|
|
50
|
+
- Security vulnerabilities
|
|
51
|
+
- Data leakage between organisations
|
|
52
|
+
|
|
53
|
+
Fix: Replace with:
|
|
54
|
+
import { useSecureSupabase } from '@jmruthers/pace-core/rbac';
|
|
55
|
+
const supabase = useSecureSupabase();
|
|
56
|
+
|
|
57
|
+
See: https://github.com/jmruthers/pace-core/blob/main/packages/core/docs/rbac/getting-started.md`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function markClientAsSecure(client) {
|
|
62
|
+
client[SECURE_CLIENT_SYMBOL] = true;
|
|
63
|
+
}
|
|
64
|
+
|
|
29
65
|
// src/rbac/secureClient.ts
|
|
30
66
|
import { createClient } from "@supabase/supabase-js";
|
|
31
67
|
var _SecureSupabaseClient = class _SecureSupabaseClient {
|
|
@@ -54,6 +90,7 @@ var _SecureSupabaseClient = class _SecureSupabaseClient {
|
|
|
54
90
|
}
|
|
55
91
|
this.setupContextInjection();
|
|
56
92
|
this.setupEdgeFunctionHandling();
|
|
93
|
+
markClientAsSecure(this.supabase);
|
|
57
94
|
}
|
|
58
95
|
/**
|
|
59
96
|
* Setup context injection for all database operations
|
|
@@ -69,13 +106,18 @@ var _SecureSupabaseClient = class _SecureSupabaseClient {
|
|
|
69
106
|
const originalRpc = this.supabase.rpc.bind(this.supabase);
|
|
70
107
|
this.supabase.rpc = (fn, args, options) => {
|
|
71
108
|
this.validateContextForRpc(fn);
|
|
109
|
+
const acceptedParams = this.getRpcAcceptedParams(fn);
|
|
72
110
|
const safeArgs = args ?? {};
|
|
73
|
-
const contextArgs = {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
111
|
+
const contextArgs = { ...safeArgs };
|
|
112
|
+
if (acceptedParams.has("p_organisation_id") && this.organisationId && safeArgs.p_organisation_id === void 0) {
|
|
113
|
+
contextArgs.p_organisation_id = this.organisationId;
|
|
114
|
+
}
|
|
115
|
+
if (acceptedParams.has("p_event_id") && this.eventId && safeArgs.p_event_id === void 0) {
|
|
116
|
+
contextArgs.p_event_id = this.eventId;
|
|
117
|
+
}
|
|
118
|
+
if (acceptedParams.has("p_app_id") && this.appId && safeArgs.p_app_id === void 0) {
|
|
119
|
+
contextArgs.p_app_id = this.appId;
|
|
120
|
+
}
|
|
79
121
|
return originalRpc(fn, contextArgs, options);
|
|
80
122
|
};
|
|
81
123
|
}
|
|
@@ -113,6 +155,7 @@ var _SecureSupabaseClient = class _SecureSupabaseClient {
|
|
|
113
155
|
const originalDelete = query.delete.bind(query);
|
|
114
156
|
query.select = (columns) => {
|
|
115
157
|
const result = originalSelect(columns);
|
|
158
|
+
result._tableName = tableName;
|
|
116
159
|
return this.addOrganisationFilter(result, tableName);
|
|
117
160
|
};
|
|
118
161
|
query.insert = (values) => {
|
|
@@ -227,7 +270,7 @@ var _SecureSupabaseClient = class _SecureSupabaseClient {
|
|
|
227
270
|
if (this.isSuperAdmin) {
|
|
228
271
|
return query;
|
|
229
272
|
}
|
|
230
|
-
return query.
|
|
273
|
+
return query.or(`organisation_id.eq.${this.organisationId},organisation_id.is.null`);
|
|
231
274
|
}
|
|
232
275
|
if (this.isSuperAdmin) {
|
|
233
276
|
return query.eq("organisation_id", this.organisationId);
|
|
@@ -323,7 +366,7 @@ var _SecureSupabaseClient = class _SecureSupabaseClient {
|
|
|
323
366
|
* @internal
|
|
324
367
|
*/
|
|
325
368
|
getClient() {
|
|
326
|
-
|
|
369
|
+
const proxiedClient = new Proxy(this.supabase, {
|
|
327
370
|
get: (target, prop) => {
|
|
328
371
|
if (prop === "functions" && this.edgeFunctionClient) {
|
|
329
372
|
return this.edgeFunctionClient.functions;
|
|
@@ -331,8 +374,40 @@ var _SecureSupabaseClient = class _SecureSupabaseClient {
|
|
|
331
374
|
return target[prop];
|
|
332
375
|
}
|
|
333
376
|
});
|
|
377
|
+
markClientAsSecure(proxiedClient);
|
|
378
|
+
return proxiedClient;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Get the set of parameter names that an RPC function accepts.
|
|
382
|
+
* Uses a static whitelist of RPCs that we know accept context parameters.
|
|
383
|
+
*
|
|
384
|
+
* This is an opt-in approach: by default, we don't inject context unless
|
|
385
|
+
* the function is explicitly whitelisted. This prevents PGRST202 errors from
|
|
386
|
+
* injecting unexpected parameters.
|
|
387
|
+
*
|
|
388
|
+
* @param fn - The RPC function name
|
|
389
|
+
* @returns Set of parameter names the function accepts
|
|
390
|
+
*/
|
|
391
|
+
getRpcAcceptedParams(fn) {
|
|
392
|
+
if (_SecureSupabaseClient.rpcSignatureCache.has(fn)) {
|
|
393
|
+
return _SecureSupabaseClient.rpcSignatureCache.get(fn);
|
|
394
|
+
}
|
|
395
|
+
const rpcContextWhitelist = {
|
|
396
|
+
// RPCs that accept all three context parameters
|
|
397
|
+
"rbac_roles_list": /* @__PURE__ */ new Set(["p_organisation_id", "p_event_id", "p_app_id"]),
|
|
398
|
+
// RPCs that accept only p_organisation_id (not p_app_id or p_event_id)
|
|
399
|
+
"data_file_reference_by_category_list": /* @__PURE__ */ new Set(["p_organisation_id"])
|
|
400
|
+
// Add more RPCs here as we discover them
|
|
401
|
+
// Format: 'function_name': new Set(['p_organisation_id', 'p_event_id', 'p_app_id']),
|
|
402
|
+
};
|
|
403
|
+
const acceptedParams = rpcContextWhitelist[fn] || /* @__PURE__ */ new Set();
|
|
404
|
+
_SecureSupabaseClient.rpcSignatureCache.set(fn, acceptedParams);
|
|
405
|
+
return acceptedParams;
|
|
334
406
|
}
|
|
335
407
|
};
|
|
408
|
+
// Cache for RPC function signatures to avoid repeated database queries
|
|
409
|
+
// Maps function name -> Set of parameter names it accepts
|
|
410
|
+
_SecureSupabaseClient.rpcSignatureCache = /* @__PURE__ */ new Map();
|
|
336
411
|
/**
|
|
337
412
|
* RPC functions that are safe to call without organisation context.
|
|
338
413
|
*
|
|
@@ -357,7 +432,7 @@ function fromSupabaseClient(client, organisationId, eventId, appId, isSuperAdmin
|
|
|
357
432
|
// src/rbac/hooks/useResolvedScope.ts
|
|
358
433
|
import { useEffect, useState, useRef, useMemo } from "react";
|
|
359
434
|
var log = createLogger("useResolvedScope");
|
|
360
|
-
var
|
|
435
|
+
var appIdCache = /* @__PURE__ */ new Map();
|
|
361
436
|
var CACHE_TTL = 5 * 60 * 1e3;
|
|
362
437
|
function useResolvedScope({
|
|
363
438
|
supabase,
|
|
@@ -408,20 +483,18 @@ function useResolvedScope({
|
|
|
408
483
|
try {
|
|
409
484
|
const appName2 = getCurrentAppName();
|
|
410
485
|
let appId = void 0;
|
|
411
|
-
let appConfig = null;
|
|
412
486
|
if (supabase && appName2) {
|
|
413
487
|
try {
|
|
414
488
|
const { data: session } = await supabase.auth.getSession();
|
|
415
489
|
if (!session?.session) {
|
|
416
490
|
log.debug(`Skipping app resolution for "${appName2}" - user not authenticated`);
|
|
417
491
|
} else {
|
|
418
|
-
const cached =
|
|
492
|
+
const cached = appIdCache.get(appName2);
|
|
419
493
|
const now = Date.now();
|
|
420
494
|
if (cached && now - cached.timestamp < CACHE_TTL) {
|
|
421
495
|
appId = cached.appId;
|
|
422
|
-
appConfig = cached.appConfig;
|
|
423
496
|
} else {
|
|
424
|
-
const { data: app, error: error2 } = await supabase.from("rbac_apps").select("id, name,
|
|
497
|
+
const { data: app, error: error2 } = await supabase.from("rbac_apps").select("id, name, is_active").eq("name", appName2).eq("is_active", true).single();
|
|
425
498
|
if (error2) {
|
|
426
499
|
if (error2.code === "406" || error2.code === "PGRST116" || error2.message?.includes("406")) {
|
|
427
500
|
log.debug(`App resolution blocked by RLS for "${appName2}" - user may not be authenticated`);
|
|
@@ -438,47 +511,47 @@ function useResolvedScope({
|
|
|
438
511
|
}
|
|
439
512
|
} else if (app) {
|
|
440
513
|
appId = app.id;
|
|
441
|
-
|
|
442
|
-
appConfigCache.set(appName2, { appId, appConfig, timestamp: now });
|
|
514
|
+
appIdCache.set(appName2, { appId, timestamp: now });
|
|
443
515
|
}
|
|
444
516
|
}
|
|
445
517
|
}
|
|
446
518
|
} catch (error2) {
|
|
447
519
|
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
448
520
|
if (!errorMessage.includes("406") && !errorMessage.includes("PGRST116")) {
|
|
449
|
-
log.error("Unexpected error resolving app
|
|
521
|
+
log.error("Unexpected error resolving app ID:", error2);
|
|
450
522
|
} else {
|
|
451
523
|
log.debug("App resolution skipped - authentication required");
|
|
452
524
|
}
|
|
453
525
|
}
|
|
454
526
|
}
|
|
455
527
|
const initialScope = {
|
|
456
|
-
organisationId:
|
|
528
|
+
organisationId: selectedOrganisationId || void 0,
|
|
457
529
|
eventId: selectedEventId || void 0,
|
|
458
530
|
appId
|
|
459
531
|
};
|
|
460
|
-
|
|
532
|
+
if (appName2 === "PORTAL" || appName2 === "ADMIN") {
|
|
533
|
+
if (!cancelled) {
|
|
534
|
+
const optionalContextScope = {
|
|
535
|
+
organisationId: void 0,
|
|
536
|
+
eventId: void 0,
|
|
537
|
+
appId: appId || void 0
|
|
538
|
+
};
|
|
539
|
+
setResolvedScope(optionalContextScope);
|
|
540
|
+
setError(null);
|
|
541
|
+
setIsLoading(false);
|
|
542
|
+
}
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
const { ContextValidator: ContextValidator2 } = await import("./contextValidator-3JNZKUTX.js");
|
|
546
|
+
const validation = await ContextValidator2.resolveScopeForPage(
|
|
461
547
|
initialScope,
|
|
462
|
-
|
|
548
|
+
"organisation",
|
|
549
|
+
// Default to organisation scope when no page context
|
|
463
550
|
appName2 || void 0,
|
|
464
551
|
supabase
|
|
465
552
|
);
|
|
466
553
|
if (!validation.isValid) {
|
|
467
|
-
if (
|
|
468
|
-
if (!cancelled) {
|
|
469
|
-
const optionalContextScope = {
|
|
470
|
-
organisationId: void 0,
|
|
471
|
-
eventId: void 0,
|
|
472
|
-
appId: appId || void 0
|
|
473
|
-
// appId might be undefined if query failed, that's OK
|
|
474
|
-
};
|
|
475
|
-
setResolvedScope(optionalContextScope);
|
|
476
|
-
setError(null);
|
|
477
|
-
setIsLoading(false);
|
|
478
|
-
}
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
481
|
-
if (appConfig?.requires_event && selectedEventId) {
|
|
554
|
+
if (selectedEventId) {
|
|
482
555
|
if (!cancelled) {
|
|
483
556
|
const eventScope = {
|
|
484
557
|
organisationId: void 0,
|
|
@@ -565,7 +638,6 @@ function useRBAC(pageId) {
|
|
|
565
638
|
session,
|
|
566
639
|
supabase,
|
|
567
640
|
appName,
|
|
568
|
-
appConfig,
|
|
569
641
|
appId: contextAppId,
|
|
570
642
|
selectedOrganisation,
|
|
571
643
|
isContextReady: orgContextReady,
|
|
@@ -594,20 +666,15 @@ function useRBAC(pageId) {
|
|
|
594
666
|
return;
|
|
595
667
|
}
|
|
596
668
|
const initialScope = {
|
|
597
|
-
organisationId:
|
|
669
|
+
organisationId: selectedEvent?.organisation_id || selectedOrganisation?.id || void 0,
|
|
598
670
|
eventId: selectedEvent?.event_id || void 0,
|
|
599
671
|
appId: void 0
|
|
600
672
|
};
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
!!selectedOrganisation
|
|
607
|
-
);
|
|
608
|
-
if (appName !== "PORTAL" && appName !== "ADMIN" && !contextReady) {
|
|
609
|
-
setIsLoading(true);
|
|
610
|
-
return;
|
|
673
|
+
if (appName !== "PORTAL" && appName !== "ADMIN") {
|
|
674
|
+
if (!selectedOrganisation && !selectedEvent) {
|
|
675
|
+
setIsLoading(true);
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
611
678
|
}
|
|
612
679
|
setIsLoading(true);
|
|
613
680
|
setError(null);
|
|
@@ -618,11 +685,6 @@ function useRBAC(pageId) {
|
|
|
618
685
|
const resolved = await resolveAppContext({ userId: user.id, appName });
|
|
619
686
|
if (!resolved) {
|
|
620
687
|
if (appName === "PORTAL" || appName === "ADMIN") {
|
|
621
|
-
try {
|
|
622
|
-
const { getAppConfigByName } = await import("./api-MVVQZLJI.js");
|
|
623
|
-
await getAppConfigByName(appName);
|
|
624
|
-
} catch (err) {
|
|
625
|
-
}
|
|
626
688
|
} else {
|
|
627
689
|
throw new Error(`User does not have access to app "${appName}"`);
|
|
628
690
|
}
|
|
@@ -652,9 +714,20 @@ function useRBAC(pageId) {
|
|
|
652
714
|
...initialScope,
|
|
653
715
|
appId: appId || contextAppId
|
|
654
716
|
};
|
|
655
|
-
|
|
717
|
+
let pageScopeType = "organisation";
|
|
718
|
+
if (pageId && scope.appId) {
|
|
719
|
+
try {
|
|
720
|
+
pageScopeType = await getPageScopeType(pageId, scope.appId, appName);
|
|
721
|
+
} catch (error2) {
|
|
722
|
+
logger2.warn("[useRBAC] Failed to get page scope type, defaulting to organisation", {
|
|
723
|
+
pageId,
|
|
724
|
+
error: error2 instanceof Error ? error2.message : String(error2)
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
const validation = await ContextValidator.resolveScopeForPage(
|
|
656
729
|
scope,
|
|
657
|
-
|
|
730
|
+
pageScopeType,
|
|
658
731
|
appName,
|
|
659
732
|
supabase || null
|
|
660
733
|
);
|
|
@@ -664,9 +737,9 @@ function useRBAC(pageId) {
|
|
|
664
737
|
const resolvedScope = validation.resolvedScope;
|
|
665
738
|
setCurrentScope(resolvedScope);
|
|
666
739
|
const [map, roleContext, accessLevel] = await Promise.all([
|
|
667
|
-
getPermissionMap({ userId: user.id, scope: resolvedScope }
|
|
668
|
-
getRoleContext({ userId: user.id, scope: resolvedScope }
|
|
669
|
-
getAccessLevel({ userId: user.id, scope: resolvedScope }
|
|
740
|
+
getPermissionMap({ userId: user.id, scope: resolvedScope }),
|
|
741
|
+
getRoleContext({ userId: user.id, scope: resolvedScope }),
|
|
742
|
+
getAccessLevel({ userId: user.id, scope: resolvedScope })
|
|
670
743
|
]);
|
|
671
744
|
setPermissionMap(map);
|
|
672
745
|
setGlobalRole(roleContext.globalRole);
|
|
@@ -688,7 +761,7 @@ function useRBAC(pageId) {
|
|
|
688
761
|
} finally {
|
|
689
762
|
setIsLoading(false);
|
|
690
763
|
}
|
|
691
|
-
}, [appName, logger2, resetState, selectedEvent?.event_id, selectedOrganisation?.id, session, user, eventLoading,
|
|
764
|
+
}, [appName, logger2, resetState, selectedEvent?.event_id, selectedOrganisation?.id, session, user, eventLoading, orgContextReady, orgLoading]);
|
|
692
765
|
const hasGlobalPermission = useCallback(
|
|
693
766
|
(permission) => {
|
|
694
767
|
if (globalRole === "super_admin" || permissionMap["*"]) {
|
|
@@ -711,7 +784,7 @@ function useRBAC(pageId) {
|
|
|
711
784
|
const canManageEvent = useMemo2(() => isSuperAdmin || eventAppRole === "event_admin", [isSuperAdmin, eventAppRole]);
|
|
712
785
|
useEffect2(() => {
|
|
713
786
|
loadRBACContext();
|
|
714
|
-
}, [loadRBACContext, appName,
|
|
787
|
+
}, [loadRBACContext, appName, eventLoading, selectedEvent?.event_id, user, session, selectedOrganisation?.id, orgContextReady, orgLoading]);
|
|
715
788
|
return {
|
|
716
789
|
user,
|
|
717
790
|
globalRole,
|
|
@@ -749,7 +822,7 @@ function useAccessLevel(userId, scope) {
|
|
|
749
822
|
try {
|
|
750
823
|
setIsLoading(true);
|
|
751
824
|
setError(null);
|
|
752
|
-
const { isSuperAdmin: checkSuperAdmin } = await import("./api-
|
|
825
|
+
const { isSuperAdmin: checkSuperAdmin } = await import("./api-IAGWF3ZG.js");
|
|
753
826
|
const isSuperAdminUser = await checkSuperAdmin(userId);
|
|
754
827
|
if (isSuperAdminUser) {
|
|
755
828
|
setAccessLevel("super");
|
|
@@ -763,7 +836,7 @@ function useAccessLevel(userId, scope) {
|
|
|
763
836
|
setIsLoading(false);
|
|
764
837
|
return;
|
|
765
838
|
}
|
|
766
|
-
const level = await getAccessLevel({ userId, scope },
|
|
839
|
+
const level = await getAccessLevel({ userId, scope }, appName);
|
|
767
840
|
setAccessLevel(level);
|
|
768
841
|
} catch (err) {
|
|
769
842
|
const error2 = err instanceof Error ? err : new Error("Failed to fetch access level");
|
|
@@ -838,14 +911,26 @@ function scopeEqual(a, b) {
|
|
|
838
911
|
|
|
839
912
|
// src/rbac/hooks/permissions/useCan.ts
|
|
840
913
|
function useCan(userId, scope, permission, pageId, useCache = true, precomputedSuperAdmin = null, appName) {
|
|
841
|
-
const [can, setCan] = useState5(false);
|
|
842
|
-
const [isLoading, setIsLoading] = useState5(true);
|
|
843
|
-
const [error, setError] = useState5(null);
|
|
844
914
|
const [isSuperAdmin, setIsSuperAdmin] = useState5(precomputedSuperAdmin ?? null);
|
|
915
|
+
const initialCan = precomputedSuperAdmin === true ? true : false;
|
|
916
|
+
const initialIsLoading = precomputedSuperAdmin === true ? false : true;
|
|
917
|
+
const [can, setCan] = useState5(initialCan);
|
|
918
|
+
const [isLoading, setIsLoading] = useState5(initialIsLoading);
|
|
919
|
+
const [error, setError] = useState5(null);
|
|
845
920
|
const isValidScope = scope && typeof scope === "object";
|
|
846
921
|
const organisationId = isValidScope ? scope.organisationId : void 0;
|
|
847
922
|
const eventId = isValidScope ? scope.eventId : void 0;
|
|
848
923
|
const appId = isValidScope ? scope.appId : void 0;
|
|
924
|
+
useEffect5(() => {
|
|
925
|
+
if (precomputedSuperAdmin === true && isSuperAdmin !== true) {
|
|
926
|
+
setIsSuperAdmin(true);
|
|
927
|
+
setCan(true);
|
|
928
|
+
setIsLoading(false);
|
|
929
|
+
setError(null);
|
|
930
|
+
} else if (precomputedSuperAdmin === false && isSuperAdmin !== false) {
|
|
931
|
+
setIsSuperAdmin(false);
|
|
932
|
+
}
|
|
933
|
+
}, [precomputedSuperAdmin, isSuperAdmin]);
|
|
849
934
|
useEffect5(() => {
|
|
850
935
|
if (precomputedSuperAdmin === null) {
|
|
851
936
|
if (!userId) {
|
|
@@ -856,7 +941,7 @@ function useCan(userId, scope, permission, pageId, useCache = true, precomputedS
|
|
|
856
941
|
const checkSuperAdmin = async () => {
|
|
857
942
|
const startTime = Date.now();
|
|
858
943
|
try {
|
|
859
|
-
const { isSuperAdmin: checkSuperAdmin2 } = await import("./api-
|
|
944
|
+
const { isSuperAdmin: checkSuperAdmin2 } = await import("./api-IAGWF3ZG.js");
|
|
860
945
|
const timeoutWarning = setTimeout(() => {
|
|
861
946
|
if (!cancelled) {
|
|
862
947
|
console.warn("[useCan] Super admin check taking longer than 5 seconds", {
|
|
@@ -876,6 +961,11 @@ function useCan(userId, scope, permission, pageId, useCache = true, precomputedS
|
|
|
876
961
|
});
|
|
877
962
|
}
|
|
878
963
|
setIsSuperAdmin(isSuper);
|
|
964
|
+
if (isSuper) {
|
|
965
|
+
setCan(true);
|
|
966
|
+
setIsLoading(false);
|
|
967
|
+
setError(null);
|
|
968
|
+
}
|
|
879
969
|
}
|
|
880
970
|
} catch (err) {
|
|
881
971
|
if (!cancelled) {
|
|
@@ -893,8 +983,6 @@ function useCan(userId, scope, permission, pageId, useCache = true, precomputedS
|
|
|
893
983
|
return () => {
|
|
894
984
|
cancelled = true;
|
|
895
985
|
};
|
|
896
|
-
} else {
|
|
897
|
-
setIsSuperAdmin(precomputedSuperAdmin);
|
|
898
986
|
}
|
|
899
987
|
}, [userId, precomputedSuperAdmin]);
|
|
900
988
|
useEffect5(() => {
|
|
@@ -920,6 +1008,7 @@ function useCan(userId, scope, permission, pageId, useCache = true, precomputedS
|
|
|
920
1008
|
const lastPermissionRef = useRef2(null);
|
|
921
1009
|
const lastPageIdRef = useRef2(null);
|
|
922
1010
|
const lastUseCacheRef = useRef2(null);
|
|
1011
|
+
const lastIsSuperAdminRef = useRef2(null);
|
|
923
1012
|
const stableScope = useMemo5(() => {
|
|
924
1013
|
if (!isValidScope) {
|
|
925
1014
|
return null;
|
|
@@ -933,7 +1022,9 @@ function useCan(userId, scope, permission, pageId, useCache = true, precomputedS
|
|
|
933
1022
|
const prevScopeRef = useRef2(null);
|
|
934
1023
|
useEffect5(() => {
|
|
935
1024
|
const scopeChanged = !scopeEqual(prevScopeRef.current, stableScope);
|
|
936
|
-
|
|
1025
|
+
const isSuperAdminChanged = lastIsSuperAdminRef.current !== isSuperAdmin;
|
|
1026
|
+
if (lastUserIdRef.current !== userId || scopeChanged || lastPermissionRef.current !== permission || lastPageIdRef.current !== pageId || lastUseCacheRef.current !== useCache || isSuperAdminChanged) {
|
|
1027
|
+
lastIsSuperAdminRef.current = isSuperAdmin;
|
|
937
1028
|
lastUserIdRef.current = userId;
|
|
938
1029
|
prevScopeRef.current = stableScope;
|
|
939
1030
|
lastPermissionRef.current = permission;
|
|
@@ -987,7 +1078,7 @@ function useCan(userId, scope, permission, pageId, useCache = true, precomputedS
|
|
|
987
1078
|
...eventId ? { eventId } : {},
|
|
988
1079
|
...appId ? { appId } : {}
|
|
989
1080
|
};
|
|
990
|
-
const result = useCache ? await isPermittedCached({ userId, scope: validScope, permission, pageId },
|
|
1081
|
+
const result = useCache ? await isPermittedCached({ userId, scope: validScope, permission, pageId }, appName) : await isPermitted({ userId, scope: validScope, permission, pageId }, appName, isSuperAdmin === false ? false : null);
|
|
991
1082
|
setCan(result);
|
|
992
1083
|
} catch (err) {
|
|
993
1084
|
const logger2 = getRBACLogger();
|
|
@@ -1030,7 +1121,7 @@ function useCan(userId, scope, permission, pageId, useCache = true, precomputedS
|
|
|
1030
1121
|
...eventId ? { eventId } : {},
|
|
1031
1122
|
...appId ? { appId } : {}
|
|
1032
1123
|
};
|
|
1033
|
-
const result = useCache ? await isPermittedCached({ userId, scope: validScope, permission, pageId },
|
|
1124
|
+
const result = useCache ? await isPermittedCached({ userId, scope: validScope, permission, pageId }, appName) : await isPermitted({ userId, scope: validScope, permission, pageId }, appName, null);
|
|
1034
1125
|
setCan(result);
|
|
1035
1126
|
} catch (err) {
|
|
1036
1127
|
setError(err instanceof Error ? err : new Error("Failed to check permission"));
|
|
@@ -1064,7 +1155,7 @@ function useHasAllPermissions(userId, scope, permissions, useCache = true) {
|
|
|
1064
1155
|
setError(null);
|
|
1065
1156
|
let hasAllPermissions = true;
|
|
1066
1157
|
for (const permission of permissions) {
|
|
1067
|
-
const result = useCache ? await isPermittedCached({ userId, scope, permission }) : await isPermitted({ userId, scope, permission }
|
|
1158
|
+
const result = useCache ? await isPermittedCached({ userId, scope, permission }) : await isPermitted({ userId, scope, permission });
|
|
1068
1159
|
if (!result) {
|
|
1069
1160
|
hasAllPermissions = false;
|
|
1070
1161
|
break;
|
|
@@ -1106,7 +1197,7 @@ function useHasAnyPermission(userId, scope, permissions, useCache = true) {
|
|
|
1106
1197
|
setError(null);
|
|
1107
1198
|
let hasAnyPermission = false;
|
|
1108
1199
|
for (const permission of permissions) {
|
|
1109
|
-
const result = useCache ? await isPermittedCached({ userId, scope, permission }) : await isPermitted({ userId, scope, permission }
|
|
1200
|
+
const result = useCache ? await isPermittedCached({ userId, scope, permission }) : await isPermitted({ userId, scope, permission });
|
|
1110
1201
|
if (result) {
|
|
1111
1202
|
hasAnyPermission = true;
|
|
1112
1203
|
break;
|
|
@@ -1148,7 +1239,7 @@ function useMultiplePermissions(userId, scope, permissions, useCache = true) {
|
|
|
1148
1239
|
setError(null);
|
|
1149
1240
|
const permissionResults = {};
|
|
1150
1241
|
for (const permission of permissions) {
|
|
1151
|
-
const result = useCache ? await isPermittedCached({ userId, scope, permission }) : await isPermitted({ userId, scope, permission }
|
|
1242
|
+
const result = useCache ? await isPermittedCached({ userId, scope, permission }) : await isPermitted({ userId, scope, permission });
|
|
1152
1243
|
permissionResults[permission] = result;
|
|
1153
1244
|
}
|
|
1154
1245
|
setResults(permissionResults);
|
|
@@ -1831,6 +1922,9 @@ function useSecureSupabase(baseClient) {
|
|
|
1831
1922
|
}
|
|
1832
1923
|
|
|
1833
1924
|
export {
|
|
1925
|
+
SECURE_CLIENT_SYMBOL,
|
|
1926
|
+
isSecureClient,
|
|
1927
|
+
warnIfInsecureClient,
|
|
1834
1928
|
SecureSupabaseClient,
|
|
1835
1929
|
createSecureClient,
|
|
1836
1930
|
fromSupabaseClient,
|
|
@@ -1848,4 +1942,4 @@ export {
|
|
|
1848
1942
|
useRoleManagement,
|
|
1849
1943
|
useSecureSupabase
|
|
1850
1944
|
};
|
|
1851
|
-
//# sourceMappingURL=chunk-
|
|
1945
|
+
//# sourceMappingURL=chunk-YDQHOZNA.js.map
|