@memberjunction/server 6.2.0-edge.5 → 6.2.0-edge.6
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/README.md +27 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/agentSessions/SessionJanitor.d.ts +3 -3
- package/dist/agentSessions/SessionJanitor.js +3 -3
- package/dist/agentSessions/SessionManager.d.ts +15 -5
- package/dist/agentSessions/SessionManager.d.ts.map +1 -1
- package/dist/agentSessions/SessionManager.js +34 -12
- package/dist/agentSessions/SessionManager.js.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.js +2 -0
- package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +51 -10
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.d.ts +10 -0
- package/dist/auth/initializeProviders.d.ts.map +1 -1
- package/dist/auth/initializeProviders.js +37 -1
- package/dist/auth/initializeProviders.js.map +1 -1
- package/dist/auth/localDevAuth.d.ts +79 -0
- package/dist/auth/localDevAuth.d.ts.map +1 -0
- package/dist/auth/localDevAuth.js +439 -0
- package/dist/auth/localDevAuth.js.map +1 -0
- package/dist/auth/magicLink/MagicLinkKeys.d.ts +2 -2
- package/dist/auth/magicLink/MagicLinkKeys.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkKeys.js +1 -1
- package/dist/auth/magicLink/MagicLinkKeys.js.map +1 -1
- package/dist/auth/magicLink/types.d.ts +12 -0
- package/dist/auth/magicLink/types.d.ts.map +1 -1
- package/dist/auth/sessionUserClone.d.ts +1 -1
- package/dist/auth/sessionUserClone.d.ts.map +1 -1
- package/dist/auth/sessionUserClone.js +3 -2
- package/dist/auth/sessionUserClone.js.map +1 -1
- package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.d.ts +292 -0
- package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.d.ts.map +1 -0
- package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.js +442 -0
- package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.js.map +1 -0
- package/dist/broadcast/index.d.ts +6 -0
- package/dist/broadcast/index.d.ts.map +1 -0
- package/dist/broadcast/index.js +6 -0
- package/dist/broadcast/index.js.map +1 -0
- package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.d.ts +43 -0
- package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.d.ts.map +1 -0
- package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.js +144 -0
- package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.js.map +1 -0
- package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.d.ts +46 -0
- package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.d.ts.map +1 -0
- package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.js +149 -0
- package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.js.map +1 -0
- package/dist/broadcast/providers/GCPPubSubBroadcastProvider.d.ts +49 -0
- package/dist/broadcast/providers/GCPPubSubBroadcastProvider.d.ts.map +1 -0
- package/dist/broadcast/providers/GCPPubSubBroadcastProvider.js +131 -0
- package/dist/broadcast/providers/GCPPubSubBroadcastProvider.js.map +1 -0
- package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.d.ts +24 -0
- package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.d.ts.map +1 -0
- package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.js +51 -0
- package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.js.map +1 -0
- package/dist/cache.d.ts +3 -2
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js.map +1 -1
- package/dist/config.d.ts +496 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +61 -0
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +3 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +29 -8
- package/dist/context.js.map +1 -1
- package/dist/coreRoutes.d.ts.map +1 -1
- package/dist/coreRoutes.js +14 -0
- package/dist/coreRoutes.js.map +1 -1
- package/dist/generated/graphql-schemas/__mj.d.ts +635 -14
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +3366 -418
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/CacheInvalidationResolver.d.ts +50 -30
- package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
- package/dist/generic/CacheInvalidationResolver.js +154 -79
- package/dist/generic/CacheInvalidationResolver.js.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.js +2 -0
- package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
- package/dist/generic/PubSubManager.d.ts +10 -0
- package/dist/generic/PubSubManager.d.ts.map +1 -1
- package/dist/generic/PubSubManager.js +44 -1
- package/dist/generic/PubSubManager.js.map +1 -1
- package/dist/generic/PushStatusResolver.d.ts +39 -6
- package/dist/generic/PushStatusResolver.d.ts.map +1 -1
- package/dist/generic/PushStatusResolver.js +93 -11
- package/dist/generic/PushStatusResolver.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +65 -25
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +201 -101
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +11 -3
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +79 -13
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/generic/actionOutputFieldSecurity.d.ts +26 -0
- package/dist/generic/actionOutputFieldSecurity.d.ts.map +1 -0
- package/dist/generic/actionOutputFieldSecurity.js +47 -0
- package/dist/generic/actionOutputFieldSecurity.js.map +1 -0
- package/dist/generic/fieldSecurityTransport.d.ts +30 -0
- package/dist/generic/fieldSecurityTransport.d.ts.map +1 -0
- package/dist/generic/fieldSecurityTransport.js +30 -0
- package/dist/generic/fieldSecurityTransport.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +122 -66
- package/dist/index.js.map +1 -1
- package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
- package/dist/integration/CustomColumnPromoter.js +6 -1
- package/dist/integration/CustomColumnPromoter.js.map +1 -1
- package/dist/logging/variablesLoggingMiddleware.d.ts +12 -0
- package/dist/logging/variablesLoggingMiddleware.d.ts.map +1 -1
- package/dist/logging/variablesLoggingMiddleware.js +50 -1
- package/dist/logging/variablesLoggingMiddleware.js.map +1 -1
- package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts.map +1 -1
- package/dist/realtimeSessions/SessionVerificationPortsBase.js +1 -0
- package/dist/realtimeSessions/SessionVerificationPortsBase.js.map +1 -1
- package/dist/realtimeSessions/ownedRealtimeSession.d.ts +8 -6
- package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -1
- package/dist/realtimeSessions/ownedRealtimeSession.js +15 -6
- package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -1
- package/dist/realtimeSessions/sessionAccess.d.ts +88 -11
- package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -1
- package/dist/realtimeSessions/sessionAccess.js +125 -22
- package/dist/realtimeSessions/sessionAccess.js.map +1 -1
- package/dist/realtimeSessions/sessionConfigStamps.js +1 -1
- package/dist/realtimeSessions/sessionConfigStamps.js.map +1 -1
- package/dist/realtimeSessions/subscriptionAuthorization.d.ts.map +1 -1
- package/dist/realtimeSessions/subscriptionAuthorization.js +5 -2
- package/dist/realtimeSessions/subscriptionAuthorization.js.map +1 -1
- package/dist/realtimeSessions/verificationWorkflow.d.ts +2 -0
- package/dist/realtimeSessions/verificationWorkflow.d.ts.map +1 -1
- package/dist/realtimeSessions/verificationWorkflow.js +1 -1
- package/dist/realtimeSessions/verificationWorkflow.js.map +1 -1
- package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -1
- package/dist/realtimeWidget/WidgetRouter.js +19 -3
- package/dist/realtimeWidget/WidgetRouter.js.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.d.ts +67 -7
- package/dist/realtimeWidget/WidgetSessionService.d.ts.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.js +201 -19
- package/dist/realtimeWidget/WidgetSessionService.js.map +1 -1
- package/dist/realtimeWidget/host-identity.d.ts +1 -1
- package/dist/realtimeWidget/host-identity.js +1 -1
- package/dist/realtimeWidget/widgetCore.d.ts +20 -1
- package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetCore.js +17 -1
- package/dist/realtimeWidget/widgetCore.js.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.d.ts +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js +2 -1
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- package/dist/resolvers/ActionResolver.d.ts +19 -1
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +63 -12
- package/dist/resolvers/ActionResolver.js.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.js +1 -0
- package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
- package/dist/resolvers/AgentRunStatusPublisher.d.ts +18 -4
- package/dist/resolvers/AgentRunStatusPublisher.d.ts.map +1 -1
- package/dist/resolvers/AgentRunStatusPublisher.js +32 -8
- package/dist/resolvers/AgentRunStatusPublisher.js.map +1 -1
- package/dist/resolvers/AgentSessionResolver.d.ts +10 -4
- package/dist/resolvers/AgentSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/AgentSessionResolver.js +40 -17
- package/dist/resolvers/AgentSessionResolver.js.map +1 -1
- package/dist/resolvers/EntityCommunicationsResolver.d.ts +13 -1
- package/dist/resolvers/EntityCommunicationsResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityCommunicationsResolver.js +50 -14
- package/dist/resolvers/EntityCommunicationsResolver.js.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts +28 -0
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.js +117 -21
- package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
- package/dist/resolvers/FileCategoryResolver.d.ts.map +1 -1
- package/dist/resolvers/FileCategoryResolver.js +1 -0
- package/dist/resolvers/FileCategoryResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.d.ts +5 -0
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +13 -4
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +45 -7
- package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.d.ts +8 -1
- package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.js +31 -3
- package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
- package/dist/resolvers/PipelineProgressResolver.d.ts +6 -0
- package/dist/resolvers/PipelineProgressResolver.d.ts.map +1 -1
- package/dist/resolvers/PipelineProgressResolver.js +5 -3
- package/dist/resolvers/PipelineProgressResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +20 -6
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts +2 -0
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +15 -6
- package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
- package/dist/resolvers/RSUResolver.d.ts.map +1 -1
- package/dist/resolvers/RSUResolver.js +12 -0
- package/dist/resolvers/RSUResolver.js.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +16 -2
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +82 -28
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +11 -9
- package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +56 -8
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +209 -64
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +4 -4
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/RunTestResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTestResolver.js +3 -1
- package/dist/resolvers/RunTestResolver.js.map +1 -1
- package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncDataResolver.js +4 -0
- package/dist/resolvers/SyncDataResolver.js.map +1 -1
- package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
- package/dist/resolvers/TestQuerySQLResolver.js +1 -0
- package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts +17 -2
- package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.js +60 -15
- package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
- package/dist/resolvers/UserViewResolver.d.ts +1 -1
- package/dist/resolvers/UserViewResolver.d.ts.map +1 -1
- package/dist/resolvers/UserViewResolver.js +2 -1
- package/dist/resolvers/UserViewResolver.js.map +1 -1
- package/dist/rest/EntityCRUDHandler.d.ts +6 -0
- package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
- package/dist/rest/EntityCRUDHandler.js +19 -5
- package/dist/rest/EntityCRUDHandler.js.map +1 -1
- package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
- package/dist/rest/RESTEndpointHandler.js +8 -5
- package/dist/rest/RESTEndpointHandler.js.map +1 -1
- package/dist/rest/RealtimeRecordingHandler.d.ts +3 -3
- package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -1
- package/dist/rest/RealtimeRecordingHandler.js +7 -7
- package/dist/rest/RealtimeRecordingHandler.js.map +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts +6 -0
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +22 -5
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/serverRoleConfigUnits.d.ts +29 -0
- package/dist/serverRoleConfigUnits.d.ts.map +1 -0
- package/dist/serverRoleConfigUnits.js +33 -0
- package/dist/serverRoleConfigUnits.js.map +1 -0
- package/dist/services/TaskGraphContinuationDeliverer.d.ts +5 -0
- package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.js +42 -15
- package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
- package/dist/types.d.ts +23 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +98 -98
- package/src/__tests__/ActionResolver.fieldSecurity.test.ts +237 -0
- package/src/__tests__/AdhocQueryResolver.dialect.test.ts +137 -0
- package/src/__tests__/AgentRunStatusPublisher.test.ts +49 -0
- package/src/__tests__/AgentSessionResolver.ownership.test.ts +137 -0
- package/src/__tests__/CustomColumnPromoterOnePass.test.ts +15 -1
- package/src/__tests__/EntityCommunicationsResolver.actingUser.test.ts +151 -0
- package/src/__tests__/EvolutionActsOnWhatItDetects.test.ts +113 -0
- package/src/__tests__/FetchEntityVectorsResolver.test.ts +206 -3
- package/src/__tests__/FileResolver.fieldSecurity.test.ts +82 -0
- package/src/__tests__/PipelineProgressResolver.filter.test.ts +58 -0
- package/src/__tests__/QuerySystemUserResolver.fieldSecurity.test.ts +49 -0
- package/src/__tests__/RESTEndpointHandler.test.ts +25 -0
- package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +23 -3
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +324 -46
- package/src/__tests__/RemoteBrowserActionResolver.ownership.test.ts +98 -0
- package/src/__tests__/ResolverBase.clientOldValues.test.ts +37 -4
- package/src/__tests__/ResolverBase.deleteReturnProjection.test.ts +52 -0
- package/src/__tests__/ResolverBase.entityMessageRelay.test.ts +176 -0
- package/src/__tests__/ResolverBase.includeBinaryFields.test.ts +23 -1
- package/src/__tests__/ResolverBase.publishStatusUpdate.test.ts +68 -0
- package/src/__tests__/ResolverBase.userViewCacheAndDedup.test.ts +130 -0
- package/src/__tests__/RunAIAgentResolver.branch.test.ts +68 -13
- package/src/__tests__/RunAIAgentResolver.conversationWriter.test.ts +210 -0
- package/src/__tests__/RunAIAgentResolver.fireAndForgetCompletion.test.ts +209 -0
- package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +17 -27
- package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +8 -2
- package/src/__tests__/RunAIAgentResolver.serverReply.test.ts +358 -0
- package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +4 -1
- package/src/__tests__/RunTemplateResolver.test.ts +35 -2
- package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +11 -0
- package/src/__tests__/SessionManager.test.ts +95 -0
- package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +114 -3
- package/src/__tests__/TransactionGroupResolver.fieldSecurity.test.ts +199 -0
- package/src/__tests__/UserViewResolver.updateWhereClause.test.ts +15 -0
- package/src/__tests__/ViewOperationsHandler.test.ts +7 -2
- package/src/__tests__/WidgetSessionService.test.ts +583 -4
- package/src/__tests__/apiRootBoot.test.ts +1 -1
- package/src/__tests__/buildMagicLinkSessionUser.test.ts +96 -0
- package/src/__tests__/cacheBroadcastProviders.test.ts +403 -0
- package/src/__tests__/cacheInvalidationRecordData.test.ts +45 -0
- package/src/__tests__/fieldSecurityFixtures.ts +91 -0
- package/src/__tests__/globalCors.test.ts +3 -3
- package/src/__tests__/localDevAuth.test.ts +196 -0
- package/src/__tests__/orphanedConversationDetailReconciler.test.ts +10 -0
- package/src/__tests__/pushStatusResolver.filter.test.ts +57 -1
- package/src/__tests__/realtimeRecordingHandler.test.ts +19 -2
- package/src/__tests__/realtimeSessions/RealtimeSessionEventsResolver.test.ts +29 -1
- package/src/__tests__/realtimeSessions/ownedRealtimeSession.anonymous.test.ts +31 -0
- package/src/__tests__/realtimeSessions/ownedRealtimeSession.namedScoped.test.ts +37 -0
- package/src/__tests__/realtimeSessions/sessionAccess.test.ts +146 -7
- package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +1 -1
- package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +25 -4
- package/src/__tests__/resolverBase.cloudEventChangedFields.test.ts +157 -0
- package/src/__tests__/resolverBase.fieldSecurityTransport.test.ts +222 -0
- package/src/__tests__/resolverBase.fls.test.ts +146 -97
- package/src/__tests__/restTransport.fieldSecurity.test.ts +148 -0
- package/src/__tests__/runParamsTimeZone.test.ts +179 -0
- package/src/__tests__/runStreams.fieldSecurity.test.ts +100 -0
- package/src/__tests__/runViewProperties.test.ts +114 -0
- package/src/__tests__/scalabilityBenchmarks.test.ts +765 -0
- package/src/__tests__/scalabilityDatabaseIntegration.test.ts +207 -0
- package/src/__tests__/sessionUserClone.test.ts +5 -1
- package/src/__tests__/startupSweepOrder.test.ts +40 -0
- package/src/__tests__/unifiedAuth.test.ts +28 -0
- package/src/__tests__/widgetGuestElevation.test.ts +2 -0
- package/src/agentSessions/SessionJanitor.ts +3 -3
- package/src/agentSessions/SessionManager.ts +35 -12
- package/src/auth/AuthProviderCatalogRouter.ts +3 -0
- package/src/auth/index.ts +56 -12
- package/src/auth/initializeProviders.ts +43 -1
- package/src/auth/localDevAuth.ts +528 -0
- package/src/auth/magicLink/MagicLinkKeys.ts +2 -2
- package/src/auth/magicLink/types.ts +10 -0
- package/src/auth/sessionUserClone.ts +3 -2
- package/src/broadcast/BaseCacheInvalidationBroadcastProvider.ts +674 -0
- package/src/broadcast/index.ts +5 -0
- package/src/broadcast/providers/AWSIoTCoreBroadcastProvider.ts +180 -0
- package/src/broadcast/providers/AzureWebPubSubBroadcastProvider.ts +182 -0
- package/src/broadcast/providers/GCPPubSubBroadcastProvider.ts +169 -0
- package/src/broadcast/providers/SequencedRoleBucketBroadcastProvider.ts +57 -0
- package/src/cache.ts +2 -1
- package/src/config.ts +69 -0
- package/src/context.ts +32 -8
- package/src/coreRoutes.ts +15 -0
- package/src/generated/graphql-schemas/__mj.ts +2239 -102
- package/src/generic/CacheInvalidationResolver.ts +135 -78
- package/src/generic/OrphanedConversationDetailReconciler.ts +4 -2
- package/src/generic/PubSubManager.ts +54 -1
- package/src/generic/PushStatusResolver.ts +108 -11
- package/src/generic/ResolverBase.ts +237 -107
- package/src/generic/RunViewResolver.ts +80 -15
- package/src/generic/actionOutputFieldSecurity.ts +75 -0
- package/src/generic/fieldSecurityTransport.ts +62 -0
- package/src/index.ts +127 -68
- package/src/integration/CustomColumnPromoter.ts +6 -1
- package/src/logging/variablesLoggingMiddleware.ts +59 -3
- package/src/realtimeSessions/README.md +7 -3
- package/src/realtimeSessions/SessionVerificationPortsBase.ts +1 -0
- package/src/realtimeSessions/ownedRealtimeSession.ts +20 -6
- package/src/realtimeSessions/sessionAccess.ts +181 -25
- package/src/realtimeSessions/sessionConfigStamps.ts +1 -1
- package/src/realtimeSessions/subscriptionAuthorization.ts +4 -2
- package/src/realtimeSessions/verificationWorkflow.ts +3 -1
- package/src/realtimeWidget/WidgetRouter.ts +22 -4
- package/src/realtimeWidget/WidgetSessionService.ts +252 -17
- package/src/realtimeWidget/host-identity.ts +1 -1
- package/src/realtimeWidget/widgetCore.ts +30 -1
- package/src/realtimeWidget/widgetGuestElevation.ts +2 -1
- package/src/resolvers/ActionResolver.ts +78 -15
- package/src/resolvers/AdhocQueryResolver.ts +1 -0
- package/src/resolvers/AgentRunStatusPublisher.ts +36 -8
- package/src/resolvers/AgentSessionResolver.ts +46 -18
- package/src/resolvers/EntityCommunicationsResolver.ts +56 -15
- package/src/resolvers/FetchEntityVectorsResolver.ts +132 -21
- package/src/resolvers/FileCategoryResolver.ts +1 -0
- package/src/resolvers/FileResolver.ts +14 -4
- package/src/resolvers/IntegrationDiscoveryResolver.ts +49 -7
- package/src/resolvers/MergeRecordsResolver.ts +23 -2
- package/src/resolvers/PipelineProgressResolver.ts +12 -3
- package/src/resolvers/QueryResolver.ts +20 -6
- package/src/resolvers/QuerySystemUserResolver.ts +15 -6
- package/src/resolvers/RSUResolver.ts +12 -0
- package/src/resolvers/RealtimeClientSessionResolver.ts +104 -33
- package/src/resolvers/RemoteBrowserActionResolver.ts +15 -10
- package/src/resolvers/RunAIAgentResolver.ts +258 -82
- package/src/resolvers/RunTemplateResolver.ts +6 -4
- package/src/resolvers/RunTestResolver.ts +3 -1
- package/src/resolvers/SyncDataResolver.ts +4 -0
- package/src/resolvers/TestQuerySQLResolver.ts +1 -0
- package/src/resolvers/TransactionGroupResolver.ts +66 -15
- package/src/resolvers/UserViewResolver.ts +2 -1
- package/src/resolvers/__tests__/MergeRecordsResolver.test.ts +43 -0
- package/src/rest/EntityCRUDHandler.ts +22 -5
- package/src/rest/RESTEndpointHandler.ts +8 -5
- package/src/rest/RealtimeRecordingHandler.ts +13 -10
- package/src/rest/ViewOperationsHandler.ts +24 -6
- package/src/serverRoleConfigUnits.ts +48 -0
- package/src/services/TaskGraphContinuationDeliverer.ts +52 -20
- package/src/types.ts +23 -1
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { createHash, createHmac } from 'node:crypto';
|
|
8
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
9
|
+
import { BaseCacheInvalidationBroadcastProvider, } from '../BaseCacheInvalidationBroadcastProvider.js';
|
|
10
|
+
/**
|
|
11
|
+
* Topology 3 Cloud Multiplexer Provider for **AWS IoT Core MQTT over WebSockets** (`'AWSIoTCore'`).
|
|
12
|
+
*
|
|
13
|
+
* Offloads per-client WebSocket connection management and message fan-out from MJServer
|
|
14
|
+
* to AWS IoT Core's managed MQTT message broker:
|
|
15
|
+
* - Each authenticated browser client calls `NegotiateCacheBroadcastConnection` to obtain
|
|
16
|
+
* a SigV4-presigned `wss://<endpoint>/mqtt` URL and its authorized MQTT topic list
|
|
17
|
+
* (`<topicPrefix>/roles/<RoleID>`).
|
|
18
|
+
* - When an entity mutation occurs, MJServer shapes the invalidation payload once per
|
|
19
|
+
* authorized role on the entity and publishes to `<topicPrefix>/roles/<RoleID>`.
|
|
20
|
+
*/
|
|
21
|
+
let AWSIoTCoreBroadcastProvider = class AWSIoTCoreBroadcastProvider extends BaseCacheInvalidationBroadcastProvider {
|
|
22
|
+
constructor() {
|
|
23
|
+
super(...arguments);
|
|
24
|
+
this._topicPublisher = null;
|
|
25
|
+
}
|
|
26
|
+
get Topology() {
|
|
27
|
+
return 'AWSIoTCore';
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Installs a custom MQTT topic publisher (e.g., AWS SDK `IoTDataPlaneClient` adapter or test spy).
|
|
31
|
+
*/
|
|
32
|
+
SetTopicPublisher(publisher) {
|
|
33
|
+
this._topicPublisher = publisher;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Computes the MQTT topic filters (`<topicPrefix>/roles/<roleId>`) for a user's roles.
|
|
37
|
+
*/
|
|
38
|
+
GetAuthorizedTopicsForUser(user) {
|
|
39
|
+
const prefix = (this._config.awsIoTCore?.topicPrefix || 'mj/cache').replace(/\/+$/, '');
|
|
40
|
+
const roles = user.UserRoles ?? [];
|
|
41
|
+
const topics = [];
|
|
42
|
+
for (const r of roles) {
|
|
43
|
+
const roleId = (r.RoleID ?? '').trim().toLowerCase();
|
|
44
|
+
if (roleId.length > 0) {
|
|
45
|
+
topics.push(`${prefix}/roles/${roleId}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
topics.sort();
|
|
49
|
+
return topics;
|
|
50
|
+
}
|
|
51
|
+
async OnInvalidationRecorded(payload) {
|
|
52
|
+
const prefix = (this._config.awsIoTCore?.topicPrefix || 'mj/cache').replace(/\/+$/, '');
|
|
53
|
+
const entity = this.ResolveEntityForPayload(payload);
|
|
54
|
+
if (!entity) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
for (const perm of entity.Permissions) {
|
|
58
|
+
if (!perm.CanRead)
|
|
59
|
+
continue;
|
|
60
|
+
const roleId = (perm.RoleID ?? '').trim().toLowerCase();
|
|
61
|
+
if (!roleId)
|
|
62
|
+
continue;
|
|
63
|
+
const syntheticRoleHolder = { UserRoles: [{ RoleID: roleId }] };
|
|
64
|
+
const shaped = this.ShapeEventForSubscriber(payload, syntheticRoleHolder, entity);
|
|
65
|
+
const message = {
|
|
66
|
+
Topic: `${prefix}/roles/${roleId}`,
|
|
67
|
+
QoS: 1,
|
|
68
|
+
Event: shaped,
|
|
69
|
+
};
|
|
70
|
+
if (this._topicPublisher) {
|
|
71
|
+
await this._topicPublisher(message);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async NegotiateClientConnection(user, defaultGraphQLWsUrl = '/graphql') {
|
|
76
|
+
const endpoint = (this._config.awsIoTCore?.endpoint ?? '').replace(/^https?:\/\//i, '').replace(/\/+$/, '');
|
|
77
|
+
const region = this._config.awsIoTCore?.region || 'us-east-1';
|
|
78
|
+
const ttlSeconds = this._config.awsIoTCore?.tokenTtlSeconds ?? 3600;
|
|
79
|
+
const expiresAtMs = Date.now() + ttlSeconds * 1000;
|
|
80
|
+
const topics = this.GetAuthorizedTopicsForUser(user);
|
|
81
|
+
if (!endpoint) {
|
|
82
|
+
return {
|
|
83
|
+
Provider: this.Topology,
|
|
84
|
+
Url: defaultGraphQLWsUrl,
|
|
85
|
+
Groups: topics,
|
|
86
|
+
ExpiresAt: new Date(expiresAtMs).toISOString(),
|
|
87
|
+
ServerProcessID: this.ServerProcessID,
|
|
88
|
+
CurrentSequence: this.CurrentSequence,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const accessKeyId = this._config.awsIoTCore?.accessKeyId;
|
|
92
|
+
const secretAccessKey = this._config.awsIoTCore?.secretAccessKey;
|
|
93
|
+
const presignedUrl = accessKeyId && secretAccessKey
|
|
94
|
+
? this.buildSigV4PresignedMqttUrl(endpoint, region, accessKeyId, secretAccessKey, ttlSeconds)
|
|
95
|
+
: `wss://${endpoint}/mqtt`;
|
|
96
|
+
return {
|
|
97
|
+
Provider: this.Topology,
|
|
98
|
+
Url: presignedUrl,
|
|
99
|
+
Groups: topics,
|
|
100
|
+
ExpiresAt: new Date(expiresAtMs).toISOString(),
|
|
101
|
+
ServerProcessID: this.ServerProcessID,
|
|
102
|
+
CurrentSequence: this.CurrentSequence,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
buildSigV4PresignedMqttUrl(host, region, accessKeyId, secretAccessKey, expiresSeconds) {
|
|
106
|
+
const now = new Date();
|
|
107
|
+
const amzDate = now.toISOString().replace(/[:-]|\.\d{3}/g, '');
|
|
108
|
+
const dateStamp = amzDate.slice(0, 8);
|
|
109
|
+
const service = 'iotdevicegateway';
|
|
110
|
+
const credentialScope = `${dateStamp}/${region}/${service}/aws4_request`;
|
|
111
|
+
const queryParams = [
|
|
112
|
+
`X-Amz-Algorithm=AWS4-HMAC-SHA256`,
|
|
113
|
+
`X-Amz-Credential=${encodeURIComponent(`${accessKeyId}/${credentialScope}`)}`,
|
|
114
|
+
`X-Amz-Date=${amzDate}`,
|
|
115
|
+
`X-Amz-Expires=${expiresSeconds}`,
|
|
116
|
+
`X-Amz-SignedHeaders=host`,
|
|
117
|
+
].join('&');
|
|
118
|
+
const canonicalRequest = [
|
|
119
|
+
'GET',
|
|
120
|
+
'/mqtt',
|
|
121
|
+
queryParams,
|
|
122
|
+
`host:${host}\n`,
|
|
123
|
+
'host',
|
|
124
|
+
createHash('sha256').update('').digest('hex'),
|
|
125
|
+
].join('\n');
|
|
126
|
+
const stringToSign = [
|
|
127
|
+
'AWS4-HMAC-SHA256',
|
|
128
|
+
amzDate,
|
|
129
|
+
credentialScope,
|
|
130
|
+
createHash('sha256').update(canonicalRequest).digest('hex'),
|
|
131
|
+
].join('\n');
|
|
132
|
+
const kDate = createHmac('sha256', `AWS4${secretAccessKey}`).update(dateStamp).digest();
|
|
133
|
+
const kRegion = createHmac('sha256', kDate).update(region).digest();
|
|
134
|
+
const kService = createHmac('sha256', kRegion).update(service).digest();
|
|
135
|
+
const kSigning = createHmac('sha256', kService).update('aws4_request').digest();
|
|
136
|
+
const signature = createHmac('sha256', kSigning).update(stringToSign).digest('hex');
|
|
137
|
+
return `wss://${host}/mqtt?${queryParams}&X-Amz-Signature=${signature}`;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
AWSIoTCoreBroadcastProvider = __decorate([
|
|
141
|
+
RegisterClass(BaseCacheInvalidationBroadcastProvider, 'AWSIoTCore')
|
|
142
|
+
], AWSIoTCoreBroadcastProvider);
|
|
143
|
+
export { AWSIoTCoreBroadcastProvider };
|
|
144
|
+
//# sourceMappingURL=AWSIoTCoreBroadcastProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AWSIoTCoreBroadcastProvider.js","sourceRoot":"","sources":["../../../src/broadcast/providers/AWSIoTCoreBroadcastProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { UserInfo } from '@memberjunction/core';
|
|
2
|
+
import { BaseCacheInvalidationBroadcastProvider, CacheBroadcastNegotiationResult, CacheInvalidationBroadcastTopology } from '../BaseCacheInvalidationBroadcastProvider.js';
|
|
3
|
+
import type { CacheInvalidationNotification, CacheInvalidationPayload } from '../../generic/CacheInvalidationResolver.js';
|
|
4
|
+
/**
|
|
5
|
+
* Envelope published to an Azure Web PubSub role group.
|
|
6
|
+
*/
|
|
7
|
+
export interface AzureWebPubSubGroupMessage {
|
|
8
|
+
HubName: string;
|
|
9
|
+
GroupName: string;
|
|
10
|
+
Event: CacheInvalidationNotification;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Transport callback used by {@link AzureWebPubSubBroadcastProvider} to deliver a shaped
|
|
14
|
+
* invalidation notification to an Azure Web PubSub group.
|
|
15
|
+
*/
|
|
16
|
+
export type AzureWebPubSubGroupPublisher = (message: AzureWebPubSubGroupMessage) => Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Topology 3 Cloud Multiplexer Provider for **Azure Web PubSub** (`'AzureWebPubSub'`).
|
|
19
|
+
*
|
|
20
|
+
* Offloads per-client WebSocket connection management and message fan-out from MJServer
|
|
21
|
+
* to Azure Web PubSub:
|
|
22
|
+
* - Each authenticated browser client calls `NegotiateCacheBroadcastConnection` to receive
|
|
23
|
+
* a short-lived, HMAC-signed JWT access token scoped to its authorized role groups (`mj-role-<RoleID>`).
|
|
24
|
+
* - When an entity mutation occurs, MJServer shapes the invalidation payload once per
|
|
25
|
+
* authorized role group on the entity and publishes a single group broadcast to Azure Web PubSub,
|
|
26
|
+
* which fans the message out to thousands of connected browsers in C++ edge infrastructure.
|
|
27
|
+
*/
|
|
28
|
+
export declare class AzureWebPubSubBroadcastProvider extends BaseCacheInvalidationBroadcastProvider {
|
|
29
|
+
private _groupPublisher;
|
|
30
|
+
get Topology(): CacheInvalidationBroadcastTopology;
|
|
31
|
+
/**
|
|
32
|
+
* Installs a custom group publisher (e.g., Azure WebPubSubServiceClient adapter or test spy).
|
|
33
|
+
* When unset and an HTTP endpoint + accessKey are configured, defaults to the Azure Web PubSub
|
|
34
|
+
* REST Data Plane API (`POST /api/hubs/{hub}/groups/{group}/:send`).
|
|
35
|
+
*/
|
|
36
|
+
SetGroupPublisher(publisher: AzureWebPubSubGroupPublisher | null): void;
|
|
37
|
+
/**
|
|
38
|
+
* Computes the Azure Web PubSub group names (`mj-role-<roleId>`) for a user's roles.
|
|
39
|
+
*/
|
|
40
|
+
GetAuthorizedGroupsForUser(user: UserInfo): string[];
|
|
41
|
+
protected OnInvalidationRecorded(payload: CacheInvalidationPayload): Promise<void>;
|
|
42
|
+
NegotiateClientConnection(user: UserInfo, defaultGraphQLWsUrl?: string): Promise<CacheBroadcastNegotiationResult>;
|
|
43
|
+
private mintJwtToken;
|
|
44
|
+
private publishViaRestApi;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=AzureWebPubSubBroadcastProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AzureWebPubSubBroadcastProvider.d.ts","sourceRoot":"","sources":["../../../src/broadcast/providers/AzureWebPubSubBroadcastProvider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EACH,sCAAsC,EACtC,+BAA+B,EAC/B,kCAAkC,EACrC,MAAM,8CAA8C,CAAC;AACtD,OAAO,KAAK,EACR,6BAA6B,EAC7B,wBAAwB,EAC3B,MAAM,4CAA4C,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,6BAA6B,CAAC;CACxC;AAED;;;GAGG;AACH,MAAM,MAAM,4BAA4B,GAAG,CAAC,OAAO,EAAE,0BAA0B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAElG;;;;;;;;;;GAUG;AACH,qBACa,+BAAgC,SAAQ,sCAAsC;IACvF,OAAO,CAAC,eAAe,CAA6C;IAEpE,IAAoB,QAAQ,IAAI,kCAAkC,CAEjE;IAED;;;;OAIG;IACI,iBAAiB,CAAC,SAAS,EAAE,4BAA4B,GAAG,IAAI,GAAG,IAAI;IAI9E;;OAEG;IACI,0BAA0B,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE;cAalC,sBAAsB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IA6B3E,yBAAyB,CAC3C,IAAI,EAAE,QAAQ,EACd,mBAAmB,SAAa,GACjC,OAAO,CAAC,+BAA+B,CAAC;IAuC3C,OAAO,CAAC,YAAY;YAsBN,iBAAiB;CAgBlC"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { createHmac } from 'node:crypto';
|
|
8
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
9
|
+
import { BaseCacheInvalidationBroadcastProvider, } from '../BaseCacheInvalidationBroadcastProvider.js';
|
|
10
|
+
/**
|
|
11
|
+
* Topology 3 Cloud Multiplexer Provider for **Azure Web PubSub** (`'AzureWebPubSub'`).
|
|
12
|
+
*
|
|
13
|
+
* Offloads per-client WebSocket connection management and message fan-out from MJServer
|
|
14
|
+
* to Azure Web PubSub:
|
|
15
|
+
* - Each authenticated browser client calls `NegotiateCacheBroadcastConnection` to receive
|
|
16
|
+
* a short-lived, HMAC-signed JWT access token scoped to its authorized role groups (`mj-role-<RoleID>`).
|
|
17
|
+
* - When an entity mutation occurs, MJServer shapes the invalidation payload once per
|
|
18
|
+
* authorized role group on the entity and publishes a single group broadcast to Azure Web PubSub,
|
|
19
|
+
* which fans the message out to thousands of connected browsers in C++ edge infrastructure.
|
|
20
|
+
*/
|
|
21
|
+
let AzureWebPubSubBroadcastProvider = class AzureWebPubSubBroadcastProvider extends BaseCacheInvalidationBroadcastProvider {
|
|
22
|
+
constructor() {
|
|
23
|
+
super(...arguments);
|
|
24
|
+
this._groupPublisher = null;
|
|
25
|
+
}
|
|
26
|
+
get Topology() {
|
|
27
|
+
return 'AzureWebPubSub';
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Installs a custom group publisher (e.g., Azure WebPubSubServiceClient adapter or test spy).
|
|
31
|
+
* When unset and an HTTP endpoint + accessKey are configured, defaults to the Azure Web PubSub
|
|
32
|
+
* REST Data Plane API (`POST /api/hubs/{hub}/groups/{group}/:send`).
|
|
33
|
+
*/
|
|
34
|
+
SetGroupPublisher(publisher) {
|
|
35
|
+
this._groupPublisher = publisher;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Computes the Azure Web PubSub group names (`mj-role-<roleId>`) for a user's roles.
|
|
39
|
+
*/
|
|
40
|
+
GetAuthorizedGroupsForUser(user) {
|
|
41
|
+
const roles = user.UserRoles ?? [];
|
|
42
|
+
const groups = [];
|
|
43
|
+
for (const r of roles) {
|
|
44
|
+
const roleId = (r.RoleID ?? '').trim().toLowerCase();
|
|
45
|
+
if (roleId.length > 0) {
|
|
46
|
+
groups.push(`mj-role-${roleId}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
groups.sort();
|
|
50
|
+
return groups;
|
|
51
|
+
}
|
|
52
|
+
async OnInvalidationRecorded(payload) {
|
|
53
|
+
const hubName = this._config.azureWebPubSub?.hubName || 'mj_cache_hub';
|
|
54
|
+
const entity = this.ResolveEntityForPayload(payload);
|
|
55
|
+
if (!entity) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
// Group entity permissions by RoleID and shape once per authorized role
|
|
59
|
+
for (const perm of entity.Permissions) {
|
|
60
|
+
if (!perm.CanRead)
|
|
61
|
+
continue;
|
|
62
|
+
const roleId = (perm.RoleID ?? '').trim().toLowerCase();
|
|
63
|
+
if (!roleId)
|
|
64
|
+
continue;
|
|
65
|
+
const syntheticRoleHolder = { UserRoles: [{ RoleID: roleId }] };
|
|
66
|
+
const shaped = this.ShapeEventForSubscriber(payload, syntheticRoleHolder, entity);
|
|
67
|
+
const message = {
|
|
68
|
+
HubName: hubName,
|
|
69
|
+
GroupName: `mj-role-${roleId}`,
|
|
70
|
+
Event: shaped,
|
|
71
|
+
};
|
|
72
|
+
if (this._groupPublisher) {
|
|
73
|
+
await this._groupPublisher(message);
|
|
74
|
+
}
|
|
75
|
+
else if (this._config.azureWebPubSub?.endpoint && this._config.azureWebPubSub?.accessKey) {
|
|
76
|
+
await this.publishViaRestApi(message);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async NegotiateClientConnection(user, defaultGraphQLWsUrl = '/graphql') {
|
|
81
|
+
const endpoint = (this._config.azureWebPubSub?.endpoint ?? '').replace(/\/+$/, '');
|
|
82
|
+
const hubName = this._config.azureWebPubSub?.hubName || 'mj_cache_hub';
|
|
83
|
+
const accessKey = this._config.azureWebPubSub?.accessKey || '';
|
|
84
|
+
const ttlMinutes = this._config.azureWebPubSub?.tokenTtlMinutes ?? 60;
|
|
85
|
+
const expiresAtMs = Date.now() + ttlMinutes * 60 * 1000;
|
|
86
|
+
const groups = this.GetAuthorizedGroupsForUser(user);
|
|
87
|
+
if (!endpoint) {
|
|
88
|
+
return {
|
|
89
|
+
Provider: this.Topology,
|
|
90
|
+
Url: defaultGraphQLWsUrl,
|
|
91
|
+
Groups: groups,
|
|
92
|
+
ExpiresAt: new Date(expiresAtMs).toISOString(),
|
|
93
|
+
ServerProcessID: this.ServerProcessID,
|
|
94
|
+
CurrentSequence: this.CurrentSequence,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const wsEndpoint = endpoint.replace(/^http:/i, 'ws:').replace(/^https:/i, 'wss:');
|
|
98
|
+
const audience = `${endpoint}/client/hubs/${hubName}`;
|
|
99
|
+
const token = accessKey
|
|
100
|
+
? this.mintJwtToken(audience, user.ID, groups, Math.floor(expiresAtMs / 1000), accessKey)
|
|
101
|
+
: undefined;
|
|
102
|
+
const url = token
|
|
103
|
+
? `${wsEndpoint}/client/hubs/${hubName}?access_token=${encodeURIComponent(token)}`
|
|
104
|
+
: `${wsEndpoint}/client/hubs/${hubName}`;
|
|
105
|
+
return {
|
|
106
|
+
Provider: this.Topology,
|
|
107
|
+
Url: url,
|
|
108
|
+
Token: token,
|
|
109
|
+
Groups: groups,
|
|
110
|
+
ExpiresAt: new Date(expiresAtMs).toISOString(),
|
|
111
|
+
ServerProcessID: this.ServerProcessID,
|
|
112
|
+
CurrentSequence: this.CurrentSequence,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
mintJwtToken(audience, subject, groups, expSeconds, secret) {
|
|
116
|
+
const header = Buffer.from(JSON.stringify({ alg: 'HS256', typ: 'JWT' })).toString('base64url');
|
|
117
|
+
const claims = Buffer.from(JSON.stringify({
|
|
118
|
+
aud: audience,
|
|
119
|
+
sub: subject,
|
|
120
|
+
iat: Math.floor(Date.now() / 1000),
|
|
121
|
+
exp: expSeconds,
|
|
122
|
+
role: groups.map((g) => `webpubsub.joinLeaveGroup.${g}`),
|
|
123
|
+
})).toString('base64url');
|
|
124
|
+
const signingInput = `${header}.${claims}`;
|
|
125
|
+
const signature = createHmac('sha256', secret).update(signingInput).digest('base64url');
|
|
126
|
+
return `${signingInput}.${signature}`;
|
|
127
|
+
}
|
|
128
|
+
async publishViaRestApi(message) {
|
|
129
|
+
const endpoint = (this._config.azureWebPubSub?.endpoint ?? '').replace(/\/+$/, '');
|
|
130
|
+
const accessKey = this._config.azureWebPubSub?.accessKey ?? '';
|
|
131
|
+
if (!endpoint || !accessKey)
|
|
132
|
+
return;
|
|
133
|
+
const targetUrl = `${endpoint}/api/hubs/${encodeURIComponent(message.HubName)}/groups/${encodeURIComponent(message.GroupName)}/:send?api-version=2024-01-01`;
|
|
134
|
+
const token = this.mintJwtToken(targetUrl, 'mj-server', [], Math.floor(Date.now() / 1000) + 300, accessKey);
|
|
135
|
+
await fetch(targetUrl, {
|
|
136
|
+
method: 'POST',
|
|
137
|
+
headers: {
|
|
138
|
+
Authorization: `Bearer ${token}`,
|
|
139
|
+
'Content-Type': 'application/json',
|
|
140
|
+
},
|
|
141
|
+
body: JSON.stringify(message.Event),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
AzureWebPubSubBroadcastProvider = __decorate([
|
|
146
|
+
RegisterClass(BaseCacheInvalidationBroadcastProvider, 'AzureWebPubSub')
|
|
147
|
+
], AzureWebPubSubBroadcastProvider);
|
|
148
|
+
export { AzureWebPubSubBroadcastProvider };
|
|
149
|
+
//# sourceMappingURL=AzureWebPubSubBroadcastProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AzureWebPubSubBroadcastProvider.js","sourceRoot":"","sources":["../../../src/broadcast/providers/AzureWebPubSubBroadcastProvider.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EACH,sCAAsC,GAGzC,MAAM,8CAA8C,CAAC;AAqBtD;;;;;;;;;;GAUG;AAEI,IAAM,+BAA+B,GAArC,MAAM,+BAAgC,SAAQ,sCAAsC;IAApF;;QACK,oBAAe,GAAwC,IAAI,CAAC;IA4IxE,CAAC;IA1IG,IAAoB,QAAQ;QACxB,OAAO,gBAAgB,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACI,iBAAiB,CAAC,SAA8C;QACnE,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;IACrC,CAAC;IAED;;OAEG;IACI,0BAA0B,CAAC,IAAc;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC;QACnC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACpB,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YACrD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,MAAM,CAAC,IAAI,CAAC,WAAW,MAAM,EAAE,CAAC,CAAC;YACrC,CAAC;QACL,CAAC;QACD,MAAM,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,MAAM,CAAC;IAClB,CAAC;IAEkB,KAAK,CAAC,sBAAsB,CAAC,OAAiC;QAC7E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,IAAI,cAAc,CAAC;QACvE,MAAM,MAAM,GAAG,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,OAAO;QACX,CAAC;QAED,wEAAwE;QACxE,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YACpC,IAAI,CAAC,IAAI,CAAC,OAAO;gBAAE,SAAS;YAC5B,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YACxD,IAAI,CAAC,MAAM;gBAAE,SAAS;YAEtB,MAAM,mBAAmB,GAAG,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;YAChE,MAAM,MAAM,GAAG,IAAI,CAAC,uBAAuB,CAAC,OAAO,EAAE,mBAAmB,EAAE,MAAM,CAAC,CAAC;YAClF,MAAM,OAAO,GAA+B;gBACxC,OAAO,EAAE,OAAO;gBAChB,SAAS,EAAE,WAAW,MAAM,EAAE;gBAC9B,KAAK,EAAE,MAAM;aAChB,CAAC;YAEF,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;gBACvB,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YACxC,CAAC;iBAAM,IAAI,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,SAAS,EAAE,CAAC;gBACzF,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAC1C,CAAC;QACL,CAAC;IACL,CAAC;IAEe,KAAK,CAAC,yBAAyB,CAC3C,IAAc,EACd,mBAAmB,GAAG,UAAU;QAEhC,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACnF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,IAAI,cAAc,CAAC;QACvE,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,SAAS,IAAI,EAAE,CAAC;QAC/D,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,eAAe,IAAI,EAAE,CAAC;QACtE,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,EAAE,GAAG,IAAI,CAAC;QACxD,MAAM,MAAM,GAAG,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,CAAC;QAErD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,OAAO;gBACH,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,GAAG,EAAE,mBAAmB;gBACxB,MAAM,EAAE,MAAM;gBACd,SAAS,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE;gBAC9C,eAAe,EAAE,IAAI,CAAC,eAAe;gBACrC,eAAe,EAAE,IAAI,CAAC,eAAe;aACxC,CAAC;QACN,CAAC;QAED,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAClF,MAAM,QAAQ,GAAG,GAAG,QAAQ,gBAAgB,OAAO,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,SAAS;YACnB,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,EAAE,SAAS,CAAC;YACzF,CAAC,CAAC,SAAS,CAAC;QAChB,MAAM,GAAG,GAAG,KAAK;YACb,CAAC,CAAC,GAAG,UAAU,gBAAgB,OAAO,iBAAiB,kBAAkB,CAAC,KAAK,CAAC,EAAE;YAClF,CAAC,CAAC,GAAG,UAAU,gBAAgB,OAAO,EAAE,CAAC;QAE7C,OAAO;YACH,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,MAAM;YACd,SAAS,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE;YAC9C,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,eAAe,EAAE,IAAI,CAAC,eAAe;SACxC,CAAC;IACN,CAAC;IAEO,YAAY,CAChB,QAAgB,EAChB,OAAe,EACf,MAAgB,EAChB,UAAkB,EAClB,MAAc;QAEd,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC/F,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CACtB,IAAI,CAAC,SAAS,CAAC;YACX,GAAG,EAAE,QAAQ;YACb,GAAG,EAAE,OAAO;YACZ,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YAClC,GAAG,EAAE,UAAU;YACf,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,4BAA4B,CAAC,EAAE,CAAC;SAC3D,CAAC,CACL,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QACxB,MAAM,YAAY,GAAG,GAAG,MAAM,IAAI,MAAM,EAAE,CAAC;QAC3C,MAAM,SAAS,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACxF,OAAO,GAAG,YAAY,IAAI,SAAS,EAAE,CAAC;IAC1C,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,OAAmC;QAC/D,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACnF,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,SAAS,IAAI,EAAE,CAAC;QAC/D,IAAI,CAAC,QAAQ,IAAI,CAAC,SAAS;YAAE,OAAO;QAEpC,MAAM,SAAS,GAAG,GAAG,QAAQ,aAAa,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,+BAA+B,CAAC;QAC7J,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,GAAG,EAAE,SAAS,CAAC,CAAC;QAC5G,MAAM,KAAK,CAAC,SAAS,EAAE;YACnB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACL,aAAa,EAAE,UAAU,KAAK,EAAE;gBAChC,cAAc,EAAE,kBAAkB;aACrC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC;SACtC,CAAC,CAAC;IACP,CAAC;CACJ,CAAA;AA7IY,+BAA+B;IAD3C,aAAa,CAAC,sCAAsC,EAAE,gBAAgB,CAAC;GAC3D,+BAA+B,CA6I3C"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { UserInfo } from '@memberjunction/core';
|
|
2
|
+
import { BaseCacheInvalidationBroadcastProvider, CacheBroadcastNegotiationResult, CacheInvalidationBroadcastTopology } from '../BaseCacheInvalidationBroadcastProvider.js';
|
|
3
|
+
import type { CacheInvalidationNotification, CacheInvalidationPayload } from '../../generic/CacheInvalidationResolver.js';
|
|
4
|
+
/**
|
|
5
|
+
* Envelope published to a Google Cloud Pub/Sub role topic.
|
|
6
|
+
*/
|
|
7
|
+
export interface GCPPubSubTopicMessage {
|
|
8
|
+
ProjectId: string;
|
|
9
|
+
TopicName: string;
|
|
10
|
+
Attributes: {
|
|
11
|
+
roleId: string;
|
|
12
|
+
entityName: string;
|
|
13
|
+
action: string;
|
|
14
|
+
sequence: string;
|
|
15
|
+
};
|
|
16
|
+
Event: CacheInvalidationNotification;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Transport callback used by {@link GCPPubSubBroadcastProvider} to publish a shaped
|
|
20
|
+
* invalidation notification to Google Cloud Pub/Sub.
|
|
21
|
+
*/
|
|
22
|
+
export type GCPPubSubTopicPublisher = (message: GCPPubSubTopicMessage) => Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Topology 3 Cloud Multiplexer Provider for **Google Cloud Pub/Sub + Cloud Run WebSockets** (`'GCPPubSub'`).
|
|
25
|
+
*
|
|
26
|
+
* Offloads per-client WebSocket connection management and message fan-out from MJServer
|
|
27
|
+
* to a Google Cloud Pub/Sub + Cloud Run WebSocket fan-out gateway:
|
|
28
|
+
* - Each authenticated browser client calls `NegotiateCacheBroadcastConnection` to obtain
|
|
29
|
+
* a signed gateway token and its authorized Pub/Sub role subscription attributes
|
|
30
|
+
* (`projects/<projectId>/topics/<topicPrefix>-role-<RoleID>`).
|
|
31
|
+
* - When an entity mutation occurs, MJServer shapes the invalidation payload once per
|
|
32
|
+
* authorized role on the entity and publishes a message with Pub/Sub filtering attributes.
|
|
33
|
+
*/
|
|
34
|
+
export declare class GCPPubSubBroadcastProvider extends BaseCacheInvalidationBroadcastProvider {
|
|
35
|
+
private _topicPublisher;
|
|
36
|
+
get Topology(): CacheInvalidationBroadcastTopology;
|
|
37
|
+
/**
|
|
38
|
+
* Installs a custom Google Cloud Pub/Sub topic publisher (e.g., `@google-cloud/pubsub` adapter or test spy).
|
|
39
|
+
*/
|
|
40
|
+
SetTopicPublisher(publisher: GCPPubSubTopicPublisher | null): void;
|
|
41
|
+
/**
|
|
42
|
+
* Computes the fully-qualified GCP Pub/Sub topic names for a user's roles.
|
|
43
|
+
*/
|
|
44
|
+
GetAuthorizedTopicsForUser(user: UserInfo): string[];
|
|
45
|
+
protected OnInvalidationRecorded(payload: CacheInvalidationPayload): Promise<void>;
|
|
46
|
+
NegotiateClientConnection(user: UserInfo, defaultGraphQLWsUrl?: string): Promise<CacheBroadcastNegotiationResult>;
|
|
47
|
+
private mintGatewayToken;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=GCPPubSubBroadcastProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GCPPubSubBroadcastProvider.d.ts","sourceRoot":"","sources":["../../../src/broadcast/providers/GCPPubSubBroadcastProvider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EACH,sCAAsC,EACtC,+BAA+B,EAC/B,kCAAkC,EACrC,MAAM,8CAA8C,CAAC;AACtD,OAAO,KAAK,EACR,6BAA6B,EAC7B,wBAAwB,EAC3B,MAAM,4CAA4C,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,KAAK,EAAE,6BAA6B,CAAC;CACxC;AAED;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAExF;;;;;;;;;;GAUG;AACH,qBACa,0BAA2B,SAAQ,sCAAsC;IAClF,OAAO,CAAC,eAAe,CAAwC;IAE/D,IAAoB,QAAQ,IAAI,kCAAkC,CAEjE;IAED;;OAEG;IACI,iBAAiB,CAAC,SAAS,EAAE,uBAAuB,GAAG,IAAI,GAAG,IAAI;IAIzE;;OAEG;IACI,0BAA0B,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE;cAelC,sBAAsB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IAiC3E,yBAAyB,CAC3C,IAAI,EAAE,QAAQ,EACd,mBAAmB,SAAa,GACjC,OAAO,CAAC,+BAA+B,CAAC;IAmC3C,OAAO,CAAC,gBAAgB;CAmB3B"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { createHmac } from 'node:crypto';
|
|
8
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
9
|
+
import { BaseCacheInvalidationBroadcastProvider, } from '../BaseCacheInvalidationBroadcastProvider.js';
|
|
10
|
+
/**
|
|
11
|
+
* Topology 3 Cloud Multiplexer Provider for **Google Cloud Pub/Sub + Cloud Run WebSockets** (`'GCPPubSub'`).
|
|
12
|
+
*
|
|
13
|
+
* Offloads per-client WebSocket connection management and message fan-out from MJServer
|
|
14
|
+
* to a Google Cloud Pub/Sub + Cloud Run WebSocket fan-out gateway:
|
|
15
|
+
* - Each authenticated browser client calls `NegotiateCacheBroadcastConnection` to obtain
|
|
16
|
+
* a signed gateway token and its authorized Pub/Sub role subscription attributes
|
|
17
|
+
* (`projects/<projectId>/topics/<topicPrefix>-role-<RoleID>`).
|
|
18
|
+
* - When an entity mutation occurs, MJServer shapes the invalidation payload once per
|
|
19
|
+
* authorized role on the entity and publishes a message with Pub/Sub filtering attributes.
|
|
20
|
+
*/
|
|
21
|
+
let GCPPubSubBroadcastProvider = class GCPPubSubBroadcastProvider extends BaseCacheInvalidationBroadcastProvider {
|
|
22
|
+
constructor() {
|
|
23
|
+
super(...arguments);
|
|
24
|
+
this._topicPublisher = null;
|
|
25
|
+
}
|
|
26
|
+
get Topology() {
|
|
27
|
+
return 'GCPPubSub';
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Installs a custom Google Cloud Pub/Sub topic publisher (e.g., `@google-cloud/pubsub` adapter or test spy).
|
|
31
|
+
*/
|
|
32
|
+
SetTopicPublisher(publisher) {
|
|
33
|
+
this._topicPublisher = publisher;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Computes the fully-qualified GCP Pub/Sub topic names for a user's roles.
|
|
37
|
+
*/
|
|
38
|
+
GetAuthorizedTopicsForUser(user) {
|
|
39
|
+
const projectId = this._config.gcpPubSub?.projectId || 'mj-default-project';
|
|
40
|
+
const prefix = this._config.gcpPubSub?.topicPrefix || 'mj-cache';
|
|
41
|
+
const roles = user.UserRoles ?? [];
|
|
42
|
+
const topics = [];
|
|
43
|
+
for (const r of roles) {
|
|
44
|
+
const roleId = (r.RoleID ?? '').trim().toLowerCase();
|
|
45
|
+
if (roleId.length > 0) {
|
|
46
|
+
topics.push(`projects/${projectId}/topics/${prefix}-role-${roleId}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
topics.sort();
|
|
50
|
+
return topics;
|
|
51
|
+
}
|
|
52
|
+
async OnInvalidationRecorded(payload) {
|
|
53
|
+
const projectId = this._config.gcpPubSub?.projectId || 'mj-default-project';
|
|
54
|
+
const prefix = this._config.gcpPubSub?.topicPrefix || 'mj-cache';
|
|
55
|
+
const entity = this.ResolveEntityForPayload(payload);
|
|
56
|
+
if (!entity) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
for (const perm of entity.Permissions) {
|
|
60
|
+
if (!perm.CanRead)
|
|
61
|
+
continue;
|
|
62
|
+
const roleId = (perm.RoleID ?? '').trim().toLowerCase();
|
|
63
|
+
if (!roleId)
|
|
64
|
+
continue;
|
|
65
|
+
const syntheticRoleHolder = { UserRoles: [{ RoleID: roleId }] };
|
|
66
|
+
const shaped = this.ShapeEventForSubscriber(payload, syntheticRoleHolder, entity);
|
|
67
|
+
const message = {
|
|
68
|
+
ProjectId: projectId,
|
|
69
|
+
TopicName: `projects/${projectId}/topics/${prefix}-role-${roleId}`,
|
|
70
|
+
Attributes: {
|
|
71
|
+
roleId,
|
|
72
|
+
entityName: payload.entityName,
|
|
73
|
+
action: payload.action,
|
|
74
|
+
sequence: String(payload.sequence ?? 0),
|
|
75
|
+
},
|
|
76
|
+
Event: shaped,
|
|
77
|
+
};
|
|
78
|
+
if (this._topicPublisher) {
|
|
79
|
+
await this._topicPublisher(message);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async NegotiateClientConnection(user, defaultGraphQLWsUrl = '/graphql') {
|
|
84
|
+
const gatewayUrl = (this._config.gcpPubSub?.gatewayUrl ?? '').replace(/\/+$/, '');
|
|
85
|
+
const signingSecret = this._config.gcpPubSub?.signingSecret || '';
|
|
86
|
+
const ttlSeconds = this._config.gcpPubSub?.tokenTtlSeconds ?? 3600;
|
|
87
|
+
const expiresAtMs = Date.now() + ttlSeconds * 1000;
|
|
88
|
+
const topics = this.GetAuthorizedTopicsForUser(user);
|
|
89
|
+
if (!gatewayUrl) {
|
|
90
|
+
return {
|
|
91
|
+
Provider: this.Topology,
|
|
92
|
+
Url: defaultGraphQLWsUrl,
|
|
93
|
+
Groups: topics,
|
|
94
|
+
ExpiresAt: new Date(expiresAtMs).toISOString(),
|
|
95
|
+
ServerProcessID: this.ServerProcessID,
|
|
96
|
+
CurrentSequence: this.CurrentSequence,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const wsGatewayUrl = gatewayUrl.replace(/^http:/i, 'ws:').replace(/^https:/i, 'wss:');
|
|
100
|
+
const token = signingSecret
|
|
101
|
+
? this.mintGatewayToken(user.ID, topics, Math.floor(expiresAtMs / 1000), signingSecret)
|
|
102
|
+
: undefined;
|
|
103
|
+
const url = token ? `${wsGatewayUrl}?token=${encodeURIComponent(token)}` : wsGatewayUrl;
|
|
104
|
+
return {
|
|
105
|
+
Provider: this.Topology,
|
|
106
|
+
Url: url,
|
|
107
|
+
Token: token,
|
|
108
|
+
Groups: topics,
|
|
109
|
+
ExpiresAt: new Date(expiresAtMs).toISOString(),
|
|
110
|
+
ServerProcessID: this.ServerProcessID,
|
|
111
|
+
CurrentSequence: this.CurrentSequence,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
mintGatewayToken(subject, topics, expSeconds, secret) {
|
|
115
|
+
const header = Buffer.from(JSON.stringify({ alg: 'HS256', typ: 'JWT' })).toString('base64url');
|
|
116
|
+
const claims = Buffer.from(JSON.stringify({
|
|
117
|
+
sub: subject,
|
|
118
|
+
iat: Math.floor(Date.now() / 1000),
|
|
119
|
+
exp: expSeconds,
|
|
120
|
+
topics,
|
|
121
|
+
})).toString('base64url');
|
|
122
|
+
const signingInput = `${header}.${claims}`;
|
|
123
|
+
const signature = createHmac('sha256', secret).update(signingInput).digest('base64url');
|
|
124
|
+
return `${signingInput}.${signature}`;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
GCPPubSubBroadcastProvider = __decorate([
|
|
128
|
+
RegisterClass(BaseCacheInvalidationBroadcastProvider, 'GCPPubSub')
|
|
129
|
+
], GCPPubSubBroadcastProvider);
|
|
130
|
+
export { GCPPubSubBroadcastProvider };
|
|
131
|
+
//# sourceMappingURL=GCPPubSubBroadcastProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GCPPubSubBroadcastProvider.js","sourceRoot":"","sources":["../../../src/broadcast/providers/GCPPubSubBroadcastProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { UserInfo } from '@memberjunction/core';
|
|
2
|
+
import { BaseCacheInvalidationBroadcastProvider, CacheBroadcastNegotiationResult, CacheInvalidationBroadcastTopology } from '../BaseCacheInvalidationBroadcastProvider.js';
|
|
3
|
+
import type { CacheInvalidationPayload } from '../../generic/CacheInvalidationResolver.js';
|
|
4
|
+
/**
|
|
5
|
+
* Default MemberJunction cache invalidation broadcast provider (`'SequencedRoleBucket'`).
|
|
6
|
+
*
|
|
7
|
+
* Combines:
|
|
8
|
+
* - **Topology 1 (Monotonic Sequence Ring Buffer + HTTP Header Piggybacking)**:
|
|
9
|
+
* Every mutation assigns a monotonic `Sequence` integer, stores the event in a bounded ring buffer,
|
|
10
|
+
* and piggybacks `X-MJ-Cache-Seq` and `X-MJ-Server-ID` onto GraphQL HTTP responses so clients can
|
|
11
|
+
* detect and recover missed invalidations via `GetCacheInvalidationsSince` in a single delta query.
|
|
12
|
+
* - **Topology 2 (Role-Fingerprint $O(\text{Roles})$ Evaluation & Shaping Memoizer)**:
|
|
13
|
+
* Memoizes entity-level read permission (`CanRead`) and row-level security key-withholding
|
|
14
|
+
* (`ReadIsRowFiltered`) once per unique role fingerprint (`RoleID` set) per event instead of
|
|
15
|
+
* re-evaluating permissions $N$ times across all connected WebSocket clients.
|
|
16
|
+
*
|
|
17
|
+
* Zero external cloud infrastructure is required.
|
|
18
|
+
*/
|
|
19
|
+
export declare class SequencedRoleBucketBroadcastProvider extends BaseCacheInvalidationBroadcastProvider {
|
|
20
|
+
get Topology(): CacheInvalidationBroadcastTopology;
|
|
21
|
+
protected OnInvalidationRecorded(_payload: CacheInvalidationPayload): Promise<void>;
|
|
22
|
+
NegotiateClientConnection(user: UserInfo, defaultGraphQLWsUrl?: string): Promise<CacheBroadcastNegotiationResult>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=SequencedRoleBucketBroadcastProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SequencedRoleBucketBroadcastProvider.d.ts","sourceRoot":"","sources":["../../../src/broadcast/providers/SequencedRoleBucketBroadcastProvider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EACH,sCAAsC,EACtC,+BAA+B,EAE/B,kCAAkC,EACrC,MAAM,8CAA8C,CAAC;AACtD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AAE3F;;;;;;;;;;;;;;GAcG;AACH,qBACa,oCAAqC,SAAQ,sCAAsC;IAC5F,IAAoB,QAAQ,IAAI,kCAAkC,CAEjE;cAEwB,sBAAsB,CAAC,QAAQ,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5E,yBAAyB,CAC3C,IAAI,EAAE,QAAQ,EACd,mBAAmB,SAAa,GACjC,OAAO,CAAC,+BAA+B,CAAC;CAY9C"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
8
|
+
import { BaseCacheInvalidationBroadcastProvider, CacheInvalidationBroadcastManager, } from '../BaseCacheInvalidationBroadcastProvider.js';
|
|
9
|
+
/**
|
|
10
|
+
* Default MemberJunction cache invalidation broadcast provider (`'SequencedRoleBucket'`).
|
|
11
|
+
*
|
|
12
|
+
* Combines:
|
|
13
|
+
* - **Topology 1 (Monotonic Sequence Ring Buffer + HTTP Header Piggybacking)**:
|
|
14
|
+
* Every mutation assigns a monotonic `Sequence` integer, stores the event in a bounded ring buffer,
|
|
15
|
+
* and piggybacks `X-MJ-Cache-Seq` and `X-MJ-Server-ID` onto GraphQL HTTP responses so clients can
|
|
16
|
+
* detect and recover missed invalidations via `GetCacheInvalidationsSince` in a single delta query.
|
|
17
|
+
* - **Topology 2 (Role-Fingerprint $O(\text{Roles})$ Evaluation & Shaping Memoizer)**:
|
|
18
|
+
* Memoizes entity-level read permission (`CanRead`) and row-level security key-withholding
|
|
19
|
+
* (`ReadIsRowFiltered`) once per unique role fingerprint (`RoleID` set) per event instead of
|
|
20
|
+
* re-evaluating permissions $N$ times across all connected WebSocket clients.
|
|
21
|
+
*
|
|
22
|
+
* Zero external cloud infrastructure is required.
|
|
23
|
+
*/
|
|
24
|
+
let SequencedRoleBucketBroadcastProvider = class SequencedRoleBucketBroadcastProvider extends BaseCacheInvalidationBroadcastProvider {
|
|
25
|
+
get Topology() {
|
|
26
|
+
return 'SequencedRoleBucket';
|
|
27
|
+
}
|
|
28
|
+
async OnInvalidationRecorded(_payload) {
|
|
29
|
+
// In-process GraphQL WebSocket subscriptions read directly from PubSub + role-bucket memoizer;
|
|
30
|
+
// no external cloud multiplexer dispatch is needed in SequencedRoleBucket mode.
|
|
31
|
+
}
|
|
32
|
+
async NegotiateClientConnection(user, defaultGraphQLWsUrl = '/graphql') {
|
|
33
|
+
const fingerprint = this.GetRoleFingerprint(user);
|
|
34
|
+
const expiresAt = new Date(Date.now() + 60 * 60 * 1000).toISOString();
|
|
35
|
+
return {
|
|
36
|
+
Provider: this.Topology,
|
|
37
|
+
Url: defaultGraphQLWsUrl,
|
|
38
|
+
Groups: [fingerprint],
|
|
39
|
+
ExpiresAt: expiresAt,
|
|
40
|
+
ServerProcessID: this.ServerProcessID,
|
|
41
|
+
CurrentSequence: this.CurrentSequence,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
SequencedRoleBucketBroadcastProvider = __decorate([
|
|
46
|
+
RegisterClass(BaseCacheInvalidationBroadcastProvider, 'SequencedRoleBucket')
|
|
47
|
+
], SequencedRoleBucketBroadcastProvider);
|
|
48
|
+
export { SequencedRoleBucketBroadcastProvider };
|
|
49
|
+
// Ensure the default provider factory is always registered even if ClassFactory lookup happens early.
|
|
50
|
+
CacheInvalidationBroadcastManager.Instance.RegisterDefaultProviderFactory(() => new SequencedRoleBucketBroadcastProvider());
|
|
51
|
+
//# sourceMappingURL=SequencedRoleBucketBroadcastProvider.js.map
|