From fcc90e884b227b2438224eb15a282cee07fd06a5 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 23 Oct 2017 19:07:04 +0100 Subject: [PATCH 1/3] Fix power level of sentinel members When a ppower_levels event arrived, the current member objects were being updated but the sentinel members were not, meaning that the power levels of RoomMember objects associated with events had stale power levels. This was causing power level based push rules to be wrong. --- src/models/room-state.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/models/room-state.js b/src/models/room-state.js index 7e40dd7b1..13993eef6 100644 --- a/src/models/room-state.js +++ b/src/models/room-state.js @@ -197,6 +197,21 @@ RoomState.prototype.setStateEvents = function(stateEvents) { member.setPowerLevelEvent(event); self.emit("RoomState.members", event, self, member); }); + + // Go through the sentinel members and see if any of them would be + // affected by the new power levels. If so, replace the sentinel. + for (const userId of Object.keys(self._sentinels)) { + const oldSentinel = self._sentinels[userId]; + const newSentinel = new RoomMember(event.getRoomId(), userId); + newSentinel.setMembershipEvent(oldSentinel.events.member, self); + newSentinel.setPowerLevelEvent(event); + if ( + newSentinel.powerLevel != oldSentinel.powerLevel || + newSentinel.powerLevelNorm != oldSentinel.powerLevelNorm + ) { + self._sentinels[userId] = newSentinel; + } + } } }); }; From 34428a811c3554043cbe58526cc273e759e70fb4 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 25 Oct 2017 10:40:15 +0100 Subject: [PATCH 2/3] Fix setPowerLevelEvent() semantics * Make setPowerLevelEvent() use getDirectionalContent() rather than getContent(), otherwise power level events from pagination set power levels the wrong way * Don't assume the presence of a `users` key since the first power_levels event in a room will have no prev_content --- src/models/room-member.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/models/room-member.js b/src/models/room-member.js index 66f80a5e4..fa5152ed0 100644 --- a/src/models/room-member.js +++ b/src/models/room-member.js @@ -104,17 +104,20 @@ RoomMember.prototype.setPowerLevelEvent = function(powerLevelEvent) { if (powerLevelEvent.getType() !== "m.room.power_levels") { return; } - let maxLevel = powerLevelEvent.getContent().users_default || 0; - utils.forEach(utils.values(powerLevelEvent.getContent().users), function(lvl) { + + const evContent = powerLevelEvent.getDirectionalContent(); + + let maxLevel = evContent.users_default || 0; + utils.forEach(utils.values(evContent.users), function(lvl) { maxLevel = Math.max(maxLevel, lvl); }); const oldPowerLevel = this.powerLevel; const oldPowerLevelNorm = this.powerLevelNorm; - if (powerLevelEvent.getContent().users[this.userId] !== undefined) { - this.powerLevel = powerLevelEvent.getContent().users[this.userId]; - } else if (powerLevelEvent.getContent().users_default !== undefined) { - this.powerLevel = powerLevelEvent.getContent().users_default; + if (evContent.users && evContent.users[this.userId] !== undefined) { + this.powerLevel = evContent.users[this.userId]; + } else if (evContent.users_default !== undefined) { + this.powerLevel = evContent.users_default; } else { this.powerLevel = 0; } From 99f4968888f598ec81abec42303fd1d4ff06f376 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 25 Oct 2017 10:57:28 +0100 Subject: [PATCH 3/3] Replace all the sentinel members on power_levels Rather than trying to be clever and keep ones whose power level isn't affected, since they'll still have an associated power_levels event that isn't the one actually in effect, which could be confusing. --- src/models/room-state.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/models/room-state.js b/src/models/room-state.js index 13993eef6..96350b031 100644 --- a/src/models/room-state.js +++ b/src/models/room-state.js @@ -205,12 +205,7 @@ RoomState.prototype.setStateEvents = function(stateEvents) { const newSentinel = new RoomMember(event.getRoomId(), userId); newSentinel.setMembershipEvent(oldSentinel.events.member, self); newSentinel.setPowerLevelEvent(event); - if ( - newSentinel.powerLevel != oldSentinel.powerLevel || - newSentinel.powerLevelNorm != oldSentinel.powerLevelNorm - ) { - self._sentinels[userId] = newSentinel; - } + self._sentinels[userId] = newSentinel; } } });