From ee7c1fbf5cc91e895cf9946da4f61d43542e3103 Mon Sep 17 00:00:00 2001 From: bosiraphael <71827178+bosiraphael@users.noreply.github.com> Date: Wed, 21 Feb 2024 13:22:01 +0100 Subject: [PATCH] 4008 dont create a contact company if it matches the persons domain (#4088) * Add SettingsAccountsEmailsBlocklistInput story * prevent contact creation from the same company * add todo * improvements * Delete packages/twenty-front/src/modules/settings/accounts/components/__stories__/SettingsAccountsEmailsBlocklistInput.stories.tsx * refactor * modify after review * improve code * create utils * fix * Fix getAllByWorkspaceId to throw NotFoundException when no workspace member found * fix after merge * use map * modify after review --- .../workspace-member.service.ts | 22 ++++++++++- .../create-companies-and-contacts.module.ts | 2 + .../create-companies-and-contacts.service.ts | 39 +++++++++---------- ...icipants-from-company-or-workspace.util.ts | 27 +++++++++++++ ...et-unique-participants-and-handles.util.ts | 24 ++++++++++++ 5 files changed, 93 insertions(+), 21 deletions(-) create mode 100644 packages/twenty-server/src/workspace/messaging/utils/filter-out-participants-from-company-or-workspace.util.ts create mode 100644 packages/twenty-server/src/workspace/messaging/utils/get-unique-participants-and-handles.util.ts 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 index 7b6b7a965..ab39b2764 100644 --- 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 @@ -1,5 +1,7 @@ import { Injectable, NotFoundException } from '@nestjs/common'; +import { EntityManager } from 'typeorm'; + 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'; @@ -24,7 +26,7 @@ export class WorkspaceMemberService { workspaceId, ); - return result.rows; + return result; } public async getByIdOrFail( @@ -47,4 +49,22 @@ export class WorkspaceMemberService { return workspaceMembers[0]; } + + public async getAllByWorkspaceId( + workspaceId: string, + transactionManager?: EntityManager, + ): Promise[]> { + const dataSourceSchema = + this.workspaceDataSourceService.getSchemaName(workspaceId); + + const workspaceMembers = + await this.workspaceDataSourceService.executeRawQuery( + `SELECT * FROM ${dataSourceSchema}."workspaceMember"`, + [], + workspaceId, + transactionManager, + ); + + return workspaceMembers; + } } diff --git a/packages/twenty-server/src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.module.ts b/packages/twenty-server/src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.module.ts index 36970fe7d..2baba41f0 100644 --- a/packages/twenty-server/src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.module.ts +++ b/packages/twenty-server/src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.module.ts @@ -1,6 +1,7 @@ import { Module } from '@nestjs/common'; import { PersonModule } from 'src/workspace/messaging/repositories/person/person.module'; +import { WorkspaceMemberModule } from 'src/workspace/messaging/repositories/workspace-member/workspace-member.module'; import { CreateCompaniesAndContactsService } from 'src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.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'; @@ -11,6 +12,7 @@ import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/wo WorkspaceDataSourceModule, CreateContactModule, CreateCompanyModule, + WorkspaceMemberModule, PersonModule, ], providers: [CreateCompaniesAndContactsService], diff --git a/packages/twenty-server/src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.service.ts b/packages/twenty-server/src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.service.ts index 2757edd70..9ff76c479 100644 --- a/packages/twenty-server/src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.service.ts +++ b/packages/twenty-server/src/workspace/messaging/services/create-companies-and-contacts/create-companies-and-contacts.service.ts @@ -7,6 +7,9 @@ import { getDomainNameFromHandle } from 'src/workspace/messaging/utils/get-domai import { CreateCompanyService } from 'src/workspace/messaging/services/create-company/create-company.service'; import { CreateContactService } from 'src/workspace/messaging/services/create-contact/create-contact.service'; import { PersonService } from 'src/workspace/messaging/repositories/person/person.service'; +import { WorkspaceMemberService } from 'src/workspace/messaging/repositories/workspace-member/workspace-member.service'; +import { getUniqueParticipantsAndHandles } from 'src/workspace/messaging/utils/get-unique-participants-and-handles.util'; +import { filterOutParticipantsFromCompanyOrWorkspace } from 'src/workspace/messaging/utils/filter-out-participants-from-company-or-workspace.util'; @Injectable() export class CreateCompaniesAndContactsService { @@ -14,6 +17,7 @@ export class CreateCompaniesAndContactsService { private readonly personService: PersonService, private readonly createContactService: CreateContactService, private readonly createCompaniesService: CreateCompanyService, + private readonly workspaceMemberService: WorkspaceMemberService, ) {} async createCompaniesAndContacts( @@ -22,31 +26,26 @@ export class CreateCompaniesAndContactsService { workspaceId: string, transactionManager?: EntityManager, ) { - const selfDomainName = getDomainNameFromHandle(selfHandle); - - // TODO: use isWorkEmail so we can create a contact even if the email is a personal email - const participantsFromOtherCompanies = participants.filter( - (participant) => - getDomainNameFromHandle(participant.handle) !== selfDomainName, - ); - - if (!participantsFromOtherCompanies.length) { + if (participants.length === 0) { return; } - const uniqueHandles = Array.from( - new Set( - participantsFromOtherCompanies.map((participant) => participant.handle), - ), - ); - - const uniqueParticipants = uniqueHandles.map((handle) => { - const participant = participantsFromOtherCompanies.find( - (participant) => participant.handle === handle, + const workspaceMembers = + await this.workspaceMemberService.getAllByWorkspaceId( + workspaceId, + transactionManager, ); - return participant; - }) as Participant[]; + // TODO: use isWorkEmail so we can create a contact even if the email is a personal email ex: @gmail.com + const participantsFromOtherCompanies = + filterOutParticipantsFromCompanyOrWorkspace( + participants, + selfHandle, + workspaceMembers, + ); + + const { uniqueParticipants, uniqueHandles } = + getUniqueParticipantsAndHandles(participantsFromOtherCompanies); const alreadyCreatedContacts = await this.personService.getByEmails( uniqueHandles, diff --git a/packages/twenty-server/src/workspace/messaging/utils/filter-out-participants-from-company-or-workspace.util.ts b/packages/twenty-server/src/workspace/messaging/utils/filter-out-participants-from-company-or-workspace.util.ts new file mode 100644 index 000000000..d9e272fd9 --- /dev/null +++ b/packages/twenty-server/src/workspace/messaging/utils/filter-out-participants-from-company-or-workspace.util.ts @@ -0,0 +1,27 @@ +import { Participant } from 'src/workspace/messaging/types/gmail-message'; +import { getDomainNameFromHandle } from 'src/workspace/messaging/utils/get-domain-name-from-handle.util'; +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'; + +export function filterOutParticipantsFromCompanyOrWorkspace( + participants: Participant[], + selfHandle: string, + workspaceMembers: ObjectRecord[], +): Participant[] { + const selfDomainName = getDomainNameFromHandle(selfHandle); + + const workspaceMembersMap = workspaceMembers.reduce( + (map, workspaceMember) => { + map[workspaceMember.userEmail] = true; + + return map; + }, + new Map(), + ); + + return participants.filter( + (participant) => + getDomainNameFromHandle(participant.handle) !== selfDomainName && + !workspaceMembersMap[participant.handle], + ); +} diff --git a/packages/twenty-server/src/workspace/messaging/utils/get-unique-participants-and-handles.util.ts b/packages/twenty-server/src/workspace/messaging/utils/get-unique-participants-and-handles.util.ts new file mode 100644 index 000000000..bfe455020 --- /dev/null +++ b/packages/twenty-server/src/workspace/messaging/utils/get-unique-participants-and-handles.util.ts @@ -0,0 +1,24 @@ +import { Participant } from 'src/workspace/messaging/types/gmail-message'; + +export function getUniqueParticipantsAndHandles(participants: Participant[]): { + uniqueParticipants: Participant[]; + uniqueHandles: string[]; +} { + if (participants.length === 0) { + return { uniqueParticipants: [], uniqueHandles: [] }; + } + + const uniqueHandles = Array.from( + new Set(participants.map((participant) => participant.handle)), + ); + + const uniqueParticipants = uniqueHandles.map((handle) => { + const participant = participants.find( + (participant) => participant.handle === handle, + ); + + return participant; + }) as Participant[]; + + return { uniqueParticipants, uniqueHandles }; +}