Update workspace entities to make all TEXT nullable (#16144)
Follow up on #15926 --------- Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com> Co-authored-by: guillim <guigloo@msn.com>
This commit is contained in:
+5
@@ -1,5 +1,6 @@
|
||||
import { Scope } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { And, Any, ILike, In, Not, Or } from 'typeorm';
|
||||
|
||||
import { type ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event';
|
||||
@@ -54,6 +55,10 @@ export class BlocklistItemDeleteMessagesJob {
|
||||
acc.set(workspaceMemberId, []);
|
||||
}
|
||||
|
||||
if (!isDefined(handle)) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
acc.get(workspaceMemberId)?.push(handle);
|
||||
|
||||
return acc;
|
||||
|
||||
+4
-2
@@ -146,7 +146,8 @@ export class MessageChannelWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
description: msg`Handle`,
|
||||
icon: 'IconAt',
|
||||
})
|
||||
handle: string;
|
||||
@WorkspaceIsNullable()
|
||||
handle: string | null;
|
||||
|
||||
@WorkspaceField({
|
||||
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.type,
|
||||
@@ -304,7 +305,8 @@ export class MessageChannelWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
description: msg`Last sync cursor`,
|
||||
icon: 'IconHistory',
|
||||
})
|
||||
syncCursor: string;
|
||||
@WorkspaceIsNullable()
|
||||
syncCursor: string | null;
|
||||
|
||||
@WorkspaceField({
|
||||
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.syncedAt,
|
||||
|
||||
+5
-3
@@ -1,9 +1,9 @@
|
||||
import { registerEnumType } from '@nestjs/graphql';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
import { Relation } from 'typeorm';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
@@ -47,7 +47,8 @@ export class MessageFolderWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
description: msg`Folder name`,
|
||||
icon: 'IconFolder',
|
||||
})
|
||||
name: string;
|
||||
@WorkspaceIsNullable()
|
||||
name: string | null;
|
||||
|
||||
@WorkspaceRelation({
|
||||
standardId: MESSAGE_FOLDER_STANDARD_FIELD_IDS.messageChannel,
|
||||
@@ -68,7 +69,8 @@ export class MessageFolderWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
description: msg`Sync Cursor`,
|
||||
icon: 'IconHash',
|
||||
})
|
||||
syncCursor: string;
|
||||
@WorkspaceIsNullable()
|
||||
syncCursor: string | null;
|
||||
|
||||
@WorkspaceField({
|
||||
standardId: MESSAGE_FOLDER_STANDARD_FIELD_IDS.isSentFolder,
|
||||
|
||||
+5
-3
@@ -1,6 +1,6 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
@@ -55,7 +55,8 @@ export class MessageParticipantWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
description: msg`Handle`,
|
||||
icon: 'IconAt',
|
||||
})
|
||||
handle: string;
|
||||
@WorkspaceIsNullable()
|
||||
handle: string | null;
|
||||
|
||||
@WorkspaceField({
|
||||
standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.displayName,
|
||||
@@ -64,7 +65,8 @@ export class MessageParticipantWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
description: msg`Display Name`,
|
||||
icon: 'IconUser',
|
||||
})
|
||||
displayName: string;
|
||||
@WorkspaceIsNullable()
|
||||
displayName: string | null;
|
||||
|
||||
@WorkspaceRelation({
|
||||
standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.message,
|
||||
|
||||
+7
-4
@@ -1,6 +1,6 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
@@ -39,7 +39,8 @@ export class MessageWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
description: msg`Message id from the message header`,
|
||||
icon: 'IconHash',
|
||||
})
|
||||
headerMessageId: string;
|
||||
@WorkspaceIsNullable()
|
||||
headerMessageId: string | null;
|
||||
|
||||
@WorkspaceField({
|
||||
standardId: MESSAGE_STANDARD_FIELD_IDS.subject,
|
||||
@@ -48,7 +49,8 @@ export class MessageWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
description: msg`Subject`,
|
||||
icon: 'IconMessage',
|
||||
})
|
||||
subject: string;
|
||||
@WorkspaceIsNullable()
|
||||
subject: string | null;
|
||||
|
||||
@WorkspaceField({
|
||||
standardId: MESSAGE_STANDARD_FIELD_IDS.text,
|
||||
@@ -57,7 +59,8 @@ export class MessageWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
description: msg`Text`,
|
||||
icon: 'IconMessage',
|
||||
})
|
||||
text: string;
|
||||
@WorkspaceIsNullable()
|
||||
text: string | null;
|
||||
|
||||
@WorkspaceField({
|
||||
standardId: MESSAGE_STANDARD_FIELD_IDS.receivedAt,
|
||||
|
||||
+2
-2
@@ -218,7 +218,7 @@ export class SyncMessageFoldersService {
|
||||
if (isDefined(existingFolder.externalId)) {
|
||||
existingFolderMap.set(existingFolder.externalId, existingFolder);
|
||||
}
|
||||
existingFolderMap.set(existingFolder.name, existingFolder);
|
||||
existingFolderMap.set(existingFolder.name ?? '', existingFolder);
|
||||
}
|
||||
|
||||
return existingFolderMap;
|
||||
@@ -250,6 +250,6 @@ export class SyncMessageFoldersService {
|
||||
return MessageFolderName.SENT_ITEMS;
|
||||
}
|
||||
|
||||
return folder.name;
|
||||
return folder.name ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -43,4 +43,6 @@ export enum MessageImportDriverExceptionCode {
|
||||
SYNC_CURSOR_ERROR = 'SYNC_CURSOR_ERROR',
|
||||
PROVIDER_NOT_SUPPORTED = 'PROVIDER_NOT_SUPPORTED',
|
||||
CLIENT_NOT_AVAILABLE = 'CLIENT_NOT_AVAILABLE',
|
||||
ACCESS_TOKEN_MISSING = 'ACCESS_TOKEN_MISSING',
|
||||
CHANNEL_MISCONFIGURED = 'CHANNEL_MISCONFIGURED',
|
||||
}
|
||||
|
||||
+10
@@ -5,6 +5,10 @@ import { type gmail_v1 as gmailV1 } from 'googleapis';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||
import {
|
||||
MessageImportDriverException,
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { GmailFetchByBatchService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-fetch-by-batch.service';
|
||||
import { GmailMessagesImportErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-messages-import-error-handler.service';
|
||||
import { parseAndFormatGmailMessage } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/parse-and-format-gmail-message.util';
|
||||
@@ -24,6 +28,12 @@ export class GmailGetMessagesService {
|
||||
'accessToken' | 'id' | 'handle' | 'handleAliases'
|
||||
>,
|
||||
): Promise<MessageWithParticipants[]> {
|
||||
if (!isDefined(connectedAccount.accessToken)) {
|
||||
throw new MessageImportDriverException(
|
||||
'Access token is required',
|
||||
MessageImportDriverExceptionCode.ACCESS_TOKEN_MISSING,
|
||||
);
|
||||
}
|
||||
const { messageIdsByBatch, batchResponses } =
|
||||
await this.fetchByBatchesService.fetchAllByBatches(
|
||||
messageIds,
|
||||
|
||||
+19
-3
@@ -1,12 +1,15 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { ImapFlow } from 'imapflow';
|
||||
import { ConnectedAccountProvider } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { CustomError, isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type ImapSmtpCaldavParams } from 'src/engine/core-modules/imap-smtp-caldav-connection/types/imap-smtp-caldav-connection.type';
|
||||
import { type ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||
import {
|
||||
MessageImportDriverException,
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
|
||||
type ConnectedAccountIdentifier = Pick<
|
||||
ConnectedAccountWorkspaceEntity,
|
||||
@@ -83,13 +86,26 @@ export class ImapClientProvider {
|
||||
let client: ImapFlow | null = null;
|
||||
let timeoutId: NodeJS.Timeout | null = null;
|
||||
|
||||
if (!isDefined(connectionParameters.IMAP?.username)) {
|
||||
throw new MessageImportDriverException(
|
||||
'Username is required',
|
||||
MessageImportDriverExceptionCode.CHANNEL_MISCONFIGURED,
|
||||
);
|
||||
}
|
||||
|
||||
if (!isDefined(connectedAccount.handle)) {
|
||||
throw new CustomError(
|
||||
'Handle is required',
|
||||
MessageImportDriverExceptionCode.CHANNEL_MISCONFIGURED,
|
||||
);
|
||||
}
|
||||
try {
|
||||
client = new ImapFlow({
|
||||
host: connectionParameters.IMAP?.host || '',
|
||||
port: connectionParameters.IMAP?.port || 993,
|
||||
secure: connectionParameters.IMAP?.secure,
|
||||
auth: {
|
||||
user: isNonEmptyString(connectionParameters.IMAP?.username)
|
||||
user: isDefined(connectionParameters.IMAP?.username)
|
||||
? connectionParameters.IMAP?.username
|
||||
: connectedAccount.handle,
|
||||
pass: connectionParameters.IMAP?.password || '',
|
||||
|
||||
+15
-3
@@ -1,11 +1,16 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { type ImapFlow } from 'imapflow';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type MessageFolderWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-folder.workspace-entity';
|
||||
import {
|
||||
MessageImportDriverException,
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { ImapClientProvider } from 'src/modules/messaging/message-import-manager/drivers/imap/providers/imap-client.provider';
|
||||
import { ImapMessageListFetchErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-message-list-fetch-error-handler.service';
|
||||
import { ImapIncrementalSyncService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-incremental-sync.service';
|
||||
import { ImapMessageListFetchErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-message-list-fetch-error-handler.service';
|
||||
import { createSyncCursor } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/create-sync-cursor.util';
|
||||
import { extractMailboxState } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/extract-mailbox-state.util';
|
||||
import {
|
||||
@@ -67,7 +72,7 @@ export class ImapGetMessageListService {
|
||||
result.push({
|
||||
messageExternalIds: [],
|
||||
nextSyncCursor: folder.syncCursor || '',
|
||||
previousSyncCursor: folder.syncCursor,
|
||||
previousSyncCursor: folder.syncCursor || '',
|
||||
messageExternalIdsToDelete: [],
|
||||
folderId: folder.id,
|
||||
});
|
||||
@@ -86,7 +91,7 @@ export class ImapGetMessageListService {
|
||||
return messageFolders.map((folder) => ({
|
||||
messageExternalIds: [],
|
||||
nextSyncCursor: folder.syncCursor || '',
|
||||
previousSyncCursor: folder.syncCursor,
|
||||
previousSyncCursor: folder.syncCursor || '',
|
||||
messageExternalIdsToDelete: [],
|
||||
folderId: folder.id,
|
||||
}));
|
||||
@@ -102,6 +107,13 @@ export class ImapGetMessageListService {
|
||||
folder: string,
|
||||
messageFolder: Pick<MessageFolderWorkspaceEntity, 'syncCursor'>,
|
||||
): Promise<GetOneMessageListResponse> {
|
||||
if (!isDefined(messageFolder.syncCursor)) {
|
||||
throw new MessageImportDriverException(
|
||||
'Message folder sync cursor is required',
|
||||
MessageImportDriverExceptionCode.SYNC_CURSOR_ERROR,
|
||||
);
|
||||
}
|
||||
|
||||
const { messages, messageExternalUidsToDelete, syncCursor } =
|
||||
await this.getMessagesFromFolder(
|
||||
client,
|
||||
|
||||
+8
@@ -6,6 +6,7 @@ import {
|
||||
type PageIteratorCallback,
|
||||
} from '@microsoft/microsoft-graph-client';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { OAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/services/oauth2-client-manager.service';
|
||||
import { type ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||
@@ -115,6 +116,13 @@ export class MicrosoftGetMessageListService {
|
||||
this.microsoftMessageListFetchErrorHandler.handleError(error);
|
||||
});
|
||||
|
||||
if (!isDefined(messageFolder.syncCursor)) {
|
||||
throw new MessageImportDriverException(
|
||||
'Message folder sync cursor is required',
|
||||
MessageImportDriverExceptionCode.SYNC_CURSOR_ERROR,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
messageExternalIds,
|
||||
messageExternalIdsToDelete,
|
||||
|
||||
+9
-4
@@ -1,6 +1,9 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { createTransport, type Transporter } from 'nodemailer';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import type SMTPConnection from 'nodemailer/lib/smtp-connection';
|
||||
|
||||
import { type ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||
|
||||
@@ -14,21 +17,23 @@ export class SmtpClientProvider {
|
||||
): Promise<Transporter> {
|
||||
const smtpParams = connectedAccount.connectionParameters?.SMTP;
|
||||
|
||||
if (!smtpParams) {
|
||||
if (!isDefined(smtpParams)) {
|
||||
throw new Error('SMTP settings not configured for this account');
|
||||
}
|
||||
|
||||
const transporter = createTransport({
|
||||
const options: SMTPConnection.Options = {
|
||||
host: smtpParams.host,
|
||||
port: smtpParams.port,
|
||||
auth: {
|
||||
user: smtpParams.username ?? connectedAccount.handle,
|
||||
user: smtpParams.username ?? connectedAccount.handle ?? '',
|
||||
pass: smtpParams.password,
|
||||
},
|
||||
tls: {
|
||||
rejectUnauthorized: false,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const transporter = createTransport(options);
|
||||
|
||||
return transporter;
|
||||
}
|
||||
|
||||
+2
@@ -87,6 +87,8 @@ export class MessageImportExceptionHandlerService {
|
||||
workspaceId,
|
||||
);
|
||||
break;
|
||||
case MessageImportDriverExceptionCode.CHANNEL_MISCONFIGURED:
|
||||
case MessageImportDriverExceptionCode.ACCESS_TOKEN_MISSING:
|
||||
case MessageImportDriverExceptionCode.UNKNOWN:
|
||||
case MessageImportDriverExceptionCode.UNKNOWN_NETWORK_ERROR:
|
||||
default:
|
||||
|
||||
+23
-1
@@ -1,5 +1,7 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator';
|
||||
import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service';
|
||||
import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum';
|
||||
@@ -14,6 +16,10 @@ import {
|
||||
MessageChannelSyncStage,
|
||||
type MessageChannelWorkspaceEntity,
|
||||
} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||
import {
|
||||
MessageImportDriverException,
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { MESSAGING_GMAIL_USERS_MESSAGES_GET_BATCH_SIZE } from 'src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-get-batch-size.constant';
|
||||
import { MessagingAccountAuthenticationService } from 'src/modules/messaging/message-import-manager/services/messaging-account-authentication.service';
|
||||
import { MessagingGetMessagesService } from 'src/modules/messaging/message-import-manager/services/messaging-get-messages.service';
|
||||
@@ -114,11 +120,27 @@ export class MessagingMessagesImportService {
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
if (!isDefined(messageChannel.handle)) {
|
||||
throw new MessageImportDriverException(
|
||||
'Message channel handle is required',
|
||||
MessageImportDriverExceptionCode.CHANNEL_MISCONFIGURED,
|
||||
);
|
||||
}
|
||||
|
||||
if (!isDefined(connectedAccountWithFreshTokens.handleAliases)) {
|
||||
throw new MessageImportDriverException(
|
||||
'Message channel handle is required',
|
||||
MessageImportDriverExceptionCode.CHANNEL_MISCONFIGURED,
|
||||
);
|
||||
}
|
||||
|
||||
const messagesToSave = filterEmails(
|
||||
messageChannel.handle,
|
||||
[...connectedAccountWithFreshTokens.handleAliases.split(',')],
|
||||
allMessages,
|
||||
blocklist.map((blocklistItem) => blocklistItem.handle),
|
||||
blocklist
|
||||
.map((blocklistItem) => blocklistItem.handle)
|
||||
.filter(isDefined),
|
||||
messageChannel.excludeGroupEmails,
|
||||
);
|
||||
|
||||
|
||||
+12
-1
@@ -8,6 +8,10 @@ import { z } from 'zod';
|
||||
|
||||
import { OAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/services/oauth2-client-manager.service';
|
||||
import { type ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||
import {
|
||||
MessageImportDriverException,
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { ImapClientProvider } from 'src/modules/messaging/message-import-manager/drivers/imap/providers/imap-client.provider';
|
||||
import { SmtpClientProvider } from 'src/modules/messaging/message-import-manager/drivers/smtp/providers/smtp-client.provider';
|
||||
import { mimeEncode } from 'src/modules/messaging/message-import-manager/utils/mime-encode.util';
|
||||
@@ -140,6 +144,13 @@ export class MessagingSendMessageService {
|
||||
const smtpClient =
|
||||
await this.smtpClientProvider.getSmtpClient(connectedAccount);
|
||||
|
||||
if (!isDefined(handle)) {
|
||||
throw new MessageImportDriverException(
|
||||
'Handle is required',
|
||||
MessageImportDriverExceptionCode.CHANNEL_MISCONFIGURED,
|
||||
);
|
||||
}
|
||||
|
||||
const mail = new MailComposer({
|
||||
from: handle,
|
||||
to: sendMessageInput.to,
|
||||
@@ -178,7 +189,7 @@ export class MessagingSendMessageService {
|
||||
(messageFolder) => messageFolder.isSentFolder,
|
||||
);
|
||||
|
||||
if (isDefined(sentFolder)) {
|
||||
if (isDefined(sentFolder) && isDefined(sentFolder.name)) {
|
||||
await imapClient.append(sentFolder.name, messageBuffer);
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -1,3 +1,5 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type MessageWithParticipants } from 'src/modules/messaging/message-import-manager/types/message';
|
||||
import { getDomainNameByEmail } from 'src/utils/get-domain-name-by-email';
|
||||
|
||||
@@ -14,9 +16,10 @@ export const filterOutInternals = (
|
||||
|
||||
try {
|
||||
const isAllHandlesFromSameDomain = message.participants
|
||||
.filter((participant) => !!participant.handle)
|
||||
.filter((participant) => isDefined(participant.handle))
|
||||
.every(
|
||||
(participant) =>
|
||||
isDefined(participant.handle) &&
|
||||
getDomainNameByEmail(participant.handle) === primaryHandleDomain,
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user