From cfcf5c0847e1009e396d7859ce8b458b1faccc04 Mon Sep 17 00:00:00 2001 From: Alec Gibson <12036746+alecgibson@users.noreply.github.com> Date: Fri, 1 Dec 2023 07:08:50 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Prevent=20caching=20presence=20b?= =?UTF-8?q?roadcasts=20rejected=20by=20middleware?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `Agent` stores the most recent presence broadcast sent by a client. However, it eagerly stores this before running the `receivePresence` middleware, which may actually decide that the presence broadcast is invalid (eg malformed, unauthorized, etc.). This means that the latest cached presence state may not be "legal". This change moves the caching inside the `trigger()` call, so we only store presence values that have "passed" the middleware. --- lib/agent.js | 11 ++++++----- test/client/presence/presence.js | 2 ++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/agent.js b/lib/agent.js index 294c53ffc..f55f1f9f4 100644 --- a/lib/agent.js +++ b/lib/agent.js @@ -788,11 +788,7 @@ Agent.prototype._src = function() { Agent.prototype._broadcastPresence = function(presence, callback) { var agent = this; var backend = this.backend; - var requests = this.presenceRequests[presence.ch] || (this.presenceRequests[presence.ch] = Object.create(null)); - var previousRequest = requests[presence.id]; - if (!previousRequest || previousRequest.pv < presence.pv) { - this.presenceRequests[presence.ch][presence.id] = presence; - } + var presenceRequests = this.presenceRequests; var context = { presence: presence, collection: presence.c @@ -800,6 +796,11 @@ Agent.prototype._broadcastPresence = function(presence, callback) { var start = Date.now(); backend.trigger(backend.MIDDLEWARE_ACTIONS.receivePresence, this, context, function(error) { if (error) return callback(error); + var requests = presenceRequests[presence.ch] || (presenceRequests[presence.ch] = Object.create(null)); + var previousRequest = requests[presence.id]; + if (!previousRequest || previousRequest.pv < presence.pv) { + presenceRequests[presence.ch][presence.id] = presence; + } backend.transformPresenceToLatestVersion(agent, presence, function(error, presence) { if (error) return callback(error); var channel = agent._getPresenceChannel(presence.ch); diff --git a/test/client/presence/presence.js b/test/client/presence/presence.js index 42d6b4780..b5e010b22 100644 --- a/test/client/presence/presence.js +++ b/test/client/presence/presence.js @@ -669,6 +669,7 @@ describe('Presence', function() { function(next) { presence2.on('receive', function(id, value) { expect(value).to.eql({index: 6}); + expect(connection1.agent.presenceRequests['test-channel']['presence-1'].p).to.eql({index: 6}); next(); }); localPresence1.submit({index: 5}, errorHandler(done)); @@ -691,6 +692,7 @@ describe('Presence', function() { }); localPresence1.submit({index: 5}, function(error) { expect(error.message).to.contain('bad!'); + expect(connection1.agent.presenceRequests['test-channel']).not.to.be.ok; next(); }); }