@jmruthers/pace-core 0.5.185 → 0.5.187
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-Z9NLVJh0.d.ts → DataTable-IVYljGJ6.d.ts} +1 -1
- package/dist/{DataTable-IX2NBUTP.js → DataTable-K3RJRSOX.js} +7 -7
- package/dist/{PublicPageProvider-BABf6JCh.d.ts → PublicPageProvider-DrLDztHt.d.ts} +214 -107
- package/dist/{UnifiedAuthProvider-A4BCQRJY.js → UnifiedAuthProvider-B76OWOAT.js} +2 -2
- package/dist/{api-BMFCXVQX.js → api-YP7XD5L6.js} +3 -3
- package/dist/{audit-WRS3KJKI.js → audit-B5P6FFIR.js} +2 -2
- package/dist/{chunk-445GEP27.js → chunk-3IC5WCMO.js} +33 -8
- package/dist/chunk-3IC5WCMO.js.map +1 -0
- package/dist/{chunk-OKI34GZD.js → chunk-3NFNJOO7.js} +8 -8
- package/dist/chunk-3NFNJOO7.js.map +1 -0
- package/dist/{chunk-FSFQFJCU.js → chunk-63FOKYGO.js} +174 -6
- package/dist/chunk-63FOKYGO.js.map +1 -0
- package/dist/{chunk-MX3EIJGQ.js → chunk-C4OYJOV4.js} +631 -97
- package/dist/chunk-C4OYJOV4.js.map +1 -0
- package/dist/{chunk-HGPQUCBC.js → chunk-FMTK4XNN.js} +3 -3
- package/dist/{chunk-U6WNSFX5.js → chunk-HEHYGYOX.js} +279 -44
- package/dist/chunk-HEHYGYOX.js.map +1 -0
- package/dist/{chunk-XAUHJD3L.js → chunk-K2JGDXGU.js} +2 -2
- package/dist/{chunk-HC67NW5K.js → chunk-LBBUPSSC.js} +863 -552
- package/dist/chunk-LBBUPSSC.js.map +1 -0
- package/dist/{chunk-IXSNYUCT.js → chunk-SAUPYVLF.js} +1 -1
- package/dist/chunk-SAUPYVLF.js.map +1 -0
- package/dist/{chunk-AISXLWGZ.js → chunk-T6ZJVI3A.js} +27 -23
- package/dist/chunk-T6ZJVI3A.js.map +1 -0
- package/dist/{chunk-STTZQK2I.js → chunk-ULX5FYEM.js} +9 -7
- package/dist/chunk-ULX5FYEM.js.map +1 -0
- package/dist/{chunk-FXFJRTKI.js → chunk-WK2Y6TGA.js} +3 -3
- package/dist/chunk-WK2Y6TGA.js.map +1 -0
- package/dist/chunk-YHCN776L.js +447 -0
- package/dist/chunk-YHCN776L.js.map +1 -0
- package/dist/components.d.ts +4 -4
- package/dist/components.js +12 -10
- package/dist/components.js.map +1 -1
- package/dist/{database.generated-CBmg2950.d.ts → database.generated-DI89OQeI.d.ts} +63 -9
- package/dist/{file-reference-BjR39ktt.d.ts → file-reference-D037xOFK.d.ts} +3 -1
- package/dist/hooks.d.ts +265 -6
- package/dist/hooks.js +148 -49
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +25 -10
- package/dist/index.js +65 -30
- package/dist/index.js.map +1 -1
- package/dist/providers.js +1 -1
- package/dist/rbac/index.d.ts +125 -8
- package/dist/rbac/index.js +27 -7
- package/dist/{types-DUyCRSTj.d.ts → types-Bwgl--Xo.d.ts} +162 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.js +1 -1
- package/dist/{usePublicRouteParams-CvnC3d-e.d.ts → usePublicRouteParams-CTDELQ7H.d.ts} +3 -3
- package/dist/utils.d.ts +214 -4
- package/dist/utils.js +22 -2
- package/dist/utils.js.map +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/Logger.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/RBACAuditManager.md +21 -17
- package/docs/api/classes/RBACCache.md +31 -23
- package/docs/api/classes/RBACEngine.md +6 -6
- 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 +1 -1
- package/docs/api/enums/RBACErrorCode.md +1 -1
- package/docs/api/enums/RPCFunction.md +1 -1
- package/docs/api/interfaces/AddressFieldProps.md +241 -0
- package/docs/api/interfaces/AddressFieldRef.md +94 -0
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/AutocompleteOptions.md +75 -0
- 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/ComplianceResult.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/DatabaseComplianceResult.md +1 -1
- package/docs/api/interfaces/DatabaseIssue.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/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +15 -15
- 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 +33 -9
- package/docs/api/interfaces/FileUploadProps.md +36 -14
- 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 +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/LoggerConfig.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 +11 -11
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/ParsedAddress.md +120 -0
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProgressProps.md +1 -1
- package/docs/api/interfaces/ProtectedRouteProps.md +6 -6
- 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 +1 -1
- 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 +27 -4
- package/docs/api/interfaces/RBACContext.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +5 -5
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPerformanceMetrics.md +138 -0
- 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 +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/RuntimeComplianceResult.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/SetupIssue.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/UseFormDialogOptions.md +1 -1
- package/docs/api/interfaces/UseFormDialogReturn.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 +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 +328 -69
- package/docs/api-reference/components.md +26 -12
- package/docs/best-practices/performance.md +11 -0
- package/docs/implementation-guides/file-reference-system.md +24 -2
- package/docs/implementation-guides/file-upload-storage.md +38 -1
- package/docs/rbac/README.md +2 -1
- package/docs/rbac/api-reference.md +11 -0
- package/docs/rbac/performance.md +320 -0
- package/docs/standards/01-architecture-standard.md +5 -0
- package/docs/standards/05-security-standard.md +12 -0
- package/package.json +1 -1
- package/scripts/check-pace-core-compliance.js +512 -0
- package/src/components/AddressField/AddressField.test.tsx +411 -0
- package/src/components/AddressField/AddressField.tsx +323 -0
- package/src/components/AddressField/README.md +336 -0
- package/src/components/AddressField/index.ts +10 -0
- package/src/components/AddressField/types.ts +65 -0
- package/src/components/FileDisplay/FileDisplay.test.tsx +454 -0
- package/src/components/FileDisplay/FileDisplay.tsx +28 -1
- package/src/components/FileUpload/FileUpload.test.tsx +2 -0
- package/src/components/FileUpload/FileUpload.tsx +7 -1
- package/src/components/Header/Header.tsx +2 -5
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +134 -1
- package/src/components/index.ts +2 -0
- package/src/hooks/__tests__/useFileDisplay.unit.test.ts +30 -5
- package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +11 -10
- package/src/hooks/__tests__/usePublicFileDisplay.test.ts +31 -6
- package/src/hooks/index.ts +9 -0
- package/src/hooks/public/usePublicFileDisplay.ts +8 -10
- package/src/hooks/useAddressAutocomplete.test.ts +318 -0
- package/src/hooks/useAddressAutocomplete.ts +268 -0
- package/src/hooks/useFileDisplay.ts +3 -15
- package/src/hooks/useFileReference.test.ts +21 -3
- package/src/hooks/useFileReference.ts +3 -24
- package/src/hooks/useFileUrlCache.ts +246 -0
- package/src/hooks/useInactivityTracker.ts +31 -20
- package/src/hooks/useOrganisationSecurity.test.ts +10 -7
- package/src/hooks/useOrganisationSecurity.ts +3 -3
- package/src/hooks/usePreventTabReload.ts +106 -0
- package/src/hooks/useQueryCache.ts +315 -0
- package/src/hooks/useSecureDataAccess.ts +2 -2
- package/src/index.ts +2 -0
- package/src/providers/services/EventServiceProvider.tsx +4 -1
- package/src/rbac/__tests__/rbac-role-isolation.test.ts +456 -0
- package/src/rbac/api.test.ts +21 -6
- package/src/rbac/api.ts +32 -11
- package/src/rbac/audit-batched.ts +223 -0
- package/src/rbac/audit-enhanced.ts +2 -2
- package/src/rbac/audit.test.ts +6 -5
- package/src/rbac/audit.ts +34 -6
- package/src/rbac/cache-invalidation.ts +63 -12
- package/src/rbac/cache.test.ts +2 -2
- package/src/rbac/cache.ts +61 -14
- package/src/rbac/components/PagePermissionGuard.tsx +19 -10
- package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +248 -0
- package/src/rbac/config.ts +9 -0
- package/src/rbac/engine.ts +2 -21
- package/src/rbac/hooks/usePermissions.ts +21 -5
- package/src/rbac/index.ts +19 -0
- package/src/rbac/performance.ts +210 -0
- package/src/rbac/request-deduplication.ts +87 -0
- package/src/rbac/utils/deep-equal.ts +93 -0
- package/src/styles/core.css +5 -5
- package/src/types/database.generated.ts +63 -9
- package/src/types/file-reference.ts +3 -1
- package/src/utils/file-reference/__tests__/file-reference.test.ts +89 -8
- package/src/utils/file-reference/index.ts +56 -17
- package/src/utils/google-places/googlePlacesUtils.test.ts +403 -0
- package/src/utils/google-places/googlePlacesUtils.ts +475 -0
- package/src/utils/google-places/index.ts +26 -0
- package/src/utils/google-places/loadGoogleMapsScript.ts +207 -0
- package/src/utils/google-places/types.ts +94 -0
- package/src/utils/index.ts +23 -0
- package/src/utils/request-deduplication.ts +165 -0
- package/src/utils/security/secureDataAccess.ts +1 -1
- package/src/utils/storage/helpers.ts +211 -4
- package/dist/chunk-445GEP27.js.map +0 -1
- package/dist/chunk-AISXLWGZ.js.map +0 -1
- package/dist/chunk-FMUCXFII.js +0 -76
- package/dist/chunk-FMUCXFII.js.map +0 -1
- package/dist/chunk-FSFQFJCU.js.map +0 -1
- package/dist/chunk-FXFJRTKI.js.map +0 -1
- package/dist/chunk-HC67NW5K.js.map +0 -1
- package/dist/chunk-IXSNYUCT.js.map +0 -1
- package/dist/chunk-MX3EIJGQ.js.map +0 -1
- package/dist/chunk-OKI34GZD.js.map +0 -1
- package/dist/chunk-STTZQK2I.js.map +0 -1
- package/dist/chunk-U6WNSFX5.js.map +0 -1
- /package/dist/{DataTable-IX2NBUTP.js.map → DataTable-K3RJRSOX.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-A4BCQRJY.js.map → UnifiedAuthProvider-B76OWOAT.js.map} +0 -0
- /package/dist/{api-BMFCXVQX.js.map → api-YP7XD5L6.js.map} +0 -0
- /package/dist/{audit-WRS3KJKI.js.map → audit-B5P6FFIR.js.map} +0 -0
- /package/dist/{chunk-HGPQUCBC.js.map → chunk-FMTK4XNN.js.map} +0 -0
- /package/dist/{chunk-XAUHJD3L.js.map → chunk-K2JGDXGU.js.map} +0 -0
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
createAuditManager,
|
|
3
3
|
emitAuditEvent,
|
|
4
4
|
setGlobalAuditManager
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-63FOKYGO.js";
|
|
6
6
|
import {
|
|
7
7
|
createLogger
|
|
8
8
|
} from "./chunk-PWLANIRT.js";
|
|
@@ -68,26 +68,41 @@ var MissingUserContextError = class extends RBACError {
|
|
|
68
68
|
var RBACCache = class {
|
|
69
69
|
constructor() {
|
|
70
70
|
this.cache = /* @__PURE__ */ new Map();
|
|
71
|
-
this.
|
|
72
|
-
|
|
71
|
+
this.sessionCache = /* @__PURE__ */ new Map();
|
|
72
|
+
this.TTL = 120 * 1e3;
|
|
73
|
+
// 120 seconds (short-term) - increased from 60s
|
|
74
|
+
this.SESSION_TTL = 15 * 60 * 1e3;
|
|
75
|
+
// 15 minutes (session-level) - increased from 5min
|
|
73
76
|
this.invalidationCallbacks = /* @__PURE__ */ new Set();
|
|
74
77
|
}
|
|
75
78
|
/**
|
|
76
79
|
* Get a value from the cache
|
|
77
80
|
*
|
|
81
|
+
* Checks both short-term cache and session cache.
|
|
82
|
+
*
|
|
78
83
|
* @param key - Cache key
|
|
84
|
+
* @param useSessionCache - Whether to check session cache (default: true)
|
|
79
85
|
* @returns Cached value or null if not found/expired
|
|
80
86
|
*/
|
|
81
|
-
get(key) {
|
|
87
|
+
get(key, useSessionCache = true) {
|
|
88
|
+
const now = Date.now();
|
|
82
89
|
const entry = this.cache.get(key);
|
|
83
|
-
if (
|
|
84
|
-
return
|
|
90
|
+
if (entry && now <= entry.expires) {
|
|
91
|
+
return entry.data;
|
|
85
92
|
}
|
|
86
|
-
if (
|
|
93
|
+
if (entry && now > entry.expires) {
|
|
87
94
|
this.cache.delete(key);
|
|
88
|
-
return null;
|
|
89
95
|
}
|
|
90
|
-
|
|
96
|
+
if (useSessionCache) {
|
|
97
|
+
const sessionEntry = this.sessionCache.get(key);
|
|
98
|
+
if (sessionEntry && now <= sessionEntry.expires) {
|
|
99
|
+
return sessionEntry.data;
|
|
100
|
+
}
|
|
101
|
+
if (sessionEntry && now > sessionEntry.expires) {
|
|
102
|
+
this.sessionCache.delete(key);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
91
106
|
}
|
|
92
107
|
/**
|
|
93
108
|
* Set a value in the cache
|
|
@@ -95,13 +110,22 @@ var RBACCache = class {
|
|
|
95
110
|
* @param key - Cache key
|
|
96
111
|
* @param data - Data to cache
|
|
97
112
|
* @param ttl - Time to live in milliseconds (defaults to 60s)
|
|
113
|
+
* @param useSessionCache - Whether to also store in session cache (default: false for page-level checks)
|
|
98
114
|
*/
|
|
99
|
-
set(key, data, ttl = this.TTL) {
|
|
100
|
-
const
|
|
115
|
+
set(key, data, ttl = this.TTL, useSessionCache = false) {
|
|
116
|
+
const now = Date.now();
|
|
117
|
+
const expires = ttl <= 0 ? now - 1 : now + ttl;
|
|
101
118
|
this.cache.set(key, {
|
|
102
119
|
data,
|
|
103
120
|
expires
|
|
104
121
|
});
|
|
122
|
+
if (useSessionCache) {
|
|
123
|
+
const sessionExpires = ttl <= 0 ? now - 1 : now + this.SESSION_TTL;
|
|
124
|
+
this.sessionCache.set(key, {
|
|
125
|
+
data,
|
|
126
|
+
expires: sessionExpires
|
|
127
|
+
});
|
|
128
|
+
}
|
|
105
129
|
}
|
|
106
130
|
/**
|
|
107
131
|
* Delete a specific key from the cache
|
|
@@ -110,6 +134,7 @@ var RBACCache = class {
|
|
|
110
134
|
*/
|
|
111
135
|
delete(key) {
|
|
112
136
|
this.cache.delete(key);
|
|
137
|
+
this.sessionCache.delete(key);
|
|
113
138
|
}
|
|
114
139
|
/**
|
|
115
140
|
* Invalidate cache entries matching a pattern
|
|
@@ -128,7 +153,15 @@ var RBACCache = class {
|
|
|
128
153
|
keysToDelete.push(key);
|
|
129
154
|
}
|
|
130
155
|
}
|
|
131
|
-
|
|
156
|
+
for (const key of this.sessionCache.keys()) {
|
|
157
|
+
if (matcher(key) && !keysToDelete.includes(key)) {
|
|
158
|
+
keysToDelete.push(key);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
keysToDelete.forEach((key) => {
|
|
162
|
+
this.cache.delete(key);
|
|
163
|
+
this.sessionCache.delete(key);
|
|
164
|
+
});
|
|
132
165
|
this.invalidationCallbacks.forEach((callback) => callback(trimmedPattern));
|
|
133
166
|
}
|
|
134
167
|
createMatcher(pattern) {
|
|
@@ -145,6 +178,7 @@ var RBACCache = class {
|
|
|
145
178
|
*/
|
|
146
179
|
clear() {
|
|
147
180
|
this.cache.clear();
|
|
181
|
+
this.sessionCache.clear();
|
|
148
182
|
}
|
|
149
183
|
/**
|
|
150
184
|
* Get cache statistics
|
|
@@ -152,7 +186,9 @@ var RBACCache = class {
|
|
|
152
186
|
getStats() {
|
|
153
187
|
return {
|
|
154
188
|
size: this.cache.size,
|
|
189
|
+
sessionSize: this.sessionCache.size,
|
|
155
190
|
ttl: this.TTL,
|
|
191
|
+
sessionTtl: this.SESSION_TTL,
|
|
156
192
|
keys: Array.from(this.cache.keys())
|
|
157
193
|
};
|
|
158
194
|
}
|
|
@@ -296,6 +332,7 @@ var INVALIDATION_PATTERNS = {
|
|
|
296
332
|
var RBACCacheInvalidationManager = class {
|
|
297
333
|
constructor(supabase) {
|
|
298
334
|
this.invalidationCallbacks = /* @__PURE__ */ new Set();
|
|
335
|
+
this.channels = [];
|
|
299
336
|
this.supabase = supabase;
|
|
300
337
|
this.setupRealtimeSubscriptions();
|
|
301
338
|
}
|
|
@@ -393,13 +430,18 @@ var RBACCacheInvalidationManager = class {
|
|
|
393
430
|
}
|
|
394
431
|
/**
|
|
395
432
|
* Setup realtime subscriptions for automatic cache invalidation
|
|
433
|
+
* Prevents duplicate subscriptions by checking if already set up
|
|
396
434
|
*/
|
|
397
435
|
setupRealtimeSubscriptions() {
|
|
398
436
|
if (!this.supabase.channel || typeof this.supabase.channel !== "function") {
|
|
399
437
|
log.debug("Realtime not available, skipping subscriptions");
|
|
400
438
|
return;
|
|
401
439
|
}
|
|
402
|
-
this.
|
|
440
|
+
if (this.channels.length > 0) {
|
|
441
|
+
log.debug("Realtime subscriptions already set up, skipping duplicate setup");
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
const orgRolesChannel = this.supabase.channel("rbac_organisation_roles_changes").on("postgres_changes", {
|
|
403
445
|
event: "*",
|
|
404
446
|
schema: "public",
|
|
405
447
|
table: "rbac_organisation_roles"
|
|
@@ -411,8 +453,10 @@ var RBACCacheInvalidationManager = class {
|
|
|
411
453
|
if (user_id) {
|
|
412
454
|
this.invalidateUser(user_id, `organisation_role_${payload.eventType}`);
|
|
413
455
|
}
|
|
414
|
-
})
|
|
415
|
-
|
|
456
|
+
});
|
|
457
|
+
const orgRolesSubscription = orgRolesChannel.subscribe();
|
|
458
|
+
this.channels.push(orgRolesSubscription);
|
|
459
|
+
const eventAppRolesChannel = this.supabase.channel("rbac_event_app_roles_changes").on("postgres_changes", {
|
|
416
460
|
event: "*",
|
|
417
461
|
schema: "public",
|
|
418
462
|
table: "rbac_event_app_roles"
|
|
@@ -430,8 +474,10 @@ var RBACCacheInvalidationManager = class {
|
|
|
430
474
|
if (app_id) {
|
|
431
475
|
this.invalidateApp(app_id, `event_app_role_${payload.eventType}`);
|
|
432
476
|
}
|
|
433
|
-
})
|
|
434
|
-
|
|
477
|
+
});
|
|
478
|
+
const eventAppRolesSubscription = eventAppRolesChannel.subscribe();
|
|
479
|
+
this.channels.push(eventAppRolesSubscription);
|
|
480
|
+
const globalRolesChannel = this.supabase.channel("rbac_global_roles_changes").on("postgres_changes", {
|
|
435
481
|
event: "*",
|
|
436
482
|
schema: "public",
|
|
437
483
|
table: "rbac_global_roles"
|
|
@@ -440,8 +486,10 @@ var RBACCacheInvalidationManager = class {
|
|
|
440
486
|
if (user_id) {
|
|
441
487
|
this.invalidateUser(user_id, `global_role_${payload.eventType}`);
|
|
442
488
|
}
|
|
443
|
-
})
|
|
444
|
-
|
|
489
|
+
});
|
|
490
|
+
const globalRolesSubscription = globalRolesChannel.subscribe();
|
|
491
|
+
this.channels.push(globalRolesSubscription);
|
|
492
|
+
const pagePermissionsChannel = this.supabase.channel("rbac_page_permissions_changes").on("postgres_changes", {
|
|
445
493
|
event: "*",
|
|
446
494
|
schema: "public",
|
|
447
495
|
table: "rbac_page_permissions"
|
|
@@ -453,7 +501,26 @@ var RBACCacheInvalidationManager = class {
|
|
|
453
501
|
if (app_page_id) {
|
|
454
502
|
this.invalidatePage(app_page_id, `page_permission_${payload.eventType}`);
|
|
455
503
|
}
|
|
456
|
-
})
|
|
504
|
+
});
|
|
505
|
+
const pagePermissionsSubscription = pagePermissionsChannel.subscribe();
|
|
506
|
+
this.channels.push(pagePermissionsSubscription);
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Cleanup all realtime subscriptions
|
|
510
|
+
* Call this when the manager is no longer needed to prevent memory leaks
|
|
511
|
+
*/
|
|
512
|
+
cleanup() {
|
|
513
|
+
this.channels.forEach((channel) => {
|
|
514
|
+
try {
|
|
515
|
+
if (channel && typeof channel.unsubscribe === "function") {
|
|
516
|
+
channel.unsubscribe();
|
|
517
|
+
}
|
|
518
|
+
} catch (error) {
|
|
519
|
+
log.warn("Failed to unsubscribe from channel:", error);
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
this.channels = [];
|
|
523
|
+
this.invalidationCallbacks.clear();
|
|
457
524
|
}
|
|
458
525
|
/**
|
|
459
526
|
* Manually trigger cache invalidation for all users in an organisation
|
|
@@ -479,6 +546,10 @@ var RBACCacheInvalidationManager = class {
|
|
|
479
546
|
};
|
|
480
547
|
var globalCacheInvalidationManager = null;
|
|
481
548
|
function initializeCacheInvalidation(supabase) {
|
|
549
|
+
if (globalCacheInvalidationManager) {
|
|
550
|
+
log.debug("Cleaning up existing cache invalidation manager before creating new one");
|
|
551
|
+
globalCacheInvalidationManager.cleanup();
|
|
552
|
+
}
|
|
482
553
|
globalCacheInvalidationManager = new RBACCacheInvalidationManager(supabase);
|
|
483
554
|
return globalCacheInvalidationManager;
|
|
484
555
|
}
|
|
@@ -1083,24 +1154,6 @@ var RBACEngine = class {
|
|
|
1083
1154
|
if (cached !== null) {
|
|
1084
1155
|
cacheHit = true;
|
|
1085
1156
|
cacheSource = "memory";
|
|
1086
|
-
const duration2 = Date.now() - startTime;
|
|
1087
|
-
if (scope.organisationId) {
|
|
1088
|
-
const resolvedPageId = await this.resolvePageId(pageId, scope.appId);
|
|
1089
|
-
await emitAuditEvent({
|
|
1090
|
-
type: "permission_check",
|
|
1091
|
-
userId,
|
|
1092
|
-
organisationId: scope.organisationId,
|
|
1093
|
-
eventId: scope.eventId,
|
|
1094
|
-
appId: scope.appId,
|
|
1095
|
-
pageId: resolvedPageId,
|
|
1096
|
-
permission,
|
|
1097
|
-
decision: cached,
|
|
1098
|
-
source: "api",
|
|
1099
|
-
duration_ms: duration2,
|
|
1100
|
-
cache_hit: true,
|
|
1101
|
-
cache_source: "memory"
|
|
1102
|
-
});
|
|
1103
|
-
}
|
|
1104
1157
|
return cached;
|
|
1105
1158
|
}
|
|
1106
1159
|
const { data, error } = await this.supabase.rpc("rbac_check_permission_simplified", {
|
|
@@ -1409,6 +1462,167 @@ function createRBACEngine(supabase, securityConfig) {
|
|
|
1409
1462
|
return new RBACEngine(supabase, securityConfig);
|
|
1410
1463
|
}
|
|
1411
1464
|
|
|
1465
|
+
// src/rbac/performance.ts
|
|
1466
|
+
var RBACPerformanceMonitor = class {
|
|
1467
|
+
constructor() {
|
|
1468
|
+
this.metrics = {
|
|
1469
|
+
totalChecks: 0,
|
|
1470
|
+
cacheHits: 0,
|
|
1471
|
+
cacheMisses: 0,
|
|
1472
|
+
cacheHitRate: 0,
|
|
1473
|
+
deduplicatedRequests: 0,
|
|
1474
|
+
networkRequests: 0,
|
|
1475
|
+
averageResponseTime: 0,
|
|
1476
|
+
totalResponseTime: 0,
|
|
1477
|
+
batchedAuditEvents: 0,
|
|
1478
|
+
individualAuditEvents: 0
|
|
1479
|
+
};
|
|
1480
|
+
this.enabled = false;
|
|
1481
|
+
}
|
|
1482
|
+
/**
|
|
1483
|
+
* Enable or disable performance monitoring
|
|
1484
|
+
*/
|
|
1485
|
+
setEnabled(enabled) {
|
|
1486
|
+
this.enabled = enabled;
|
|
1487
|
+
}
|
|
1488
|
+
/**
|
|
1489
|
+
* Check if performance monitoring is enabled
|
|
1490
|
+
*/
|
|
1491
|
+
isEnabled() {
|
|
1492
|
+
return this.enabled;
|
|
1493
|
+
}
|
|
1494
|
+
/**
|
|
1495
|
+
* Record a permission check
|
|
1496
|
+
*/
|
|
1497
|
+
recordCheck(cacheHit, responseTime, wasDeduplicated = false) {
|
|
1498
|
+
if (!this.enabled) {
|
|
1499
|
+
return;
|
|
1500
|
+
}
|
|
1501
|
+
this.metrics.totalChecks++;
|
|
1502
|
+
if (cacheHit) {
|
|
1503
|
+
this.metrics.cacheHits++;
|
|
1504
|
+
} else {
|
|
1505
|
+
this.metrics.cacheMisses++;
|
|
1506
|
+
this.metrics.networkRequests++;
|
|
1507
|
+
}
|
|
1508
|
+
if (wasDeduplicated) {
|
|
1509
|
+
this.metrics.deduplicatedRequests++;
|
|
1510
|
+
}
|
|
1511
|
+
this.metrics.totalResponseTime += responseTime;
|
|
1512
|
+
this.metrics.averageResponseTime = this.metrics.totalResponseTime / this.metrics.totalChecks;
|
|
1513
|
+
this.metrics.cacheHitRate = this.metrics.cacheHits / this.metrics.totalChecks;
|
|
1514
|
+
}
|
|
1515
|
+
/**
|
|
1516
|
+
* Record an audit event
|
|
1517
|
+
*/
|
|
1518
|
+
recordAuditEvent(batched) {
|
|
1519
|
+
if (!this.enabled) {
|
|
1520
|
+
return;
|
|
1521
|
+
}
|
|
1522
|
+
if (batched) {
|
|
1523
|
+
this.metrics.batchedAuditEvents++;
|
|
1524
|
+
} else {
|
|
1525
|
+
this.metrics.individualAuditEvents++;
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
/**
|
|
1529
|
+
* Get current metrics
|
|
1530
|
+
*/
|
|
1531
|
+
getMetrics() {
|
|
1532
|
+
return { ...this.metrics };
|
|
1533
|
+
}
|
|
1534
|
+
/**
|
|
1535
|
+
* Reset all metrics
|
|
1536
|
+
*/
|
|
1537
|
+
reset() {
|
|
1538
|
+
this.metrics = {
|
|
1539
|
+
totalChecks: 0,
|
|
1540
|
+
cacheHits: 0,
|
|
1541
|
+
cacheMisses: 0,
|
|
1542
|
+
cacheHitRate: 0,
|
|
1543
|
+
deduplicatedRequests: 0,
|
|
1544
|
+
networkRequests: 0,
|
|
1545
|
+
averageResponseTime: 0,
|
|
1546
|
+
totalResponseTime: 0,
|
|
1547
|
+
batchedAuditEvents: 0,
|
|
1548
|
+
individualAuditEvents: 0
|
|
1549
|
+
};
|
|
1550
|
+
}
|
|
1551
|
+
/**
|
|
1552
|
+
* Get metrics summary as a formatted string
|
|
1553
|
+
*/
|
|
1554
|
+
getSummary() {
|
|
1555
|
+
const m = this.metrics;
|
|
1556
|
+
return `
|
|
1557
|
+
RBAC Performance Metrics:
|
|
1558
|
+
Total Checks: ${m.totalChecks}
|
|
1559
|
+
Cache Hits: ${m.cacheHits} (${(m.cacheHitRate * 100).toFixed(1)}%)
|
|
1560
|
+
Cache Misses: ${m.cacheMisses}
|
|
1561
|
+
Deduplicated Requests: ${m.deduplicatedRequests}
|
|
1562
|
+
Network Requests: ${m.networkRequests}
|
|
1563
|
+
Average Response Time: ${m.averageResponseTime.toFixed(2)}ms
|
|
1564
|
+
Batched Audit Events: ${m.batchedAuditEvents}
|
|
1565
|
+
Individual Audit Events: ${m.individualAuditEvents}
|
|
1566
|
+
`;
|
|
1567
|
+
}
|
|
1568
|
+
};
|
|
1569
|
+
var performanceMonitor = new RBACPerformanceMonitor();
|
|
1570
|
+
function enablePerformanceMonitoring() {
|
|
1571
|
+
performanceMonitor.setEnabled(true);
|
|
1572
|
+
}
|
|
1573
|
+
function disablePerformanceMonitoring() {
|
|
1574
|
+
performanceMonitor.setEnabled(false);
|
|
1575
|
+
}
|
|
1576
|
+
function isPerformanceMonitoringEnabled() {
|
|
1577
|
+
return performanceMonitor.isEnabled();
|
|
1578
|
+
}
|
|
1579
|
+
function recordPermissionCheck(cacheHit, responseTime, wasDeduplicated = false) {
|
|
1580
|
+
performanceMonitor.recordCheck(cacheHit, responseTime, wasDeduplicated);
|
|
1581
|
+
}
|
|
1582
|
+
function recordAuditEvent(batched) {
|
|
1583
|
+
performanceMonitor.recordAuditEvent(batched);
|
|
1584
|
+
}
|
|
1585
|
+
function getPerformanceMetrics() {
|
|
1586
|
+
return performanceMonitor.getMetrics();
|
|
1587
|
+
}
|
|
1588
|
+
function resetPerformanceMetrics() {
|
|
1589
|
+
performanceMonitor.reset();
|
|
1590
|
+
}
|
|
1591
|
+
function getPerformanceSummary() {
|
|
1592
|
+
return performanceMonitor.getSummary();
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
// src/rbac/request-deduplication.ts
|
|
1596
|
+
var inFlightRequests = /* @__PURE__ */ new Map();
|
|
1597
|
+
function generateDeduplicationKey(input) {
|
|
1598
|
+
return RBACCache.generatePermissionKey({
|
|
1599
|
+
userId: input.userId,
|
|
1600
|
+
organisationId: input.scope.organisationId,
|
|
1601
|
+
eventId: input.scope.eventId,
|
|
1602
|
+
appId: input.scope.appId,
|
|
1603
|
+
permission: input.permission,
|
|
1604
|
+
pageId: input.pageId
|
|
1605
|
+
});
|
|
1606
|
+
}
|
|
1607
|
+
async function getOrCreateRequest(input, checkFn) {
|
|
1608
|
+
const key = generateDeduplicationKey(input);
|
|
1609
|
+
const existingRequest = inFlightRequests.get(key);
|
|
1610
|
+
if (existingRequest) {
|
|
1611
|
+
return existingRequest;
|
|
1612
|
+
}
|
|
1613
|
+
const requestPromise = checkFn(input).finally(() => {
|
|
1614
|
+
inFlightRequests.delete(key);
|
|
1615
|
+
});
|
|
1616
|
+
inFlightRequests.set(key, requestPromise);
|
|
1617
|
+
return requestPromise;
|
|
1618
|
+
}
|
|
1619
|
+
function clearInFlightRequests() {
|
|
1620
|
+
inFlightRequests.clear();
|
|
1621
|
+
}
|
|
1622
|
+
function getInFlightRequestCount() {
|
|
1623
|
+
return inFlightRequests.size;
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1412
1626
|
// src/rbac/api.ts
|
|
1413
1627
|
var log3 = createLogger("RBACAPI");
|
|
1414
1628
|
var globalEngine = null;
|
|
@@ -1430,8 +1644,16 @@ function setupRBAC(supabase, config) {
|
|
|
1430
1644
|
...config?.security
|
|
1431
1645
|
};
|
|
1432
1646
|
globalEngine = createRBACEngine(supabase, securityConfig);
|
|
1433
|
-
const
|
|
1647
|
+
const useBatchedAudit = config?.audit?.batched !== false && config?.performance?.enableBatchedAuditLogging !== false;
|
|
1648
|
+
const batchConfig = useBatchedAudit ? {
|
|
1649
|
+
batchWindow: config?.audit?.batchWindow,
|
|
1650
|
+
batchSize: config?.audit?.batchSize
|
|
1651
|
+
} : void 0;
|
|
1652
|
+
const auditManager = createAuditManager(supabase, useBatchedAudit, batchConfig);
|
|
1434
1653
|
setGlobalAuditManager(auditManager);
|
|
1654
|
+
if (config?.performance?.enablePerformanceTracking) {
|
|
1655
|
+
enablePerformanceMonitoring();
|
|
1656
|
+
}
|
|
1435
1657
|
logger.info("RBAC system initialized successfully");
|
|
1436
1658
|
}
|
|
1437
1659
|
function getEngine() {
|
|
@@ -1480,13 +1702,16 @@ async function isPermittedCached(input) {
|
|
|
1480
1702
|
permission,
|
|
1481
1703
|
pageId
|
|
1482
1704
|
});
|
|
1483
|
-
const cached = rbacCache.get(cacheKey);
|
|
1705
|
+
const cached = rbacCache.get(cacheKey, true);
|
|
1484
1706
|
if (cached !== null) {
|
|
1485
1707
|
return cached;
|
|
1486
1708
|
}
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1709
|
+
return getOrCreateRequest(input, async (checkInput) => {
|
|
1710
|
+
const result = await isPermitted(checkInput);
|
|
1711
|
+
const isPageLevelCheck = !!pageId || permission.includes("page.");
|
|
1712
|
+
rbacCache.set(cacheKey, result, void 0, isPageLevelCheck);
|
|
1713
|
+
return result;
|
|
1714
|
+
});
|
|
1490
1715
|
}
|
|
1491
1716
|
async function hasPermission(input) {
|
|
1492
1717
|
return isPermitted(input);
|
|
@@ -1589,6 +1814,16 @@ export {
|
|
|
1589
1814
|
isDevelopmentMode,
|
|
1590
1815
|
RBACEngine,
|
|
1591
1816
|
createRBACEngine,
|
|
1817
|
+
enablePerformanceMonitoring,
|
|
1818
|
+
disablePerformanceMonitoring,
|
|
1819
|
+
isPerformanceMonitoringEnabled,
|
|
1820
|
+
recordPermissionCheck,
|
|
1821
|
+
recordAuditEvent,
|
|
1822
|
+
getPerformanceMetrics,
|
|
1823
|
+
resetPerformanceMetrics,
|
|
1824
|
+
getPerformanceSummary,
|
|
1825
|
+
clearInFlightRequests,
|
|
1826
|
+
getInFlightRequestCount,
|
|
1592
1827
|
setupRBAC,
|
|
1593
1828
|
getAccessLevel,
|
|
1594
1829
|
getPermissionMap,
|
|
@@ -1610,4 +1845,4 @@ export {
|
|
|
1610
1845
|
invalidateAppCache,
|
|
1611
1846
|
clearCache
|
|
1612
1847
|
};
|
|
1613
|
-
//# sourceMappingURL=chunk-
|
|
1848
|
+
//# sourceMappingURL=chunk-HEHYGYOX.js.map
|