Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
496c5f5
feat: adds contact custom field update when visitor's contact exists
lucas-a-pelegrino Mar 21, 2025
51698f5
test: implements test case for contact custom field update via livech…
lucas-a-pelegrino Mar 27, 2025
dd3d614
chore: fixes lint errors
lucas-a-pelegrino Mar 27, 2025
2d6eea4
chore: improves the quality of contact's custom fields tests
lucas-a-pelegrino Mar 27, 2025
1f6d923
fix: fixes test case before setup
lucas-a-pelegrino Mar 31, 2025
bbe62c2
chore: change contact find method in setCustomFields
lucas-a-pelegrino Mar 31, 2025
c5c8a9d
fix: simplifies before setup
lucas-a-pelegrino Mar 31, 2025
ddadd9d
tests: refactors tests to be more independently
lucas-a-pelegrino Apr 1, 2025
440039a
test: fix contact creation
sampaiodiego Apr 1, 2025
0553d69
test: fix visitor fetch and custom fields validation
sampaiodiego Apr 1, 2025
c2e72b8
refactor: adds minor improvements to setCustomFields logic and tests
lucas-a-pelegrino Apr 1, 2025
6aca79b
fix: removes .only method call
lucas-a-pelegrino Apr 1, 2025
d4ece99
Merge branch 'develop' into bugfix/CTZ-17
lucas-a-pelegrino Apr 2, 2025
3b5e363
refactor: adds changes in the .setCustomFields() return values
lucas-a-pelegrino Apr 2, 2025
4a4c11d
Merge branch 'develop' of github.com:RocketChat/Rocket.Chat into bugf…
lucas-a-pelegrino Apr 2, 2025
4e2ff22
Merge branch 'bugfix/CTZ-17' of github.com:RocketChat/Rocket.Chat int…
lucas-a-pelegrino Apr 2, 2025
0be6691
fix: adds a placeholder return number.
lucas-a-pelegrino Apr 2, 2025
0c8c699
chore: adds minor improvements to the logic that checks for the conta…
lucas-a-pelegrino Apr 2, 2025
6b485f0
chore: adds improvements requested in code review
lucas-a-pelegrino Apr 7, 2025
079c71e
chore: adds changeset
lucas-a-pelegrino Apr 7, 2025
87a6e4e
fix: merge conflicts
lucas-a-pelegrino Apr 11, 2025
8009336
fix: customFields are not wiped when adding new ones
lucas-a-pelegrino Apr 11, 2025
a103c38
Merge branch 'bugfix/CTZ-17' of github.com:RocketChat/Rocket.Chat int…
lucas-a-pelegrino Apr 11, 2025
64785a6
chore: improves logic for contact's custom fields updates
lucas-a-pelegrino Apr 15, 2025
4bb3c61
fix: removes .only leftover by mistake
lucas-a-pelegrino Apr 15, 2025
be33ee8
refactor: adds an improvement to the query and logic that updates the…
lucas-a-pelegrino Apr 16, 2025
f6108f4
chore: removes commented code
lucas-a-pelegrino Apr 16, 2025
76343dd
chore: removes .only leftover
lucas-a-pelegrino Apr 16, 2025
fdd12d8
chore: removes commented code
lucas-a-pelegrino Apr 16, 2025
1177d65
refactor: adds improvements that covers an edge case
lucas-a-pelegrino Apr 17, 2025
42b7e03
Merge remote-tracking branch 'origin/develop' into bugfix/CTZ-17
sampaiodiego Apr 17, 2025
03ce299
doc: improve changeset
sampaiodiego Apr 17, 2025
bdc9272
add TODO
sampaiodiego Apr 17, 2025
63fc15a
remove file again
sampaiodiego Apr 17, 2025
7df9768
revert old behavior
sampaiodiego Apr 17, 2025
9e70f13
Merge branch 'develop' into bugfix/CTZ-17
kodiakhq[bot] Apr 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/young-kiwis-fly.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Fixes contact custom fields not being updated when updating a visitor's custom field
9 changes: 2 additions & 7 deletions apps/meteor/app/livechat/server/api/v1/customField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,12 @@ API.v1.addRoute(
{
async post() {
const { token, key, value, overwrite } = this.bodyParams;

const guest = await findGuest(token);
if (!guest) {
throw new Error('invalid-token');
}

if (!(await setCustomFields({ token, key, value, overwrite }))) {
return API.v1.failure();
}
await setCustomFields({ token, key, value, overwrite });

return API.v1.success({ field: { key, value, overwrite } });
},
Expand All @@ -46,9 +43,7 @@ API.v1.addRoute(
overwrite: boolean;
}): Promise<{ Key: string; value: string; overwrite: boolean }> => {
const data = Object.assign({ token }, customField);
if (!(await setCustomFields(data))) {
throw new Error('error-setting-custom-field');
}
await setCustomFields(data);

return { Key: customField.key, value: customField.value, overwrite: customField.overwrite };
},
Expand Down
16 changes: 11 additions & 5 deletions apps/meteor/app/livechat/server/api/v1/visitor.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { IRoom } from '@rocket.chat/core-typings';
import { LivechatVisitors as VisitorsRaw, LivechatCustomField, LivechatRooms } from '@rocket.chat/models';
import type { IRoom, ILivechatCustomField } from '@rocket.chat/core-typings';
import { LivechatVisitors as VisitorsRaw, LivechatCustomField, LivechatRooms, LivechatContacts } from '@rocket.chat/models';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';

import { callbacks } from '../../../../../lib/callbacks';
import { API } from '../../../../api/server';
import { settings } from '../../../../settings/server';
import { validateRequiredCustomFields } from '../../lib/custom-fields';
import { updateContactsCustomFields, validateRequiredCustomFields } from '../../lib/custom-fields';
import { registerGuest, removeGuest, notifyGuestStatusChanged } from '../../lib/guests';
import { livechatLogger } from '../../lib/logger';
import { saveRoomInfo } from '../../lib/rooms';
Expand Down Expand Up @@ -93,9 +93,9 @@ API.v1.addRoute(
).toArray();
validateRequiredCustomFields(keys, livechatCustomFields);

const matchingCustomFields = livechatCustomFields.filter((field) => keys.includes(field._id));
const matchingCustomFields = livechatCustomFields.filter((field: ILivechatCustomField) => keys.includes(field._id));
const processedKeys = await Promise.all(
matchingCustomFields.map(async (field) => {
matchingCustomFields.map(async (field: ILivechatCustomField) => {
const customField = customFields.find((f) => f.key === field._id);
if (!customField) {
return;
Expand All @@ -107,6 +107,12 @@ API.v1.addRoute(
errors.push(key);
}

// TODO deduplicate this code and the one at the function setCustomFields (apps/meteor/app/livechat/server/lib/custom-fields.ts)
const contacts = await LivechatContacts.findAllByVisitorId(visitor._id).toArray();
if (contacts.length > 0) {
await Promise.all(contacts.map((contact) => updateContactsCustomFields(contact, key, value, overwrite)));
}

return key;
}),
);
Expand Down
38 changes: 35 additions & 3 deletions apps/meteor/app/livechat/server/lib/custom-fields.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ILivechatCustomField } from '@rocket.chat/core-typings';
import { LivechatCustomField, LivechatRooms, LivechatVisitors } from '@rocket.chat/models';
import type { ILivechatContact, ILivechatCustomField } from '@rocket.chat/core-typings';
import { LivechatContacts, LivechatCustomField, LivechatRooms, LivechatVisitors } from '@rocket.chat/models';

import { livechatLogger } from './logger';
import { i18n } from '../../../utils/lib/i18n';
Expand All @@ -19,7 +19,31 @@ export const validateRequiredCustomFields = (customFields: string[], livechatCus
}
};

export async function setCustomFields({ token, key, value, overwrite }: { key: string; value: string; overwrite: boolean; token: string }) {
export async function updateContactsCustomFields(contact: ILivechatContact, key: string, value: string, overwrite: boolean): Promise<void> {
if (overwrite || !contact.customFields || !contact.customFields[key]) {
contact.customFields ??= {};
contact.customFields[key] = value;
} else {
contact.conflictingFields ??= [];
contact.conflictingFields.push({ field: `customFields.${key}`, value });
}

await LivechatContacts.updateContact(contact._id, { customFields: contact.customFields, conflictingFields: contact.conflictingFields });

livechatLogger.debug({ msg: `Contact ${contact._id} updated with custom fields` });
}

export async function setCustomFields({
token,
key,
value,
overwrite,
}: {
key: string;
value: string;
overwrite: boolean;
token: string;
}): Promise<number> {
livechatLogger.debug(`Setting custom fields data for visitor with token ${token}`);

const customField = await LivechatCustomField.findOneById(key);
Expand All @@ -39,6 +63,14 @@ export async function setCustomFields({ token, key, value, overwrite }: { key: s
result = await LivechatRooms.updateDataByToken(token, key, value, overwrite);
} else {
result = await LivechatVisitors.updateLivechatDataByToken(token, key, value, overwrite);

const visitor = await LivechatVisitors.getVisitorByToken(token, { projection: { _id: 1 } });
if (visitor) {
const contacts = await LivechatContacts.findAllByVisitorId(visitor._id).toArray();
if (contacts.length > 0) {
await Promise.all(contacts.map((contact) => updateContactsCustomFields(contact, key, value, overwrite)));
}
}
}

if (typeof result === 'boolean') {
Expand Down
Loading
Loading