Skip to content

Commit

Permalink
feat: drop calendar repository (#5824)
Browse files Browse the repository at this point in the history
This PR is replacing and removing all the raw queries and repositories
with the new `TwentyORM` and injection system using
`@InjectWorkspaceRepository`.
Some logic that was contained inside repositories has been moved to the
services.
In this PR we're only replacing repositories for calendar feature.

---------

Co-authored-by: Weiko <[email protected]>
Co-authored-by: bosiraphael <[email protected]>
Co-authored-by: Charles Bochet <[email protected]>
  • Loading branch information
4 people authored Jun 22, 2024
1 parent 91b0c2b commit 0b4bfce
Show file tree
Hide file tree
Showing 90 changed files with 975 additions and 1,537 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ export class AnalyticsService {

async create(
createEventInput: CreateEventInput,
userId: string | undefined,
workspaceId: string | undefined,
userId: string | null | undefined,
workspaceId: string | null | undefined,
workspaceDisplayName: string | undefined,
workspaceDomainName: string | undefined,
hostName: string | undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/s
import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-channel.workspace-entity';
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
import { OnboardingModule } from 'src/engine/core-modules/onboarding/onboarding.module';
import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';

import { AuthResolver } from './auth.resolver';

Expand Down Expand Up @@ -60,11 +62,12 @@ const jwtModule = JwtModule.registerAsync({
ObjectMetadataRepositoryModule.forFeature([
ConnectedAccountWorkspaceEntity,
MessageChannelWorkspaceEntity,
CalendarChannelWorkspaceEntity,
]),
HttpModule,
UserWorkspaceModule,
OnboardingModule,
TwentyORMModule.forFeature([CalendarChannelWorkspaceEntity]),
WorkspaceDataSourceModule,
],
controllers: [
GoogleAuthController,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ export class AuthResolver {
}
const transientToken = await this.tokenService.generateTransientToken(
workspaceMember.id,
user.id,
user.defaultWorkspace.id,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ import { GoogleAPIsService } from 'src/engine/core-modules/auth/services/google-
import { TokenService } from 'src/engine/core-modules/auth/services/token.service';
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service';
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 { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
import { LoadServiceWithWorkspaceContext } from 'src/engine/twenty-orm/context/load-service-with-workspace.context';

@Controller('auth/google-apis')
export class GoogleAPIsAuthController {
Expand All @@ -27,8 +25,7 @@ export class GoogleAPIsAuthController {
private readonly tokenService: TokenService,
private readonly environmentService: EnvironmentService,
private readonly onboardingService: OnboardingService,
@InjectObjectMetadataRepository(WorkspaceMemberWorkspaceEntity)
private readonly workspaceMemberService: WorkspaceMemberRepository,
private readonly loadServiceWithWorkspaceContext: LoadServiceWithWorkspaceContext,
) {}

@Get()
Expand Down Expand Up @@ -56,7 +53,7 @@ export class GoogleAPIsAuthController {
messageVisibility,
} = user;

const { workspaceMemberId, workspaceId } =
const { workspaceMemberId, userId, workspaceId } =
await this.tokenService.verifyTransientToken(transientToken);

const demoWorkspaceIds = this.environmentService.get('DEMO_WORKSPACE_IDS');
Expand All @@ -71,7 +68,13 @@ export class GoogleAPIsAuthController {
throw new Error('Workspace not found');
}

await this.googleAPIsService.refreshGoogleRefreshToken({
const googleAPIsServiceInstance =
await this.loadServiceWithWorkspaceContext.load(
this.googleAPIsService,
workspaceId,
);

await googleAPIsServiceInstance.refreshGoogleRefreshToken({
handle: email,
workspaceMemberId: workspaceMemberId,
workspaceId: workspaceId,
Expand All @@ -81,12 +84,14 @@ export class GoogleAPIsAuthController {
messageVisibility,
});

const userId = (
await this.workspaceMemberService.find(workspaceMemberId, workspaceId)
)?.userId;

if (userId) {
await this.onboardingService.skipSyncEmailOnboardingStep(
const onboardingServiceInstance =
await this.loadServiceWithWorkspaceContext.load(
this.onboardingService,
workspaceId,
);

await onboardingServiceInstance.skipSyncEmailOnboardingStep(
userId,
workspaceId,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,14 @@ import { Injectable } from '@nestjs/common';
import { EntityManager } from 'typeorm';
import { v4 } from 'uuid';

import { TypeORMService } from 'src/database/typeorm/typeorm.service';
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
import {
GoogleCalendarSyncJobData,
GoogleCalendarSyncJob,
} from 'src/modules/calendar/jobs/google-calendar-sync.job';
import { CalendarChannelRepository } from 'src/modules/calendar/repositories/calendar-channel.repository';
import {
CalendarChannelWorkspaceEntity,
CalendarChannelVisibility,
Expand All @@ -35,12 +32,16 @@ import {
MessagingMessageListFetchJobData,
} from 'src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job';
import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator';
import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
import { InjectWorkspaceDatasource } from 'src/engine/twenty-orm/decorators/inject-workspace-datasource.decorator';

@Injectable()
export class GoogleAPIsService {
constructor(
private readonly dataSourceService: DataSourceService,
private readonly typeORMService: TypeORMService,
@InjectWorkspaceDatasource()
private readonly workspaceDataSource: WorkspaceDataSource,
@InjectMessageQueue(MessageQueue.messagingQueue)
private readonly messageQueueService: MessageQueueService,
@InjectMessageQueue(MessageQueue.calendarQueue)
Expand All @@ -50,8 +51,8 @@ export class GoogleAPIsService {
private readonly connectedAccountRepository: ConnectedAccountRepository,
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
private readonly messageChannelRepository: MessageChannelRepository,
@InjectObjectMetadataRepository(CalendarChannelWorkspaceEntity)
private readonly calendarChannelRepository: CalendarChannelRepository,
@InjectWorkspaceRepository(CalendarChannelWorkspaceEntity)
private readonly calendarChannelRepository: WorkspaceRepository<CalendarChannelWorkspaceEntity>,
) {}

async refreshGoogleRefreshToken(input: {
Expand All @@ -71,14 +72,6 @@ export class GoogleAPIsService {
messageVisibility,
} = input;

const dataSourceMetadata =
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail(
workspaceId,
);

const workspaceDataSource =
await this.typeORMService.connectToDataSource(dataSourceMetadata);

const isCalendarEnabled = this.environmentService.get(
'CALENDAR_PROVIDER_GOOGLE_ENABLED',
);
Expand All @@ -93,65 +86,67 @@ export class GoogleAPIsService {
const existingAccountId = connectedAccounts?.[0]?.id;
const newOrExistingConnectedAccountId = existingAccountId ?? v4();

await workspaceDataSource?.transaction(async (manager: EntityManager) => {
if (!existingAccountId) {
await this.connectedAccountRepository.create(
{
id: newOrExistingConnectedAccountId,
handle,
provider: ConnectedAccountProvider.GOOGLE,
accessToken: input.accessToken,
refreshToken: input.refreshToken,
accountOwnerId: workspaceMemberId,
},
workspaceId,
manager,
);

await this.messageChannelRepository.create(
{
id: v4(),
connectedAccountId: newOrExistingConnectedAccountId,
type: MessageChannelType.EMAIL,
handle,
visibility:
messageVisibility || MessageChannelVisibility.SHARE_EVERYTHING,
syncStatus: MessageChannelSyncStatus.ONGOING,
},
workspaceId,
manager,
);
await this.workspaceDataSource.transaction(
async (manager: EntityManager) => {
if (!existingAccountId) {
await this.connectedAccountRepository.create(
{
id: newOrExistingConnectedAccountId,
handle,
provider: ConnectedAccountProvider.GOOGLE,
accessToken: input.accessToken,
refreshToken: input.refreshToken,
accountOwnerId: workspaceMemberId,
},
workspaceId,
manager,
);

if (isCalendarEnabled) {
await this.calendarChannelRepository.create(
await this.messageChannelRepository.create(
{
id: v4(),
connectedAccountId: newOrExistingConnectedAccountId,
type: MessageChannelType.EMAIL,
handle,
visibility:
calendarVisibility ||
CalendarChannelVisibility.SHARE_EVERYTHING,
messageVisibility || MessageChannelVisibility.SHARE_EVERYTHING,
syncStatus: MessageChannelSyncStatus.ONGOING,
},
workspaceId,
manager,
);
}
} else {
await this.connectedAccountRepository.updateAccessTokenAndRefreshToken(
input.accessToken,
input.refreshToken,
newOrExistingConnectedAccountId,
workspaceId,
manager,
);

await this.messageChannelRepository.resetSync(
newOrExistingConnectedAccountId,
workspaceId,
manager,
);
}
});
if (isCalendarEnabled) {
await this.calendarChannelRepository.save(
{
id: v4(),
connectedAccountId: newOrExistingConnectedAccountId,
handle,
visibility:
calendarVisibility ||
CalendarChannelVisibility.SHARE_EVERYTHING,
},
{},
manager,
);
}
} else {
await this.connectedAccountRepository.updateAccessTokenAndRefreshToken(
input.accessToken,
input.refreshToken,
newOrExistingConnectedAccountId,
workspaceId,
manager,
);

await this.messageChannelRepository.resetSync(
newOrExistingConnectedAccountId,
workspaceId,
manager,
);
}
},
);

if (this.environmentService.get('MESSAGING_PROVIDER_GMAIL_ENABLED')) {
const messageChannels =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ export class TokenService {

async generateTransientToken(
workspaceMemberId: string,
userId: string,
workspaceId: string,
): Promise<AuthToken> {
const secret = this.environmentService.get('LOGIN_TOKEN_SECRET');
Expand All @@ -158,6 +159,7 @@ export class TokenService {
const expiresAt = addMilliseconds(new Date().getTime(), ms(expiresIn));
const jwtPayload = {
sub: workspaceMemberId,
userId,
workspaceId,
};

Expand Down Expand Up @@ -234,6 +236,7 @@ export class TokenService {

async verifyTransientToken(transientToken: string): Promise<{
workspaceMemberId: string;
userId: string;
workspaceId: string;
}> {
const transientTokenSecret =
Expand All @@ -243,6 +246,7 @@ export class TokenService {

return {
workspaceMemberId: payload.sub,
userId: payload.userId,
workspaceId: payload.workspaceId,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,7 @@ export class BillingService {
: frontBaseUrl;

const quantity =
(await this.userWorkspaceService.getWorkspaceMemberCount(
user.defaultWorkspaceId,
)) || 1;
(await this.userWorkspaceService.getWorkspaceMemberCount()) || 1;

const stripeCustomerId = (
await this.billingSubscriptionRepository.findOneBy({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Logger } from '@nestjs/common';
import { Logger, Scope } from '@nestjs/common';

import { BillingService } from 'src/engine/core-modules/billing/billing.service';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
Expand All @@ -8,7 +8,10 @@ import { MessageQueue } from 'src/engine/integrations/message-queue/message-queu
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
export type UpdateSubscriptionJobData = { workspaceId: string };

@Processor(MessageQueue.billingQueue)
@Processor({
queueName: MessageQueue.billingQueue,
scope: Scope.REQUEST,
})
export class UpdateSubscriptionJob {
protected readonly logger = new Logger(UpdateSubscriptionJob.name);

Expand All @@ -21,7 +24,7 @@ export class UpdateSubscriptionJob {
@Process(UpdateSubscriptionJob.name)
async handle(data: UpdateSubscriptionJobData): Promise<void> {
const workspaceMembersCount =
await this.userWorkspaceService.getWorkspaceMemberCount(data.workspaceId);
await this.userWorkspaceService.getWorkspaceMemberCount();

if (!workspaceMembersCount || workspaceMembersCount <= 0) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/
@ObjectType('TimelineCalendarEventParticipant')
export class TimelineCalendarEventParticipant {
@Field(() => UUIDScalarType, { nullable: true })
personId: string;
personId: string | null;

@Field(() => UUIDScalarType, { nullable: true })
workspaceMemberId: string;
workspaceMemberId: string | null;

@Field()
firstName: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,19 +81,19 @@ export class TimelineCalendarEventService {
const participants = event.calendarEventParticipants.map(
(participant) => ({
calendarEventId: event.id,
personId: participant.person?.id,
workspaceMemberId: participant.workspaceMember?.id,
personId: participant.person?.id ?? null,
workspaceMemberId: participant.workspaceMember?.id ?? null,
firstName:
participant.person?.name.firstName ||
participant.person?.name?.firstName ||
participant.workspaceMember?.name.firstName ||
'',
lastName:
participant.person?.name.lastName ||
participant.person?.name?.lastName ||
participant.workspaceMember?.name.lastName ||
'',
displayName:
participant.person?.name.firstName ||
participant.person?.name.lastName ||
participant.person?.name?.firstName ||
participant.person?.name?.lastName ||
participant.workspaceMember?.name.firstName ||
participant.workspaceMember?.name.lastName ||
'',
Expand Down
Loading

0 comments on commit 0b4bfce

Please sign in to comment.