diff --git a/apps/meteor/app/livechat/server/api/lib/visitors.js b/apps/meteor/app/livechat/server/api/lib/visitors.js index 3823193189dc..cfa62ead68d6 100644 --- a/apps/meteor/app/livechat/server/api/lib/visitors.js +++ b/apps/meteor/app/livechat/server/api/lib/visitors.js @@ -141,6 +141,7 @@ export async function findVisitorsByEmailOrPhoneOrNameOrUsernameOrCustomField({ const { cursor, totalCount } = await LivechatVisitors.findPaginatedVisitorsByEmailOrPhoneOrNameOrUsernameOrCustomField( emailOrPhone, nameOrUsername, + allowedCF, { sort: sort || { ts: -1 }, skip: offset, @@ -154,7 +155,6 @@ export async function findVisitorsByEmailOrPhoneOrNameOrUsernameOrCustomField({ lastChat: 1, }, }, - allowedCF, ); const [visitors, total] = await Promise.all([cursor.toArray(), totalCount]); diff --git a/apps/meteor/app/livechat/server/api/v1/contact.ts b/apps/meteor/app/livechat/server/api/v1/contact.ts index fc41daa3b605..f0c49ce5d776 100644 --- a/apps/meteor/app/livechat/server/api/v1/contact.ts +++ b/apps/meteor/app/livechat/server/api/v1/contact.ts @@ -1,6 +1,7 @@ import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { LivechatCustomField, LivechatVisitors } from '@rocket.chat/models'; +import { escapeRegExp } from '@rocket.chat/string-helpers'; import { API } from '../../../../api/server'; import { Contacts } from '../../lib/Contacts'; @@ -54,21 +55,18 @@ API.v1.addRoute( if (!email && !phone && !custom) { throw new Meteor.Error('error-invalid-params'); } - let foundCF = {}; - if (custom) { + const foundCF = (async () => { + if (!custom) { + return {}; + } + const customObj = Object.fromEntries(Array.from(new URLSearchParams(custom))); - const customFields = await LivechatCustomField.findMatchingCustomFields( - 'visitor', - true, - {}, - { _id: { $in: Object.keys(customObj) } }, - ) - .map(({ _id }) => _id) - .map((id: string) => [id, customObj[id]]) - .toArray(); - foundCF = Object.fromEntries(customFields); - } + const customFields = await LivechatCustomField.findMatchingCustomFieldsByIds(Object.keys(customObj), 'visitor', true).toArray(); + + return Object.fromEntries(customFields.map(({ _id }) => [`livechatData.${_id}`, new RegExp(escapeRegExp(customObj[_id], 'i'))])); + })(); + const contact = await LivechatVisitors.findOneByEmailAndPhoneAndCustomField(email, phone, foundCF); return API.v1.success({ contact }); }, diff --git a/apps/meteor/server/models/raw/LivechatCustomField.ts b/apps/meteor/server/models/raw/LivechatCustomField.ts index d9a31a895098..be37341a8464 100644 --- a/apps/meteor/server/models/raw/LivechatCustomField.ts +++ b/apps/meteor/server/models/raw/LivechatCustomField.ts @@ -20,13 +20,26 @@ export class LivechatCustomFieldRaw extends BaseRaw implem findMatchingCustomFields( scope: ILivechatCustomField['scope'], searchable = true, - options: FindOptions = {}, - extraFilter: { [key: string]: string | string[] | { [key: string]: string | string[] } } = {}, + options?: FindOptions, ): FindCursor { const query = { scope, searchable, - ...extraFilter, + }; + + return this.find(query, options); + } + + findMatchingCustomFieldsByIds( + ids: ILivechatCustomField['_id'][], + scope: ILivechatCustomField['scope'], + searchable = true, + options?: FindOptions, + ): FindCursor { + const query = { + _id: { $in: ids }, + scope, + searchable, }; return this.find(query, options); diff --git a/apps/meteor/server/models/raw/LivechatVisitors.ts b/apps/meteor/server/models/raw/LivechatVisitors.ts index 7d84bf6672ae..e87ec9496df7 100644 --- a/apps/meteor/server/models/raw/LivechatVisitors.ts +++ b/apps/meteor/server/models/raw/LivechatVisitors.ts @@ -162,8 +162,8 @@ export class LivechatVisitorsRaw extends BaseRaw implements IL async findPaginatedVisitorsByEmailOrPhoneOrNameOrUsernameOrCustomField( emailOrPhone: string, nameOrUsername: RegExp, - options: FindOptions, allowedCustomFields: string[] = [], + options?: FindOptions, ): Promise>> { const query = { $or: [ @@ -180,7 +180,6 @@ export class LivechatVisitorsRaw extends BaseRaw implements IL username: nameOrUsername, }, // nameorusername is a clean regex, so we should be good - ...allowedCustomFields.map((c: string) => ({ [`livechatData.${c}`]: nameOrUsername })), ], }; @@ -198,14 +197,7 @@ export class LivechatVisitorsRaw extends BaseRaw implements IL { ...(email && { visitorEmails: { address: email } }), ...(phone && { phone: { phoneNumber: phone } }), - ...(customFields && - Object.keys(customFields).length && - Object.fromEntries( - Object.keys(customFields).map((fieldName: string) => [ - `livechatData.${fieldName}`, - new RegExp(escapeRegExp(customFields[fieldName]), 'i'), - ]), - )), + ...customFields, }, ); diff --git a/packages/model-typings/src/models/ILivechatCustomFieldModel.ts b/packages/model-typings/src/models/ILivechatCustomFieldModel.ts index af2a035e3933..ebe7f420868a 100644 --- a/packages/model-typings/src/models/ILivechatCustomFieldModel.ts +++ b/packages/model-typings/src/models/ILivechatCustomFieldModel.ts @@ -10,7 +10,12 @@ export interface ILivechatCustomFieldModel extends IBaseModel, - extraFilter: { [key: string]: string | string[] | { [key: string]: string | string[] } }, + options?: FindOptions, + ): FindCursor; + findMatchingCustomFieldsByIds( + ids: ILivechatCustomField['_id'][], + scope: ILivechatCustomField['scope'], + searchable: boolean, + options?: FindOptions, ): FindCursor; }