Fix an issue with ignoring power_level changes on divergent graphs
Changes to m.room.power_levels events are supposed to be handled at a high priority; however a typo meant that the relevant bit of code was never executed, so they were handled just like any other state change - which meant that a bad person could cause room state changes by forking the graph from a point in history when they were allowed to do so.pull/365/head
parent
06bfd0a3c0
commit
78f6010207
|
@ -307,19 +307,23 @@ class StateHandler(object):
|
||||||
|
|
||||||
We resolve conflicts in the following order:
|
We resolve conflicts in the following order:
|
||||||
1. power levels
|
1. power levels
|
||||||
2. memberships
|
2. join rules
|
||||||
3. other events.
|
3. memberships
|
||||||
|
4. other events.
|
||||||
"""
|
"""
|
||||||
resolved_state = {}
|
resolved_state = {}
|
||||||
power_key = (EventTypes.PowerLevels, "")
|
power_key = (EventTypes.PowerLevels, "")
|
||||||
if power_key in conflicted_state.items():
|
if power_key in conflicted_state:
|
||||||
power_levels = conflicted_state[power_key]
|
events = conflicted_state[power_key]
|
||||||
resolved_state[power_key] = self._resolve_auth_events(power_levels)
|
logger.debug("Resolving conflicted power levels %r", events)
|
||||||
|
resolved_state[power_key] = self._resolve_auth_events(
|
||||||
|
events, auth_events)
|
||||||
|
|
||||||
auth_events.update(resolved_state)
|
auth_events.update(resolved_state)
|
||||||
|
|
||||||
for key, events in conflicted_state.items():
|
for key, events in conflicted_state.items():
|
||||||
if key[0] == EventTypes.JoinRules:
|
if key[0] == EventTypes.JoinRules:
|
||||||
|
logger.debug("Resolving conflicted join rules %r", events)
|
||||||
resolved_state[key] = self._resolve_auth_events(
|
resolved_state[key] = self._resolve_auth_events(
|
||||||
events,
|
events,
|
||||||
auth_events
|
auth_events
|
||||||
|
@ -329,6 +333,7 @@ class StateHandler(object):
|
||||||
|
|
||||||
for key, events in conflicted_state.items():
|
for key, events in conflicted_state.items():
|
||||||
if key[0] == EventTypes.Member:
|
if key[0] == EventTypes.Member:
|
||||||
|
logger.debug("Resolving conflicted member lists %r", events)
|
||||||
resolved_state[key] = self._resolve_auth_events(
|
resolved_state[key] = self._resolve_auth_events(
|
||||||
events,
|
events,
|
||||||
auth_events
|
auth_events
|
||||||
|
@ -338,6 +343,7 @@ class StateHandler(object):
|
||||||
|
|
||||||
for key, events in conflicted_state.items():
|
for key, events in conflicted_state.items():
|
||||||
if key not in resolved_state:
|
if key not in resolved_state:
|
||||||
|
logger.debug("Resolving conflicted state %r:%r", key, events)
|
||||||
resolved_state[key] = self._resolve_normal_events(
|
resolved_state[key] = self._resolve_normal_events(
|
||||||
events, auth_events
|
events, auth_events
|
||||||
)
|
)
|
||||||
|
|
|
@ -317,6 +317,99 @@ class StateTestCase(unittest.TestCase):
|
||||||
{e.event_id for e in context_store["E"].current_state.values()}
|
{e.event_id for e in context_store["E"].current_state.values()}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def test_branch_have_perms_conflict(self):
|
||||||
|
userid1 = "@user_id:example.com"
|
||||||
|
userid2 = "@user_id2:example.com"
|
||||||
|
|
||||||
|
nodes = {
|
||||||
|
"A1": DictObj(
|
||||||
|
type=EventTypes.Create,
|
||||||
|
state_key="",
|
||||||
|
content={"creator": userid1},
|
||||||
|
depth=1,
|
||||||
|
),
|
||||||
|
"A2": DictObj(
|
||||||
|
type=EventTypes.Member,
|
||||||
|
state_key=userid1,
|
||||||
|
content={"membership": Membership.JOIN},
|
||||||
|
membership=Membership.JOIN,
|
||||||
|
),
|
||||||
|
"A3": DictObj(
|
||||||
|
type=EventTypes.Member,
|
||||||
|
state_key=userid2,
|
||||||
|
content={"membership": Membership.JOIN},
|
||||||
|
membership=Membership.JOIN,
|
||||||
|
),
|
||||||
|
"A4": DictObj(
|
||||||
|
type=EventTypes.PowerLevels,
|
||||||
|
state_key="",
|
||||||
|
content={
|
||||||
|
"events": {"m.room.name": 50},
|
||||||
|
"users": {userid1: 100,
|
||||||
|
userid2: 60},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
"A5": DictObj(
|
||||||
|
type=EventTypes.Name,
|
||||||
|
state_key="",
|
||||||
|
),
|
||||||
|
"B": DictObj(
|
||||||
|
type=EventTypes.PowerLevels,
|
||||||
|
state_key="",
|
||||||
|
content={
|
||||||
|
"events": {"m.room.name": 50},
|
||||||
|
"users": {userid2: 30},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
"C": DictObj(
|
||||||
|
type=EventTypes.Name,
|
||||||
|
state_key="",
|
||||||
|
sender=userid2,
|
||||||
|
),
|
||||||
|
"D": DictObj(
|
||||||
|
type=EventTypes.Message,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
edges = {
|
||||||
|
"A2": ["A1"],
|
||||||
|
"A3": ["A2"],
|
||||||
|
"A4": ["A3"],
|
||||||
|
"A5": ["A4"],
|
||||||
|
"B": ["A5"],
|
||||||
|
"C": ["A5"],
|
||||||
|
"D": ["B", "C"]
|
||||||
|
}
|
||||||
|
self._add_depths(nodes, edges)
|
||||||
|
graph = Graph(nodes, edges)
|
||||||
|
|
||||||
|
store = StateGroupStore()
|
||||||
|
self.store.get_state_groups.side_effect = store.get_state_groups
|
||||||
|
|
||||||
|
context_store = {}
|
||||||
|
|
||||||
|
for event in graph.walk():
|
||||||
|
context = yield self.state.compute_event_context(event)
|
||||||
|
store.store_state_groups(event, context)
|
||||||
|
context_store[event.event_id] = context
|
||||||
|
|
||||||
|
self.assertSetEqual(
|
||||||
|
{"A1", "A2", "A3", "A5", "B"},
|
||||||
|
{e.event_id for e in context_store["D"].current_state.values()}
|
||||||
|
)
|
||||||
|
|
||||||
|
def _add_depths(self, nodes, edges):
|
||||||
|
def _get_depth(ev):
|
||||||
|
node = nodes[ev]
|
||||||
|
if 'depth' not in node:
|
||||||
|
prevs = edges[ev]
|
||||||
|
depth = max(_get_depth(prev) for prev in prevs) + 1
|
||||||
|
node['depth'] = depth
|
||||||
|
return node['depth']
|
||||||
|
|
||||||
|
for n in nodes:
|
||||||
|
_get_depth(n)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def test_annotate_with_old_message(self):
|
def test_annotate_with_old_message(self):
|
||||||
event = create_event(type="test_message", name="event")
|
event = create_event(type="test_message", name="event")
|
||||||
|
|
Loading…
Reference in New Issue