diff --git a/packages/twenty-server/src/workspace/messaging/services/fetch-workspace-messages.module.ts b/packages/twenty-server/src/workspace/messaging/services/fetch-workspace-messages.module.ts index c4c394b2f..fadcb1024 100644 --- a/packages/twenty-server/src/workspace/messaging/services/fetch-workspace-messages.module.ts +++ b/packages/twenty-server/src/workspace/messaging/services/fetch-workspace-messages.module.ts @@ -5,10 +5,15 @@ import { EnvironmentModule } from 'src/integrations/environment/environment.modu import { DataSourceModule } from 'src/metadata/data-source/data-source.module'; import { FetchBatchMessagesService } from 'src/workspace/messaging/services/fetch-batch-messages.service'; import { FetchWorkspaceMessagesService } from 'src/workspace/messaging/services/fetch-workspace-messages.service'; +import { RefreshAccessTokenService } from 'src/workspace/messaging/services/refresh-access-token.service'; @Module({ imports: [TypeORMModule, DataSourceModule, EnvironmentModule], - providers: [FetchWorkspaceMessagesService, FetchBatchMessagesService], + providers: [ + FetchWorkspaceMessagesService, + FetchBatchMessagesService, + RefreshAccessTokenService, + ], exports: [FetchWorkspaceMessagesService], }) export class FetchWorkspaceMessagesModule {} diff --git a/packages/twenty-server/src/workspace/messaging/services/fetch-workspace-messages.service.ts b/packages/twenty-server/src/workspace/messaging/services/fetch-workspace-messages.service.ts index 61e4ade85..5eac5c618 100644 --- a/packages/twenty-server/src/workspace/messaging/services/fetch-workspace-messages.service.ts +++ b/packages/twenty-server/src/workspace/messaging/services/fetch-workspace-messages.service.ts @@ -11,6 +11,7 @@ import { FetchBatchMessagesService } from 'src/workspace/messaging/services/fetc import { GmailMessage } from 'src/workspace/messaging/types/gmailMessage'; import { MessageOrThreadQuery } from 'src/workspace/messaging/types/messageOrThreadQuery'; import { DataSourceEntity } from 'src/metadata/data-source/data-source.entity'; +import { RefreshAccessTokenService } from 'src/workspace/messaging/services/refresh-access-token.service'; @Injectable() export class FetchWorkspaceMessagesService { @@ -19,9 +20,14 @@ export class FetchWorkspaceMessagesService { private readonly dataSourceService: DataSourceService, private readonly typeORMService: TypeORMService, private readonly fetchBatchMessagesService: FetchBatchMessagesService, + private readonly refreshAccessTokenService: RefreshAccessTokenService, ) {} async fetchWorkspaceMessages(workspaceId: string): Promise { + await this.refreshAccessTokenService.refreshAndSaveAccessToken( + workspaceId, + '20202020-0687-4c41-b707-ed1bfca972a7', + ); await this.fetchWorkspaceMemberThreads( workspaceId, '20202020-0687-4c41-b707-ed1bfca972a7', diff --git a/packages/twenty-server/src/workspace/messaging/services/refresh-access-token.service.ts b/packages/twenty-server/src/workspace/messaging/services/refresh-access-token.service.ts new file mode 100644 index 000000000..17828ffff --- /dev/null +++ b/packages/twenty-server/src/workspace/messaging/services/refresh-access-token.service.ts @@ -0,0 +1,75 @@ +import { Injectable } from '@nestjs/common'; + +import axios from 'axios'; + +import { TypeORMService } from 'src/database/typeorm/typeorm.service'; +import { EnvironmentService } from 'src/integrations/environment/environment.service'; +import { DataSourceService } from 'src/metadata/data-source/data-source.service'; + +@Injectable() +export class RefreshAccessTokenService { + constructor( + private readonly environmentService: EnvironmentService, + private readonly dataSourceService: DataSourceService, + private readonly typeORMService: TypeORMService, + ) {} + + async refreshAndSaveAccessToken( + workspaceId: string, + workspaceMemberId: string, + ): Promise { + const dataSourceMetadata = + await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail( + workspaceId, + ); + + const workspaceDataSource = await this.typeORMService.connectToDataSource( + dataSourceMetadata, + ); + + if (!workspaceDataSource) { + throw new Error('No workspace data source found'); + } + + const connectedAccounts = await workspaceDataSource?.query( + `SELECT * FROM ${dataSourceMetadata.schema}."connectedAccount" WHERE "provider" = 'gmail' AND "accountOwnerId" = $1`, + [workspaceMemberId], + ); + + if (!connectedAccounts || connectedAccounts.length === 0) { + throw new Error('No connected account found'); + } + + const refreshToken = connectedAccounts[0]?.refreshToken; + + if (!refreshToken) { + throw new Error('No refresh token found'); + } + + const accessToken = await this.refreshAccessToken(refreshToken); + + await workspaceDataSource?.query( + `UPDATE ${dataSourceMetadata.schema}."connectedAccount" SET "accessToken" = $1 WHERE "id" = $2`, + [accessToken, connectedAccounts[0].id], + ); + } + + async refreshAccessToken(refreshToken: string): Promise { + const response = await axios.post( + 'https://oauth2.googleapis.com/token', + { + client_id: this.environmentService.getAuthGoogleClientId(), + client_secret: this.environmentService.getAuthGoogleClientSecret(), + refresh_token: refreshToken, + grant_type: 'refresh_token', + }, + { + headers: { + 'Content-Type': 'application/json', + }, + }, + ); + + return response.data.access_token; + } +}