Google OAuth check real permissions before creating channels (#17714)
This commit is contained in:
@@ -19,6 +19,7 @@ import { CreateCalendarChannelService } from 'src/engine/core-modules/auth/servi
|
||||
import { CreateConnectedAccountService } from 'src/engine/core-modules/auth/services/create-connected-account.service';
|
||||
import { CreateMessageChannelService } from 'src/engine/core-modules/auth/services/create-message-channel.service';
|
||||
import { GoogleAPIScopesService } from 'src/engine/core-modules/auth/services/google-apis-scopes';
|
||||
import { GoogleApisServiceAvailabilityService } from 'src/engine/core-modules/auth/services/google-apis-service-availability.service';
|
||||
import { GoogleAPIsService } from 'src/engine/core-modules/auth/services/google-apis.service';
|
||||
import { MicrosoftAPIsService } from 'src/engine/core-modules/auth/services/microsoft-apis.service';
|
||||
import { ResetPasswordService } from 'src/engine/core-modules/auth/services/reset-password.service';
|
||||
@@ -131,6 +132,7 @@ import { JwtAuthStrategy } from './strategies/jwt.auth.strategy';
|
||||
AuthResolver,
|
||||
GoogleAPIsService,
|
||||
GoogleAPIScopesService,
|
||||
GoogleApisServiceAvailabilityService,
|
||||
MicrosoftAPIsService,
|
||||
AppTokenService,
|
||||
AccessTokenService,
|
||||
|
||||
+264
@@ -0,0 +1,264 @@
|
||||
import { Test, type TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { google } from 'googleapis';
|
||||
|
||||
import { GoogleApisServiceAvailabilityService } from 'src/engine/core-modules/auth/services/google-apis-service-availability.service';
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
|
||||
jest.mock('googleapis', () => ({
|
||||
google: {
|
||||
auth: {
|
||||
OAuth2: jest.fn().mockImplementation(() => ({
|
||||
setCredentials: jest.fn(),
|
||||
})),
|
||||
},
|
||||
gmail: jest.fn(),
|
||||
calendar: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('GoogleApisServiceAvailabilityService', () => {
|
||||
let service: GoogleApisServiceAvailabilityService;
|
||||
let mockTwentyConfigService: { get: jest.Mock };
|
||||
|
||||
beforeEach(async () => {
|
||||
mockTwentyConfigService = {
|
||||
get: jest.fn(),
|
||||
};
|
||||
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
GoogleApisServiceAvailabilityService,
|
||||
{
|
||||
provide: TwentyConfigService,
|
||||
useValue: mockTwentyConfigService,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
service = module.get<GoogleApisServiceAvailabilityService>(
|
||||
GoogleApisServiceAvailabilityService,
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('checkServicesAvailability', () => {
|
||||
it('should return both services available when Gmail and Calendar are enabled and accessible', async () => {
|
||||
mockTwentyConfigService.get.mockImplementation((key) => {
|
||||
if (key === 'AUTH_GOOGLE_CLIENT_ID') return 'client-id';
|
||||
if (key === 'AUTH_GOOGLE_CLIENT_SECRET') return 'client-secret';
|
||||
if (key === 'MESSAGING_PROVIDER_GMAIL_ENABLED') return true;
|
||||
if (key === 'CALENDAR_PROVIDER_GOOGLE_ENABLED') return true;
|
||||
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const mockGmailClient = {
|
||||
users: {
|
||||
getProfile: jest.fn().mockResolvedValue({ data: {} }),
|
||||
},
|
||||
};
|
||||
|
||||
const mockCalendarClient = {
|
||||
events: {
|
||||
list: jest.fn().mockResolvedValue({ data: {} }),
|
||||
},
|
||||
};
|
||||
|
||||
(google.gmail as jest.Mock).mockReturnValue(mockGmailClient);
|
||||
(google.calendar as jest.Mock).mockReturnValue(mockCalendarClient);
|
||||
|
||||
const result = await service.checkServicesAvailability('access-token');
|
||||
|
||||
expect(result).toEqual({
|
||||
isMessagingAvailable: true,
|
||||
isCalendarAvailable: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return messaging unavailable when messaging provider is disabled', async () => {
|
||||
mockTwentyConfigService.get.mockImplementation((key) => {
|
||||
if (key === 'AUTH_GOOGLE_CLIENT_ID') return 'client-id';
|
||||
if (key === 'AUTH_GOOGLE_CLIENT_SECRET') return 'client-secret';
|
||||
if (key === 'MESSAGING_PROVIDER_GMAIL_ENABLED') return false;
|
||||
if (key === 'CALENDAR_PROVIDER_GOOGLE_ENABLED') return true;
|
||||
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const mockCalendarClient = {
|
||||
events: {
|
||||
list: jest.fn().mockResolvedValue({ data: {} }),
|
||||
},
|
||||
};
|
||||
|
||||
(google.calendar as jest.Mock).mockReturnValue(mockCalendarClient);
|
||||
|
||||
const result = await service.checkServicesAvailability('access-token');
|
||||
|
||||
expect(result).toEqual({
|
||||
isMessagingAvailable: false,
|
||||
isCalendarAvailable: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return messaging unavailable when messaging service is not enabled in Google Workspace', async () => {
|
||||
mockTwentyConfigService.get.mockImplementation((key) => {
|
||||
if (key === 'AUTH_GOOGLE_CLIENT_ID') return 'client-id';
|
||||
if (key === 'AUTH_GOOGLE_CLIENT_SECRET') return 'client-secret';
|
||||
if (key === 'MESSAGING_PROVIDER_GMAIL_ENABLED') return true;
|
||||
if (key === 'CALENDAR_PROVIDER_GOOGLE_ENABLED') return true;
|
||||
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const gmailServiceNotEnabledError = {
|
||||
response: {
|
||||
status: 400,
|
||||
data: {
|
||||
error: {
|
||||
code: 400,
|
||||
message: 'Mail service not enabled',
|
||||
errors: [
|
||||
{
|
||||
message: 'Mail service not enabled',
|
||||
domain: 'global',
|
||||
reason: 'failedPrecondition',
|
||||
},
|
||||
],
|
||||
status: 'FAILED_PRECONDITION',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const mockGmailClient = {
|
||||
users: {
|
||||
getProfile: jest.fn().mockRejectedValue(gmailServiceNotEnabledError),
|
||||
},
|
||||
};
|
||||
|
||||
const mockCalendarClient = {
|
||||
events: {
|
||||
list: jest.fn().mockResolvedValue({ data: {} }),
|
||||
},
|
||||
};
|
||||
|
||||
(google.gmail as jest.Mock).mockReturnValue(mockGmailClient);
|
||||
(google.calendar as jest.Mock).mockReturnValue(mockCalendarClient);
|
||||
|
||||
const result = await service.checkServicesAvailability('access-token');
|
||||
|
||||
expect(result).toEqual({
|
||||
isMessagingAvailable: false,
|
||||
isCalendarAvailable: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return Calendar unavailable when Calendar service is not enabled in Google Workspace', async () => {
|
||||
mockTwentyConfigService.get.mockImplementation((key) => {
|
||||
if (key === 'AUTH_GOOGLE_CLIENT_ID') return 'client-id';
|
||||
if (key === 'AUTH_GOOGLE_CLIENT_SECRET') return 'client-secret';
|
||||
if (key === 'MESSAGING_PROVIDER_GMAIL_ENABLED') return true;
|
||||
if (key === 'CALENDAR_PROVIDER_GOOGLE_ENABLED') return true;
|
||||
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const calendarServiceNotEnabledError = {
|
||||
response: {
|
||||
status: 400,
|
||||
data: {
|
||||
error: {
|
||||
code: 400,
|
||||
message: 'Calendar service not enabled',
|
||||
errors: [
|
||||
{
|
||||
message: 'Calendar service not enabled',
|
||||
domain: 'global',
|
||||
reason: 'failedPrecondition',
|
||||
},
|
||||
],
|
||||
status: 'FAILED_PRECONDITION',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const mockGmailClient = {
|
||||
users: {
|
||||
getProfile: jest.fn().mockResolvedValue({ data: {} }),
|
||||
},
|
||||
};
|
||||
|
||||
const mockCalendarClient = {
|
||||
events: {
|
||||
list: jest.fn().mockRejectedValue(calendarServiceNotEnabledError),
|
||||
},
|
||||
};
|
||||
|
||||
(google.gmail as jest.Mock).mockReturnValue(mockGmailClient);
|
||||
(google.calendar as jest.Mock).mockReturnValue(mockCalendarClient);
|
||||
|
||||
const result = await service.checkServicesAvailability('access-token');
|
||||
|
||||
expect(result).toEqual({
|
||||
isMessagingAvailable: true,
|
||||
isCalendarAvailable: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw error for non-service-availability related errors', async () => {
|
||||
mockTwentyConfigService.get.mockImplementation((key) => {
|
||||
if (key === 'AUTH_GOOGLE_CLIENT_ID') return 'client-id';
|
||||
if (key === 'AUTH_GOOGLE_CLIENT_SECRET') return 'client-secret';
|
||||
if (key === 'MESSAGING_PROVIDER_GMAIL_ENABLED') return true;
|
||||
if (key === 'CALENDAR_PROVIDER_GOOGLE_ENABLED') return true;
|
||||
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const rateLimitError = {
|
||||
response: {
|
||||
status: 429,
|
||||
data: {
|
||||
error: {
|
||||
code: 429,
|
||||
message: 'Rate Limit Exceeded',
|
||||
errors: [
|
||||
{
|
||||
message: 'Rate Limit Exceeded',
|
||||
domain: 'usageLimits',
|
||||
reason: 'rateLimitExceeded',
|
||||
},
|
||||
],
|
||||
status: 'RESOURCE_EXHAUSTED',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const mockGmailClient = {
|
||||
users: {
|
||||
getProfile: jest.fn().mockRejectedValue(rateLimitError),
|
||||
},
|
||||
};
|
||||
|
||||
const mockCalendarClient = {
|
||||
events: {
|
||||
list: jest.fn().mockResolvedValue({ data: {} }),
|
||||
},
|
||||
};
|
||||
|
||||
(google.gmail as jest.Mock).mockReturnValue(mockGmailClient);
|
||||
(google.calendar as jest.Mock).mockReturnValue(mockCalendarClient);
|
||||
|
||||
await expect(
|
||||
service.checkServicesAvailability('access-token'),
|
||||
).rejects.toMatchObject(rateLimitError);
|
||||
});
|
||||
});
|
||||
});
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { google } from 'googleapis';
|
||||
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
|
||||
export type GoogleApisServiceAvailability = {
|
||||
isMessagingAvailable: boolean;
|
||||
isCalendarAvailable: boolean;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class GoogleApisServiceAvailabilityService {
|
||||
private readonly logger = new Logger(
|
||||
GoogleApisServiceAvailabilityService.name,
|
||||
);
|
||||
|
||||
constructor(private readonly twentyConfigService: TwentyConfigService) {}
|
||||
|
||||
async checkServicesAvailability(
|
||||
accessToken: string,
|
||||
): Promise<GoogleApisServiceAvailability> {
|
||||
const oAuth2Client = new google.auth.OAuth2(
|
||||
this.twentyConfigService.get('AUTH_GOOGLE_CLIENT_ID'),
|
||||
this.twentyConfigService.get('AUTH_GOOGLE_CLIENT_SECRET'),
|
||||
);
|
||||
|
||||
oAuth2Client.setCredentials({
|
||||
access_token: accessToken,
|
||||
});
|
||||
|
||||
const [isMessagingAvailable, isCalendarAvailable] = await Promise.all([
|
||||
this.checkMessagingAvailability(oAuth2Client),
|
||||
this.checkCalendarAvailability(oAuth2Client),
|
||||
]);
|
||||
|
||||
return {
|
||||
isMessagingAvailable,
|
||||
isCalendarAvailable,
|
||||
};
|
||||
}
|
||||
|
||||
private async checkMessagingAvailability(
|
||||
oAuth2Client: InstanceType<typeof google.auth.OAuth2>,
|
||||
): Promise<boolean> {
|
||||
if (!this.twentyConfigService.get('MESSAGING_PROVIDER_GMAIL_ENABLED')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const gmailClient = google.gmail({
|
||||
version: 'v1',
|
||||
auth: oAuth2Client,
|
||||
});
|
||||
|
||||
await gmailClient.users.getProfile({ userId: 'me' });
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
if (this.isServiceNotEnabledError(error)) {
|
||||
this.logger.log(
|
||||
'Messaging service is not enabled for this Google Workspace account',
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
this.logger.error('Error checking messaging availability', error);
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private async checkCalendarAvailability(
|
||||
oAuth2Client: InstanceType<typeof google.auth.OAuth2>,
|
||||
): Promise<boolean> {
|
||||
if (!this.twentyConfigService.get('CALENDAR_PROVIDER_GOOGLE_ENABLED')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const calendarClient = google.calendar({
|
||||
version: 'v3',
|
||||
auth: oAuth2Client,
|
||||
});
|
||||
|
||||
await calendarClient.events.list({
|
||||
calendarId: 'primary',
|
||||
maxResults: 1,
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
if (this.isServiceNotEnabledError(error)) {
|
||||
this.logger.log(
|
||||
'Calendar service is not enabled for this Google Workspace account',
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
this.logger.error('Error checking Calendar availability', error);
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private isServiceNotEnabledError(error: unknown): boolean {
|
||||
const errorResponse = (
|
||||
error as { response?: { data?: { error?: unknown } } }
|
||||
)?.response?.data?.error;
|
||||
|
||||
if (!errorResponse || typeof errorResponse !== 'object') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const gmailError = errorResponse as {
|
||||
errors?: Array<{ reason?: string; message?: string }>;
|
||||
};
|
||||
|
||||
const firstError = gmailError.errors?.[0];
|
||||
|
||||
if (!firstError) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const isFailedPrecondition = firstError.reason === 'failedPrecondition';
|
||||
const isServiceNotEnabled =
|
||||
firstError.message?.includes('service not enabled') ?? false;
|
||||
|
||||
return isFailedPrecondition && isServiceNotEnabled;
|
||||
}
|
||||
}
|
||||
+12
-2
@@ -7,6 +7,7 @@ import { CreateCalendarChannelService } from 'src/engine/core-modules/auth/servi
|
||||
import { CreateConnectedAccountService } from 'src/engine/core-modules/auth/services/create-connected-account.service';
|
||||
import { CreateMessageChannelService } from 'src/engine/core-modules/auth/services/create-message-channel.service';
|
||||
import { GoogleAPIScopesService } from 'src/engine/core-modules/auth/services/google-apis-scopes';
|
||||
import { GoogleApisServiceAvailabilityService } from 'src/engine/core-modules/auth/services/google-apis-service-availability.service';
|
||||
import { GoogleAPIsService } from 'src/engine/core-modules/auth/services/google-apis.service';
|
||||
import { UpdateConnectedAccountOnReconnectService } from 'src/engine/core-modules/auth/services/update-connected-account-on-reconnect.service';
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
@@ -127,6 +128,15 @@ describe('GoogleAPIsService', () => {
|
||||
}),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: GoogleApisServiceAvailabilityService,
|
||||
useValue: {
|
||||
checkServicesAvailability: jest.fn().mockResolvedValue({
|
||||
isMessagingAvailable: true,
|
||||
isCalendarAvailable: true,
|
||||
}),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: MessageChannelSyncStatusService,
|
||||
useValue: {
|
||||
@@ -238,11 +248,11 @@ describe('GoogleAPIsService', () => {
|
||||
|
||||
expect(
|
||||
calendarChannelSyncStatusService.resetAndMarkAsCalendarEventListFetchPending,
|
||||
).toHaveBeenCalledWith([existingConnectedAccount.id], 'workspace-id');
|
||||
).toHaveBeenCalledWith([failedCalendarChannel.id], 'workspace-id');
|
||||
|
||||
expect(
|
||||
messagingChannelSyncStatusService.resetAndMarkAsMessagesListFetchPending,
|
||||
).toHaveBeenCalledWith([existingConnectedAccount.id], 'workspace-id');
|
||||
).not.toHaveBeenCalled();
|
||||
|
||||
expect(
|
||||
createMessageChannelService.createMessageChannel,
|
||||
|
||||
+69
-48
@@ -11,6 +11,7 @@ import { CreateCalendarChannelService } from 'src/engine/core-modules/auth/servi
|
||||
import { CreateConnectedAccountService } from 'src/engine/core-modules/auth/services/create-connected-account.service';
|
||||
import { CreateMessageChannelService } from 'src/engine/core-modules/auth/services/create-message-channel.service';
|
||||
import { GoogleAPIScopesService } from 'src/engine/core-modules/auth/services/google-apis-scopes';
|
||||
import { GoogleApisServiceAvailabilityService } from 'src/engine/core-modules/auth/services/google-apis-service-availability.service';
|
||||
import { UpdateConnectedAccountOnReconnectService } from 'src/engine/core-modules/auth/services/update-connected-account-on-reconnect.service';
|
||||
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';
|
||||
@@ -34,6 +35,7 @@ import { type ConnectedAccountWorkspaceEntity } from 'src/modules/connected-acco
|
||||
import { MessageChannelSyncStatusService } from 'src/modules/messaging/common/services/message-channel-sync-status.service';
|
||||
import {
|
||||
MessageChannelSyncStage,
|
||||
MessageChannelSyncStatus,
|
||||
type MessageChannelVisibility,
|
||||
type MessageChannelWorkspaceEntity,
|
||||
} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||
@@ -60,6 +62,7 @@ export class GoogleAPIsService {
|
||||
private readonly createConnectedAccountService: CreateConnectedAccountService,
|
||||
private readonly updateConnectedAccountOnReconnectService: UpdateConnectedAccountOnReconnectService,
|
||||
private readonly googleAPIScopesService: GoogleAPIScopesService,
|
||||
private readonly googleApisServiceAvailabilityService: GoogleApisServiceAvailabilityService,
|
||||
) {}
|
||||
|
||||
async refreshGoogleRefreshToken(input: {
|
||||
@@ -85,6 +88,10 @@ export class GoogleAPIsService {
|
||||
'CALENDAR_PROVIDER_GOOGLE_ENABLED',
|
||||
);
|
||||
|
||||
const isMessagingEnabled = this.twentyConfigService.get(
|
||||
'MESSAGING_PROVIDER_GMAIL_ENABLED',
|
||||
);
|
||||
|
||||
const { scopes, isValid } =
|
||||
await this.googleAPIScopesService.getScopesFromGoogleAccessTokenAndCheckIfExpectedScopesArePresent(
|
||||
input.accessToken,
|
||||
@@ -97,6 +104,11 @@ export class GoogleAPIsService {
|
||||
);
|
||||
}
|
||||
|
||||
const { isMessagingAvailable, isCalendarAvailable } =
|
||||
await this.googleApisServiceAvailabilityService.checkServicesAvailability(
|
||||
input.accessToken,
|
||||
);
|
||||
|
||||
const authContext = buildSystemAuthContext(workspaceId);
|
||||
|
||||
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
|
||||
@@ -144,16 +156,18 @@ export class GoogleAPIsService {
|
||||
manager,
|
||||
});
|
||||
|
||||
await this.createMessageChannelService.createMessageChannel({
|
||||
workspaceId,
|
||||
connectedAccountId: newOrExistingConnectedAccountId,
|
||||
handle,
|
||||
messageVisibility,
|
||||
manager,
|
||||
skipMessageChannelConfiguration,
|
||||
});
|
||||
if (isMessagingEnabled && isMessagingAvailable) {
|
||||
await this.createMessageChannelService.createMessageChannel({
|
||||
workspaceId,
|
||||
connectedAccountId: newOrExistingConnectedAccountId,
|
||||
handle,
|
||||
messageVisibility,
|
||||
manager,
|
||||
skipMessageChannelConfiguration,
|
||||
});
|
||||
}
|
||||
|
||||
if (isCalendarEnabled) {
|
||||
if (isCalendarEnabled && isCalendarAvailable) {
|
||||
await this.createCalendarChannelService.createCalendarChannel({
|
||||
workspaceId,
|
||||
connectedAccountId: newOrExistingConnectedAccountId,
|
||||
@@ -195,62 +209,69 @@ export class GoogleAPIsService {
|
||||
workspaceId,
|
||||
newOrExistingConnectedAccountId,
|
||||
);
|
||||
|
||||
await this.messagingChannelSyncStatusService.resetAndMarkAsMessagesListFetchPending(
|
||||
[newOrExistingConnectedAccountId],
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.calendarChannelSyncStatusService.resetAndMarkAsCalendarEventListFetchPending(
|
||||
[newOrExistingConnectedAccountId],
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (this.twentyConfigService.get('MESSAGING_PROVIDER_GMAIL_ENABLED')) {
|
||||
if (isMessagingEnabled) {
|
||||
const messageChannels = await messageChannelRepository.find({
|
||||
where: {
|
||||
connectedAccountId: newOrExistingConnectedAccountId,
|
||||
},
|
||||
where: { connectedAccountId: newOrExistingConnectedAccountId },
|
||||
});
|
||||
|
||||
for (const messageChannel of messageChannels) {
|
||||
if (
|
||||
messageChannel.syncStage !==
|
||||
MessageChannelSyncStage.PENDING_CONFIGURATION
|
||||
) {
|
||||
await this.messageQueueService.add<MessagingMessageListFetchJobData>(
|
||||
MessagingMessageListFetchJob.name,
|
||||
{
|
||||
if (!isMessagingAvailable && messageChannels.length > 0) {
|
||||
await this.messagingChannelSyncStatusService.markAsFailed(
|
||||
messageChannels.map((channel) => channel.id),
|
||||
workspaceId,
|
||||
MessageChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS,
|
||||
);
|
||||
}
|
||||
|
||||
if (isMessagingAvailable) {
|
||||
for (const messageChannel of messageChannels) {
|
||||
if (
|
||||
messageChannel.syncStage !==
|
||||
MessageChannelSyncStage.PENDING_CONFIGURATION
|
||||
) {
|
||||
await this.messagingChannelSyncStatusService.resetAndMarkAsMessagesListFetchPending(
|
||||
[messageChannel.id],
|
||||
workspaceId,
|
||||
messageChannelId: messageChannel.id,
|
||||
},
|
||||
);
|
||||
);
|
||||
await this.messageQueueService.add<MessagingMessageListFetchJobData>(
|
||||
MessagingMessageListFetchJob.name,
|
||||
{ workspaceId, messageChannelId: messageChannel.id },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isCalendarEnabled) {
|
||||
const calendarChannels = await calendarChannelRepository.find({
|
||||
where: {
|
||||
connectedAccountId: newOrExistingConnectedAccountId,
|
||||
},
|
||||
where: { connectedAccountId: newOrExistingConnectedAccountId },
|
||||
});
|
||||
|
||||
for (const calendarChannel of calendarChannels) {
|
||||
if (
|
||||
calendarChannel.syncStage !==
|
||||
CalendarChannelSyncStage.PENDING_CONFIGURATION
|
||||
) {
|
||||
await this.calendarQueueService.add<CalendarEventListFetchJobData>(
|
||||
CalendarEventListFetchJob.name,
|
||||
{
|
||||
calendarChannelId: calendarChannel.id,
|
||||
if (!isCalendarAvailable && calendarChannels.length > 0) {
|
||||
await this.calendarChannelSyncStatusService.markAsFailedInsufficientPermissionsAndFlushCalendarEventsToImport(
|
||||
calendarChannels.map((channel) => channel.id),
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
|
||||
if (isCalendarAvailable) {
|
||||
for (const calendarChannel of calendarChannels) {
|
||||
if (
|
||||
calendarChannel.syncStage !==
|
||||
CalendarChannelSyncStage.PENDING_CONFIGURATION
|
||||
) {
|
||||
await this.calendarChannelSyncStatusService.resetAndMarkAsCalendarEventListFetchPending(
|
||||
[calendarChannel.id],
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
);
|
||||
await this.calendarQueueService.add<CalendarEventListFetchJobData>(
|
||||
CalendarEventListFetchJob.name,
|
||||
{ workspaceId, calendarChannelId: calendarChannel.id },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user