diff --git a/.changeset/pretty-clocks-add.md b/.changeset/pretty-clocks-add.md new file mode 100644 index 0000000000000000000000000000000000000000..cea893b285d7b9289168c909136e8a093015f784 --- /dev/null +++ b/.changeset/pretty-clocks-add.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": patch +"@rocket.chat/model-typings": patch +--- + +fix: hidden custom fields being required in some cases diff --git a/apps/meteor/app/livechat/server/lib/Contacts.ts b/apps/meteor/app/livechat/server/lib/Contacts.ts index 74ea04fb19e547040c1b555f5bee4f94dc9c7646..9fa441bd5a60ae369d53bc246145866035683b4f 100644 --- a/apps/meteor/app/livechat/server/lib/Contacts.ts +++ b/apps/meteor/app/livechat/server/lib/Contacts.ts @@ -72,9 +72,13 @@ export const Contacts = { } } - const allowedCF = LivechatCustomField.findByScope<Pick<ILivechatCustomField, '_id' | 'label' | 'regexp' | 'required'>>('visitor', { - projection: { _id: 1, label: 1, regexp: 1, required: 1 }, - }); + const allowedCF = LivechatCustomField.findByScope<Pick<ILivechatCustomField, '_id' | 'label' | 'regexp' | 'required' | 'visibility'>>( + 'visitor', + { + projection: { _id: 1, label: 1, regexp: 1, required: 1 }, + }, + false, + ); const livechatData: Record<string, string> = {}; diff --git a/apps/meteor/server/models/raw/LivechatCustomField.ts b/apps/meteor/server/models/raw/LivechatCustomField.ts index be37341a846461746f48defb8a39cc9f82f08d91..46bc32c52177c5aa409ea3fb0594f4537bd697b9 100644 --- a/apps/meteor/server/models/raw/LivechatCustomField.ts +++ b/apps/meteor/server/models/raw/LivechatCustomField.ts @@ -13,8 +13,12 @@ export class LivechatCustomFieldRaw extends BaseRaw<ILivechatCustomField> implem return [{ key: { scope: 1 } }]; } - findByScope(scope: ILivechatCustomField['scope'], options?: FindOptions<ILivechatCustomField>): FindCursor<ILivechatCustomField> { - return this.find({ scope }, options || {}); + findByScope( + scope: ILivechatCustomField['scope'], + options?: FindOptions<ILivechatCustomField>, + includeHidden = true, + ): FindCursor<ILivechatCustomField> { + return this.find({ scope, ...(includeHidden === true ? {} : { visibility: { $ne: 'hidden' } }) }, options); } findMatchingCustomFields( diff --git a/apps/meteor/tests/e2e/omnichannel-contact-center.spec.ts b/apps/meteor/tests/e2e/omnichannel-contact-center.spec.ts index 8cb47b0556a32583e871fa5430537b91bbc79256..54a1ecf35a512cbf63eba8bc80870b03a306f10a 100644 --- a/apps/meteor/tests/e2e/omnichannel-contact-center.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel-contact-center.spec.ts @@ -1,6 +1,7 @@ import { faker } from '@faker-js/faker'; import { createToken } from '../../client/lib/utils/createToken'; +import { IS_EE } from './config/constants'; import { Users } from './fixtures/userStates'; import { OmnichannelContacts } from './page-objects/omnichannel-contacts-list'; import { OmnichannelSection } from './page-objects/omnichannel-section'; @@ -18,6 +19,16 @@ const createContact = (generateToken = false) => ({ const NEW_CONTACT = createContact(); const EDIT_CONTACT = createContact(); const EXISTING_CONTACT = createContact(true); +const NEW_CUSTOM_FIELD = { + searchable: true, + field: 'hiddenCustomField', + label: 'hiddenCustomField', + defaultValue: 'test_contact_center_hidden_customField', + scope: 'visitor', + visibility: 'hidden', + required: true, + regexp: '', +} const URL = { contactCenter: '/omnichannel-directory/contacts', @@ -47,12 +58,19 @@ test.describe('Omnichannel Contact Center', () => { // Add a contact const { id: _, ...data } = EXISTING_CONTACT; await api.post('/omnichannel/contact', data); + + if (IS_EE) { + await api.post('/livechat/custom.field', NEW_CUSTOM_FIELD); + } }); test.afterAll(async ({ api }) => { // Remove added contacts await api.delete('/livechat/visitor', { token: EXISTING_CONTACT.token }); await api.delete('/livechat/visitor', { token: NEW_CONTACT.token }); + if (IS_EE) { + await api.post('method.call/livechat:removeCustomField', { message: NEW_CUSTOM_FIELD.field }); + } }); test.beforeEach(async ({ page }) => { diff --git a/packages/model-typings/src/models/ILivechatCustomFieldModel.ts b/packages/model-typings/src/models/ILivechatCustomFieldModel.ts index 55fc49cde002fccda28561a9bb4b10b20163ba76..856d39c2dd4d0ab7c803c868ebb63d171eef1884 100644 --- a/packages/model-typings/src/models/ILivechatCustomFieldModel.ts +++ b/packages/model-typings/src/models/ILivechatCustomFieldModel.ts @@ -5,8 +5,16 @@ import type { IBaseModel } from './IBaseModel'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface ILivechatCustomFieldModel extends IBaseModel<ILivechatCustomField> { - findByScope<T extends Document = ILivechatCustomField>(scope: ILivechatCustomField['scope'], options?: FindOptions<T>): FindCursor<T>; - findByScope(scope: ILivechatCustomField['scope'], options?: FindOptions<ILivechatCustomField>): FindCursor<ILivechatCustomField>; + findByScope<T extends Document = ILivechatCustomField>( + scope: ILivechatCustomField['scope'], + options?: FindOptions<T>, + includeHidden?: boolean, + ): FindCursor<T>; + findByScope( + scope: ILivechatCustomField['scope'], + options?: FindOptions<ILivechatCustomField>, + includeHidden?: boolean, + ): FindCursor<ILivechatCustomField>; findMatchingCustomFields( scope: ILivechatCustomField['scope'], searchable: boolean,