From 80e0ef75a13047db4e11b9389f6b5296b89789f1 Mon Sep 17 00:00:00 2001 From: "dionisio-bot[bot]" <117394943+dionisio-bot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 16:28:35 +0000 Subject: [PATCH] fix: client trying to subscribe to streams before completing the login process (#34099) Co-authored-by: Pierre Lehnen <55164754+pierre-lehnen-rc@users.noreply.github.com> --- .changeset/cold-mangos-impress.md | 5 ++++ .../client/meteorOverrides/ddpOverREST.ts | 24 ++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 .changeset/cold-mangos-impress.md diff --git a/.changeset/cold-mangos-impress.md b/.changeset/cold-mangos-impress.md new file mode 100644 index 000000000000..bd805577460a --- /dev/null +++ b/.changeset/cold-mangos-impress.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixed an issue that caused clients to not properly receive certain server notifications right after login diff --git a/apps/meteor/client/meteorOverrides/ddpOverREST.ts b/apps/meteor/client/meteorOverrides/ddpOverREST.ts index 9bd2021ec027..f607d7866826 100644 --- a/apps/meteor/client/meteorOverrides/ddpOverREST.ts +++ b/apps/meteor/client/meteorOverrides/ddpOverREST.ts @@ -57,13 +57,35 @@ const withDDPOverREST = (_send: (this: Meteor.IMeteorConnection, message: Meteor sdk.rest .post(`/v1/${endpoint}/${method}`, restParams) .then(({ message: _message }) => { - processResult(_message); + // Calling Meteor.loginWithToken before processing the result of the first login will ensure that the new login request + // is added to the top of the list of methodInvokers. + // The request itself will only be sent after the first login result is processed, but + // the Accounts.onLogin callbacks will be called before this request is effectively sent; + // This way, any requests done inside of onLogin callbacks will be added to the list + // and processed only after the Meteor.loginWithToken request is done + // So, the effective order is: + // 1. regular login with password is sent + // 2. result of the password login is received + // 3. login with token is added to the list of pending requests + // 4. result of the password login is processed + // 5. Accounts.onLogin callbacks are triggered, Meteor.userId is set + // 6. the request for the login with token is effectively sent + // 7. login with token result is processed + // 8. requests initiated inside of the Accounts.onLogin callback are then finally sent + // + // Keep in mind that there's a difference in how meteor3 processes the request results, compared to older meteor versions + // On meteor3, any collection writes triggered by a request result are done async, which means that the `processResult` call + // will not immediatelly trigger the callbacks, like it used to in older versions. + // That means that on meteor3+, it doesn't really make a difference if processResult is called before or after the Meteor.loginWithToken here + // as the result will be processed async, the loginWithToken call will be initiated before it is effectively processed anyway. if (message.method === 'login') { const parsedMessage = DDPCommon.parseDDP(_message) as { result?: { token?: string } }; if (parsedMessage.result?.token) { Meteor.loginWithToken(parsedMessage.result.token); } } + + processResult(_message); }) .catch((error) => { console.error(error);