diff --git a/.changeset/brave-brooms-invent.md b/.changeset/brave-brooms-invent.md new file mode 100644 index 000000000000..35d32b485944 --- /dev/null +++ b/.changeset/brave-brooms-invent.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixes a problem that caused visitor creation to fail when GDPR setting was enabled and visitor was created via Apps Engine or the deprecated `livechat:registerGuest` method. diff --git a/apps/meteor/app/livechat/server/lib/LivechatTyped.ts b/apps/meteor/app/livechat/server/lib/LivechatTyped.ts index be79d565f6de..6c7c3c04fd1d 100644 --- a/apps/meteor/app/livechat/server/lib/LivechatTyped.ts +++ b/apps/meteor/app/livechat/server/lib/LivechatTyped.ts @@ -588,6 +588,10 @@ class LivechatClass { } } + isValidObject(obj: unknown): obj is Record { + return typeof obj === 'object' && obj !== null; + } + async registerGuest({ id, token, @@ -653,10 +657,10 @@ class LivechatClass { visitorDataToUpdate.status = status; visitorDataToUpdate.ts = new Date(); - if (settings.get('Livechat_Allow_collect_and_store_HTTP_header_informations')) { + if (settings.get('Livechat_Allow_collect_and_store_HTTP_header_informations') && Livechat.isValidObject(connectionData)) { Livechat.logger.debug(`Saving connection data for visitor ${token}`); const { httpHeaders, clientAddress } = connectionData; - if (httpHeaders) { + if (Livechat.isValidObject(httpHeaders)) { visitorDataToUpdate.userAgent = httpHeaders['user-agent']; visitorDataToUpdate.ip = httpHeaders['x-real-ip'] || httpHeaders['x-forwarded-for'] || clientAddress; visitorDataToUpdate.host = httpHeaders?.host; diff --git a/apps/meteor/tests/end-to-end/api/livechat/09-visitors.ts b/apps/meteor/tests/end-to-end/api/livechat/09-visitors.ts index 5bc961087efc..889f497bb209 100644 --- a/apps/meteor/tests/end-to-end/api/livechat/09-visitors.ts +++ b/apps/meteor/tests/end-to-end/api/livechat/09-visitors.ts @@ -1,11 +1,11 @@ import { faker } from '@faker-js/faker'; import type { ILivechatVisitor } from '@rocket.chat/core-typings'; import { expect } from 'chai'; -import { before, describe, it } from 'mocha'; +import { before, describe, it, after } from 'mocha'; import moment from 'moment'; import { type Response } from 'supertest'; -import { getCredentials, api, request, credentials } from '../../../data/api-data'; +import { getCredentials, api, request, credentials, methodCallAnon } from '../../../data/api-data'; import { createCustomField, deleteCustomField } from '../../../data/livechat/custom-fields'; import { makeAgentAvailable, @@ -216,6 +216,30 @@ describe('LIVECHAT - visitors', () => { expect(body.visitor).to.have.property('livechatData'); expect(body.visitor.livechatData).to.have.property(customFieldName, 'Not a real address :)'); }); + + describe('special cases', () => { + before(async () => { + await updateSetting('Livechat_Allow_collect_and_store_HTTP_header_informations', true); + }); + after(async () => { + await updateSetting('Livechat_Allow_collect_and_store_HTTP_header_informations', false); + }); + + // Note: this had to use the meteor method because the endpoint used `req.headers` which we cannot send as empty + // method doesn't pass them to the func allowing us to create a test for it + it('should allow to create a visitor without passing connectionData when GDPR setting is enabled', async () => { + const token = `${new Date().getTime()}-test`; + const response = await request + .post(methodCallAnon('livechat:registerGuest')) + .send({ message: `{"msg":"method","id":"23","method":"livechat:registerGuest","params":[{ "token": "${token}"}]}` }); + + expect(response.body).to.have.property('success', true); + const r = JSON.parse(response.body.message); + + expect(r.result).to.have.property('visitor'); + expect(r.result.visitor).to.have.property('token', token); + }); + }); }); describe('livechat/visitors.info', () => {