@memberjunction/server 6.2.0-edge.4 → 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 +47 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/agentSessions/SessionJanitor.d.ts +91 -30
- package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
- package/dist/agentSessions/SessionJanitor.js +311 -81
- package/dist/agentSessions/SessionJanitor.js.map +1 -1
- package/dist/agentSessions/SessionManager.d.ts +17 -3
- package/dist/agentSessions/SessionManager.d.ts.map +1 -1
- package/dist/agentSessions/SessionManager.js +44 -10
- package/dist/agentSessions/SessionManager.js.map +1 -1
- package/dist/apiRoot.d.ts +32 -0
- package/dist/apiRoot.d.ts.map +1 -0
- package/dist/apiRoot.js +67 -0
- package/dist/apiRoot.js.map +1 -0
- package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.js +27 -0
- package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
- package/dist/auth/LoginScreenEngine.d.ts +22 -0
- package/dist/auth/LoginScreenEngine.d.ts.map +1 -0
- package/dist/auth/LoginScreenEngine.js +57 -0
- package/dist/auth/LoginScreenEngine.js.map +1 -0
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +52 -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/MagicLinkRouter.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.js +3 -2
- package/dist/auth/magicLink/MagicLinkRouter.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 +632 -22
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +104 -4
- 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 +29 -0
- package/dist/coreRoutes.d.ts.map +1 -0
- package/dist/coreRoutes.js +156 -0
- package/dist/coreRoutes.js.map +1 -0
- package/dist/generated/graphql-schemas/__mj.d.ts +1016 -29
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +5125 -434
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/CacheInvalidationResolver.d.ts +85 -30
- package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
- package/dist/generic/CacheInvalidationResolver.js +175 -60
- 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 +94 -12
- package/dist/generic/PushStatusResolver.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +168 -69
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +464 -405
- 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 +91 -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/globalCors.d.ts +33 -0
- package/dist/globalCors.d.ts.map +1 -0
- package/dist/globalCors.js +58 -0
- package/dist/globalCors.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +230 -222
- 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/multiTenancy/index.d.ts.map +1 -1
- package/dist/multiTenancy/index.js +22 -2
- package/dist/multiTenancy/index.js.map +1 -1
- package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts.map +1 -1
- package/dist/realtimeSessions/RealtimeSessionVerificationService.js +2 -1
- package/dist/realtimeSessions/RealtimeSessionVerificationService.js.map +1 -1
- package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts.map +1 -1
- package/dist/realtimeSessions/RealtimeVerifyRouter.js +2 -1
- package/dist/realtimeSessions/RealtimeVerifyRouter.js.map +1 -1
- package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts +100 -0
- package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts.map +1 -0
- package/dist/realtimeSessions/RecordingAssemblyScheduler.js +173 -0
- package/dist/realtimeSessions/RecordingAssemblyScheduler.js.map +1 -0
- 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/index.d.ts +2 -0
- package/dist/realtimeSessions/index.d.ts.map +1 -1
- package/dist/realtimeSessions/index.js +2 -0
- package/dist/realtimeSessions/index.js.map +1 -1
- package/dist/realtimeSessions/ownedRealtimeSession.d.ts +32 -0
- package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -0
- package/dist/realtimeSessions/ownedRealtimeSession.js +56 -0
- package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -0
- package/dist/realtimeSessions/sessionAccess.d.ts +91 -8
- package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -1
- package/dist/realtimeSessions/sessionAccess.js +127 -20
- 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/ArtifactFileResolver.d.ts +5 -1
- package/dist/resolvers/ArtifactFileResolver.d.ts.map +1 -1
- package/dist/resolvers/ArtifactFileResolver.js +9 -7
- package/dist/resolvers/ArtifactFileResolver.js.map +1 -1
- package/dist/resolvers/ConversationRunEventsResolver.d.ts +8 -4
- package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -1
- package/dist/resolvers/ConversationRunEventsResolver.js +6 -6
- package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -1
- package/dist/resolvers/DatasetResolver.d.ts +24 -3
- package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
- package/dist/resolvers/DatasetResolver.js +57 -8
- package/dist/resolvers/DatasetResolver.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/EntityRecordNameResolver.d.ts +2 -1
- package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.js +3 -2
- package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts +46 -3
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.js +211 -50
- 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 +87 -11
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +292 -105
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts +33 -7
- package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.js +117 -38
- package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +6 -3
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +49 -9
- 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 +2 -0
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +33 -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 +18 -10
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +92 -54
- 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 +241 -67
- 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/SearchKnowledgeStreamResolver.d.ts +12 -1
- package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts.map +1 -1
- package/dist/resolvers/SearchKnowledgeStreamResolver.js +15 -2
- package/dist/resolvers/SearchKnowledgeStreamResolver.js.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +2 -3
- package/dist/resolvers/SqlLoggingConfigResolver.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/TaskGraphFrameResolver.d.ts +2 -1
- package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskGraphFrameResolver.js +28 -1
- package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
- package/dist/resolvers/TestQuerySQLResolver.d.ts +24 -0
- package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
- package/dist/resolvers/TestQuerySQLResolver.js +66 -13
- package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts +34 -2
- package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.js +150 -27
- 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/resolvers/agent-run-data-guard.d.ts +31 -0
- package/dist/resolvers/agent-run-data-guard.d.ts.map +1 -0
- package/dist/resolvers/agent-run-data-guard.js +72 -0
- package/dist/resolvers/agent-run-data-guard.js.map +1 -0
- 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 +49 -0
- package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -0
- package/dist/rest/RealtimeRecordingHandler.js +383 -0
- package/dist/rest/RealtimeRecordingHandler.js.map +1 -0
- package/dist/rest/ViewOperationsHandler.d.ts +9 -1
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +43 -17
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/rest/setupRESTEndpoints.d.ts +6 -0
- package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
- package/dist/rest/setupRESTEndpoints.js +6 -0
- package/dist/rest/setupRESTEndpoints.js.map +1 -1
- package/dist/serverExtensionReservedRoots.d.ts +12 -10
- package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
- package/dist/serverExtensionReservedRoots.js +14 -17
- package/dist/serverExtensionReservedRoots.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/MJStorageBlobStore.d.ts +8 -1
- package/dist/services/MJStorageBlobStore.d.ts.map +1 -1
- package/dist/services/MJStorageBlobStore.js +25 -19
- package/dist/services/MJStorageBlobStore.js.map +1 -1
- package/dist/services/StartTaskGraphDispatcher.js +2 -2
- package/dist/services/StartTaskGraphDispatcher.js.map +1 -1
- package/dist/services/TaskGraphActionRunner.d.ts +5 -3
- package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphActionRunner.js +27 -5
- package/dist/services/TaskGraphActionRunner.js.map +1 -1
- package/dist/services/TaskGraphAgentRunner.d.ts +14 -2
- package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphAgentRunner.js +157 -9
- package/dist/services/TaskGraphAgentRunner.js.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.d.ts +59 -2
- package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.js +626 -16
- package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
- package/dist/sharedCache.d.ts.map +1 -1
- package/dist/sharedCache.js +3 -0
- package/dist/sharedCache.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 +99 -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__/DatasetResolver.itemFilters.test.ts +201 -0
- package/src/__tests__/EntityCommunicationsResolver.actingUser.test.ts +151 -0
- package/src/__tests__/EntityRecordNameResolver.rowSecurity.test.ts +152 -0
- package/src/__tests__/EvolutionActsOnWhatItDetects.test.ts +113 -0
- package/src/__tests__/FetchEntityVectorsResolver.test.ts +369 -18
- package/src/__tests__/FileResolver.fieldSecurity.test.ts +82 -0
- package/src/__tests__/FileResolver.storageAccess.test.ts +562 -0
- package/src/__tests__/GetDataContextDataResolver.sqlItems.test.ts +416 -0
- package/src/__tests__/ListOperationsResolver.adhocScreen.test.ts +137 -0
- package/src/__tests__/LoginScreenEngine.test.ts +86 -0
- package/src/__tests__/MJStorageBlobStore.storageGate.test.ts +63 -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__/RecordingAssemblyScheduler.test.ts +178 -0
- package/src/__tests__/RemoteBrowserActionResolver.ownership.test.ts +98 -0
- package/src/__tests__/ResolverBase.adhocReadScope.test.ts +133 -2
- package/src/__tests__/ResolverBase.balancedClause.test.ts +155 -0
- package/src/__tests__/ResolverBase.clauseUnscopedRead.test.ts +127 -0
- package/src/__tests__/ResolverBase.clientOldValues.test.ts +243 -7
- package/src/__tests__/ResolverBase.deleteReturnProjection.test.ts +52 -0
- package/src/__tests__/ResolverBase.entityMessageRelay.test.ts +176 -0
- package/src/__tests__/ResolverBase.filterEscaping.test.ts +5 -2
- 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 +69 -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 +20 -28
- package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +264 -0
- 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__/RunViewResolver.cacheCheckScreen.test.ts +165 -0
- package/src/__tests__/SearchKnowledgeStreamResolver.test.ts +161 -0
- package/src/__tests__/SessionJanitor.test.ts +365 -10
- package/src/__tests__/SessionManager.test.ts +122 -0
- package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +25 -0
- package/src/__tests__/TaskGraphAgentRunner.test.ts +266 -0
- package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +468 -23
- package/src/__tests__/TaskGraphFrameResolver.test.ts +22 -0
- package/src/__tests__/TestQuerySQLResolver.test.ts +274 -0
- package/src/__tests__/TransactionGroupResolver.fieldSecurity.test.ts +199 -0
- package/src/__tests__/TransactionGroupResolver.refusals.test.ts +98 -1
- package/src/__tests__/UpdateMJDataContextItem.oldValues.test.ts +220 -0
- package/src/__tests__/UserViewResolver.updateWhereClause.test.ts +15 -0
- package/src/__tests__/ViewOperationsHandler.clauseScreen.test.ts +157 -0
- package/src/__tests__/ViewOperationsHandler.test.ts +7 -2
- package/src/__tests__/WidgetSessionService.test.ts +583 -4
- package/src/__tests__/agent-run-data-guard.test.ts +130 -0
- package/src/__tests__/apiRootBoot.test.ts +202 -0
- package/src/__tests__/buildMagicLinkSessionUser.test.ts +96 -0
- package/src/__tests__/cacheBroadcastProviders.test.ts +403 -0
- package/src/__tests__/cacheInvalidationRecordData.test.ts +109 -0
- package/src/__tests__/conversationRunEvents.test.ts +56 -14
- package/src/__tests__/fieldSecurityFixtures.ts +91 -0
- package/src/__tests__/globalCors.test.ts +217 -0
- package/src/__tests__/localDevAuth.test.ts +196 -0
- package/src/__tests__/multiTenancy.postgresRewrite.test.ts +181 -0
- package/src/__tests__/multiTenancy.security.test.ts +51 -0
- package/src/__tests__/multiTenancy.test.ts +1 -1
- package/src/__tests__/orphanedConversationDetailReconciler.test.ts +10 -0
- package/src/__tests__/ownedRealtimeSession.test.ts +39 -0
- package/src/__tests__/pushStatusResolver.filter.test.ts +64 -1
- package/src/__tests__/realtimeRecordingHandler.test.ts +669 -0
- 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__/serverExtensionHostOverlay.test.ts +66 -0
- package/src/__tests__/serverExtensionReservedRoots.test.ts +11 -98
- package/src/__tests__/sessionUserClone.test.ts +5 -1
- package/src/__tests__/sharedCache.test.ts +5 -3
- 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 +369 -93
- package/src/agentSessions/SessionManager.ts +45 -10
- package/src/apiRoot.ts +78 -0
- package/src/auth/AuthProviderCatalogRouter.ts +29 -0
- package/src/auth/LoginScreenEngine.ts +50 -0
- package/src/auth/index.ts +57 -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/MagicLinkRouter.ts +3 -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 +115 -5
- package/src/context.ts +32 -8
- package/src/coreRoutes.ts +181 -0
- package/src/generated/graphql-schemas/__mj.ts +3684 -284
- package/src/generic/CacheInvalidationResolver.ts +172 -60
- package/src/generic/OrphanedConversationDetailReconciler.ts +4 -2
- package/src/generic/PubSubManager.ts +54 -1
- package/src/generic/PushStatusResolver.ts +109 -12
- package/src/generic/ResolverBase.ts +540 -431
- package/src/generic/RunViewResolver.ts +97 -15
- package/src/generic/actionOutputFieldSecurity.ts +75 -0
- package/src/generic/fieldSecurityTransport.ts +62 -0
- package/src/globalCors.ts +71 -0
- package/src/index.ts +239 -238
- package/src/integration/CustomColumnPromoter.ts +6 -1
- package/src/logging/variablesLoggingMiddleware.ts +59 -3
- package/src/multiTenancy/index.ts +24 -2
- package/src/realtimeSessions/README.md +7 -3
- package/src/realtimeSessions/RealtimeSessionVerificationService.ts +2 -1
- package/src/realtimeSessions/RealtimeVerifyRouter.ts +2 -1
- package/src/realtimeSessions/RecordingAssemblyScheduler.ts +234 -0
- package/src/realtimeSessions/SessionVerificationPortsBase.ts +1 -0
- package/src/realtimeSessions/index.ts +2 -0
- package/src/realtimeSessions/ownedRealtimeSession.ts +69 -0
- package/src/realtimeSessions/sessionAccess.ts +183 -23
- 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/ArtifactFileResolver.ts +9 -8
- package/src/resolvers/ConversationRunEventsResolver.ts +15 -11
- package/src/resolvers/DatasetResolver.ts +70 -10
- package/src/resolvers/EntityCommunicationsResolver.ts +56 -15
- package/src/resolvers/EntityRecordNameResolver.ts +3 -2
- package/src/resolvers/FetchEntityVectorsResolver.ts +248 -55
- package/src/resolvers/FileCategoryResolver.ts +1 -0
- package/src/resolvers/FileResolver.ts +334 -109
- package/src/resolvers/GetDataContextDataResolver.ts +139 -41
- package/src/resolvers/GetDataResolver.ts +6 -3
- package/src/resolvers/IntegrationDiscoveryResolver.ts +53 -9
- package/src/resolvers/MergeRecordsResolver.ts +23 -2
- package/src/resolvers/PipelineProgressResolver.ts +12 -3
- package/src/resolvers/QueryResolver.ts +31 -6
- package/src/resolvers/QuerySystemUserResolver.ts +15 -6
- package/src/resolvers/RSUResolver.ts +12 -0
- package/src/resolvers/RealtimeClientSessionResolver.ts +114 -66
- package/src/resolvers/RemoteBrowserActionResolver.ts +15 -10
- package/src/resolvers/RunAIAgentResolver.ts +296 -85
- package/src/resolvers/RunTemplateResolver.ts +6 -4
- package/src/resolvers/RunTestResolver.ts +3 -1
- package/src/resolvers/SearchKnowledgeStreamResolver.ts +19 -3
- package/src/resolvers/SqlLoggingConfigResolver.ts +2 -4
- package/src/resolvers/SyncDataResolver.ts +4 -0
- package/src/resolvers/TaskGraphFrameResolver.ts +33 -1
- package/src/resolvers/TestQuerySQLResolver.ts +69 -13
- package/src/resolvers/TransactionGroupResolver.ts +185 -30
- package/src/resolvers/UserViewResolver.ts +2 -1
- package/src/resolvers/__tests__/GetDataResolver.validation.test.ts +95 -0
- package/src/resolvers/__tests__/MergeRecordsResolver.test.ts +43 -0
- package/src/resolvers/agent-run-data-guard.ts +89 -0
- package/src/rest/EntityCRUDHandler.ts +22 -5
- package/src/rest/RESTEndpointHandler.ts +8 -5
- package/src/rest/RealtimeRecordingHandler.ts +467 -0
- package/src/rest/ViewOperationsHandler.ts +52 -18
- package/src/rest/setupRESTEndpoints.ts +6 -0
- package/src/serverExtensionReservedRoots.ts +14 -17
- package/src/serverRoleConfigUnits.ts +48 -0
- package/src/services/MJStorageBlobStore.ts +31 -30
- package/src/services/StartTaskGraphDispatcher.ts +2 -2
- package/src/services/TaskGraphActionRunner.ts +25 -5
- package/src/services/TaskGraphAgentRunner.ts +188 -11
- package/src/services/TaskGraphContinuationDeliverer.ts +738 -16
- package/src/sharedCache.ts +3 -0
- package/src/types.ts +23 -1
|
@@ -84,7 +84,7 @@ export class RunTemplateResolver extends ResolverBase {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
// Load template content (get the first/highest priority content)
|
|
87
|
-
const rv =
|
|
87
|
+
const rv = RunView.FromMetadataProvider(p);
|
|
88
88
|
const templateContentResult = await rv.RunView<MJTemplateContentEntity>({
|
|
89
89
|
EntityName: 'MJ: Template Contents',
|
|
90
90
|
ExtraFilter: `TemplateID = '${templateId}'`,
|
|
@@ -102,12 +102,14 @@ export class RunTemplateResolver extends ResolverBase {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
// Configure and render the template
|
|
105
|
-
await TemplateEngineServer.Instance.Config(true /*always refresh to get latest templates*/, currentUser);
|
|
105
|
+
await TemplateEngineServer.Instance.Config(true /*always refresh to get latest templates*/, currentUser, p);
|
|
106
106
|
const result = await TemplateEngineServer.Instance.RenderTemplate(
|
|
107
107
|
templateEntity,
|
|
108
108
|
templateContentResult.Results[0],
|
|
109
|
-
data,
|
|
110
|
-
true // skip validation for execution
|
|
109
|
+
data,
|
|
110
|
+
true, // skip validation for execution
|
|
111
|
+
undefined,
|
|
112
|
+
{ ContextUser: currentUser },
|
|
111
113
|
);
|
|
112
114
|
|
|
113
115
|
const executionTime = Date.now() - startTime;
|
|
@@ -15,6 +15,7 @@ import { AppContext, UserPayload } from '../types.js';
|
|
|
15
15
|
import { LogError, LogStatus, UserInfo } from '@memberjunction/core';
|
|
16
16
|
import { TestEngine } from '@memberjunction/testing-engine';
|
|
17
17
|
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
18
|
+
import { ProjectEntityObjectForCaller, ProjectableEntityObject } from '../generic/fieldSecurityTransport.js';
|
|
18
19
|
import { StartLivenessPulse } from '../generic/FireAndForgetHeartbeat.js';
|
|
19
20
|
import { TestRunVariables, TestLogMessage, TestRunResult as EngineTestRunResult } from '@memberjunction/testing-engine-base';
|
|
20
21
|
|
|
@@ -447,7 +448,8 @@ export class RunTestResolver extends ResolverBase {
|
|
|
447
448
|
testRunId: (testRun as { ID?: string })?.ID || testId,
|
|
448
449
|
type: 'progress',
|
|
449
450
|
testRun: testRun && typeof (testRun as { GetAll?: () => Record<string, unknown> }).GetAll === 'function'
|
|
450
|
-
|
|
451
|
+
// projected for the recipient: the run object comes from the test engine, not a load bound to them
|
|
452
|
+
? ProjectEntityObjectForCaller(testRun as unknown as ProjectableEntityObject, userPayload.userRecord)
|
|
451
453
|
: undefined,
|
|
452
454
|
progress: {
|
|
453
455
|
currentStep: progress.step,
|
|
@@ -18,8 +18,14 @@
|
|
|
18
18
|
* Permission enforcement is identical to SearchKnowledge: each requested
|
|
19
19
|
* scopeID is run through SearchScopePermissionResolver before the engine
|
|
20
20
|
* is invoked. A denial publishes a single 'error' event and ends.
|
|
21
|
+
*
|
|
22
|
+
* 'provider' events are progress only — ProviderName, DurationMs and
|
|
23
|
+
* ResultCount. They arrive before the engine's permission pass, so they never
|
|
24
|
+
* carry a result: rows the caller's row filters would drop and unverified
|
|
25
|
+
* external-index hits must not reach the client. Results arrive in 'fused'
|
|
26
|
+
* and 'final'.
|
|
21
27
|
*/
|
|
22
|
-
import { Resolver, Mutation, Arg, Ctx, ObjectType, Field, Float, ID, Subscription, Root, PubSub, PubSubEngine } from 'type-graphql';
|
|
28
|
+
import { Resolver, Mutation, Arg, Ctx, ObjectType, Field, Float, Int, ID, Subscription, Root, PubSub, PubSubEngine } from 'type-graphql';
|
|
23
29
|
import { v4 as uuidv4 } from 'uuid';
|
|
24
30
|
import { GraphQLJSON } from 'graphql-type-json';
|
|
25
31
|
import { AppContext } from '../types.js';
|
|
@@ -59,10 +65,17 @@ export class SearchStreamNotification {
|
|
|
59
65
|
@Field(() => Float, { nullable: true })
|
|
60
66
|
DurationMs?: number;
|
|
61
67
|
|
|
62
|
-
/**
|
|
68
|
+
/**
|
|
69
|
+
* Set on `fused`, `reranked` and `final` events. Always empty on a `provider` event: a provider's
|
|
70
|
+
* hits arrive before the permission pass, so the stream reports only their count (`ResultCount`).
|
|
71
|
+
*/
|
|
63
72
|
@Field(() => [SearchKnowledgeResultItem], { nullable: true })
|
|
64
73
|
Results?: SearchKnowledgeResultItem[];
|
|
65
74
|
|
|
75
|
+
/** Set on `provider` events: how many hits the provider returned, capped at `maxResults`. */
|
|
76
|
+
@Field(() => Int, { nullable: true })
|
|
77
|
+
ResultCount?: number;
|
|
78
|
+
|
|
66
79
|
/** Set on `final` events. */
|
|
67
80
|
@Field(() => SearchSourceCounts, { nullable: true })
|
|
68
81
|
SourceCounts?: SearchSourceCounts;
|
|
@@ -253,12 +266,15 @@ export class SearchKnowledgeStreamResolver extends ResolverBase {
|
|
|
253
266
|
|
|
254
267
|
switch (ev.phase) {
|
|
255
268
|
case 'provider':
|
|
269
|
+
// Progress only. `ev.results` is never forwarded, whatever it holds: these hits have
|
|
270
|
+
// not been through the permission pass.
|
|
256
271
|
return {
|
|
257
272
|
StreamID: streamID,
|
|
258
273
|
Phase: 'provider',
|
|
259
274
|
ProviderName: ev.providerName,
|
|
260
275
|
DurationMs: ev.durationMs,
|
|
261
|
-
|
|
276
|
+
ResultCount: ev.resultCount,
|
|
277
|
+
Results: [],
|
|
262
278
|
};
|
|
263
279
|
case 'fused':
|
|
264
280
|
return {
|
|
@@ -670,10 +670,8 @@ export class SqlLoggingConfigResolver extends ResolverBase {
|
|
|
670
670
|
}
|
|
671
671
|
|
|
672
672
|
try {
|
|
673
|
-
//
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
// Read file content
|
|
673
|
+
// Read directly: a missing file surfaces as ENOENT below, so a separate existence check
|
|
674
|
+
// would only open a window for the file to change between the check and the read.
|
|
677
675
|
const content = await fs.readFile(session.filePath, 'utf-8');
|
|
678
676
|
|
|
679
677
|
// Apply line limit if specified
|
|
@@ -319,6 +319,7 @@ export class SyncDataResolver {
|
|
|
319
319
|
}
|
|
320
320
|
else {
|
|
321
321
|
// pass back the full record as it was JUST BEFORE the delete, often quite useful on the other end
|
|
322
|
+
// fls-guard: system-user-only resolver (@RequireSystemUser)
|
|
322
323
|
result.RecordJSON = await altKeyResult.GetDataObjectJSON({
|
|
323
324
|
includeRelatedEntityData: false,
|
|
324
325
|
excludeFields: [],
|
|
@@ -337,6 +338,7 @@ export class SyncDataResolver {
|
|
|
337
338
|
}
|
|
338
339
|
else if (await entityObject.InnerLoad(pk)) {
|
|
339
340
|
// pass back the full record as it was JUST BEFORE the delete, often quite useful on the other end
|
|
341
|
+
// fls-guard: system-user-only resolver (@RequireSystemUser)
|
|
340
342
|
result.RecordJSON = await entityObject.GetDataObjectJSON({
|
|
341
343
|
includeRelatedEntityData: false,
|
|
342
344
|
excludeFields: [],
|
|
@@ -368,6 +370,7 @@ export class SyncDataResolver {
|
|
|
368
370
|
result.Success = true;
|
|
369
371
|
result.PrimaryKey = new CompositeKey(entityObject.PrimaryKeys.map((pk) => ({FieldName: pk.Name, Value: pk.Value})));
|
|
370
372
|
// pass back the full record AFTER the sync, that's often quite useful on the other end
|
|
373
|
+
// fls-guard: system-user-only resolver (@RequireSystemUser)
|
|
371
374
|
result.RecordJSON = await entityObject.GetDataObjectJSON({
|
|
372
375
|
includeRelatedEntityData: false,
|
|
373
376
|
excludeFields: [],
|
|
@@ -411,6 +414,7 @@ export class SyncDataResolver {
|
|
|
411
414
|
result.PrimaryKey = new CompositeKey(entityObject.PrimaryKeys.map((pk) => ({FieldName: pk.Name, Value: pk.Value})));
|
|
412
415
|
}
|
|
413
416
|
// pass back the full record AFTER the sync, that's often quite useful on the other end
|
|
417
|
+
// fls-guard: system-user-only resolver (@RequireSystemUser)
|
|
414
418
|
result.RecordJSON = await entityObject.GetDataObjectJSON({
|
|
415
419
|
includeRelatedEntityData: false,
|
|
416
420
|
excludeFields: [],
|
|
@@ -19,6 +19,7 @@ import { Arg, Field, ID, ObjectType, PubSubEngine, Resolver, ResolverFilterData,
|
|
|
19
19
|
import { LogError } from '@memberjunction/core';
|
|
20
20
|
import { UUIDsEqual } from '@memberjunction/global';
|
|
21
21
|
import type { TaskGraphFrame, TaskGraphObserver } from '@memberjunction/task-graph';
|
|
22
|
+
import { PublishStatusUpdate } from '../generic/PushStatusResolver.js';
|
|
22
23
|
|
|
23
24
|
export const TASK_GRAPH_FRAMES_TOPIC = 'TASK_GRAPH_FRAMES';
|
|
24
25
|
|
|
@@ -173,7 +174,10 @@ export function taskGraphFrameFilter(data: {
|
|
|
173
174
|
* the same reason.
|
|
174
175
|
*/
|
|
175
176
|
export class TaskGraphFrameBroadcaster implements TaskGraphObserver {
|
|
176
|
-
constructor(
|
|
177
|
+
constructor(
|
|
178
|
+
private readonly pubSub: PubSubEngine,
|
|
179
|
+
private readonly bridgeToPushStatus: boolean = false,
|
|
180
|
+
) {}
|
|
177
181
|
|
|
178
182
|
public OnFrame(frame: TaskGraphFrame): void {
|
|
179
183
|
try {
|
|
@@ -187,6 +191,34 @@ export class TaskGraphFrameBroadcaster implements TaskGraphObserver {
|
|
|
187
191
|
TASK_GRAPH_FRAMES_TOPIC,
|
|
188
192
|
{ ...frame, ownerUserId: frame.OwnerUserID } satisfies TaskGraphFramePayload,
|
|
189
193
|
);
|
|
194
|
+
|
|
195
|
+
if (
|
|
196
|
+
this.bridgeToPushStatus &&
|
|
197
|
+
(frame.Kind === 'TaskStarted' ||
|
|
198
|
+
frame.Kind === 'TaskCompleted' ||
|
|
199
|
+
frame.Kind === 'TaskFailed' ||
|
|
200
|
+
frame.Kind === 'NodeProgress' ||
|
|
201
|
+
frame.Kind === 'GraphSettled')
|
|
202
|
+
) {
|
|
203
|
+
const defaultMsg = frame.TaskName
|
|
204
|
+
? `${frame.TaskName}: ${frame.Status ?? frame.Kind}`
|
|
205
|
+
: `Workflow: ${frame.Status ?? frame.Kind}`;
|
|
206
|
+
PublishStatusUpdate(this.pubSub, {
|
|
207
|
+
sessionId: '*',
|
|
208
|
+
ownerUserId: frame.OwnerUserID,
|
|
209
|
+
message: JSON.stringify({
|
|
210
|
+
resolver: 'TaskOrchestrator',
|
|
211
|
+
type: 'TaskGraphFrame',
|
|
212
|
+
status: 'ok',
|
|
213
|
+
data: {
|
|
214
|
+
...frame,
|
|
215
|
+
taskName: frame.TaskName,
|
|
216
|
+
message: frame.ProgressMessage || defaultMsg,
|
|
217
|
+
percentComplete: frame.ProgressPercent,
|
|
218
|
+
},
|
|
219
|
+
}),
|
|
220
|
+
});
|
|
221
|
+
}
|
|
190
222
|
} catch (e) {
|
|
191
223
|
LogError(`[TaskGraphFrameBroadcaster] Could not publish ${frame.Kind} (ignored): ${e instanceof Error ? e.message : String(e)}`);
|
|
192
224
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { Arg, Ctx, Field, InputType, Int, ObjectType, Query, Resolver } from 'type-graphql';
|
|
2
2
|
import { GraphQLJSONObject } from 'graphql-type-json';
|
|
3
3
|
import { RunQuery, IRunQueryProvider, LogError, LogStatus, QueryExecutionSpec } from '@memberjunction/core';
|
|
4
|
+
import type { DatabaseProviderBase, UserInfo } from '@memberjunction/core';
|
|
5
|
+
import { RenderPipeline } from '@memberjunction/generic-database-provider';
|
|
4
6
|
import { AppContext } from '../types.js';
|
|
5
7
|
import { GetReadOnlyProvider } from '../util.js';
|
|
6
8
|
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
9
|
+
import { IsScopeLimitedPrincipal } from '../auth/scopeLimitedPrincipal.js';
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* GraphQL input type for inline dependency queries.
|
|
@@ -88,6 +91,14 @@ export class TestQuerySQLResult {
|
|
|
88
91
|
*
|
|
89
92
|
* Security:
|
|
90
93
|
* - Requires `query:test` scope for API key users (no-op for JWT auth)
|
|
94
|
+
* - Refuses scope-limited principals (see {@link IsScopeLimitedPrincipal}). Raw SQL bypasses
|
|
95
|
+
* RunView, entity permissions and row-level security, so the RLS scope tokens that confine a
|
|
96
|
+
* magic-link session are never applied on this path — there is no narrower filter to fall back
|
|
97
|
+
* to, only refusal.
|
|
98
|
+
* - Authorizes the RENDERED SQL: every table reference must be an entity base view the caller
|
|
99
|
+
* reads unscoped (CanRead, no row-level filter, no denied fields). Entities with row/field
|
|
100
|
+
* policy for this user are refused — raw SQL cannot apply that policy, so those reads belong
|
|
101
|
+
* on RunView. Same screen as {@link AdhocQueryResolver.ExecuteAdhocQuery}.
|
|
91
102
|
* - Uses read-only database connection (no mutation possible)
|
|
92
103
|
* - Enforces MaxRows limit (default 100) to prevent unbounded queries
|
|
93
104
|
*
|
|
@@ -104,15 +115,24 @@ export class TestQuerySQLResolver extends ResolverBase {
|
|
|
104
115
|
): Promise<TestQuerySQLResult> {
|
|
105
116
|
try {
|
|
106
117
|
await this.CheckAPIKeyScopeAuthorization('query:test', '*', context.userPayload);
|
|
118
|
+
// SECURITY: refuse principals whose read authority is narrower than their role grant.
|
|
119
|
+
// Transient test SQL does not go through RunView, entity permissions or row-level
|
|
120
|
+
// security, so the RLS scope tokens that confine a magic-link session are never
|
|
121
|
+
// substituted. There is no filter to narrow, so the only correct answer for such a
|
|
122
|
+
// principal is no — the same refusal ExecuteAdhocQuery applies.
|
|
123
|
+
if (IsScopeLimitedPrincipal(context.userPayload?.userRecord)) {
|
|
124
|
+
return this.buildErrorResult('Ad-hoc SQL execution is not permitted for scope-limited sessions.');
|
|
125
|
+
}
|
|
107
126
|
// Use read-only provider for security — no mutation possible
|
|
108
127
|
const provider = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: false });
|
|
109
128
|
if (!provider) {
|
|
110
|
-
return
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
129
|
+
return this.buildErrorResult('Read-only data source is not available. TestQuerySQL requires a read-only connection for security.');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const contextUser = context.userPayload?.userRecord;
|
|
133
|
+
const refusal = this.AuthorizeRenderedTestSQL(input, provider, contextUser);
|
|
134
|
+
if (refusal) {
|
|
135
|
+
return this.buildErrorResult(refusal);
|
|
116
136
|
}
|
|
117
137
|
|
|
118
138
|
const rq = new RunQuery(provider as unknown as IRunQueryProvider);
|
|
@@ -127,10 +147,11 @@ export class TestQuerySQLResolver extends ResolverBase {
|
|
|
127
147
|
|
|
128
148
|
LogStatus(`TestQuerySQL: Executing transient query (MaxRows=${spec.MaxRows}, UsesTemplate=${spec.UsesTemplate ?? false}, Dependencies=${spec.Dependencies?.length ?? 0})`);
|
|
129
149
|
|
|
130
|
-
const result = await rq.ExecuteFromSpec(spec,
|
|
150
|
+
const result = await rq.ExecuteFromSpec(spec, contextUser);
|
|
131
151
|
|
|
132
152
|
return {
|
|
133
153
|
Success: result.Success,
|
|
154
|
+
// fls-guard: query rows; the SQL is refused before it runs if it reads a field the caller is denied
|
|
134
155
|
Results: result.Results ? JSON.stringify(result.Results) : undefined,
|
|
135
156
|
RowCount: result.RowCount,
|
|
136
157
|
ExecutionTime: result.ExecutionTime,
|
|
@@ -141,12 +162,47 @@ export class TestQuerySQLResolver extends ResolverBase {
|
|
|
141
162
|
} catch (err) {
|
|
142
163
|
LogError(err);
|
|
143
164
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
144
|
-
return {
|
|
145
|
-
Success: false,
|
|
146
|
-
RowCount: 0,
|
|
147
|
-
ExecutionTime: 0,
|
|
148
|
-
ErrorMessage: `TestQuerySQL failed: ${errorMessage}`,
|
|
149
|
-
};
|
|
165
|
+
return this.buildErrorResult(`TestQuerySQL failed: ${errorMessage}`);
|
|
150
166
|
}
|
|
151
167
|
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* SECURITY: authorizes the READ itself, against the SQL that will actually run — the same
|
|
171
|
+
* screen `AdhocQueryResolver.AuthorizeRenderedSQL` applies to ad-hoc SQL. Rendering comes
|
|
172
|
+
* first because composition (`{{query:"..."}}`), inline dependencies and Nunjucks templates
|
|
173
|
+
* can introduce table references the raw input never named, so the render here uses the same
|
|
174
|
+
* Parameters / UsesTemplate / Dependencies the execution spec will. Every table reference in
|
|
175
|
+
* the rendered SQL must be an entity base view the caller can read UNSCOPED — CanRead with no
|
|
176
|
+
* row-level filter and no denied fields — because raw SQL applies neither (see
|
|
177
|
+
* `assertFullQueryUsesReadableEntityViews`). The provider renders the same input the same way
|
|
178
|
+
* and only wraps it in server-built MaxRows capping, so the rendered SQL is the full set of
|
|
179
|
+
* reads. Returns the refusal message, or null.
|
|
180
|
+
*/
|
|
181
|
+
public AuthorizeRenderedTestSQL(input: TestQuerySQLInput, provider: DatabaseProviderBase, contextUser: UserInfo | undefined): string | null {
|
|
182
|
+
try {
|
|
183
|
+
const rendered = RenderPipeline.Run(input.SQL, {
|
|
184
|
+
Platform: provider.PlatformKey,
|
|
185
|
+
ContextUser: contextUser,
|
|
186
|
+
Parameters: input.Parameters,
|
|
187
|
+
UsesTemplate: input.UsesTemplate,
|
|
188
|
+
Dependencies: input.Dependencies,
|
|
189
|
+
OriginalSQL: input.SQL,
|
|
190
|
+
RequireReadStatement: true,
|
|
191
|
+
});
|
|
192
|
+
this.assertFullQueryUsesReadableEntityViews(rendered.Trace.AfterTemplates, provider, contextUser, 'transient test SQL');
|
|
193
|
+
return null;
|
|
194
|
+
} catch (err) {
|
|
195
|
+
return err instanceof Error ? err.message : String(err);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** Builds a failed TestQuerySQLResult carrying the given message. */
|
|
200
|
+
private buildErrorResult(errorMessage: string): TestQuerySQLResult {
|
|
201
|
+
return {
|
|
202
|
+
Success: false,
|
|
203
|
+
RowCount: 0,
|
|
204
|
+
ExecutionTime: 0,
|
|
205
|
+
ErrorMessage: errorMessage,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
152
208
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Arg, Ctx, Field, InputType, Int, Mutation, ObjectType, registerEnumType } from 'type-graphql';
|
|
2
2
|
import { AppContext } from '../types.js';
|
|
3
|
-
import { CompositeKey, IMetadataProvider, KeyValuePair, LogError, Metadata, TransactionVariable,
|
|
4
|
-
import { SafeJSONParse } from '@memberjunction/global';
|
|
3
|
+
import { AssertClientInputWritableForUser, CompositeKey, EntityInfo, IMetadataProvider, KeyValuePair, LogError, Metadata, RecordChangeMetadataSource, TransactionVariable, TransactionGroupBase, BaseEntity, UserInfo } from '@memberjunction/core';
|
|
4
|
+
import { SafeJSONParse, ValuesEqual } from '@memberjunction/global';
|
|
5
5
|
import { GetReadWriteProvider } from '../util.js';
|
|
6
6
|
import { ResolverBase } from '../generic/ResolverBase.js';
|
|
7
|
+
import { ProjectValuesForCaller } from '../generic/fieldSecurityTransport.js';
|
|
7
8
|
|
|
8
9
|
export enum TransactionVariableType {
|
|
9
10
|
Define = "Define",
|
|
@@ -142,14 +143,24 @@ export class TransactionResolver extends ResolverBase {
|
|
|
142
143
|
// rows were all refused arrive at Submit() empty, take its legitimate "nothing to do"
|
|
143
144
|
// branch, and report success for writes that never happened.
|
|
144
145
|
const refusals: string[] = [];
|
|
146
|
+
const preUpdateValues = new Map<number, Record<string, unknown>>();
|
|
147
|
+
|
|
148
|
+
// instantiate an entity object for every item first, so the group's variables are known
|
|
149
|
+
// BEFORE any Save()/Delete() runs below: a 'Use' variable sets its field at Submit(), after
|
|
150
|
+
// every server-side write check has passed, so an entity whose check depends on a field's
|
|
151
|
+
// final value must be able to see that a variable will set it.
|
|
152
|
+
const user: UserInfo = context.userPayload.userRecord;
|
|
153
|
+
for (const item of group.Items) {
|
|
154
|
+
entityObjects.push(await md.GetEntityObject(item.EntityName, user));
|
|
155
|
+
}
|
|
156
|
+
this.AssertNetworkInputWritable(group, entityObjects, user);
|
|
157
|
+
this.AddNetworkVariables(group, entityObjects, tg);
|
|
145
158
|
|
|
146
159
|
for (const [index, item] of group.Items.entries()) {
|
|
147
|
-
|
|
148
|
-
const entity = await md.GetEntityObject(item.EntityName, context.userPayload.userRecord);
|
|
149
|
-
entityObjects.push(entity); // save for later for mapping variables if needed
|
|
160
|
+
const entity = entityObjects[index];
|
|
150
161
|
|
|
151
162
|
// get the values from the payload
|
|
152
|
-
const itemValues = SafeJSONParse(item.EntityObjectJSON);
|
|
163
|
+
const itemValues = SafeJSONParse<Record<string, unknown>>(item.EntityObjectJSON) ?? {};
|
|
153
164
|
// build a primary key for the item
|
|
154
165
|
const pkey = new CompositeKey(entity.PrimaryKeys.map(pk => {
|
|
155
166
|
const kv = new KeyValuePair();
|
|
@@ -162,6 +173,13 @@ export class TransactionResolver extends ResolverBase {
|
|
|
162
173
|
case "Create":
|
|
163
174
|
if (item.OperationType === "Update") {
|
|
164
175
|
await entity.InnerLoad(pkey);
|
|
176
|
+
if (typeof entity.GetDataObject === 'function') {
|
|
177
|
+
// fls-guard: pre-update snapshot; projected before the delta is built
|
|
178
|
+
preUpdateValues.set(index, await entity.GetDataObject());
|
|
179
|
+
} else if (typeof entity.GetAll === 'function') {
|
|
180
|
+
// fls-guard: pre-update snapshot; projected before the delta is built
|
|
181
|
+
preUpdateValues.set(index, { ...(entity.GetAll() as Record<string, unknown>) });
|
|
182
|
+
}
|
|
165
183
|
}
|
|
166
184
|
objectValues.push(itemValues);
|
|
167
185
|
entity.SetMany(itemValues, true);
|
|
@@ -184,6 +202,7 @@ export class TransactionResolver extends ResolverBase {
|
|
|
184
202
|
// Awaiting costs nothing here — DataObjectParams defaults
|
|
185
203
|
// includeRelatedEntityData to false, which guards the method's only awaited
|
|
186
204
|
// work, so with no params this is GetAll() plus a filter loop.
|
|
205
|
+
// fls-guard: projected in PrepareReturnValue
|
|
187
206
|
objectValues.push(await entity.GetDataObject());
|
|
188
207
|
entity.TransactionGroup = tg;
|
|
189
208
|
if (!await entity.Delete()) {
|
|
@@ -208,32 +227,17 @@ export class TransactionResolver extends ResolverBase {
|
|
|
208
227
|
`TransactionResolver::ExecuteTransactionGroup --- ${refusals.length} of ${group.Items.length} ` +
|
|
209
228
|
`item(s) were refused, so the group was not submitted:\n${refusals.join('\n')}`
|
|
210
229
|
);
|
|
211
|
-
return await this.PrepareReturnValue(false, entityObjects, objectValues, group);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// now, we need to set the variables
|
|
215
|
-
if (group.Variables && group.Variables.length > 0) {
|
|
216
|
-
for (const networkVar of group.Variables) {
|
|
217
|
-
// for each variable, add it to the transaction group and map the index from the network payload to the specific entity object loaded up above
|
|
218
|
-
if (networkVar.ItemIndex >= 0 && networkVar.ItemIndex < entityObjects.length) {
|
|
219
|
-
const entityObject = entityObjects[networkVar.ItemIndex];
|
|
220
|
-
const newVar = new TransactionVariable(networkVar.Name, entityObject, networkVar.FieldName, networkVar.Type);
|
|
221
|
-
tg.AddVariable(newVar);
|
|
222
|
-
}
|
|
223
|
-
else {
|
|
224
|
-
throw new Error(`TransactionResolver::ExecuteTransactionGroup --- Error\n\n' + 'Invalid ItemIndex ${networkVar.ItemIndex} in TransactionVariable "${JSON.stringify(networkVar)}"`);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
230
|
+
return await this.PrepareReturnValue(false, entityObjects, objectValues, group, preUpdateValues, md, user);
|
|
227
231
|
}
|
|
228
232
|
|
|
229
233
|
// after all that, we are ready to roll, so let's run the TG
|
|
230
234
|
if (await tg.Submit()) {
|
|
231
235
|
// success!
|
|
232
|
-
return await this.PrepareReturnValue(true, entityObjects, objectValues, group);
|
|
236
|
+
return await this.PrepareReturnValue(true, entityObjects, objectValues, group, preUpdateValues, md, user);
|
|
233
237
|
}
|
|
234
238
|
else {
|
|
235
239
|
// failure, send back the results
|
|
236
|
-
return await this.PrepareReturnValue(false, entityObjects, objectValues, group);
|
|
240
|
+
return await this.PrepareReturnValue(false, entityObjects, objectValues, group, preUpdateValues, md, user);
|
|
237
241
|
}
|
|
238
242
|
}
|
|
239
243
|
catch (err) {
|
|
@@ -242,16 +246,82 @@ export class TransactionResolver extends ResolverBase {
|
|
|
242
246
|
}
|
|
243
247
|
}
|
|
244
248
|
|
|
245
|
-
|
|
249
|
+
/**
|
|
250
|
+
* Field-level security gate on everything the client sent, run before any item is applied.
|
|
251
|
+
*
|
|
252
|
+
* Each create or update payload must name only fields the caller may read, and so must every transaction
|
|
253
|
+
* variable: a `Define` on a denied field would copy its value into another item's readable
|
|
254
|
+
* field at `Submit()`, and a `Use` would write it. A key that names no field is refused with
|
|
255
|
+
* the same message as a denied one (see `AssertClientInputWritableForUser`). Callers denied
|
|
256
|
+
* nothing on an entity are not affected. A delete payload is not gated: only its primary key
|
|
257
|
+
* is read, and the record is loaded from the database.
|
|
258
|
+
*/
|
|
259
|
+
protected AssertNetworkInputWritable(group: TransactionInputType, entityObjects: BaseEntity[], user: UserInfo): void {
|
|
260
|
+
for (const [index, item] of group.Items.entries()) {
|
|
261
|
+
if (item.OperationType === TransactionOperationType.Delete) {
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
const values = SafeJSONParse<Record<string, unknown>>(item.EntityObjectJSON);
|
|
265
|
+
AssertClientInputWritableForUser(entityObjects[index]?.EntityInfo, values, user);
|
|
266
|
+
}
|
|
267
|
+
for (const networkVar of group.Variables ?? []) {
|
|
268
|
+
const target = entityObjects[networkVar.ItemIndex];
|
|
269
|
+
if (target && networkVar.FieldName) {
|
|
270
|
+
AssertClientInputWritableForUser(target.EntityInfo, { [networkVar.FieldName]: null }, user);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Adds the network payload's variables to the group, mapping each one's item index to the entity
|
|
277
|
+
* object built for that item.
|
|
278
|
+
*/
|
|
279
|
+
protected AddNetworkVariables(group: TransactionInputType, entityObjects: BaseEntity[], tg: TransactionGroupBase): void {
|
|
280
|
+
for (const networkVar of group.Variables ?? []) {
|
|
281
|
+
if (networkVar.ItemIndex >= 0 && networkVar.ItemIndex < entityObjects.length) {
|
|
282
|
+
const entityObject = entityObjects[networkVar.ItemIndex];
|
|
283
|
+
tg.AddVariable(new TransactionVariable(networkVar.Name, entityObject, networkVar.FieldName, networkVar.Type));
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
throw new Error(`TransactionResolver::ExecuteTransactionGroup --- Error\n\n' + 'Invalid ItemIndex ${networkVar.ItemIndex} in TransactionVariable "${JSON.stringify(networkVar)}"`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
protected async PrepareReturnValue(
|
|
292
|
+
success: boolean,
|
|
293
|
+
entityObjects: BaseEntity[],
|
|
294
|
+
objectValues: unknown[],
|
|
295
|
+
group: TransactionInputType,
|
|
296
|
+
preUpdateValues?: Map<number, Record<string, unknown>>,
|
|
297
|
+
provider?: RecordChangeMetadataSource,
|
|
298
|
+
user?: UserInfo
|
|
299
|
+
): Promise<TransactionOutputType> {
|
|
246
300
|
const jsonResults = [];
|
|
247
301
|
for (let i = 0; i < group.Items.length; i++) {
|
|
248
302
|
const item = group.Items[i];
|
|
249
|
-
|
|
250
|
-
|
|
303
|
+
const project = (values: Record<string, unknown>) =>
|
|
304
|
+
ProjectValuesForCaller(entityObjects[i]?.EntityInfo, values, user, provider);
|
|
305
|
+
if (item.OperationType === 'Delete') {
|
|
306
|
+
const deleted = objectValues[i];
|
|
307
|
+
jsonResults.push(JSON.stringify(deleted && typeof deleted === 'object' ? project(deleted as Record<string, unknown>) : deleted));
|
|
308
|
+
}
|
|
309
|
+
else if (item.OperationType === 'Update') {
|
|
310
|
+
jsonResults.push(
|
|
311
|
+
await this.serializeUpdateReturnValue(
|
|
312
|
+
entityObjects[i],
|
|
313
|
+
objectValues[i],
|
|
314
|
+
preUpdateValues?.get(i),
|
|
315
|
+
group,
|
|
316
|
+
i,
|
|
317
|
+
project
|
|
318
|
+
)
|
|
319
|
+
);
|
|
251
320
|
}
|
|
252
321
|
else {
|
|
253
|
-
// create
|
|
254
|
-
|
|
322
|
+
// create, return what is in the database, as the caller may read it
|
|
323
|
+
// fls-guard: projected by project()
|
|
324
|
+
jsonResults.push(JSON.stringify(project(await entityObjects[i].GetDataObject())));
|
|
255
325
|
}
|
|
256
326
|
}
|
|
257
327
|
|
|
@@ -261,6 +331,91 @@ export class TransactionResolver extends ResolverBase {
|
|
|
261
331
|
ResultsJSON: jsonResults
|
|
262
332
|
}
|
|
263
333
|
}
|
|
264
|
-
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Serializes a delta return payload for an `Update` transaction group item containing:
|
|
337
|
+
* - Primary key fields
|
|
338
|
+
* - All keys sent by the client in `sentValues` (`objectValues[i]`)
|
|
339
|
+
* - Any `TransactionVariable` fields targeting this item
|
|
340
|
+
* - `__mj_CreatedAt` and `__mj_UpdatedAt`
|
|
341
|
+
* - Virtual fields when any foreign key field was in `sentValues`
|
|
342
|
+
* - Any field whose post-save value differs from its pre-update DB snapshot (`preSaveValues`),
|
|
343
|
+
* capturing virtual fields, triggers, or server-side `BeforeSave()` mutations automatically
|
|
344
|
+
* while omitting unchanged columns.
|
|
345
|
+
*
|
|
346
|
+
* Both rows are projected for the caller BEFORE they are compared. Comparing a full-width
|
|
347
|
+
* post-save row against a snapshot taken from a narrowed load would count every denied value
|
|
348
|
+
* as changed, and the delta would then deliver exactly the values the caller may not read.
|
|
349
|
+
*/
|
|
350
|
+
private async serializeUpdateReturnValue(
|
|
351
|
+
entity: BaseEntity,
|
|
352
|
+
sentValues: unknown,
|
|
353
|
+
preSaveValues: Record<string, unknown> | undefined,
|
|
354
|
+
group: TransactionInputType,
|
|
355
|
+
itemIndex: number,
|
|
356
|
+
project: (values: Record<string, unknown>) => Record<string, unknown>
|
|
357
|
+
): Promise<string> {
|
|
358
|
+
const rawDataObj: Record<string, unknown> | null = typeof entity.GetDataObject === 'function'
|
|
359
|
+
// fls-guard: projected by project() below
|
|
360
|
+
? (await entity.GetDataObject() as Record<string, unknown>)
|
|
361
|
+
// fls-guard: projected by project() below
|
|
362
|
+
: SafeJSONParse<Record<string, unknown>>(await entity.GetDataObjectJSON());
|
|
363
|
+
if (!rawDataObj || typeof rawDataObj !== 'object') {
|
|
364
|
+
return JSON.stringify(rawDataObj);
|
|
365
|
+
}
|
|
366
|
+
const fullDataObj = project(rawDataObj);
|
|
367
|
+
if (!sentValues || typeof sentValues !== 'object') {
|
|
368
|
+
return JSON.stringify(fullDataObj);
|
|
369
|
+
}
|
|
370
|
+
preSaveValues = preSaveValues ? project(preSaveValues) : preSaveValues;
|
|
371
|
+
|
|
372
|
+
const sentRecord = sentValues as Record<string, unknown>;
|
|
373
|
+
const includeKeys = new Set<string>([
|
|
374
|
+
EntityInfo.CreatedAtFieldName,
|
|
375
|
+
EntityInfo.UpdatedAtFieldName,
|
|
376
|
+
]);
|
|
377
|
+
|
|
378
|
+
for (const pk of entity.PrimaryKeys ?? []) {
|
|
379
|
+
if (pk?.Name) {
|
|
380
|
+
includeKeys.add(pk.Name);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
for (const key of Object.keys(sentRecord)) {
|
|
384
|
+
includeKeys.add(key);
|
|
385
|
+
}
|
|
386
|
+
for (const v of group.Variables ?? []) {
|
|
387
|
+
if (v.ItemIndex === itemIndex && v.FieldName) {
|
|
388
|
+
includeKeys.add(v.FieldName);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
if (Array.isArray(entity.Fields)) {
|
|
392
|
+
for (const f of entity.Fields) {
|
|
393
|
+
if (
|
|
394
|
+
f.EntityFieldInfo?.IsSpecialDateField ||
|
|
395
|
+
Boolean(f.EntityFieldInfo?.IsVirtual) ||
|
|
396
|
+
Boolean(f.EntityFieldInfo?.IsComputed) ||
|
|
397
|
+
f.ReadOnly
|
|
398
|
+
) {
|
|
399
|
+
includeKeys.add(f.Name);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
if (preSaveValues) {
|
|
404
|
+
for (const key of Object.keys(fullDataObj)) {
|
|
405
|
+
if (!ValuesEqual(fullDataObj[key], preSaveValues[key])) {
|
|
406
|
+
includeKeys.add(key);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const deltaObj: Record<string, unknown> = {};
|
|
412
|
+
for (const key of Object.keys(fullDataObj)) {
|
|
413
|
+
if (includeKeys.has(key)) {
|
|
414
|
+
deltaObj[key] = fullDataObj[key];
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
return JSON.stringify(deltaObj);
|
|
418
|
+
}
|
|
419
|
+
|
|
265
420
|
}
|
|
266
421
|
|
|
@@ -5,6 +5,7 @@ import { MJUserView_, MJUserViewResolverBase } from '../generated/generated.js';
|
|
|
5
5
|
import { UserResolver } from './UserResolver.js';
|
|
6
6
|
import { MJUserViewEntity, MJUserViewEntityExtended } from '@memberjunction/core-entities';
|
|
7
7
|
import { GetReadOnlyProvider, GetReadWriteProvider } from '../util.js';
|
|
8
|
+
import { ProjectEntityObjectForCaller } from '../generic/fieldSecurityTransport.js';
|
|
8
9
|
|
|
9
10
|
@Resolver(MJUserView_)
|
|
10
11
|
export class UserViewResolver extends MJUserViewResolverBase {
|
|
@@ -63,7 +64,7 @@ export class UserViewResolver extends MJUserViewResolverBase {
|
|
|
63
64
|
await viewEntity.UpdateWhereClause(true); // force regeneration regardless of dirty state — that is the whole point of this endpoint
|
|
64
65
|
|
|
65
66
|
if (await viewEntity.Save()) {
|
|
66
|
-
return viewEntity
|
|
67
|
+
return ProjectEntityObjectForCaller(viewEntity, u, p);
|
|
67
68
|
} else {
|
|
68
69
|
throw new Error('Failed to update where clause');
|
|
69
70
|
}
|