From 1d575f0496ca349398fe4ec9d0de9b7510188dfe Mon Sep 17 00:00:00 2001 From: neo773 <62795688+neo773@users.noreply.github.com> Date: Sat, 18 Apr 2026 14:50:23 +0530 Subject: [PATCH] fix oauth permission check (#19829) was regressed due to https://github.com/twentyhq/twenty/pull/19441 --- ...ging-infrastructure-to-metadata.command.ts | 1 + .../create-connected-account.service.ts | 10 ++++++++++ ...workspace-member-connected-accounts.job.ts | 1 + .../imap-smtp-caldav-apis.service.spec.ts | 20 +++++++++++++++++++ .../services/imap-smtp-caldav-apis.service.ts | 14 +++++++++---- 5 files changed, 42 insertions(+), 4 deletions(-) diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500012000-migrate-messaging-infrastructure-to-metadata.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500012000-migrate-messaging-infrastructure-to-metadata.command.ts index 4a8ec2a326..b297594f6a 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500012000-migrate-messaging-infrastructure-to-metadata.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-21/1-21-workspace-command-1775500012000-migrate-messaging-infrastructure-to-metadata.command.ts @@ -359,6 +359,7 @@ export class MigrateMessagingInfrastructureToMetadataCommand extends ActiveOrSus await this.twentyORMGlobalManager.getRepository( workspaceId, 'workspaceMember', + { shouldBypassPermissionChecks: true }, ); const workspaceMembers = await workspaceMemberRepository.find(); diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/create-connected-account.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/create-connected-account.service.ts index 3a262b1fd8..0a9a6ced35 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/create-connected-account.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/create-connected-account.service.ts @@ -7,7 +7,9 @@ import { EntityManager, Repository } from 'typeorm'; import { UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { ConnectedAccountEntity } from 'src/engine/metadata-modules/connected-account/entities/connected-account.entity'; import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager'; +import { getWorkspaceContext } from 'src/engine/twenty-orm/storage/orm-workspace-context.storage'; import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util'; +import { resolveRolePermissionConfig } from 'src/engine/twenty-orm/utils/resolve-role-permission-config.util'; import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; export type CreateConnectedAccountInput = { @@ -47,10 +49,18 @@ export class CreateConnectedAccountService { const authContext = buildSystemAuthContext(workspaceId); await this.globalWorkspaceOrmManager.executeInWorkspaceContext(async () => { + const workspaceContext = getWorkspaceContext(); + const rolePermissionConfig = resolveRolePermissionConfig({ + authContext, + userWorkspaceRoleMap: workspaceContext.userWorkspaceRoleMap, + apiKeyRoleMap: workspaceContext.apiKeyRoleMap, + }); + const workspaceMemberRepo = await this.globalWorkspaceOrmManager.getRepository( workspaceId, 'workspaceMember', + rolePermissionConfig ?? undefined, ); const member = await workspaceMemberRepo.findOne({ diff --git a/packages/twenty-server/src/modules/connected-account/jobs/delete-workspace-member-connected-accounts.job.ts b/packages/twenty-server/src/modules/connected-account/jobs/delete-workspace-member-connected-accounts.job.ts index 90c4963cd3..fcd9780643 100644 --- a/packages/twenty-server/src/modules/connected-account/jobs/delete-workspace-member-connected-accounts.job.ts +++ b/packages/twenty-server/src/modules/connected-account/jobs/delete-workspace-member-connected-accounts.job.ts @@ -39,6 +39,7 @@ export class DeleteWorkspaceMemberConnectedAccountsCleanupJob { await this.globalWorkspaceOrmManager.getRepository( workspaceId, 'workspaceMember', + { shouldBypassPermissionChecks: true }, ); const member = await workspaceMemberRepo.findOne({ diff --git a/packages/twenty-server/src/modules/connected-account/services/imap-smtp-caldav-apis.service.spec.ts b/packages/twenty-server/src/modules/connected-account/services/imap-smtp-caldav-apis.service.spec.ts index 015f5a65ea..1838499544 100644 --- a/packages/twenty-server/src/modules/connected-account/services/imap-smtp-caldav-apis.service.spec.ts +++ b/packages/twenty-server/src/modules/connected-account/services/imap-smtp-caldav-apis.service.spec.ts @@ -18,6 +18,26 @@ jest.mock('uuid', () => ({ v4: jest.fn(() => 'mocked-uuid'), })); +jest.mock( + 'src/engine/twenty-orm/storage/orm-workspace-context.storage', + () => ({ + getWorkspaceContext: jest.fn(() => ({ + authContext: { type: 'user', workspace: { id: 'workspace-id' } }, + userWorkspaceRoleMap: {}, + apiKeyRoleMap: {}, + })), + }), +); + +jest.mock( + 'src/engine/twenty-orm/utils/resolve-role-permission-config.util', + () => ({ + resolveRolePermissionConfig: jest.fn(() => ({ + intersectionOf: ['role-id'], + })), + }), +); + describe('ImapSmtpCalDavAPIService', () => { let service: ImapSmtpCalDavAPIService; diff --git a/packages/twenty-server/src/modules/connected-account/services/imap-smtp-caldav-apis.service.ts b/packages/twenty-server/src/modules/connected-account/services/imap-smtp-caldav-apis.service.ts index f9e4ec8f2f..011a2f5a11 100644 --- a/packages/twenty-server/src/modules/connected-account/services/imap-smtp-caldav-apis.service.ts +++ b/packages/twenty-server/src/modules/connected-account/services/imap-smtp-caldav-apis.service.ts @@ -15,7 +15,9 @@ import { CalendarChannelEntity } from 'src/engine/metadata-modules/calendar-chan import { ConnectedAccountEntity } from 'src/engine/metadata-modules/connected-account/entities/connected-account.entity'; import { MessageChannelEntity } from 'src/engine/metadata-modules/message-channel/entities/message-channel.entity'; import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager'; +import { getWorkspaceContext } from 'src/engine/twenty-orm/storage/orm-workspace-context.storage'; import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util'; +import { resolveRolePermissionConfig } from 'src/engine/twenty-orm/utils/resolve-role-permission-config.util'; import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; import { SyncMessageFoldersService } from 'src/modules/messaging/message-folder-manager/services/sync-message-folders.service'; @@ -68,15 +70,20 @@ export class ImapSmtpCalDavAPIService { const { handle, workspaceId, workspaceMemberId, connectedAccountId } = input; - const authContext = buildSystemAuthContext(workspaceId); - return this.globalWorkspaceOrmManager.executeInWorkspaceContext( async () => { - // Resolve userWorkspaceId from workspaceMemberId + const workspaceContext = getWorkspaceContext(); + const rolePermissionConfig = resolveRolePermissionConfig({ + authContext: workspaceContext.authContext, + userWorkspaceRoleMap: workspaceContext.userWorkspaceRoleMap, + apiKeyRoleMap: workspaceContext.apiKeyRoleMap, + }); + const workspaceMemberRepo = await this.globalWorkspaceOrmManager.getRepository( workspaceId, 'workspaceMember', + rolePermissionConfig ?? undefined, ); const member = await workspaceMemberRepo.findOne({ @@ -190,7 +197,6 @@ export class ImapSmtpCalDavAPIService { return newOrExistingAccountId; }, - authContext, ); } }