Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions .changeset/nine-houses-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@rocket.chat/meteor": patch
"@rocket.chat/livechat": patch
---

Livechat: A registered user loses their messages if 'registerGuest' is called using the same token.
Original file line number Diff line number Diff line change
Expand Up @@ -460,8 +460,6 @@ test.describe('OC - Livechat API', () => {
};

await test.step('Expect registerGuest work with the same token, multiple times', async () => {
test.fail();

await poLiveChat.page.evaluate(() => window.RocketChat.livechat.maximizeWidget());
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).toBeVisible();

Expand Down
75 changes: 56 additions & 19 deletions packages/livechat/src/lib/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,49 @@ import { createToken } from './random';
import { loadMessages } from './room';
import Triggers from './triggers';

const evaluateChangesAndLoadConfigByFields = async (fn) => {
const oldStore = JSON.parse(
JSON.stringify({
user: store.state.user || {},
department: store.state.department,
token: store.state.token,
}),
);
await fn();

/**
* it solves the issues where the registerGuest is called every time the widget is opened
* and the guest is already registered. If there is nothing different in the data,
* it will not call the loadConfig again.
*
* if user changes, it will call loadConfig
* if department changes, it will call loadConfig
* if token changes, it will call loadConfig
*/

if (oldStore.user._id !== store.state.user?._id) {
await loadConfig();
await loadMessages();
return;
}

if (oldStore.department !== store.state.department) {
await loadConfig();
await loadMessages();
return;
}

if (oldStore.token !== store.state.token) {
await loadConfig();
await loadMessages();
}
};

const createOrUpdateGuest = async (guest) => {
const { token } = guest;
token && (await store.setState({ token }));
const { visitor: user } = await Livechat.grantVisitor({ visitor: { ...guest } });
store.setState({ user });
await loadConfig();
};

const updateIframeGuestData = (data) => {
Expand Down Expand Up @@ -76,15 +113,16 @@ const api = {
});
},

async setDepartment(value) {
setDepartment: async (value) => {
await evaluateChangesAndLoadConfigByFields(async () => api._setDepartment(value));
},

async _setDepartment(value) {
const {
user,
config: { departments = [] },
defaultAgent,
} = store.state;

const { department: existingDepartment } = user || {};

const department = departments.find((dep) => dep._id === value || dep.name === value)?._id || '';

updateIframeGuestData({ department });
Expand All @@ -93,11 +131,6 @@ const api = {
if (defaultAgent && defaultAgent.department !== department) {
store.setState({ defaultAgent: null });
}

if (department !== existingDepartment) {
await loadConfig();
await loadMessages();
}
},

async setBusinessUnit(newBusinessUnit) {
Expand Down Expand Up @@ -143,7 +176,9 @@ const api = {
if (token === localToken) {
return;
}
await createOrUpdateGuest({ token });
await evaluateChangesAndLoadConfigByFields(async () => {
await createOrUpdateGuest({ token });
});
},

setGuestName(name) {
Expand All @@ -159,17 +194,19 @@ const api = {
return;
}

if (!data.token) {
data.token = createToken();
}
await evaluateChangesAndLoadConfigByFields(async () => {
if (!data.token) {
data.token = createToken();
}

if (data.department) {
api.setDepartment(data.department);
}
if (data.department) {
await api._setDepartment(data.department);
}

Livechat.unsubscribeAll();
Livechat.unsubscribeAll();

await createOrUpdateGuest(data);
await createOrUpdateGuest(data);
});
},

async setLanguage(language) {
Expand Down