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
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 132 additions and 1 deletions

1
changelog.d/18534.bugfix Normal file
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.

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

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")