bugfix: ensure _get_power_level_for_sender works when there is no PL event (#18534)

This commit is contained in:
Kegan Dougal
2025-06-10 15:11:49 +01:00
committed by GitHub
parent 142ba5df89
commit 978032141b
3 changed files with 132 additions and 1 deletions
+1
View File
@@ -0,0 +1 @@
Fix an issue where during state resolution for v11 rooms Synapse would incorrectly calculate the power level of the creator when there was no power levels event in the room.
+13 -1
View File
@@ -254,7 +254,19 @@ async def _get_power_level_for_sender(
room_id, aid, event_map, state_res_store, allow_none=True
)
if aev and (aev.type, aev.state_key) == (EventTypes.Create, ""):
if aev.content.get("creator") == event.sender:
creator = (
event.sender
if event.room_version.implicit_room_creator
else aev.content.get("creator")
)
if not creator:
logger.warning(
"_get_power_level_for_sender: event %s has no PL in auth_events and "
"creator is missing from create event %s",
event_id,
aev.event_id,
)
if creator == event.sender:
return 100
break
return 0
+118
View File
@@ -41,6 +41,7 @@ from synapse.event_auth import auth_types_for_event
from synapse.events import EventBase, make_event_from_dict
from synapse.state.v2 import (
_get_auth_chain_difference,
_get_power_level_for_sender,
lexicographical_topological_sort,
resolve_events_with_store,
)
@@ -863,6 +864,123 @@ class AuthChainDifferenceTestCase(unittest.TestCase):
self.assertEqual(difference, {d.event_id, e.event_id})
def test_get_power_level_for_sender(self) -> None:
"""Test that we use the correct definition of `creator` depending
on room version"""
store = TestStateResolutionStore({})
for room_version in [RoomVersions.V10, RoomVersions.V11]:
create_event = make_event_from_dict(
{
"room_id": ROOM_ID,
"sender": ALICE,
"type": EventTypes.Create,
"state_key": "",
"content": {
"room_version": room_version.identifier,
}
# conditionally add 'creator' if the version doesn't use implicit room creators
| (
{"creator": ALICE}
if not room_version.implicit_room_creator
else {}
),
},
room_version,
)
member_event = make_event_from_dict(
{
"room_id": ROOM_ID,
"sender": ALICE,
"type": EventTypes.Member,
"state_key": ALICE,
"content": {
"membership": "join",
},
"auth_events": [create_event.event_id],
"prev_events": [create_event.event_id],
},
room_version,
)
pl_event = make_event_from_dict(
{
"room_id": ROOM_ID,
"sender": ALICE,
"type": EventTypes.PowerLevels,
"state_key": "",
"content": {
"users": {
ALICE: 100,
BOB: 50,
},
"users_default": 10,
},
"auth_events": [create_event.event_id, member_event.event_id],
"prev_events": [member_event.event_id],
},
room_version,
)
event_map = {
create_event.event_id: create_event,
member_event.event_id: member_event,
pl_event.event_id: pl_event,
}
want_pls = {
ALICE: 100,
BOB: 50,
CHARLIE: 10,
}
for user_id, want_pl in want_pls.items():
test_event = make_event_from_dict(
{
"room_id": ROOM_ID,
"sender": user_id,
"type": EventTypes.Topic,
"state_key": "",
"content": {"topic": "Test"},
"auth_events": [
create_event.event_id,
member_event.event_id,
pl_event.event_id,
],
"prev_events": [pl_event.event_id],
},
room_version,
)
event_map[test_event.event_id] = test_event
got_pl = self.successResultOf(
defer.ensureDeferred(
_get_power_level_for_sender(
ROOM_ID, test_event.event_id, event_map, store
)
)
)
self.assertEqual(
got_pl,
want_pl,
f"wrong pl for {user_id} on v{room_version.identifier}",
)
# the creator alone without PL is 100
got_creator_pl = self.successResultOf(
defer.ensureDeferred(
_get_power_level_for_sender(
ROOM_ID,
member_event.event_id,
{
member_event.event_id: member_event,
create_event.event_id: create_event,
},
store,
)
)
)
self.assertEqual(
got_creator_pl,
100,
f"wrong pl for creator with no PL event on v{room_version.identifier}",
)
T = TypeVar("T")