diff --git a/packages/twenty-server/src/engine/core-modules/auth/auth.module.ts b/packages/twenty-server/src/engine/core-modules/auth/auth.module.ts index 1560c7f97..d88f37a14 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/auth.module.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/auth.module.ts @@ -24,11 +24,9 @@ import { UserModule } from 'src/engine/core-modules/user/user.module'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module'; import { ConnectedAccountModule } from 'src/modules/connected-account/connected-account.module'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { AuthResolver } from './auth.resolver'; @@ -47,9 +45,6 @@ import { JwtAuthStrategy } from './strategies/jwt.auth.strategy'; [Workspace, User, AppToken, FeatureFlagEntity], 'core', ), - ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, - ]), HttpModule, TokenModule, UserWorkspaceModule, diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts index b20072ed5..e140ecedd 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts @@ -7,7 +7,6 @@ import { EnvironmentService } from 'src/engine/core-modules/environment/environm import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { CalendarEventListFetchJob, @@ -17,7 +16,6 @@ import { CalendarChannelVisibility, CalendarChannelWorkspaceEntity, } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { AccountsToReconnectService } from 'src/modules/connected-account/services/accounts-to-reconnect.service'; import { ConnectedAccountProvider, @@ -45,8 +43,6 @@ export class GoogleAPIsService { @InjectMessageQueue(MessageQueue.calendarQueue) private readonly calendarQueueService: MessageQueueService, private readonly environmentService: EnvironmentService, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, private readonly accountsToReconnectService: AccountsToReconnectService, ) {} @@ -71,14 +67,17 @@ export class GoogleAPIsService { 'CALENDAR_PROVIDER_GOOGLE_ENABLED', ); - const connectedAccounts = - await this.connectedAccountRepository.getAllByHandleAndWorkspaceMemberId( - handle, - workspaceMemberId, + const connectedAccountRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace( workspaceId, + 'connectedAccount', ); - const existingAccountId = connectedAccounts?.[0]?.id; + const connectedAccount = await connectedAccountRepository.findOne({ + where: { handle, accountOwnerId: workspaceMemberId }, + }); + + const existingAccountId = connectedAccount?.id; const newOrExistingConnectedAccountId = existingAccountId ?? v4(); const calendarChannelRepository = @@ -98,7 +97,7 @@ export class GoogleAPIsService { await workspaceDataSource.transaction(async (manager: EntityManager) => { if (!existingAccountId) { - await this.connectedAccountRepository.create( + await connectedAccountRepository.save( { id: newOrExistingConnectedAccountId, handle, @@ -107,7 +106,7 @@ export class GoogleAPIsService { refreshToken: input.refreshToken, accountOwnerId: workspaceMemberId, }, - workspaceId, + {}, manager, ); @@ -140,11 +139,14 @@ export class GoogleAPIsService { ); } } else { - await this.connectedAccountRepository.updateAccessTokenAndRefreshToken( - input.accessToken, - input.refreshToken, - newOrExistingConnectedAccountId, - workspaceId, + await connectedAccountRepository.update( + { + id: newOrExistingConnectedAccountId, + }, + { + accessToken: input.accessToken, + refreshToken: input.refreshToken, + }, manager, ); diff --git a/packages/twenty-server/src/engine/object-metadata-repository/metadata-to-repository.mapping.ts b/packages/twenty-server/src/engine/object-metadata-repository/metadata-to-repository.mapping.ts index b2053e44c..6f0bc8dff 100644 --- a/packages/twenty-server/src/engine/object-metadata-repository/metadata-to-repository.mapping.ts +++ b/packages/twenty-server/src/engine/object-metadata-repository/metadata-to-repository.mapping.ts @@ -1,5 +1,4 @@ import { BlocklistRepository } from 'src/modules/blocklist/repositories/blocklist.repository'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { AuditLogRepository } from 'src/modules/timeline/repositiories/audit-log.repository'; import { TimelineActivityRepository } from 'src/modules/timeline/repositiories/timeline-activity.repository'; import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository'; @@ -7,7 +6,6 @@ import { WorkspaceMemberRepository } from 'src/modules/workspace-member/reposito export const metadataToRepositoryMapping = { AuditLogWorkspaceEntity: AuditLogRepository, BlocklistWorkspaceEntity: BlocklistRepository, - ConnectedAccountWorkspaceEntity: ConnectedAccountRepository, TimelineActivityWorkspaceEntity: TimelineActivityRepository, WorkspaceMemberWorkspaceEntity: WorkspaceMemberRepository, }; diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module.ts index 0e472d465..0385ae884 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module.ts @@ -25,13 +25,11 @@ import { CalendarCommonModule } from 'src/modules/calendar/common/calendar-commo import { CalendarChannelSyncStatusService } from 'src/modules/calendar/common/services/calendar-channel-sync-status.service'; import { ConnectedAccountModule } from 'src/modules/connected-account/connected-account.module'; import { RefreshAccessTokenManagerModule } from 'src/modules/connected-account/refresh-access-token-manager/refresh-access-token-manager.module'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; @Module({ imports: [ ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, BlocklistWorkspaceEntity, WorkspaceMemberWorkspaceEntity, ]), diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job.ts index 406e71702..1e28927e2 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job.ts @@ -3,15 +3,12 @@ import { Scope } from '@nestjs/common'; import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { CalendarEventsImportService } from 'src/modules/calendar/calendar-event-import-manager/services/calendar-events-import.service'; import { CalendarChannelSyncStage, CalendarChannelWorkspaceEntity, } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { isThrottled } from 'src/modules/connected-account/utils/is-throttled'; export type CalendarEventsImportJobData = { @@ -27,8 +24,6 @@ export class CalendarEventListFetchJob { constructor( private readonly twentyORMManager: TwentyORMManager, private readonly calendarEventsImportService: CalendarEventsImportService, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, ) {} @Process(CalendarEventListFetchJob.name) @@ -47,6 +42,7 @@ export class CalendarEventListFetchJob { id: calendarChannelId, isSyncEnabled: true, }, + relations: ['connectedAccount'], }); if (!calendarChannel) { @@ -62,12 +58,6 @@ export class CalendarEventListFetchJob { return; } - const connectedAccount = - await this.connectedAccountRepository.getConnectedAccountOrThrow( - workspaceId, - calendarChannel.connectedAccountId, - ); - switch (calendarChannel.syncStage) { case CalendarChannelSyncStage.FULL_CALENDAR_EVENT_LIST_FETCH_PENDING: await calendarChannelRepository.update(calendarChannelId, { @@ -77,7 +67,7 @@ export class CalendarEventListFetchJob { await this.calendarEventsImportService.processCalendarEventsImport( calendarChannel, - connectedAccount, + calendarChannel.connectedAccount, workspaceId, ); break; @@ -85,7 +75,7 @@ export class CalendarEventListFetchJob { case CalendarChannelSyncStage.PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING: await this.calendarEventsImportService.processCalendarEventsImport( calendarChannel, - connectedAccount, + calendarChannel.connectedAccount, workspaceId, ); break; diff --git a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-event.service.ts b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-event.service.ts index 041c3a648..2e8810d1f 100644 --- a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-event.service.ts +++ b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-event.service.ts @@ -1,12 +1,12 @@ import { ForbiddenException, Injectable } from '@nestjs/common'; import groupBy from 'lodash.groupby'; +import { Any } from 'typeorm'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity'; import { CalendarChannelVisibility } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; @@ -15,8 +15,6 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta export class CanAccessCalendarEventService { constructor( private readonly twentyORMManager: TwentyORMManager, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, @InjectObjectMetadataRepository(WorkspaceMemberWorkspaceEntity) private readonly workspaceMemberService: WorkspaceMemberRepository, ) {} @@ -46,20 +44,20 @@ export class CanAccessCalendarEventService { const currentWorkspaceMember = await this.workspaceMemberService.getByIdOrFail(userId, workspaceId); - const calendarChannelsConnectedAccounts = - await this.connectedAccountRepository.getByIds( - calendarChannels.map((channel) => channel.connectedAccountId), - workspaceId, + const connectedAccountRepository = + await this.twentyORMManager.getRepository( + 'connectedAccount', ); - const calendarChannelsWorkspaceMemberIds = - calendarChannelsConnectedAccounts.map( - (connectedAccount) => connectedAccount.accountOwnerId, - ); + const connectedAccounts = await connectedAccountRepository.find({ + select: ['id'], + where: { + calendarChannels: Any(calendarChannels.map((channel) => channel.id)), + accountOwnerId: currentWorkspaceMember.id, + }, + }); - if ( - calendarChannelsWorkspaceMemberIds.includes(currentWorkspaceMember.id) - ) { + if (connectedAccounts.length > 0) { return; } diff --git a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-query-hook.module.ts b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-query-hook.module.ts index ff3d178c4..2c5a26b18 100644 --- a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-query-hook.module.ts +++ b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-query-hook.module.ts @@ -4,15 +4,11 @@ import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repos import { CalendarEventFindManyPreQueryHook } from 'src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook'; import { CalendarEventFindOnePreQueryHook } from 'src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook'; import { CanAccessCalendarEventService } from 'src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-event.service'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; @Module({ imports: [ - ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, - WorkspaceMemberWorkspaceEntity, - ]), + ObjectMetadataRepositoryModule.forFeature([WorkspaceMemberWorkspaceEntity]), ], providers: [ CanAccessCalendarEventService, diff --git a/packages/twenty-server/src/modules/connected-account/email-alias-manager/email-alias-manager.module.ts b/packages/twenty-server/src/modules/connected-account/email-alias-manager/email-alias-manager.module.ts index e1678e3d7..a634ff0fe 100644 --- a/packages/twenty-server/src/modules/connected-account/email-alias-manager/email-alias-manager.module.ts +++ b/packages/twenty-server/src/modules/connected-account/email-alias-manager/email-alias-manager.module.ts @@ -1,18 +1,11 @@ import { Module } from '@nestjs/common'; -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { GoogleEmailAliasManagerService } from 'src/modules/connected-account/email-alias-manager/drivers/google/google-email-alias-manager.service'; import { EmailAliasManagerService } from 'src/modules/connected-account/email-alias-manager/services/email-alias-manager.service'; import { OAuth2ClientManagerModule } from 'src/modules/connected-account/oauth2-client-manager/oauth2-client-manager.module'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; @Module({ - imports: [ - ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, - ]), - OAuth2ClientManagerModule, - ], + imports: [OAuth2ClientManagerModule], providers: [EmailAliasManagerService, GoogleEmailAliasManagerService], exports: [EmailAliasManagerService], }) diff --git a/packages/twenty-server/src/modules/connected-account/email-alias-manager/services/email-alias-manager.service.ts b/packages/twenty-server/src/modules/connected-account/email-alias-manager/services/email-alias-manager.service.ts index 50a855ba3..e4ec7e083 100644 --- a/packages/twenty-server/src/modules/connected-account/email-alias-manager/services/email-alias-manager.service.ts +++ b/packages/twenty-server/src/modules/connected-account/email-alias-manager/services/email-alias-manager.service.ts @@ -1,21 +1,18 @@ import { Injectable } from '@nestjs/common'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { GoogleEmailAliasManagerService } from 'src/modules/connected-account/email-alias-manager/drivers/google/google-email-alias-manager.service'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; @Injectable() export class EmailAliasManagerService { constructor( - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, private readonly googleEmailAliasManagerService: GoogleEmailAliasManagerService, + private readonly twentyORMManager: TwentyORMManager, ) {} public async refreshHandleAliases( connectedAccount: ConnectedAccountWorkspaceEntity, - workspaceId: string, ) { let handleAliases: string[]; @@ -32,10 +29,16 @@ export class EmailAliasManagerService { ); } - await this.connectedAccountRepository.updateHandleAliases( - handleAliases, - connectedAccount.id, - workspaceId, + const connectedAccountRepository = + await this.twentyORMManager.getRepository( + 'connectedAccount', + ); + + await connectedAccountRepository.update( + { id: connectedAccount.id }, + { + handleAliases: handleAliases.join(','), // TODO: modify handleAliases to be of fieldmetadatatype array + }, ); } } diff --git a/packages/twenty-server/src/modules/connected-account/refresh-access-token-manager/drivers/google/google-api-refresh-access-token.module.ts b/packages/twenty-server/src/modules/connected-account/refresh-access-token-manager/drivers/google/google-api-refresh-access-token.module.ts index 14529ba0b..5c8308ec7 100644 --- a/packages/twenty-server/src/modules/connected-account/refresh-access-token-manager/drivers/google/google-api-refresh-access-token.module.ts +++ b/packages/twenty-server/src/modules/connected-account/refresh-access-token-manager/drivers/google/google-api-refresh-access-token.module.ts @@ -1,17 +1,10 @@ import { Module } from '@nestjs/common'; -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/refresh-access-token-manager/drivers/google/services/google-api-refresh-access-token.service'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module'; @Module({ - imports: [ - ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, - ]), - MessagingCommonModule, - ], + imports: [MessagingCommonModule], providers: [GoogleAPIRefreshAccessTokenService], exports: [GoogleAPIRefreshAccessTokenService], }) diff --git a/packages/twenty-server/src/modules/connected-account/refresh-access-token-manager/services/refresh-access-token.service.ts b/packages/twenty-server/src/modules/connected-account/refresh-access-token-manager/services/refresh-access-token.service.ts index 3326cd4ba..853401356 100644 --- a/packages/twenty-server/src/modules/connected-account/refresh-access-token-manager/services/refresh-access-token.service.ts +++ b/packages/twenty-server/src/modules/connected-account/refresh-access-token-manager/services/refresh-access-token.service.ts @@ -1,20 +1,18 @@ import { Injectable } from '@nestjs/common'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/refresh-access-token-manager/drivers/google/services/google-api-refresh-access-token.service'; import { RefreshAccessTokenException, RefreshAccessTokenExceptionCode, } from 'src/modules/connected-account/refresh-access-token-manager/exceptions/refresh-access-token.exception'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; @Injectable() export class RefreshAccessTokenService { constructor( private readonly googleAPIRefreshAccessTokenService: GoogleAPIRefreshAccessTokenService, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, + private readonly twentyORMManager: TwentyORMManager, ) {} async refreshAndSaveAccessToken( @@ -44,10 +42,16 @@ export class RefreshAccessTokenService { ); } - await this.connectedAccountRepository.updateAccessToken( - accessToken, - connectedAccount.id, - workspaceId, + const connectedAccountRepository = + await this.twentyORMManager.getRepository( + 'connectedAccount', + ); + + await connectedAccountRepository.update( + { id: connectedAccount.id }, + { + accessToken, + }, ); return accessToken; diff --git a/packages/twenty-server/src/modules/connected-account/repositories/connected-account.repository.ts b/packages/twenty-server/src/modules/connected-account/repositories/connected-account.repository.ts deleted file mode 100644 index 7be9d5d65..000000000 --- a/packages/twenty-server/src/modules/connected-account/repositories/connected-account.repository.ts +++ /dev/null @@ -1,240 +0,0 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; - -import { EntityManager } from 'typeorm'; - -import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; - -@Injectable() -export class ConnectedAccountRepository { - constructor( - private readonly workspaceDataSourceService: WorkspaceDataSourceService, - ) {} - - public async getAll( - workspaceId: string, - transactionManager?: EntityManager, - ): Promise { - const dataSourceSchema = - this.workspaceDataSourceService.getSchemaName(workspaceId); - - return await this.workspaceDataSourceService.executeRawQuery( - `SELECT * FROM ${dataSourceSchema}."connectedAccount" WHERE "provider" = 'google'`, - [], - workspaceId, - transactionManager, - ); - } - - public async getByIds( - connectedAccountIds: string[], - workspaceId: string, - transactionManager?: EntityManager, - ): Promise { - const dataSourceSchema = - this.workspaceDataSourceService.getSchemaName(workspaceId); - - return await this.workspaceDataSourceService.executeRawQuery( - `SELECT * FROM ${dataSourceSchema}."connectedAccount" WHERE "id" = ANY($1)`, - [connectedAccountIds], - workspaceId, - transactionManager, - ); - } - - public async getAllByWorkspaceMemberId( - workspaceMemberId: string, - workspaceId: string, - transactionManager?: EntityManager, - ): Promise { - const dataSourceSchema = - this.workspaceDataSourceService.getSchemaName(workspaceId); - - const connectedAccounts = - await this.workspaceDataSourceService.executeRawQuery( - `SELECT * FROM ${dataSourceSchema}."connectedAccount" WHERE "accountOwnerId" = $1`, - [workspaceMemberId], - workspaceId, - transactionManager, - ); - - return connectedAccounts; - } - - public async getAllByHandleAndWorkspaceMemberId( - handle: string, - workspaceMemberId: string, - workspaceId: string, - transactionManager?: EntityManager, - ): Promise { - const dataSourceSchema = - this.workspaceDataSourceService.getSchemaName(workspaceId); - - const connectedAccounts = - await this.workspaceDataSourceService.executeRawQuery( - `SELECT * FROM ${dataSourceSchema}."connectedAccount" WHERE "handle" = $1 AND "accountOwnerId" = $2 LIMIT 1`, - [handle, workspaceMemberId], - workspaceId, - transactionManager, - ); - - return connectedAccounts; - } - - public async create( - connectedAccount: Pick< - ConnectedAccountWorkspaceEntity, - | 'id' - | 'handle' - | 'provider' - | 'accessToken' - | 'refreshToken' - | 'accountOwnerId' - >, - workspaceId: string, - transactionManager?: EntityManager, - ): Promise { - const dataSourceSchema = - this.workspaceDataSourceService.getSchemaName(workspaceId); - - return await this.workspaceDataSourceService.executeRawQuery( - `INSERT INTO ${dataSourceSchema}."connectedAccount" ("id", "handle", "provider", "accessToken", "refreshToken", "accountOwnerId") VALUES ($1, $2, $3, $4, $5, $6)`, - [ - connectedAccount.id, - connectedAccount.handle, - connectedAccount.provider, - connectedAccount.accessToken, - connectedAccount.refreshToken, - connectedAccount.accountOwnerId, - ], - workspaceId, - transactionManager, - ); - } - - public async updateAccessTokenAndRefreshToken( - accessToken: string, - refreshToken: string, - connectedAccountId: string, - workspaceId: string, - transactionManager?: EntityManager, - ) { - const dataSourceSchema = - this.workspaceDataSourceService.getSchemaName(workspaceId); - - await this.workspaceDataSourceService.executeRawQuery( - `UPDATE ${dataSourceSchema}."connectedAccount" SET "accessToken" = $1, "refreshToken" = $2, "authFailedAt" = NULL WHERE "id" = $3`, - [accessToken, refreshToken, connectedAccountId], - workspaceId, - transactionManager, - ); - } - - public async getById( - connectedAccountId: string, - workspaceId: string, - transactionManager?: EntityManager, - ): Promise { - const dataSourceSchema = - this.workspaceDataSourceService.getSchemaName(workspaceId); - - const connectedAccounts = - await this.workspaceDataSourceService.executeRawQuery( - `SELECT * FROM ${dataSourceSchema}."connectedAccount" WHERE "id" = $1 LIMIT 1`, - [connectedAccountId], - workspaceId, - transactionManager, - ); - - return connectedAccounts[0]; - } - - public async getByIdOrFail( - connectedAccountId: string, - workspaceId: string, - transactionManager?: EntityManager, - ): Promise { - const connectedAccount = await this.getById( - connectedAccountId, - workspaceId, - transactionManager, - ); - - if (!connectedAccount) { - throw new NotFoundException( - `Connected account with id ${connectedAccountId} not found in workspace ${workspaceId}`, - ); - } - - return connectedAccount; - } - - public async updateAccessToken( - accessToken: string, - connectedAccountId: string, - workspaceId: string, - transactionManager?: EntityManager, - ) { - const dataSourceSchema = - this.workspaceDataSourceService.getSchemaName(workspaceId); - - await this.workspaceDataSourceService.executeRawQuery( - `UPDATE ${dataSourceSchema}."connectedAccount" SET "accessToken" = $1, "authFailedAt" = NULL WHERE "id" = $2`, - [accessToken, connectedAccountId], - workspaceId, - transactionManager, - ); - } - - public async updateAuthFailedAt( - connectedAccountId: string, - workspaceId: string, - transactionManager?: EntityManager, - ) { - const dataSourceSchema = - this.workspaceDataSourceService.getSchemaName(workspaceId); - - await this.workspaceDataSourceService.executeRawQuery( - `UPDATE ${dataSourceSchema}."connectedAccount" SET "authFailedAt" = NOW() WHERE "id" = $1`, - [connectedAccountId], - workspaceId, - transactionManager, - ); - } - - public async getConnectedAccountOrThrow( - workspaceId: string, - connectedAccountId: string, - ): Promise { - const connectedAccount = await this.getById( - connectedAccountId, - workspaceId, - ); - - if (!connectedAccount) { - throw new Error( - `Connected account ${connectedAccountId} not found in workspace ${workspaceId}`, - ); - } - - return connectedAccount; - } - - public async updateHandleAliases( - handleAliases: string[], - connectedAccountId: string, - workspaceId: string, - transactionManager?: EntityManager, - ) { - const dataSourceSchema = - this.workspaceDataSourceService.getSchemaName(workspaceId); - - await this.workspaceDataSourceService.executeRawQuery( - `UPDATE ${dataSourceSchema}."connectedAccount" SET "handleAliases" = $1 WHERE "id" = $2`, - // TODO: modify handleAliases to be of fieldmetadatatype array - [handleAliases.join(','), connectedAccountId], - workspaceId, - transactionManager, - ); - } -} diff --git a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/can-access-message-thread.service.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/can-access-message-thread.service.ts index 44141f3dd..0e3022584 100644 --- a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/can-access-message-thread.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/can-access-message-thread.service.ts @@ -5,17 +5,13 @@ import { Any } from 'typeorm'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; -import { isDefined } from 'src/utils/is-defined'; export class CanAccessMessageThreadService { constructor( - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, @InjectObjectMetadataRepository(WorkspaceMemberWorkspaceEntity) private readonly workspaceMemberRepository: WorkspaceMemberRepository, private readonly twentyORMManager: TwentyORMManager, @@ -31,6 +27,7 @@ export class CanAccessMessageThreadService { 'messageChannel', ); const messageChannels = await messageChannelRepository.find({ + select: ['id', 'visibility'], where: { id: Any( messageChannelMessageAssociations.map( @@ -52,20 +49,20 @@ export class CanAccessMessageThreadService { const currentWorkspaceMember = await this.workspaceMemberRepository.getByIdOrFail(userId, workspaceId); - const messageChannelsConnectedAccounts = - await this.connectedAccountRepository.getByIds( - messageChannels - .map((channel) => channel.connectedAccountId) - .filter(isDefined), - workspaceId, + const connectedAccountRepository = + await this.twentyORMManager.getRepository( + 'connectedAccount', ); - const messageChannelsWorkspaceMemberIds = - messageChannelsConnectedAccounts.map( - (connectedAccount) => connectedAccount.accountOwnerId, - ); + const connectedAccounts = await connectedAccountRepository.find({ + select: ['id'], + where: { + messageChannels: Any(messageChannels.map((channel) => channel.id)), + accountOwnerId: currentWorkspaceMember.id, + }, + }); - if (messageChannelsWorkspaceMemberIds.includes(currentWorkspaceMember.id)) { + if (connectedAccounts.length > 0) { return; } diff --git a/packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts index 9c8464076..1222865f6 100644 --- a/packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts +++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts @@ -1,7 +1,6 @@ import { Module } from '@nestjs/common'; import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { CanAccessMessageThreadService } from 'src/modules/messaging/common/query-hooks/message/can-access-message-thread.service'; import { MessageFindManyPreQueryHook } from 'src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook'; import { MessageFindOnePreQueryHook } from 'src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook'; @@ -9,10 +8,7 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta @Module({ imports: [ - ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, - WorkspaceMemberWorkspaceEntity, - ]), + ObjectMetadataRepositoryModule.forFeature([WorkspaceMemberWorkspaceEntity]), ], providers: [ CanAccessMessageThreadService, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts index 3fc555a87..fec4a7693 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts @@ -2,15 +2,14 @@ import { HttpModule } from '@nestjs/axios'; import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; +import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity'; import { EmailAliasManagerModule } from 'src/modules/connected-account/email-alias-manager/email-alias-manager.module'; import { OAuth2ClientManagerModule } from 'src/modules/connected-account/oauth2-client-manager/oauth2-client-manager.module'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module'; import { GmailClientProvider } from 'src/modules/messaging/message-import-manager/drivers/gmail/providers/gmail-client.provider'; import { GmailFetchByBatchService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-fetch-by-batch.service'; @@ -26,10 +25,7 @@ import { MessageParticipantManagerModule } from 'src/modules/messaging/message-p baseURL: 'https://www.googleapis.com/batch/gmail/v1', }), EnvironmentModule, - ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, - BlocklistWorkspaceEntity, - ]), + ObjectMetadataRepositoryModule.forFeature([BlocklistWorkspaceEntity]), MessagingCommonModule, TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), OAuth2ClientManagerModule, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job.ts index cc66a1ff5..67761ec5d 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job.ts @@ -3,16 +3,12 @@ import { Logger, Scope } from '@nestjs/common'; import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { isThrottled } from 'src/modules/connected-account/utils/is-throttled'; import { MessageChannelSyncStage, MessageChannelWorkspaceEntity, } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; -import { MessageImportExceptionHandlerService } from 'src/modules/messaging/message-import-manager/services/message-import-exception-handler.service'; import { MessagingFullMessageListFetchService } from 'src/modules/messaging/message-import-manager/services/messaging-full-message-list-fetch.service'; import { MessagingPartialMessageListFetchService } from 'src/modules/messaging/message-import-manager/services/messaging-partial-message-list-fetch.service'; import { MessagingTelemetryService } from 'src/modules/messaging/monitoring/services/messaging-telemetry.service'; @@ -32,11 +28,8 @@ export class MessagingMessageListFetchJob { constructor( private readonly messagingFullMessageListFetchService: MessagingFullMessageListFetchService, private readonly messagingPartialMessageListFetchService: MessagingPartialMessageListFetchService, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, private readonly messagingTelemetryService: MessagingTelemetryService, private readonly twentyORMManager: TwentyORMManager, - private readonly messageImportErrorHandlerService: MessageImportExceptionHandlerService, ) {} @Process(MessagingMessageListFetchJob.name) @@ -60,6 +53,7 @@ export class MessagingMessageListFetchJob { where: { id: messageChannelId, }, + relations: ['connectedAccount'], }); if (!messageChannel) { @@ -72,16 +66,6 @@ export class MessagingMessageListFetchJob { return; } - const connectedAccount = - await this.connectedAccountRepository.getByIdOrFail( - messageChannel.connectedAccountId, - workspaceId, - ); - - if (!messageChannel?.isSyncEnabled) { - return; - } - if ( isThrottled( messageChannel.syncStageStartedAt, @@ -100,20 +84,20 @@ export class MessagingMessageListFetchJob { await this.messagingTelemetryService.track({ eventName: 'partial_message_list_fetch.started', workspaceId, - connectedAccountId: connectedAccount.id, + connectedAccountId: messageChannel.connectedAccount.id, messageChannelId: messageChannel.id, }); await this.messagingPartialMessageListFetchService.processMessageListFetch( messageChannel, - connectedAccount, + messageChannel.connectedAccount, workspaceId, ); await this.messagingTelemetryService.track({ eventName: 'partial_message_list_fetch.completed', workspaceId, - connectedAccountId: connectedAccount.id, + connectedAccountId: messageChannel.connectedAccount.id, messageChannelId: messageChannel.id, }); @@ -121,26 +105,26 @@ export class MessagingMessageListFetchJob { case MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING: this.logger.log( - `Fetching full message list for workspace ${workspaceId} and account ${connectedAccount.id}`, + `Fetching full message list for workspace ${workspaceId} and account ${messageChannel.connectedAccount.id}`, ); await this.messagingTelemetryService.track({ eventName: 'full_message_list_fetch.started', workspaceId, - connectedAccountId: connectedAccount.id, + connectedAccountId: messageChannel.connectedAccount.id, messageChannelId: messageChannel.id, }); await this.messagingFullMessageListFetchService.processMessageListFetch( messageChannel, - connectedAccount, + messageChannel.connectedAccount, workspaceId, ); await this.messagingTelemetryService.track({ eventName: 'full_message_list_fetch.completed', workspaceId, - connectedAccountId: connectedAccount.id, + connectedAccountId: messageChannel.connectedAccount.id, messageChannelId: messageChannel.id, }); diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job.ts index a22e1b26a..f062400d1 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job.ts @@ -3,16 +3,12 @@ import { Scope } from '@nestjs/common'; import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { isThrottled } from 'src/modules/connected-account/utils/is-throttled'; import { MessageChannelSyncStage, MessageChannelWorkspaceEntity, } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; -import { MessageImportExceptionHandlerService } from 'src/modules/messaging/message-import-manager/services/message-import-exception-handler.service'; import { MessagingMessagesImportService } from 'src/modules/messaging/message-import-manager/services/messaging-messages-import.service'; import { MessagingTelemetryService } from 'src/modules/messaging/monitoring/services/messaging-telemetry.service'; @@ -27,12 +23,9 @@ export type MessagingMessagesImportJobData = { }) export class MessagingMessagesImportJob { constructor( - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, private readonly messagingMessagesImportService: MessagingMessagesImportService, private readonly messagingTelemetryService: MessagingTelemetryService, private readonly twentyORMManager: TwentyORMManager, - private readonly messageImportErrorHandlerService: MessageImportExceptionHandlerService, ) {} @Process(MessagingMessagesImportJob.name) @@ -56,6 +49,7 @@ export class MessagingMessagesImportJob { where: { id: messageChannelId, }, + relations: ['connectedAccount'], }); if (!messageChannel) { @@ -68,12 +62,6 @@ export class MessagingMessagesImportJob { return; } - const connectedAccount = - await this.connectedAccountRepository.getConnectedAccountOrThrow( - workspaceId, - messageChannel.connectedAccountId, - ); - if (!messageChannel?.isSyncEnabled) { return; } @@ -96,7 +84,7 @@ export class MessagingMessagesImportJob { await this.messagingMessagesImportService.processMessageBatchImport( messageChannel, - connectedAccount, + messageChannel.connectedAccount, workspaceId, ); diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-messages-import.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-messages-import.service.ts index 601744100..09c59c557 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-messages-import.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-messages-import.service.ts @@ -110,7 +110,6 @@ export class MessagingMessagesImportService { await this.emailAliasManagerService.refreshHandleAliases( connectedAccount, - workspaceId, ); messageIdsToFetch = await this.cacheStorage.setPop( diff --git a/packages/twenty-server/src/modules/messaging/message-participant-manager/jobs/messaging-create-company-and-contact-after-sync.job.ts b/packages/twenty-server/src/modules/messaging/message-participant-manager/jobs/messaging-create-company-and-contact-after-sync.job.ts index 8529ebaef..ee556d672 100644 --- a/packages/twenty-server/src/modules/messaging/message-participant-manager/jobs/messaging-create-company-and-contact-after-sync.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-participant-manager/jobs/messaging-create-company-and-contact-after-sync.job.ts @@ -6,9 +6,7 @@ import { Process } from 'src/engine/core-modules/message-queue/decorators/proces import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { CreateCompanyAndContactService } from 'src/modules/contact-creation-manager/services/create-company-and-contact.service'; import { MessageDirection } from 'src/modules/messaging/common/enums/message-direction.enum'; @@ -30,8 +28,6 @@ export class MessagingCreateCompanyAndContactAfterSyncJob { ); constructor( private readonly createCompanyAndContactService: CreateCompanyAndContactService, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, private readonly twentyORMManager: TwentyORMManager, ) {} @@ -63,10 +59,16 @@ export class MessagingCreateCompanyAndContactAfterSyncJob { return; } - const connectedAccount = await this.connectedAccountRepository.getById( - connectedAccountId, - workspaceId, - ); + const connectedAccountRepository = + await this.twentyORMManager.getRepository( + 'connectedAccount', + ); + + const connectedAccount = await connectedAccountRepository.findOne({ + where: { + id: connectedAccountId, + }, + }); if (!connectedAccount) { throw new Error(