diff --git a/.changeset/wicked-months-laugh.md b/.changeset/wicked-months-laugh.md new file mode 100644 index 0000000000000..684b4180a257c --- /dev/null +++ b/.changeset/wicked-months-laugh.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fix users presence stuck as online after connecting using mobile apps diff --git a/apps/meteor/ee/server/startup/presence.ts b/apps/meteor/ee/server/startup/presence.ts index ea3cd789f6f35..3e8daad4b259d 100644 --- a/apps/meteor/ee/server/startup/presence.ts +++ b/apps/meteor/ee/server/startup/presence.ts @@ -30,9 +30,16 @@ Meteor.startup(() => { }); Accounts.onLogin((login: any): void => { - if (login.type !== 'resume') { + if (login.type !== 'resume' || !login.connection.id) { return; } + + // validate if it is a real WS connection and is still open + const session = Meteor.server.sessions.get(login.connection.id); + if (!session) { + return; + } + void (async function () { await Presence.newConnection(login.user._id, login.connection.id, nodeId); updateConns(); diff --git a/apps/meteor/tests/end-to-end/api/01-users.js b/apps/meteor/tests/end-to-end/api/01-users.js index 204d1413155f1..1103f8a3cbc5e 100644 --- a/apps/meteor/tests/end-to-end/api/01-users.js +++ b/apps/meteor/tests/end-to-end/api/01-users.js @@ -686,6 +686,41 @@ describe('[Users]', function () { }) .end(done); }); + + describe('Logging in with type: "resume"', () => { + let user; + let userCredentials; + + before(async () => { + user = await createUser({ joinDefaultChannels: false }); + userCredentials = await login(user.username, password); + }); + + after(async () => deleteUser(user)); + + it('should return "offline" after a login type "resume" via REST', async () => { + await request + .post(api('login')) + .send({ + resume: userCredentials['X-Auth-Token'], + }) + .expect('Content-Type', 'application/json') + .expect(200); + + await request + .get(api('users.getPresence')) + .set(credentials) + .query({ + userId: user._id, + }) + .expect('Content-Type', 'application/json') + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.nested.property('presence', 'offline'); + }); + }); + }); }); describe('[/users.presence]', () => {