Compare commits

...
Author SHA1 Message Date
Sonarly Claude Code 27b0a9e0f3 fix: wrap markMessageChannelAsPendingGroupEmailsAction in workspace context in metadata resolver
https://sonarly.com/issue/17668?type=bug

The metadata resolver for `UpdateMessageChannel` calls `MessagingProcessGroupEmailActionsService.markMessageChannelAsPendingGroupEmailsAction()` without wrapping it in `executeInWorkspaceContext()`, causing a crash when the underlying data access service tries to access the workspace ORM repository.

Fix: The `MessageChannelResolver.updateMessageChannel()` method calls `MessagingProcessGroupEmailActionsService.markMessageChannelAsPendingGroupEmailsAction()` when the user toggles the `excludeGroupEmails` setting. This service method internally uses `MessageChannelDataAccessService.update()`, which accesses the workspace ORM repository via `GlobalWorkspaceOrmManager.getRepository()`. The workspace ORM requires an `AsyncLocalStorage` context (set via `withWorkspaceContext()`), but the metadata resolver operates outside any such context.

The fix wraps the `markMessageChannelAsPendingGroupEmailsAction` call in `globalWorkspaceOrmManager.executeInWorkspaceContext()` with a system auth context, exactly matching the pattern used in the existing pre-query hook (`message-channel-update-one.pre-query.hook.ts` line 59) that performs the same operation.

Changes:
1. Added imports for `GlobalWorkspaceOrmManager` and `buildSystemAuthContext`
2. Injected `GlobalWorkspaceOrmManager` into the resolver constructor
3. Wrapped the `markMessageChannelAsPendingGroupEmailsAction` call in `executeInWorkspaceContext` with a system auth context built from `workspace.id`
2026-03-23 19:43:36 +00:00
@@ -23,6 +23,8 @@ import {
} from 'src/engine/metadata-modules/message-channel/message-channel.exception';
import { MessageChannelGraphqlApiExceptionInterceptor } from 'src/engine/metadata-modules/message-channel/interceptors/message-channel-graphql-api-exception.interceptor';
import { MessageChannelMetadataService } from 'src/engine/metadata-modules/message-channel/message-channel-metadata.service';
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util';
import {
MessageChannelPendingGroupEmailsAction,
MessageChannelSyncStage,
@@ -41,6 +43,7 @@ export class MessageChannelResolver {
private readonly messageChannelMetadataService: MessageChannelMetadataService,
private readonly messageFolderDataAccessService: MessageFolderDataAccessService,
private readonly messagingProcessGroupEmailActionsService: MessagingProcessGroupEmailActionsService,
private readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
) {}
@Query(() => [MessageChannelDTO])
@@ -116,13 +119,19 @@ export class MessageChannelResolver {
isDefined(input.update.excludeGroupEmails) &&
input.update.excludeGroupEmails !== messageChannel.excludeGroupEmails
) {
// Service expects WorkspaceEntity type but only reads .id
await this.messagingProcessGroupEmailActionsService.markMessageChannelAsPendingGroupEmailsAction(
messageChannel as unknown as MessageChannelWorkspaceEntity,
workspace.id,
input.update.excludeGroupEmails
? MessageChannelPendingGroupEmailsAction.GROUP_EMAILS_DELETION
: MessageChannelPendingGroupEmailsAction.GROUP_EMAILS_IMPORT,
const systemAuthContext = buildSystemAuthContext(workspace.id);
await this.globalWorkspaceOrmManager.executeInWorkspaceContext(
async () => {
await this.messagingProcessGroupEmailActionsService.markMessageChannelAsPendingGroupEmailsAction(
messageChannel as unknown as MessageChannelWorkspaceEntity,
workspace.id,
input.update.excludeGroupEmails
? MessageChannelPendingGroupEmailsAction.GROUP_EMAILS_DELETION
: MessageChannelPendingGroupEmailsAction.GROUP_EMAILS_IMPORT,
);
},
systemAuthContext,
);
}