From 458e8c839f3f989a0727f75b302e6291c75b5d91 Mon Sep 17 00:00:00 2001 From: Weiko Date: Tue, 13 Feb 2024 18:23:29 +0100 Subject: [PATCH] Add workspacePreQueryHook module (#3879) * rebase * reorganise messaging folders * fix * fix after review * fix yarn lock --- packages/twenty-server/package.json | 1 + .../src/core/auth/services/token.service.ts | 7 +- .../src/core/auth/types/jwt-data.type.ts | 7 ++ .../graphql-config/graphql-config.service.ts | 10 +- .../integrations/message-queue/jobs.module.ts | 6 +- ...ch-all-workspaces-messages.cron.pattern.ts | 0 .../fetch-all-workspaces-messages.job.ts | 2 +- ...etch-workspace-messages-commands.module.ts | 2 +- .../commands/gmail-full-sync.command.ts | 2 +- .../commands/gmail-partial-sync.command.ts | 2 +- ...ch-all-workspaces-messages.cron.command.ts | 4 +- ...ch-all-workspaces-messages.cron.command.ts | 4 +- ...message-channel-message-association.job.ts | 2 +- .../jobs/match-message-participant.job.ts | 2 +- .../workspace/messaging/messaging.module.ts | 23 ++--- .../message-find-many.pre-query.hook.ts | 94 +++++++++++++++++++ .../message-find-one.pre-query-hook.ts | 16 ++++ .../messaging-query-hook.module.ts | 28 ++++++ .../connected-account.module.ts | 2 +- .../connected-account.service.ts | 20 +++- ...ssage-channel-message-assocation.module.ts | 2 +- ...age-channel-message-association.service.ts | 17 ++++ .../message-channel/message-channel.module.ts | 2 +- .../message-channel.service.ts | 16 ++++ .../message-participant.module.ts | 6 +- .../message-participant.service.ts | 4 +- .../message-thread/message-thread.module.ts | 4 +- .../message-thread/message-thread.service.ts | 2 +- .../message/message.module.ts | 8 +- .../message/message.service.ts | 7 +- .../workspace-member.module.ts | 12 +++ .../workspace-member.service.ts | 50 ++++++++++ .../create-company/create-company.module.ts | 2 +- .../create-company/create-company.service.ts | 0 .../create-contact/create-contact.module.ts | 2 +- .../create-contact/create-contact.service.ts | 0 .../services/gmail-full-sync.service.ts | 10 +- .../services/gmail-partial-sync.service.ts | 8 +- .../gmail-refresh-access-token.service.ts | 2 +- .../providers/gmail/gmail-client.provider.ts | 0 .../providers/messaging-providers.module.ts | 2 +- .../query-runner-option.interface.ts | 1 + .../workspace-pre-query-hook.interface.ts | 9 ++ .../types/workspace-query-hook.type.ts | 48 ++++++++++ .../workspace-pre-query-hook.config.ts | 11 +++ .../workspace-pre-query-hook.module.ts | 11 +++ .../workspace-pre-query-hook.service.ts | 34 +++++++ .../workspace-query-runner.module.ts | 7 +- .../workspace-query-runner.service.ts | 27 +++++- .../factories/create-many-resolver.factory.ts | 1 + .../factories/create-one-resolver.factory.ts | 1 + .../factories/delete-many-resolver.factory.ts | 1 + .../factories/delete-one-resolver.factory.ts | 1 + ...te-quick-action-on-one-resolver.factory.ts | 1 + .../factories/find-many-resolver.factory.ts | 1 + .../factories/find-one-resolver.factory.ts | 1 + .../factories/update-many-resolver.factory.ts | 1 + .../factories/update-one-resolver.factory.ts | 1 + .../workspace-resolvers-builder.interface.ts | 10 ++ .../workspace-resolver.factory.ts | 3 + ...kspace-schema-builder-context.interface.ts | 1 + .../src/workspace/workspace.factory.ts | 2 + yarn.lock | 1 + 63 files changed, 494 insertions(+), 70 deletions(-) create mode 100644 packages/twenty-server/src/core/auth/types/jwt-data.type.ts rename packages/twenty-server/src/workspace/messaging/{ => commands}/crons/fetch-all-workspaces-messages.cron.pattern.ts (100%) rename packages/twenty-server/src/workspace/messaging/{ => commands}/crons/fetch-all-workspaces-messages.job.ts (97%) create mode 100644 packages/twenty-server/src/workspace/messaging/query-hooks/message/message-find-many.pre-query.hook.ts create mode 100644 packages/twenty-server/src/workspace/messaging/query-hooks/message/message-find-one.pre-query-hook.ts create mode 100644 packages/twenty-server/src/workspace/messaging/query-hooks/messaging-query-hook.module.ts rename packages/twenty-server/src/workspace/messaging/{ => repositories}/connected-account/connected-account.module.ts (86%) rename packages/twenty-server/src/workspace/messaging/{ => repositories}/connected-account/connected-account.service.ts (80%) rename packages/twenty-server/src/workspace/messaging/{ => repositories}/message-channel-message-association/message-channel-message-assocation.module.ts (79%) rename packages/twenty-server/src/workspace/messaging/{ => repositories}/message-channel-message-association/message-channel-message-association.service.ts (90%) rename packages/twenty-server/src/workspace/messaging/{ => repositories}/message-channel/message-channel.module.ts (72%) rename packages/twenty-server/src/workspace/messaging/{ => repositories}/message-channel/message-channel.service.ts (76%) rename packages/twenty-server/src/workspace/messaging/{ => repositories}/message-participant/message-participant.module.ts (61%) rename packages/twenty-server/src/workspace/messaging/{ => repositories}/message-participant/message-participant.service.ts (96%) rename packages/twenty-server/src/workspace/messaging/{ => repositories}/message-thread/message-thread.module.ts (65%) rename packages/twenty-server/src/workspace/messaging/{ => repositories}/message-thread/message-thread.service.ts (94%) rename packages/twenty-server/src/workspace/messaging/{ => repositories}/message/message.module.ts (58%) rename packages/twenty-server/src/workspace/messaging/{ => repositories}/message/message.service.ts (97%) create mode 100644 packages/twenty-server/src/workspace/messaging/repositories/workspace-member/workspace-member.module.ts create mode 100644 packages/twenty-server/src/workspace/messaging/repositories/workspace-member/workspace-member.service.ts rename packages/twenty-server/src/workspace/messaging/{ => services}/create-company/create-company.module.ts (61%) rename packages/twenty-server/src/workspace/messaging/{ => services}/create-company/create-company.service.ts (100%) rename packages/twenty-server/src/workspace/messaging/{ => services}/create-contact/create-contact.module.ts (61%) rename packages/twenty-server/src/workspace/messaging/{ => services}/create-contact/create-contact.service.ts (100%) rename packages/twenty-server/src/workspace/messaging/{ => services}/providers/gmail/gmail-client.provider.ts (100%) rename packages/twenty-server/src/workspace/messaging/{ => services}/providers/messaging-providers.module.ts (72%) create mode 100644 packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface.ts create mode 100644 packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/types/workspace-query-hook.type.ts create mode 100644 packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config.ts create mode 100644 packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module.ts create mode 100644 packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.service.ts diff --git a/packages/twenty-server/package.json b/packages/twenty-server/package.json index 02e6d1239..d7060c0cc 100644 --- a/packages/twenty-server/package.json +++ b/packages/twenty-server/package.json @@ -81,6 +81,7 @@ "graphql-upload": "^13.0.0", "graphql-yoga": "^4.0.4", "lodash.camelcase": "^4.3.0", + "lodash.groupby": "^4.6.0", "lodash.isempty": "^4.4.0", "lodash.isobject": "^3.0.2", "lodash.kebabcase": "^4.1.1", diff --git a/packages/twenty-server/src/core/auth/services/token.service.ts b/packages/twenty-server/src/core/auth/services/token.service.ts index 96a87d7bf..0c27dc043 100644 --- a/packages/twenty-server/src/core/auth/services/token.service.ts +++ b/packages/twenty-server/src/core/auth/services/token.service.ts @@ -34,11 +34,11 @@ import { import { EnvironmentService } from 'src/integrations/environment/environment.service'; import { User } from 'src/core/user/user.entity'; import { RefreshToken } from 'src/core/refresh-token/refresh-token.entity'; -import { Workspace } from 'src/core/workspace/workspace.entity'; import { ValidatePasswordResetToken } from 'src/core/auth/dto/validate-password-reset-token.entity'; import { EmailService } from 'src/integrations/email/email.service'; import { InvalidatePassword } from 'src/core/auth/dto/invalidate-password.entity'; import { EmailPasswordResetLink } from 'src/core/auth/dto/email-password-reset-link.entity'; +import { JwtData } from 'src/core/auth/types/jwt-data.type'; @Injectable() export class TokenService { @@ -192,10 +192,7 @@ export class TokenService { return !!token; } - async validateToken(request: Request): Promise<{ - user?: User; - workspace: Workspace; - }> { + async validateToken(request: Request): Promise { const token = ExtractJwt.fromAuthHeaderAsBearerToken()(request); if (!token) { diff --git a/packages/twenty-server/src/core/auth/types/jwt-data.type.ts b/packages/twenty-server/src/core/auth/types/jwt-data.type.ts new file mode 100644 index 000000000..c93ee8d9d --- /dev/null +++ b/packages/twenty-server/src/core/auth/types/jwt-data.type.ts @@ -0,0 +1,7 @@ +import { User } from 'src/core/user/user.entity'; +import { Workspace } from 'src/core/workspace/workspace.entity'; + +export type JwtData = { + user?: User | undefined; + workspace: Workspace; +}; diff --git a/packages/twenty-server/src/graphql-config/graphql-config.service.ts b/packages/twenty-server/src/graphql-config/graphql-config.service.ts index 9fddf661d..f999ee639 100644 --- a/packages/twenty-server/src/graphql-config/graphql-config.service.ts +++ b/packages/twenty-server/src/graphql-config/graphql-config.service.ts @@ -22,6 +22,7 @@ import { EnvironmentService } from 'src/integrations/environment/environment.ser import { useExceptionHandler } from 'src/integrations/exception-handler/hooks/use-exception-handler.hook'; import { User } from 'src/core/user/user.entity'; import { useThrottler } from 'src/integrations/throttler/hooks/use-throttler'; +import { JwtData } from 'src/core/auth/types/jwt-data.type'; import { CreateContextFactory } from './factories/create-context.factory'; @@ -60,7 +61,7 @@ export class GraphQLConfigService user = data.user; - return await this.createSchema(context, data.workspace); + return await this.createSchema(context, data); } catch (error) { if (error instanceof UnauthorizedException) { throw new GraphQLError('Unauthenticated', { @@ -125,7 +126,7 @@ export class GraphQLConfigService async createSchema( context: YogaDriverServerContext<'express'> & YogaInitialContext, - workspace: Workspace, + data: JwtData, ): Promise>> { // Create a new contextId for each request const contextId = ContextIdFactory.create(); @@ -142,6 +143,9 @@ export class GraphQLConfigService }, ); - return await workspaceFactory.createGraphQLSchema(workspace.id); + return await workspaceFactory.createGraphQLSchema( + data.workspace.id, + data.user?.id, + ); } } diff --git a/packages/twenty-server/src/integrations/message-queue/jobs.module.ts b/packages/twenty-server/src/integrations/message-queue/jobs.module.ts index e29b4579b..f8e474904 100644 --- a/packages/twenty-server/src/integrations/message-queue/jobs.module.ts +++ b/packages/twenty-server/src/integrations/message-queue/jobs.module.ts @@ -17,10 +17,10 @@ import { EmailSenderJob } from 'src/integrations/email/email-sender.job'; import { UserModule } from 'src/core/user/user.module'; import { EnvironmentModule } from 'src/integrations/environment/environment.module'; import { FeatureFlagEntity } from 'src/core/feature-flag/feature-flag.entity'; -import { FetchAllWorkspacesMessagesJob } from 'src/workspace/messaging/crons/fetch-all-workspaces-messages.job'; -import { ConnectedAccountModule } from 'src/workspace/messaging/connected-account/connected-account.module'; +import { FetchAllWorkspacesMessagesJob } from 'src/workspace/messaging/commands/crons/fetch-all-workspaces-messages.job'; +import { ConnectedAccountModule } from 'src/workspace/messaging/repositories/connected-account/connected-account.module'; import { MatchMessageParticipantJob } from 'src/workspace/messaging/jobs/match-message-participant.job'; -import { MessageParticipantModule } from 'src/workspace/messaging/message-participant/message-participant.module'; +import { MessageParticipantModule } from 'src/workspace/messaging/repositories/message-participant/message-participant.module'; @Module({ imports: [ diff --git a/packages/twenty-server/src/workspace/messaging/crons/fetch-all-workspaces-messages.cron.pattern.ts b/packages/twenty-server/src/workspace/messaging/commands/crons/fetch-all-workspaces-messages.cron.pattern.ts similarity index 100% rename from packages/twenty-server/src/workspace/messaging/crons/fetch-all-workspaces-messages.cron.pattern.ts rename to packages/twenty-server/src/workspace/messaging/commands/crons/fetch-all-workspaces-messages.cron.pattern.ts diff --git a/packages/twenty-server/src/workspace/messaging/crons/fetch-all-workspaces-messages.job.ts b/packages/twenty-server/src/workspace/messaging/commands/crons/fetch-all-workspaces-messages.job.ts similarity index 97% rename from packages/twenty-server/src/workspace/messaging/crons/fetch-all-workspaces-messages.job.ts rename to packages/twenty-server/src/workspace/messaging/commands/crons/fetch-all-workspaces-messages.job.ts index 4673daf1f..50b1c1820 100644 --- a/packages/twenty-server/src/workspace/messaging/crons/fetch-all-workspaces-messages.job.ts +++ b/packages/twenty-server/src/workspace/messaging/commands/crons/fetch-all-workspaces-messages.job.ts @@ -11,7 +11,7 @@ import { } from 'src/core/feature-flag/feature-flag.entity'; import { MessageQueue } from 'src/integrations/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/integrations/message-queue/services/message-queue.service'; -import { ConnectedAccountService } from 'src/workspace/messaging/connected-account/connected-account.service'; +import { ConnectedAccountService } from 'src/workspace/messaging/repositories/connected-account/connected-account.service'; import { GmailPartialSyncJobData, GmailPartialSyncJob, diff --git a/packages/twenty-server/src/workspace/messaging/commands/fetch-workspace-messages-commands.module.ts b/packages/twenty-server/src/workspace/messaging/commands/fetch-workspace-messages-commands.module.ts index fe2f56cb9..9e1dba862 100644 --- a/packages/twenty-server/src/workspace/messaging/commands/fetch-workspace-messages-commands.module.ts +++ b/packages/twenty-server/src/workspace/messaging/commands/fetch-workspace-messages-commands.module.ts @@ -6,7 +6,7 @@ import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; import { DataSourceModule } from 'src/metadata/data-source/data-source.module'; import { GmailFullSyncCommand } from 'src/workspace/messaging/commands/gmail-full-sync.command'; import { GmailPartialSyncCommand } from 'src/workspace/messaging/commands/gmail-partial-sync.command'; -import { ConnectedAccountModule } from 'src/workspace/messaging/connected-account/connected-account.module'; +import { ConnectedAccountModule } from 'src/workspace/messaging/repositories/connected-account/connected-account.module'; import { StartFetchAllWorkspacesMessagesCronCommand } from 'src/workspace/messaging/commands/start-fetch-all-workspaces-messages.cron.command'; import { StopFetchAllWorkspacesMessagesCronCommand } from 'src/workspace/messaging/commands/stop-fetch-all-workspaces-messages.cron.command'; diff --git a/packages/twenty-server/src/workspace/messaging/commands/gmail-full-sync.command.ts b/packages/twenty-server/src/workspace/messaging/commands/gmail-full-sync.command.ts index 15c460f49..eec592563 100644 --- a/packages/twenty-server/src/workspace/messaging/commands/gmail-full-sync.command.ts +++ b/packages/twenty-server/src/workspace/messaging/commands/gmail-full-sync.command.ts @@ -14,7 +14,7 @@ import { GmailFullSyncJobData, GmailFullSyncJob, } from 'src/workspace/messaging/jobs/gmail-full-sync.job'; -import { ConnectedAccountService } from 'src/workspace/messaging/connected-account/connected-account.service'; +import { ConnectedAccountService } from 'src/workspace/messaging/repositories/connected-account/connected-account.service'; interface GmailFullSyncOptions { workspaceId: string; diff --git a/packages/twenty-server/src/workspace/messaging/commands/gmail-partial-sync.command.ts b/packages/twenty-server/src/workspace/messaging/commands/gmail-partial-sync.command.ts index b64f93b2e..cdf7e4ef3 100644 --- a/packages/twenty-server/src/workspace/messaging/commands/gmail-partial-sync.command.ts +++ b/packages/twenty-server/src/workspace/messaging/commands/gmail-partial-sync.command.ts @@ -14,7 +14,7 @@ import { GmailPartialSyncJob, GmailPartialSyncJobData, } from 'src/workspace/messaging/jobs/gmail-partial-sync.job'; -import { ConnectedAccountService } from 'src/workspace/messaging/connected-account/connected-account.service'; +import { ConnectedAccountService } from 'src/workspace/messaging/repositories/connected-account/connected-account.service'; interface GmailPartialSyncOptions { workspaceId: string; diff --git a/packages/twenty-server/src/workspace/messaging/commands/start-fetch-all-workspaces-messages.cron.command.ts b/packages/twenty-server/src/workspace/messaging/commands/start-fetch-all-workspaces-messages.cron.command.ts index 0b0a970d7..04e4381ba 100644 --- a/packages/twenty-server/src/workspace/messaging/commands/start-fetch-all-workspaces-messages.cron.command.ts +++ b/packages/twenty-server/src/workspace/messaging/commands/start-fetch-all-workspaces-messages.cron.command.ts @@ -4,8 +4,8 @@ import { Command, CommandRunner } from 'nest-commander'; import { MessageQueue } from 'src/integrations/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/integrations/message-queue/services/message-queue.service'; -import { fetchAllWorkspacesMessagesCronPattern } from 'src/workspace/messaging/crons/fetch-all-workspaces-messages.cron.pattern'; -import { FetchAllWorkspacesMessagesJob } from 'src/workspace/messaging/crons/fetch-all-workspaces-messages.job'; +import { fetchAllWorkspacesMessagesCronPattern } from 'src/workspace/messaging/commands/crons/fetch-all-workspaces-messages.cron.pattern'; +import { FetchAllWorkspacesMessagesJob } from 'src/workspace/messaging/commands/crons/fetch-all-workspaces-messages.job'; @Command({ name: 'fetch-all-workspaces-messages:cron:start', diff --git a/packages/twenty-server/src/workspace/messaging/commands/stop-fetch-all-workspaces-messages.cron.command.ts b/packages/twenty-server/src/workspace/messaging/commands/stop-fetch-all-workspaces-messages.cron.command.ts index 2e2ce0126..418994c94 100644 --- a/packages/twenty-server/src/workspace/messaging/commands/stop-fetch-all-workspaces-messages.cron.command.ts +++ b/packages/twenty-server/src/workspace/messaging/commands/stop-fetch-all-workspaces-messages.cron.command.ts @@ -4,8 +4,8 @@ import { Command, CommandRunner } from 'nest-commander'; import { MessageQueue } from 'src/integrations/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/integrations/message-queue/services/message-queue.service'; -import { fetchAllWorkspacesMessagesCronPattern } from 'src/workspace/messaging/crons/fetch-all-workspaces-messages.cron.pattern'; -import { FetchAllWorkspacesMessagesJob } from 'src/workspace/messaging/crons/fetch-all-workspaces-messages.job'; +import { fetchAllWorkspacesMessagesCronPattern } from 'src/workspace/messaging/commands/crons/fetch-all-workspaces-messages.cron.pattern'; +import { FetchAllWorkspacesMessagesJob } from 'src/workspace/messaging/commands/crons/fetch-all-workspaces-messages.job'; @Command({ name: 'fetch-all-workspaces-messages:cron:stop', diff --git a/packages/twenty-server/src/workspace/messaging/jobs/delete-message-channel-message-association.job.ts b/packages/twenty-server/src/workspace/messaging/jobs/delete-message-channel-message-association.job.ts index f4495feb8..15ddcec85 100644 --- a/packages/twenty-server/src/workspace/messaging/jobs/delete-message-channel-message-association.job.ts +++ b/packages/twenty-server/src/workspace/messaging/jobs/delete-message-channel-message-association.job.ts @@ -2,7 +2,7 @@ import { Injectable, Logger } from '@nestjs/common'; import { MessageQueueJob } from 'src/integrations/message-queue/interfaces/message-queue-job.interface'; -import { MessageChannelMessageAssociationService } from 'src/workspace/messaging/message-channel-message-association/message-channel-message-association.service'; +import { MessageChannelMessageAssociationService } from 'src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-association.service'; export type DeleteMessageChannelMessageAssociationJobData = { workspaceId: string; diff --git a/packages/twenty-server/src/workspace/messaging/jobs/match-message-participant.job.ts b/packages/twenty-server/src/workspace/messaging/jobs/match-message-participant.job.ts index 29df24412..04ad5e4de 100644 --- a/packages/twenty-server/src/workspace/messaging/jobs/match-message-participant.job.ts +++ b/packages/twenty-server/src/workspace/messaging/jobs/match-message-participant.job.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { MessageQueueJob } from 'src/integrations/message-queue/interfaces/message-queue-job.interface'; -import { MessageParticipantService } from 'src/workspace/messaging/message-participant/message-participant.service'; +import { MessageParticipantService } from 'src/workspace/messaging/repositories/message-participant/message-participant.service'; export type MatchMessageParticipantsJobData = { workspaceId: string; diff --git a/packages/twenty-server/src/workspace/messaging/messaging.module.ts b/packages/twenty-server/src/workspace/messaging/messaging.module.ts index fc3b68b18..080f761ab 100644 --- a/packages/twenty-server/src/workspace/messaging/messaging.module.ts +++ b/packages/twenty-server/src/workspace/messaging/messaging.module.ts @@ -1,25 +1,25 @@ import { Module } from '@nestjs/common'; -import { ConnectedAccountModule } from 'src/workspace/messaging/connected-account/connected-account.module'; -import { MessageChannelMessageAssociationModule } from 'src/workspace/messaging/message-channel-message-association/message-channel-message-assocation.module'; -import { MessageChannelModule } from 'src/workspace/messaging/message-channel/message-channel.module'; -import { MessageThreadModule } from 'src/workspace/messaging/message-thread/message-thread.module'; +import { ConnectedAccountModule } from 'src/workspace/messaging/repositories/connected-account/connected-account.module'; +import { MessageChannelMessageAssociationModule } from 'src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-assocation.module'; +import { MessageChannelModule } from 'src/workspace/messaging/repositories/message-channel/message-channel.module'; +import { MessageThreadModule } from 'src/workspace/messaging/repositories/message-thread/message-thread.module'; import { EnvironmentModule } from 'src/integrations/environment/environment.module'; import { MessagingPersonListener } from 'src/workspace/messaging/listeners/messaging-person.listener'; -import { MessageModule } from 'src/workspace/messaging/message/message.module'; -import { GmailClientProvider } from 'src/workspace/messaging/providers/gmail/gmail-client.provider'; -import { CreateContactService } from 'src/workspace/messaging/create-contact/create-contact.service'; -import { CreateCompanyService } from 'src/workspace/messaging/create-company/create-company.service'; +import { MessageModule } from 'src/workspace/messaging/repositories/message/message.module'; +import { GmailClientProvider } from 'src/workspace/messaging/services/providers/gmail/gmail-client.provider'; +import { CreateContactService } from 'src/workspace/messaging/services/create-contact/create-contact.service'; +import { CreateCompanyService } from 'src/workspace/messaging/services/create-company/create-company.service'; import { FetchMessagesByBatchesService } from 'src/workspace/messaging/services/fetch-messages-by-batches.service'; import { GmailFullSyncService } from 'src/workspace/messaging/services/gmail-full-sync.service'; import { GmailPartialSyncService } from 'src/workspace/messaging/services/gmail-partial-sync.service'; import { GmailRefreshAccessTokenService } from 'src/workspace/messaging/services/gmail-refresh-access-token.service'; import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/workspace-datasource.module'; -import { MessageParticipantModule } from 'src/workspace/messaging/message-participant/message-participant.module'; +import { MessageParticipantModule } from 'src/workspace/messaging/repositories/message-participant/message-participant.module'; import { MessagingWorkspaceMemberListener } from 'src/workspace/messaging/listeners/messaging-workspace-member.listener'; import { MessagingMessageChannelListener } from 'src/workspace/messaging/listeners/messaging-message-channel.listener'; -import { MessageService } from 'src/workspace/messaging/message/message.service'; - +import { MessageService } from 'src/workspace/messaging/repositories/message/message.service'; +import { WorkspaceMemberModule } from 'src/workspace/messaging/repositories/workspace-member/workspace-member.module'; @Module({ imports: [ EnvironmentModule, @@ -30,6 +30,7 @@ import { MessageService } from 'src/workspace/messaging/message/message.service' MessageModule, MessageThreadModule, MessageParticipantModule, + WorkspaceMemberModule, ], providers: [ GmailFullSyncService, diff --git a/packages/twenty-server/src/workspace/messaging/query-hooks/message/message-find-many.pre-query.hook.ts b/packages/twenty-server/src/workspace/messaging/query-hooks/message/message-find-many.pre-query.hook.ts new file mode 100644 index 000000000..b5da50554 --- /dev/null +++ b/packages/twenty-server/src/workspace/messaging/query-hooks/message/message-find-many.pre-query.hook.ts @@ -0,0 +1,94 @@ +import { + BadRequestException, + ForbiddenException, + Injectable, + NotFoundException, +} from '@nestjs/common'; + +import { groupBy } from 'lodash'; + +import { WorkspacePreQueryHook } from 'src/workspace/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; +import { FindManyResolverArgs } from 'src/workspace/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +import { MessageChannelMessageAssociationService } from 'src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-association.service'; +import { MessageChannelService } from 'src/workspace/messaging/repositories/message-channel/message-channel.service'; +import { ConnectedAccountService } from 'src/workspace/messaging/repositories/connected-account/connected-account.service'; +import { WorkspaceMemberService } from 'src/workspace/messaging/repositories/workspace-member/workspace-member.service'; + +@Injectable() +export class MessageFindManyPreQueryHook implements WorkspacePreQueryHook { + constructor( + private readonly messageChannelMessageAssociationService: MessageChannelMessageAssociationService, + private readonly messageChannelService: MessageChannelService, + private readonly connectedAccountService: ConnectedAccountService, + private readonly workspaceMemberService: WorkspaceMemberService, + ) {} + + async execute( + userId: string, + workspaceId: string, + payload: FindManyResolverArgs, + ): Promise { + if (!payload?.filter?.messageThreadId?.eq) { + throw new BadRequestException('messageThreadId filter is required'); + } + + const messageChannelMessageAssociations = + await this.messageChannelMessageAssociationService.getByMessageThreadId( + payload?.filter?.messageThreadId?.eq, + workspaceId, + ); + + if (messageChannelMessageAssociations.length === 0) { + throw new NotFoundException(); + } + + await this.canAccessMessageThread( + userId, + workspaceId, + messageChannelMessageAssociations, + ); + } + + private async canAccessMessageThread( + userId: string, + workspaceId: string, + messageChannelMessageAssociations: any[], + ) { + const messageChannels = await this.messageChannelService.getByIds( + messageChannelMessageAssociations.map( + (association) => association.messageChannelId, + ), + workspaceId, + ); + + const messageChannelsGroupByVisibility = groupBy( + messageChannels, + (channel) => channel.visibility, + ); + + if (messageChannelsGroupByVisibility.share_everything) { + return; + } + + const currentWorkspaceMember = + await this.workspaceMemberService.getByIdOrFail(userId, workspaceId); + + const messageChannelsConnectedAccounts = + await this.connectedAccountService.getByIds( + messageChannels.map((channel) => channel.connectedAccountId), + workspaceId, + ); + + const messageChannelsWorkspaceMemberIds = + messageChannelsConnectedAccounts.map( + (connectedAccount) => connectedAccount.accountOwnerId, + ); + + if (messageChannelsWorkspaceMemberIds.includes(currentWorkspaceMember.id)) { + return; + } + + throw new ForbiddenException(); + } +} diff --git a/packages/twenty-server/src/workspace/messaging/query-hooks/message/message-find-one.pre-query-hook.ts b/packages/twenty-server/src/workspace/messaging/query-hooks/message/message-find-one.pre-query-hook.ts new file mode 100644 index 000000000..c5e3fa869 --- /dev/null +++ b/packages/twenty-server/src/workspace/messaging/query-hooks/message/message-find-one.pre-query-hook.ts @@ -0,0 +1,16 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { BadRequestException, Injectable } from '@nestjs/common'; + +import { WorkspacePreQueryHook } from 'src/workspace/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; +import { FindOneResolverArgs } from 'src/workspace/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +@Injectable() +export class MessageFindOnePreQueryHook implements WorkspacePreQueryHook { + async execute( + _userId: string, + _workspaceId: string, + _payload: FindOneResolverArgs, + ): Promise { + throw new BadRequestException('Method not implemented.'); + } +} diff --git a/packages/twenty-server/src/workspace/messaging/query-hooks/messaging-query-hook.module.ts b/packages/twenty-server/src/workspace/messaging/query-hooks/messaging-query-hook.module.ts new file mode 100644 index 000000000..daa52af28 --- /dev/null +++ b/packages/twenty-server/src/workspace/messaging/query-hooks/messaging-query-hook.module.ts @@ -0,0 +1,28 @@ +import { Module } from '@nestjs/common'; + +import { MessageFindManyPreQueryHook } from 'src/workspace/messaging/query-hooks/message/message-find-many.pre-query.hook'; +import { MessageFindOnePreQueryHook } from 'src/workspace/messaging/query-hooks/message/message-find-one.pre-query-hook'; +import { ConnectedAccountModule } from 'src/workspace/messaging/repositories/connected-account/connected-account.module'; +import { MessageChannelMessageAssociationModule } from 'src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-assocation.module'; +import { MessageChannelModule } from 'src/workspace/messaging/repositories/message-channel/message-channel.module'; +import { WorkspaceMemberModule } from 'src/workspace/messaging/repositories/workspace-member/workspace-member.module'; + +@Module({ + imports: [ + MessageChannelMessageAssociationModule, + MessageChannelModule, + ConnectedAccountModule, + WorkspaceMemberModule, + ], + providers: [ + { + provide: MessageFindOnePreQueryHook.name, + useClass: MessageFindOnePreQueryHook, + }, + { + provide: MessageFindManyPreQueryHook.name, + useClass: MessageFindManyPreQueryHook, + }, + ], +}) +export class MessagingQueryHookModule {} diff --git a/packages/twenty-server/src/workspace/messaging/connected-account/connected-account.module.ts b/packages/twenty-server/src/workspace/messaging/repositories/connected-account/connected-account.module.ts similarity index 86% rename from packages/twenty-server/src/workspace/messaging/connected-account/connected-account.module.ts rename to packages/twenty-server/src/workspace/messaging/repositories/connected-account/connected-account.module.ts index 376c7c6fe..12292e445 100644 --- a/packages/twenty-server/src/workspace/messaging/connected-account/connected-account.module.ts +++ b/packages/twenty-server/src/workspace/messaging/repositories/connected-account/connected-account.module.ts @@ -1,6 +1,6 @@ import { Module } from '@nestjs/common'; -import { ConnectedAccountService } from 'src/workspace/messaging/connected-account/connected-account.service'; +import { ConnectedAccountService } from 'src/workspace/messaging/repositories/connected-account/connected-account.service'; import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/workspace-datasource.module'; @Module({ diff --git a/packages/twenty-server/src/workspace/messaging/connected-account/connected-account.service.ts b/packages/twenty-server/src/workspace/messaging/repositories/connected-account/connected-account.service.ts similarity index 80% rename from packages/twenty-server/src/workspace/messaging/connected-account/connected-account.service.ts rename to packages/twenty-server/src/workspace/messaging/repositories/connected-account/connected-account.service.ts index accc80902..830f98697 100644 --- a/packages/twenty-server/src/workspace/messaging/connected-account/connected-account.service.ts +++ b/packages/twenty-server/src/workspace/messaging/repositories/connected-account/connected-account.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, NotFoundException } from '@nestjs/common'; import { EntityManager } from 'typeorm'; @@ -27,6 +27,22 @@ export class ConnectedAccountService { ); } + 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 getByIdOrFail( connectedAccountId: string, workspaceId: string, @@ -44,7 +60,7 @@ export class ConnectedAccountService { ); if (!connectedAccounts || connectedAccounts.length === 0) { - throw new Error('No connected account found'); + throw new NotFoundException('No connected account found'); } return connectedAccounts[0]; diff --git a/packages/twenty-server/src/workspace/messaging/message-channel-message-association/message-channel-message-assocation.module.ts b/packages/twenty-server/src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-assocation.module.ts similarity index 79% rename from packages/twenty-server/src/workspace/messaging/message-channel-message-association/message-channel-message-assocation.module.ts rename to packages/twenty-server/src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-assocation.module.ts index 6a6b22d97..4a4f6c6b7 100644 --- a/packages/twenty-server/src/workspace/messaging/message-channel-message-association/message-channel-message-assocation.module.ts +++ b/packages/twenty-server/src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-assocation.module.ts @@ -1,6 +1,6 @@ import { Module } from '@nestjs/common'; -import { MessageChannelMessageAssociationService } from 'src/workspace/messaging/message-channel-message-association/message-channel-message-association.service'; +import { MessageChannelMessageAssociationService } from 'src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-association.service'; import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/workspace-datasource.module'; @Module({ diff --git a/packages/twenty-server/src/workspace/messaging/message-channel-message-association/message-channel-message-association.service.ts b/packages/twenty-server/src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-association.service.ts similarity index 90% rename from packages/twenty-server/src/workspace/messaging/message-channel-message-association/message-channel-message-association.service.ts rename to packages/twenty-server/src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-association.service.ts index ed9b67539..72c456462 100644 --- a/packages/twenty-server/src/workspace/messaging/message-channel-message-association/message-channel-message-association.service.ts +++ b/packages/twenty-server/src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-association.service.ts @@ -154,4 +154,21 @@ export class MessageChannelMessageAssociationService { transactionManager, ); } + + public async getByMessageThreadId( + messageThreadId: string, + workspaceId: string, + transactionManager?: EntityManager, + ): Promise[]> { + const dataSourceSchema = + this.workspaceDataSourceService.getSchemaName(workspaceId); + + return await this.workspaceDataSourceService.executeRawQuery( + `SELECT * FROM ${dataSourceSchema}."messageChannelMessageAssociation" + WHERE "messageThreadId" = $1`, + [messageThreadId], + workspaceId, + transactionManager, + ); + } } diff --git a/packages/twenty-server/src/workspace/messaging/message-channel/message-channel.module.ts b/packages/twenty-server/src/workspace/messaging/repositories/message-channel/message-channel.module.ts similarity index 72% rename from packages/twenty-server/src/workspace/messaging/message-channel/message-channel.module.ts rename to packages/twenty-server/src/workspace/messaging/repositories/message-channel/message-channel.module.ts index ef8d77674..f7f017c89 100644 --- a/packages/twenty-server/src/workspace/messaging/message-channel/message-channel.module.ts +++ b/packages/twenty-server/src/workspace/messaging/repositories/message-channel/message-channel.module.ts @@ -1,6 +1,6 @@ import { Module } from '@nestjs/common'; -import { MessageChannelService } from 'src/workspace/messaging/message-channel/message-channel.service'; +import { MessageChannelService } from 'src/workspace/messaging/repositories/message-channel/message-channel.service'; import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/workspace-datasource.module'; @Module({ diff --git a/packages/twenty-server/src/workspace/messaging/message-channel/message-channel.service.ts b/packages/twenty-server/src/workspace/messaging/repositories/message-channel/message-channel.service.ts similarity index 76% rename from packages/twenty-server/src/workspace/messaging/message-channel/message-channel.service.ts rename to packages/twenty-server/src/workspace/messaging/repositories/message-channel/message-channel.service.ts index b9ece9fa2..8f0673df8 100644 --- a/packages/twenty-server/src/workspace/messaging/message-channel/message-channel.service.ts +++ b/packages/twenty-server/src/workspace/messaging/repositories/message-channel/message-channel.service.ts @@ -43,4 +43,20 @@ export class MessageChannelService { return messageChannels[0]; } + + public async getByIds( + ids: string[], + workspaceId: string, + transactionManager?: EntityManager, + ): Promise[]> { + const dataSourceSchema = + this.workspaceDataSourceService.getSchemaName(workspaceId); + + return await this.workspaceDataSourceService.executeRawQuery( + `SELECT * FROM ${dataSourceSchema}."messageChannel" WHERE "id" = ANY($1)`, + [ids], + workspaceId, + transactionManager, + ); + } } diff --git a/packages/twenty-server/src/workspace/messaging/message-participant/message-participant.module.ts b/packages/twenty-server/src/workspace/messaging/repositories/message-participant/message-participant.module.ts similarity index 61% rename from packages/twenty-server/src/workspace/messaging/message-participant/message-participant.module.ts rename to packages/twenty-server/src/workspace/messaging/repositories/message-participant/message-participant.module.ts index 9a866627b..162505973 100644 --- a/packages/twenty-server/src/workspace/messaging/message-participant/message-participant.module.ts +++ b/packages/twenty-server/src/workspace/messaging/repositories/message-participant/message-participant.module.ts @@ -1,8 +1,8 @@ import { Module } from '@nestjs/common'; -import { CreateCompanyModule } from 'src/workspace/messaging/create-company/create-company.module'; -import { CreateContactModule } from 'src/workspace/messaging/create-contact/create-contact.module'; -import { MessageParticipantService } from 'src/workspace/messaging/message-participant/message-participant.service'; +import { CreateCompanyModule } from 'src/workspace/messaging/services/create-company/create-company.module'; +import { CreateContactModule } from 'src/workspace/messaging/services/create-contact/create-contact.module'; +import { MessageParticipantService } from 'src/workspace/messaging/repositories/message-participant/message-participant.service'; import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/workspace-datasource.module'; @Module({ diff --git a/packages/twenty-server/src/workspace/messaging/message-participant/message-participant.service.ts b/packages/twenty-server/src/workspace/messaging/repositories/message-participant/message-participant.service.ts similarity index 96% rename from packages/twenty-server/src/workspace/messaging/message-participant/message-participant.service.ts rename to packages/twenty-server/src/workspace/messaging/repositories/message-participant/message-participant.service.ts index 9a8680a93..ce2c0fb8c 100644 --- a/packages/twenty-server/src/workspace/messaging/message-participant/message-participant.service.ts +++ b/packages/twenty-server/src/workspace/messaging/repositories/message-participant/message-participant.service.ts @@ -7,8 +7,8 @@ import { MessageParticipantObjectMetadata } from 'src/workspace/workspace-sync-m import { ObjectRecord } from 'src/workspace/workspace-sync-metadata/types/object-record'; import { DataSourceEntity } from 'src/metadata/data-source/data-source.entity'; import { Participant } from 'src/workspace/messaging/types/gmail-message'; -import { CreateContactService } from 'src/workspace/messaging/create-contact/create-contact.service'; -import { CreateCompanyService } from 'src/workspace/messaging/create-company/create-company.service'; +import { CreateContactService } from 'src/workspace/messaging/services/create-contact/create-contact.service'; +import { CreateCompanyService } from 'src/workspace/messaging/services/create-company/create-company.service'; @Injectable() export class MessageParticipantService { diff --git a/packages/twenty-server/src/workspace/messaging/message-thread/message-thread.module.ts b/packages/twenty-server/src/workspace/messaging/repositories/message-thread/message-thread.module.ts similarity index 65% rename from packages/twenty-server/src/workspace/messaging/message-thread/message-thread.module.ts rename to packages/twenty-server/src/workspace/messaging/repositories/message-thread/message-thread.module.ts index f2c9b54c5..4d4cfc932 100644 --- a/packages/twenty-server/src/workspace/messaging/message-thread/message-thread.module.ts +++ b/packages/twenty-server/src/workspace/messaging/repositories/message-thread/message-thread.module.ts @@ -1,7 +1,7 @@ import { Module } from '@nestjs/common'; -import { MessageChannelMessageAssociationModule } from 'src/workspace/messaging/message-channel-message-association/message-channel-message-assocation.module'; -import { MessageThreadService } from 'src/workspace/messaging/message-thread/message-thread.service'; +import { MessageChannelMessageAssociationModule } from 'src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-assocation.module'; +import { MessageThreadService } from 'src/workspace/messaging/repositories/message-thread/message-thread.service'; import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/workspace-datasource.module'; @Module({ diff --git a/packages/twenty-server/src/workspace/messaging/message-thread/message-thread.service.ts b/packages/twenty-server/src/workspace/messaging/repositories/message-thread/message-thread.service.ts similarity index 94% rename from packages/twenty-server/src/workspace/messaging/message-thread/message-thread.service.ts rename to packages/twenty-server/src/workspace/messaging/repositories/message-thread/message-thread.service.ts index 57fbda912..294934d5e 100644 --- a/packages/twenty-server/src/workspace/messaging/message-thread/message-thread.service.ts +++ b/packages/twenty-server/src/workspace/messaging/repositories/message-thread/message-thread.service.ts @@ -5,7 +5,7 @@ import { v4 } from 'uuid'; import { WorkspaceDataSourceService } from 'src/workspace/workspace-datasource/workspace-datasource.service'; import { DataSourceEntity } from 'src/metadata/data-source/data-source.entity'; -import { MessageChannelMessageAssociationService } from 'src/workspace/messaging/message-channel-message-association/message-channel-message-association.service'; +import { MessageChannelMessageAssociationService } from 'src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-association.service'; @Injectable() export class MessageThreadService { diff --git a/packages/twenty-server/src/workspace/messaging/message/message.module.ts b/packages/twenty-server/src/workspace/messaging/repositories/message/message.module.ts similarity index 58% rename from packages/twenty-server/src/workspace/messaging/message/message.module.ts rename to packages/twenty-server/src/workspace/messaging/repositories/message/message.module.ts index cf3b92975..ce9a95db9 100644 --- a/packages/twenty-server/src/workspace/messaging/message/message.module.ts +++ b/packages/twenty-server/src/workspace/messaging/repositories/message/message.module.ts @@ -1,9 +1,9 @@ import { Module } from '@nestjs/common'; -import { MessageChannelMessageAssociationModule } from 'src/workspace/messaging/message-channel-message-association/message-channel-message-assocation.module'; -import { MessageParticipantModule } from 'src/workspace/messaging/message-participant/message-participant.module'; -import { MessageThreadModule } from 'src/workspace/messaging/message-thread/message-thread.module'; -import { MessageService } from 'src/workspace/messaging/message/message.service'; +import { MessageChannelMessageAssociationModule } from 'src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-assocation.module'; +import { MessageParticipantModule } from 'src/workspace/messaging/repositories/message-participant/message-participant.module'; +import { MessageThreadModule } from 'src/workspace/messaging/repositories/message-thread/message-thread.module'; +import { MessageService } from 'src/workspace/messaging/repositories/message/message.service'; import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/workspace-datasource.module'; @Module({ diff --git a/packages/twenty-server/src/workspace/messaging/message/message.service.ts b/packages/twenty-server/src/workspace/messaging/repositories/message/message.service.ts similarity index 97% rename from packages/twenty-server/src/workspace/messaging/message/message.service.ts rename to packages/twenty-server/src/workspace/messaging/repositories/message/message.service.ts index 605d26b89..8f5ab9008 100644 --- a/packages/twenty-server/src/workspace/messaging/message/message.service.ts +++ b/packages/twenty-server/src/workspace/messaging/repositories/message/message.service.ts @@ -9,11 +9,10 @@ import { ObjectRecord } from 'src/workspace/workspace-sync-metadata/types/object import { DataSourceEntity } from 'src/metadata/data-source/data-source.entity'; import { GmailMessage } from 'src/workspace/messaging/types/gmail-message'; import { ConnectedAccountObjectMetadata } from 'src/workspace/workspace-sync-metadata/standard-objects/connected-account.object-metadata'; -import { MessageChannelMessageAssociationService } from 'src/workspace/messaging/message-channel-message-association/message-channel-message-association.service'; -import { MessageThreadService } from 'src/workspace/messaging/message-thread/message-thread.service'; -import { MessageParticipantService } from 'src/workspace/messaging/message-participant/message-participant.service'; +import { MessageChannelMessageAssociationService } from 'src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-association.service'; +import { MessageParticipantService } from 'src/workspace/messaging/repositories/message-participant/message-participant.service'; +import { MessageThreadService } from 'src/workspace/messaging/repositories/message-thread/message-thread.service'; import { isPersonEmail } from 'src/workspace/messaging/utils/is-person-email.util'; - @Injectable() export class MessageService { constructor( diff --git a/packages/twenty-server/src/workspace/messaging/repositories/workspace-member/workspace-member.module.ts b/packages/twenty-server/src/workspace/messaging/repositories/workspace-member/workspace-member.module.ts new file mode 100644 index 000000000..cb7538f62 --- /dev/null +++ b/packages/twenty-server/src/workspace/messaging/repositories/workspace-member/workspace-member.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; + +import { WorkspaceMemberService } from 'src/workspace/messaging/repositories/workspace-member/workspace-member.service'; +import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/workspace-datasource.module'; + +// TODO: Move outside of the messaging module +@Module({ + imports: [WorkspaceDataSourceModule], + providers: [WorkspaceMemberService], + exports: [WorkspaceMemberService], +}) +export class WorkspaceMemberModule {} diff --git a/packages/twenty-server/src/workspace/messaging/repositories/workspace-member/workspace-member.service.ts b/packages/twenty-server/src/workspace/messaging/repositories/workspace-member/workspace-member.service.ts new file mode 100644 index 000000000..7b6b7a965 --- /dev/null +++ b/packages/twenty-server/src/workspace/messaging/repositories/workspace-member/workspace-member.service.ts @@ -0,0 +1,50 @@ +import { Injectable, NotFoundException } from '@nestjs/common'; + +import { WorkspaceDataSourceService } from 'src/workspace/workspace-datasource/workspace-datasource.service'; +import { WorkspaceMemberObjectMetadata } from 'src/workspace/workspace-sync-metadata/standard-objects/workspace-member.object-metadata'; +import { ObjectRecord } from 'src/workspace/workspace-sync-metadata/types/object-record'; + +// TODO: Move outside of the messaging module +@Injectable() +export class WorkspaceMemberService { + constructor( + private readonly workspaceDataSourceService: WorkspaceDataSourceService, + ) {} + + public async getByIds( + userIds: string[], + workspaceId: string, + ): Promise[]> { + const dataSourceSchema = + this.workspaceDataSourceService.getSchemaName(workspaceId); + + const result = await this.workspaceDataSourceService.executeRawQuery( + `SELECT * FROM ${dataSourceSchema}."workspaceMember" WHERE "userId" = ANY($1)`, + [userIds], + workspaceId, + ); + + return result.rows; + } + + public async getByIdOrFail( + userId: string, + workspaceId: string, + ): Promise> { + const dataSourceSchema = + this.workspaceDataSourceService.getSchemaName(workspaceId); + + const workspaceMembers = + await this.workspaceDataSourceService.executeRawQuery( + `SELECT * FROM ${dataSourceSchema}."workspaceMember" WHERE "userId" = $1`, + [userId], + workspaceId, + ); + + if (!workspaceMembers || workspaceMembers.length === 0) { + throw new NotFoundException('No workspace member found'); + } + + return workspaceMembers[0]; + } +} diff --git a/packages/twenty-server/src/workspace/messaging/create-company/create-company.module.ts b/packages/twenty-server/src/workspace/messaging/services/create-company/create-company.module.ts similarity index 61% rename from packages/twenty-server/src/workspace/messaging/create-company/create-company.module.ts rename to packages/twenty-server/src/workspace/messaging/services/create-company/create-company.module.ts index 36a00ae43..85df4a1c5 100644 --- a/packages/twenty-server/src/workspace/messaging/create-company/create-company.module.ts +++ b/packages/twenty-server/src/workspace/messaging/services/create-company/create-company.module.ts @@ -1,6 +1,6 @@ import { Module } from '@nestjs/common'; -import { CreateCompanyService } from 'src/workspace/messaging/create-company/create-company.service'; +import { CreateCompanyService } from 'src/workspace/messaging/services/create-company/create-company.service'; @Module({ imports: [], diff --git a/packages/twenty-server/src/workspace/messaging/create-company/create-company.service.ts b/packages/twenty-server/src/workspace/messaging/services/create-company/create-company.service.ts similarity index 100% rename from packages/twenty-server/src/workspace/messaging/create-company/create-company.service.ts rename to packages/twenty-server/src/workspace/messaging/services/create-company/create-company.service.ts diff --git a/packages/twenty-server/src/workspace/messaging/create-contact/create-contact.module.ts b/packages/twenty-server/src/workspace/messaging/services/create-contact/create-contact.module.ts similarity index 61% rename from packages/twenty-server/src/workspace/messaging/create-contact/create-contact.module.ts rename to packages/twenty-server/src/workspace/messaging/services/create-contact/create-contact.module.ts index f90a1c6b1..0c7200784 100644 --- a/packages/twenty-server/src/workspace/messaging/create-contact/create-contact.module.ts +++ b/packages/twenty-server/src/workspace/messaging/services/create-contact/create-contact.module.ts @@ -1,6 +1,6 @@ import { Module } from '@nestjs/common'; -import { CreateContactService } from 'src/workspace/messaging/create-contact/create-contact.service'; +import { CreateContactService } from 'src/workspace/messaging/services/create-contact/create-contact.service'; @Module({ imports: [], diff --git a/packages/twenty-server/src/workspace/messaging/create-contact/create-contact.service.ts b/packages/twenty-server/src/workspace/messaging/services/create-contact/create-contact.service.ts similarity index 100% rename from packages/twenty-server/src/workspace/messaging/create-contact/create-contact.service.ts rename to packages/twenty-server/src/workspace/messaging/services/create-contact/create-contact.service.ts diff --git a/packages/twenty-server/src/workspace/messaging/services/gmail-full-sync.service.ts b/packages/twenty-server/src/workspace/messaging/services/gmail-full-sync.service.ts index 2009b89db..fa1654193 100644 --- a/packages/twenty-server/src/workspace/messaging/services/gmail-full-sync.service.ts +++ b/packages/twenty-server/src/workspace/messaging/services/gmail-full-sync.service.ts @@ -1,18 +1,18 @@ import { Inject, Injectable, Logger } from '@nestjs/common'; import { FetchMessagesByBatchesService } from 'src/workspace/messaging/services/fetch-messages-by-batches.service'; -import { GmailClientProvider } from 'src/workspace/messaging/providers/gmail/gmail-client.provider'; +import { GmailClientProvider } from 'src/workspace/messaging/services/providers/gmail/gmail-client.provider'; import { MessageQueue } from 'src/integrations/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/integrations/message-queue/services/message-queue.service'; import { GmailFullSyncJobData, GmailFullSyncJob, } from 'src/workspace/messaging/jobs/gmail-full-sync.job'; -import { ConnectedAccountService } from 'src/workspace/messaging/connected-account/connected-account.service'; -import { MessageChannelService } from 'src/workspace/messaging/message-channel/message-channel.service'; -import { MessageChannelMessageAssociationService } from 'src/workspace/messaging/message-channel-message-association/message-channel-message-association.service'; +import { ConnectedAccountService } from 'src/workspace/messaging/repositories/connected-account/connected-account.service'; +import { MessageChannelService } from 'src/workspace/messaging/repositories/message-channel/message-channel.service'; +import { MessageChannelMessageAssociationService } from 'src/workspace/messaging/repositories/message-channel-message-association/message-channel-message-association.service'; import { WorkspaceDataSourceService } from 'src/workspace/workspace-datasource/workspace-datasource.service'; -import { MessageService } from 'src/workspace/messaging/message/message.service'; +import { MessageService } from 'src/workspace/messaging/repositories/message/message.service'; import { createQueriesFromMessageIds } from 'src/workspace/messaging/utils/create-queries-from-message-ids.util'; @Injectable() diff --git a/packages/twenty-server/src/workspace/messaging/services/gmail-partial-sync.service.ts b/packages/twenty-server/src/workspace/messaging/services/gmail-partial-sync.service.ts index 7b6a7e8f2..d5d04f697 100644 --- a/packages/twenty-server/src/workspace/messaging/services/gmail-partial-sync.service.ts +++ b/packages/twenty-server/src/workspace/messaging/services/gmail-partial-sync.service.ts @@ -3,17 +3,17 @@ import { Inject, Injectable, Logger } from '@nestjs/common'; import { gmail_v1 } from 'googleapis'; import { FetchMessagesByBatchesService } from 'src/workspace/messaging/services/fetch-messages-by-batches.service'; -import { GmailClientProvider } from 'src/workspace/messaging/providers/gmail/gmail-client.provider'; +import { GmailClientProvider } from 'src/workspace/messaging/services/providers/gmail/gmail-client.provider'; import { MessageQueueService } from 'src/integrations/message-queue/services/message-queue.service'; import { MessageQueue } from 'src/integrations/message-queue/message-queue.constants'; import { GmailFullSyncJob, GmailFullSyncJobData, } from 'src/workspace/messaging/jobs/gmail-full-sync.job'; -import { ConnectedAccountService } from 'src/workspace/messaging/connected-account/connected-account.service'; +import { ConnectedAccountService } from 'src/workspace/messaging/repositories/connected-account/connected-account.service'; import { WorkspaceDataSourceService } from 'src/workspace/workspace-datasource/workspace-datasource.service'; -import { MessageChannelService } from 'src/workspace/messaging/message-channel/message-channel.service'; -import { MessageService } from 'src/workspace/messaging/message/message.service'; +import { MessageChannelService } from 'src/workspace/messaging/repositories/message-channel/message-channel.service'; +import { MessageService } from 'src/workspace/messaging/repositories/message/message.service'; import { createQueriesFromMessageIds } from 'src/workspace/messaging/utils/create-queries-from-message-ids.util'; @Injectable() diff --git a/packages/twenty-server/src/workspace/messaging/services/gmail-refresh-access-token.service.ts b/packages/twenty-server/src/workspace/messaging/services/gmail-refresh-access-token.service.ts index 99fb83e46..eeb25de9a 100644 --- a/packages/twenty-server/src/workspace/messaging/services/gmail-refresh-access-token.service.ts +++ b/packages/twenty-server/src/workspace/messaging/services/gmail-refresh-access-token.service.ts @@ -3,7 +3,7 @@ import { Injectable } from '@nestjs/common'; import axios from 'axios'; import { EnvironmentService } from 'src/integrations/environment/environment.service'; -import { ConnectedAccountService } from 'src/workspace/messaging/connected-account/connected-account.service'; +import { ConnectedAccountService } from 'src/workspace/messaging/repositories/connected-account/connected-account.service'; @Injectable() export class GmailRefreshAccessTokenService { diff --git a/packages/twenty-server/src/workspace/messaging/providers/gmail/gmail-client.provider.ts b/packages/twenty-server/src/workspace/messaging/services/providers/gmail/gmail-client.provider.ts similarity index 100% rename from packages/twenty-server/src/workspace/messaging/providers/gmail/gmail-client.provider.ts rename to packages/twenty-server/src/workspace/messaging/services/providers/gmail/gmail-client.provider.ts diff --git a/packages/twenty-server/src/workspace/messaging/providers/messaging-providers.module.ts b/packages/twenty-server/src/workspace/messaging/services/providers/messaging-providers.module.ts similarity index 72% rename from packages/twenty-server/src/workspace/messaging/providers/messaging-providers.module.ts rename to packages/twenty-server/src/workspace/messaging/services/providers/messaging-providers.module.ts index e63b5b74d..eb2cc40a1 100644 --- a/packages/twenty-server/src/workspace/messaging/providers/messaging-providers.module.ts +++ b/packages/twenty-server/src/workspace/messaging/services/providers/messaging-providers.module.ts @@ -1,7 +1,7 @@ import { Module } from '@nestjs/common'; import { EnvironmentModule } from 'src/integrations/environment/environment.module'; -import { GmailClientProvider } from 'src/workspace/messaging/providers/gmail/gmail-client.provider'; +import { GmailClientProvider } from 'src/workspace/messaging/services/providers/gmail/gmail-client.provider'; @Module({ imports: [EnvironmentModule], diff --git a/packages/twenty-server/src/workspace/workspace-query-runner/interfaces/query-runner-option.interface.ts b/packages/twenty-server/src/workspace/workspace-query-runner/interfaces/query-runner-option.interface.ts index 3141d542c..a0d5deb7c 100644 --- a/packages/twenty-server/src/workspace/workspace-query-runner/interfaces/query-runner-option.interface.ts +++ b/packages/twenty-server/src/workspace/workspace-query-runner/interfaces/query-runner-option.interface.ts @@ -5,6 +5,7 @@ import { ObjectMetadataInterface } from 'src/metadata/field-metadata/interfaces/ export interface WorkspaceQueryRunnerOptions { workspaceId: string; + userId: string | undefined; info: GraphQLResolveInfo; objectMetadataItem: ObjectMetadataInterface; fieldMetadataCollection: FieldMetadataInterface[]; diff --git a/packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface.ts b/packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface.ts new file mode 100644 index 000000000..37a5fc711 --- /dev/null +++ b/packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface.ts @@ -0,0 +1,9 @@ +import { ResolverArgs } from 'src/workspace/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +export interface WorkspacePreQueryHook { + execute( + userId: string | undefined, + workspaceId: string, + payload: ResolverArgs, + ): Promise; +} diff --git a/packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/types/workspace-query-hook.type.ts b/packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/types/workspace-query-hook.type.ts new file mode 100644 index 000000000..c98882941 --- /dev/null +++ b/packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/types/workspace-query-hook.type.ts @@ -0,0 +1,48 @@ +import { + CreateManyResolverArgs, + CreateOneResolverArgs, + DeleteManyResolverArgs, + DeleteOneResolverArgs, + FindManyResolverArgs, + FindOneResolverArgs, + UpdateManyResolverArgs, + UpdateOneResolverArgs, +} from 'src/workspace/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; + +export type ExecutePreHookMethod = + | 'createMany' + | 'createOne' + | 'deleteMany' + | 'deleteOne' + | 'findMany' + | 'findOne' + | 'updateMany' + | 'updateOne'; + +export type ObjectName = string; + +export type HookName = string; + +export type WorkspaceQueryHook = { + [key in ObjectName]: { + [key in ExecutePreHookMethod]?: HookName[]; + }; +}; + +export type WorkspacePreQueryHookPayload = T extends 'createMany' + ? CreateManyResolverArgs + : T extends 'createOne' + ? CreateOneResolverArgs + : T extends 'deleteMany' + ? DeleteManyResolverArgs + : T extends 'deleteOne' + ? DeleteOneResolverArgs + : T extends 'findMany' + ? FindManyResolverArgs + : T extends 'findOne' + ? FindOneResolverArgs + : T extends 'updateMany' + ? UpdateManyResolverArgs + : T extends 'updateOne' + ? UpdateOneResolverArgs + : never; diff --git a/packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config.ts b/packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config.ts new file mode 100644 index 000000000..f9e887341 --- /dev/null +++ b/packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config.ts @@ -0,0 +1,11 @@ +import { MessageFindManyPreQueryHook } from 'src/workspace/messaging/query-hooks/message/message-find-many.pre-query.hook'; +import { MessageFindOnePreQueryHook } from 'src/workspace/messaging/query-hooks/message/message-find-one.pre-query-hook'; +import { WorkspaceQueryHook } from 'src/workspace/workspace-query-runner/workspace-pre-query-hook/types/workspace-query-hook.type'; + +// TODO: move to a decorator +export const workspacePreQueryHooks: WorkspaceQueryHook = { + message: { + findOne: [MessageFindOnePreQueryHook.name], + findMany: [MessageFindManyPreQueryHook.name], + }, +}; diff --git a/packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module.ts b/packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module.ts new file mode 100644 index 000000000..31d7d9776 --- /dev/null +++ b/packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; + +import { MessagingQueryHookModule } from 'src/workspace/messaging/query-hooks/messaging-query-hook.module'; +import { WorkspacePreQueryHookService } from 'src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.service'; + +@Module({ + imports: [MessagingQueryHookModule], + providers: [WorkspacePreQueryHookService], + exports: [WorkspacePreQueryHookService], +}) +export class WorkspacePreQueryHookModule {} diff --git a/packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.service.ts b/packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.service.ts new file mode 100644 index 000000000..1b0d61b94 --- /dev/null +++ b/packages/twenty-server/src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.service.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@nestjs/common'; +import { ModuleRef } from '@nestjs/core'; + +import { WorkspacePreQueryHook } from 'src/workspace/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; + +import { + ExecutePreHookMethod, + WorkspacePreQueryHookPayload, +} from 'src/workspace/workspace-query-runner/workspace-pre-query-hook/types/workspace-query-hook.type'; +import { workspacePreQueryHooks } from 'src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config'; + +@Injectable() +export class WorkspacePreQueryHookService { + constructor(private readonly workspaceQueryHookModuleRef: ModuleRef) {} + + public async executePreHooks( + userId: string | undefined, + workspaceId: string, + objectName: string, + method: T, + payload: WorkspacePreQueryHookPayload, + ): Promise { + const hooks = workspacePreQueryHooks[objectName] || []; + + for (const hookName of Object.values(hooks[method] ?? [])) { + const hook: WorkspacePreQueryHook = + await this.workspaceQueryHookModuleRef.get(hookName, { + strict: false, + }); + + await hook.execute(userId, workspaceId, payload); + } + } +} diff --git a/packages/twenty-server/src/workspace/workspace-query-runner/workspace-query-runner.module.ts b/packages/twenty-server/src/workspace/workspace-query-runner/workspace-query-runner.module.ts index a2340ea39..0202cb4b7 100644 --- a/packages/twenty-server/src/workspace/workspace-query-runner/workspace-query-runner.module.ts +++ b/packages/twenty-server/src/workspace/workspace-query-runner/workspace-query-runner.module.ts @@ -2,11 +2,16 @@ import { Module } from '@nestjs/common'; import { WorkspaceQueryBuilderModule } from 'src/workspace/workspace-query-builder/workspace-query-builder.module'; import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/workspace-datasource.module'; +import { WorkspacePreQueryHookModule } from 'src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module'; import { WorkspaceQueryRunnerService } from './workspace-query-runner.service'; @Module({ - imports: [WorkspaceQueryBuilderModule, WorkspaceDataSourceModule], + imports: [ + WorkspaceQueryBuilderModule, + WorkspaceDataSourceModule, + WorkspacePreQueryHookModule, + ], providers: [WorkspaceQueryRunnerService], exports: [WorkspaceQueryRunnerService], }) diff --git a/packages/twenty-server/src/workspace/workspace-query-runner/workspace-query-runner.service.ts b/packages/twenty-server/src/workspace/workspace-query-runner/workspace-query-runner.service.ts index 12a82ea8d..3bee63051 100644 --- a/packages/twenty-server/src/workspace/workspace-query-runner/workspace-query-runner.service.ts +++ b/packages/twenty-server/src/workspace/workspace-query-runner/workspace-query-runner.service.ts @@ -38,6 +38,7 @@ import { computeObjectTargetTable } from 'src/workspace/utils/compute-object-tar import { ObjectRecordDeleteEvent } from 'src/integrations/event-emitter/types/object-record-delete.event'; import { ObjectRecordCreateEvent } from 'src/integrations/event-emitter/types/object-record-create.event'; import { ObjectRecordUpdateEvent } from 'src/integrations/event-emitter/types/object-record-update.event'; +import { WorkspacePreQueryHookService } from 'src/workspace/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.service'; import { WorkspaceQueryRunnerOptions } from './interfaces/query-runner-option.interface'; import { @@ -53,6 +54,7 @@ export class WorkspaceQueryRunnerService { @Inject(MessageQueue.webhookQueue) private readonly messageQueueService: MessageQueueService, private readonly eventEmitter: EventEmitter2, + private readonly workspacePreQueryHookService: WorkspacePreQueryHookService, ) {} async findMany< @@ -63,7 +65,7 @@ export class WorkspaceQueryRunnerService { args: FindManyResolverArgs, options: WorkspaceQueryRunnerOptions, ): Promise | undefined> { - const { workspaceId, objectMetadataItem } = options; + const { workspaceId, userId, objectMetadataItem } = options; const start = performance.now(); const query = await this.workspaceQueryBuilderFactory.findMany( @@ -71,6 +73,14 @@ export class WorkspaceQueryRunnerService { options, ); + await this.workspacePreQueryHookService.executePreHooks( + userId, + workspaceId, + objectMetadataItem.nameSingular, + 'findMany', + args, + ); + const result = await this.execute(query, workspaceId); const end = performance.now(); @@ -97,11 +107,20 @@ export class WorkspaceQueryRunnerService { if (!args.filter || Object.keys(args.filter).length === 0) { throw new BadRequestException('Missing filter argument'); } - const { workspaceId, objectMetadataItem } = options; + const { workspaceId, userId, objectMetadataItem } = options; const query = await this.workspaceQueryBuilderFactory.findOne( args, options, ); + + await this.workspacePreQueryHookService.executePreHooks( + userId, + workspaceId, + objectMetadataItem.nameSingular, + 'findOne', + args, + ); + const result = await this.execute(query, workspaceId); const parsedResult = this.parseResult>( result, @@ -170,6 +189,7 @@ export class WorkspaceQueryRunnerService { args, options, ); + const result = await this.execute(query, workspaceId); const parsedResults = this.parseResult>( @@ -232,6 +252,7 @@ export class WorkspaceQueryRunnerService { args, options, ); + const result = await this.execute(query, workspaceId); const parsedResults = this.parseResult>( @@ -338,7 +359,7 @@ export class WorkspaceQueryRunnerService { const result = graphqlResult?.[0]?.resolve?.data?.[entityKey]; const errors = graphqlResult?.[0]?.resolve?.errors; - if (!result) { + if (errors && errors.length > 0) { throw new InternalServerErrorException( `GraphQL errors on ${command}${ objectMetadataItem.nameSingular diff --git a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/create-many-resolver.factory.ts b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/create-many-resolver.factory.ts index 47448a653..eb606ee23 100644 --- a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/create-many-resolver.factory.ts +++ b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/create-many-resolver.factory.ts @@ -28,6 +28,7 @@ export class CreateManyResolverFactory return this.workspaceQueryRunnerService.createMany(args, { objectMetadataItem: internalContext.objectMetadataItem, workspaceId: internalContext.workspaceId, + userId: internalContext.userId, info, fieldMetadataCollection: internalContext.fieldMetadataCollection, objectMetadataCollection: internalContext.objectMetadataCollection, diff --git a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/create-one-resolver.factory.ts b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/create-one-resolver.factory.ts index caa7f22ec..f895db2de 100644 --- a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/create-one-resolver.factory.ts +++ b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/create-one-resolver.factory.ts @@ -28,6 +28,7 @@ export class CreateOneResolverFactory return this.workspaceQueryRunnerService.createOne(args, { objectMetadataItem: internalContext.objectMetadataItem, workspaceId: internalContext.workspaceId, + userId: internalContext.userId, info, fieldMetadataCollection: internalContext.fieldMetadataCollection, objectMetadataCollection: internalContext.objectMetadataCollection, diff --git a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/delete-many-resolver.factory.ts b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/delete-many-resolver.factory.ts index d4d35cad3..37deb7191 100644 --- a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/delete-many-resolver.factory.ts +++ b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/delete-many-resolver.factory.ts @@ -28,6 +28,7 @@ export class DeleteManyResolverFactory return this.workspaceQueryRunnerService.deleteMany(args, { objectMetadataItem: internalContext.objectMetadataItem, workspaceId: internalContext.workspaceId, + userId: internalContext.userId, info, fieldMetadataCollection: internalContext.fieldMetadataCollection, objectMetadataCollection: internalContext.objectMetadataCollection, diff --git a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/delete-one-resolver.factory.ts b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/delete-one-resolver.factory.ts index 0b6b9f890..28c5706d0 100644 --- a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/delete-one-resolver.factory.ts +++ b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/delete-one-resolver.factory.ts @@ -28,6 +28,7 @@ export class DeleteOneResolverFactory return this.workspaceQueryRunnerService.deleteOne(args, { objectMetadataItem: internalContext.objectMetadataItem, workspaceId: internalContext.workspaceId, + userId: internalContext.userId, info, fieldMetadataCollection: internalContext.fieldMetadataCollection, objectMetadataCollection: internalContext.objectMetadataCollection, diff --git a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/execute-quick-action-on-one-resolver.factory.ts b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/execute-quick-action-on-one-resolver.factory.ts index ca2dd9069..a2138d003 100644 --- a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/execute-quick-action-on-one-resolver.factory.ts +++ b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/execute-quick-action-on-one-resolver.factory.ts @@ -33,6 +33,7 @@ export class ExecuteQuickActionOnOneResolverFactory return (_source, args, context, info) => { return this.executeQuickActionOnOne(args, { objectMetadataItem: internalContext.objectMetadataItem, + userId: internalContext.userId, workspaceId: internalContext.workspaceId, info, fieldMetadataCollection: internalContext.fieldMetadataCollection, diff --git a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/find-many-resolver.factory.ts b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/find-many-resolver.factory.ts index 8e056dcda..3009ea39e 100644 --- a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/find-many-resolver.factory.ts +++ b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/find-many-resolver.factory.ts @@ -28,6 +28,7 @@ export class FindManyResolverFactory return this.workspaceQueryRunnerService.findMany(args, { objectMetadataItem: internalContext.objectMetadataItem, workspaceId: internalContext.workspaceId, + userId: internalContext.userId, info, fieldMetadataCollection: internalContext.fieldMetadataCollection, objectMetadataCollection: internalContext.objectMetadataCollection, diff --git a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/find-one-resolver.factory.ts b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/find-one-resolver.factory.ts index 580b0cb49..114b8ef4e 100644 --- a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/find-one-resolver.factory.ts +++ b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/find-one-resolver.factory.ts @@ -28,6 +28,7 @@ export class FindOneResolverFactory return this.workspaceQueryRunnerService.findOne(args, { objectMetadataItem: internalContext.objectMetadataItem, workspaceId: internalContext.workspaceId, + userId: internalContext.userId, info, fieldMetadataCollection: internalContext.fieldMetadataCollection, objectMetadataCollection: internalContext.objectMetadataCollection, diff --git a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/update-many-resolver.factory.ts b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/update-many-resolver.factory.ts index 23eebda68..ba3d79c34 100644 --- a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/update-many-resolver.factory.ts +++ b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/update-many-resolver.factory.ts @@ -28,6 +28,7 @@ export class UpdateManyResolverFactory return this.workspaceQueryRunnerService.updateMany(args, { objectMetadataItem: internalContext.objectMetadataItem, workspaceId: internalContext.workspaceId, + userId: internalContext.userId, info, fieldMetadataCollection: internalContext.fieldMetadataCollection, objectMetadataCollection: internalContext.objectMetadataCollection, diff --git a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/update-one-resolver.factory.ts b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/update-one-resolver.factory.ts index 67baec398..a6ba68366 100644 --- a/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/update-one-resolver.factory.ts +++ b/packages/twenty-server/src/workspace/workspace-resolver-builder/factories/update-one-resolver.factory.ts @@ -28,6 +28,7 @@ export class UpdateOneResolverFactory return this.workspaceQueryRunnerService.updateOne(args, { objectMetadataItem: internalContext.objectMetadataItem, workspaceId: internalContext.workspaceId, + userId: internalContext.userId, info, fieldMetadataCollection: internalContext.fieldMetadataCollection, objectMetadataCollection: internalContext.objectMetadataCollection, diff --git a/packages/twenty-server/src/workspace/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface.ts b/packages/twenty-server/src/workspace/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface.ts index 2e6a27684..8f44bbf9e 100644 --- a/packages/twenty-server/src/workspace/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface.ts +++ b/packages/twenty-server/src/workspace/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface.ts @@ -73,3 +73,13 @@ export interface WorkspaceResolverBuilderMethods { readonly queries: readonly WorkspaceResolverBuilderQueryMethodNames[]; readonly mutations: readonly WorkspaceResolverBuilderMutationMethodNames[]; } + +export type ResolverArgs = + | CreateManyResolverArgs + | CreateOneResolverArgs + | DeleteManyResolverArgs + | DeleteOneResolverArgs + | FindManyResolverArgs + | FindOneResolverArgs + | UpdateManyResolverArgs + | UpdateOneResolverArgs; diff --git a/packages/twenty-server/src/workspace/workspace-resolver-builder/workspace-resolver.factory.ts b/packages/twenty-server/src/workspace/workspace-resolver-builder/workspace-resolver.factory.ts index 478edf536..19e6dd00f 100644 --- a/packages/twenty-server/src/workspace/workspace-resolver-builder/workspace-resolver.factory.ts +++ b/packages/twenty-server/src/workspace/workspace-resolver-builder/workspace-resolver.factory.ts @@ -39,6 +39,7 @@ export class WorkspaceResolverFactory { async create( workspaceId: string, + userId: string | undefined, objectMetadataCollection: ObjectMetadataInterface[], workspaceResolverBuilderMethods: WorkspaceResolverBuilderMethods, ): Promise { @@ -79,6 +80,7 @@ export class WorkspaceResolverFactory { resolvers.Query[resolverName] = resolverFactory.create({ workspaceId, + userId, objectMetadataItem: objectMetadata, fieldMetadataCollection: objectMetadata.fields, objectMetadataCollection: objectMetadataCollection, @@ -102,6 +104,7 @@ export class WorkspaceResolverFactory { resolvers.Mutation[resolverName] = resolverFactory.create({ workspaceId, + userId, objectMetadataItem: objectMetadata, fieldMetadataCollection: objectMetadata.fields, objectMetadataCollection: objectMetadataCollection, diff --git a/packages/twenty-server/src/workspace/workspace-schema-builder/interfaces/workspace-schema-builder-context.interface.ts b/packages/twenty-server/src/workspace/workspace-schema-builder/interfaces/workspace-schema-builder-context.interface.ts index 9ebfb36f6..4ca4b68e0 100644 --- a/packages/twenty-server/src/workspace/workspace-schema-builder/interfaces/workspace-schema-builder-context.interface.ts +++ b/packages/twenty-server/src/workspace/workspace-schema-builder/interfaces/workspace-schema-builder-context.interface.ts @@ -3,6 +3,7 @@ import { ObjectMetadataInterface } from 'src/metadata/field-metadata/interfaces/ export interface WorkspaceSchemaBuilderContext { workspaceId: string; + userId: string | undefined; objectMetadataItem: ObjectMetadataInterface; fieldMetadataCollection: FieldMetadataInterface[]; objectMetadataCollection: ObjectMetadataInterface[]; diff --git a/packages/twenty-server/src/workspace/workspace.factory.ts b/packages/twenty-server/src/workspace/workspace.factory.ts index e0e59e9ea..bbc4b758d 100644 --- a/packages/twenty-server/src/workspace/workspace.factory.ts +++ b/packages/twenty-server/src/workspace/workspace.factory.ts @@ -26,6 +26,7 @@ export class WorkspaceFactory { async createGraphQLSchema( workspaceId: string | undefined, + userId: string | undefined, ): Promise { if (!workspaceId) { return new GraphQLSchema({}); @@ -89,6 +90,7 @@ export class WorkspaceFactory { const autoGeneratedResolvers = await this.workspaceResolverFactory.create( workspaceId, + userId, objectMetadataCollection, workspaceResolverBuilderMethodNames, ); diff --git a/yarn.lock b/yarn.lock index 0c0099e8c..740462c08 100644 --- a/yarn.lock +++ b/yarn.lock @@ -43532,6 +43532,7 @@ __metadata: graphql-yoga: "npm:^4.0.4" jest: "npm:29.7.0" lodash.camelcase: "npm:^4.3.0" + lodash.groupby: "npm:^4.6.0" lodash.isempty: "npm:^4.4.0" lodash.isobject: "npm:^3.0.2" lodash.kebabcase: "npm:^4.1.1"