mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-05-02 12:26:02 -04:00
Move some event auth checks out to a different method (#13065)
* Add auth events to events used in tests * Move some event auth checks out to a different method Some of the event auth checks apply to an event's auth_events, rather than the state at the event - which means they can play no part in state resolution. Move them out to a separate method. * Rename check_auth_rules_for_event Now it only checks the state-dependent auth rules, it needs a better name.
This commit is contained in:
parent
cba1c5cbc2
commit
8ecf6be1e1
7 changed files with 219 additions and 98 deletions
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018 New Vector Ltd
|
||||
# Copyright 2018-2022 The Matrix.org Foundation C.I.C.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -13,7 +13,7 @@
|
|||
# limitations under the License.
|
||||
|
||||
import unittest
|
||||
from typing import Optional
|
||||
from typing import Collection, Dict, Iterable, List, Optional
|
||||
|
||||
from parameterized import parameterized
|
||||
|
||||
|
@ -22,8 +22,41 @@ from synapse.api.constants import EventContentFields
|
|||
from synapse.api.errors import AuthError
|
||||
from synapse.api.room_versions import EventFormatVersions, RoomVersion, RoomVersions
|
||||
from synapse.events import EventBase, make_event_from_dict
|
||||
from synapse.storage.databases.main.events_worker import EventRedactBehaviour
|
||||
from synapse.types import JsonDict, get_domain_from_id
|
||||
|
||||
from tests.test_utils import get_awaitable_result
|
||||
|
||||
|
||||
class _StubEventSourceStore:
|
||||
"""A stub implementation of the EventSourceStore"""
|
||||
|
||||
def __init__(self):
|
||||
self._store: Dict[str, EventBase] = {}
|
||||
|
||||
def add_event(self, event: EventBase):
|
||||
self._store[event.event_id] = event
|
||||
|
||||
def add_events(self, events: Iterable[EventBase]):
|
||||
for event in events:
|
||||
self._store[event.event_id] = event
|
||||
|
||||
async def get_events(
|
||||
self,
|
||||
event_ids: Collection[str],
|
||||
redact_behaviour: EventRedactBehaviour,
|
||||
get_prev_content: bool = False,
|
||||
allow_rejected: bool = False,
|
||||
) -> Dict[str, EventBase]:
|
||||
assert allow_rejected
|
||||
assert not get_prev_content
|
||||
assert redact_behaviour == EventRedactBehaviour.as_is
|
||||
results = {}
|
||||
for e in event_ids:
|
||||
if e in self._store:
|
||||
results[e] = self._store[e]
|
||||
return results
|
||||
|
||||
|
||||
class EventAuthTestCase(unittest.TestCase):
|
||||
def test_rejected_auth_events(self):
|
||||
|
@ -36,11 +69,15 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
_join_event(RoomVersions.V9, creator),
|
||||
]
|
||||
|
||||
event_store = _StubEventSourceStore()
|
||||
event_store.add_events(auth_events)
|
||||
|
||||
# creator should be able to send state
|
||||
event_auth.check_auth_rules_for_event(
|
||||
_random_state_event(RoomVersions.V9, creator),
|
||||
auth_events,
|
||||
event = _random_state_event(RoomVersions.V9, creator, auth_events)
|
||||
get_awaitable_result(
|
||||
event_auth.check_state_independent_auth_rules(event_store, event)
|
||||
)
|
||||
event_auth.check_state_dependent_auth_rules(event, auth_events)
|
||||
|
||||
# ... but a rejected join_rules event should cause it to be rejected
|
||||
rejected_join_rules = _join_rules_event(
|
||||
|
@ -50,23 +87,27 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
)
|
||||
rejected_join_rules.rejected_reason = "stinky"
|
||||
auth_events.append(rejected_join_rules)
|
||||
event_store.add_event(rejected_join_rules)
|
||||
|
||||
self.assertRaises(
|
||||
AuthError,
|
||||
event_auth.check_auth_rules_for_event,
|
||||
_random_state_event(RoomVersions.V9, creator),
|
||||
auth_events,
|
||||
)
|
||||
with self.assertRaises(AuthError):
|
||||
get_awaitable_result(
|
||||
event_auth.check_state_independent_auth_rules(
|
||||
event_store,
|
||||
_random_state_event(RoomVersions.V9, creator),
|
||||
)
|
||||
)
|
||||
|
||||
# ... even if there is *also* a good join rules
|
||||
auth_events.append(_join_rules_event(RoomVersions.V9, creator, "public"))
|
||||
event_store.add_event(rejected_join_rules)
|
||||
|
||||
self.assertRaises(
|
||||
AuthError,
|
||||
event_auth.check_auth_rules_for_event,
|
||||
_random_state_event(RoomVersions.V9, creator),
|
||||
auth_events,
|
||||
)
|
||||
with self.assertRaises(AuthError):
|
||||
get_awaitable_result(
|
||||
event_auth.check_state_independent_auth_rules(
|
||||
event_store,
|
||||
_random_state_event(RoomVersions.V9, creator),
|
||||
)
|
||||
)
|
||||
|
||||
def test_random_users_cannot_send_state_before_first_pl(self):
|
||||
"""
|
||||
|
@ -82,7 +123,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
]
|
||||
|
||||
# creator should be able to send state
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_random_state_event(RoomVersions.V1, creator),
|
||||
auth_events,
|
||||
)
|
||||
|
@ -90,7 +131,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
# joiner should not be able to send state
|
||||
self.assertRaises(
|
||||
AuthError,
|
||||
event_auth.check_auth_rules_for_event,
|
||||
event_auth.check_state_dependent_auth_rules,
|
||||
_random_state_event(RoomVersions.V1, joiner),
|
||||
auth_events,
|
||||
)
|
||||
|
@ -119,13 +160,13 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
# pleb should not be able to send state
|
||||
self.assertRaises(
|
||||
AuthError,
|
||||
event_auth.check_auth_rules_for_event,
|
||||
event_auth.check_state_dependent_auth_rules,
|
||||
_random_state_event(RoomVersions.V1, pleb),
|
||||
auth_events,
|
||||
),
|
||||
|
||||
# king should be able to send state
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_random_state_event(RoomVersions.V1, king),
|
||||
auth_events,
|
||||
)
|
||||
|
@ -140,27 +181,27 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
]
|
||||
|
||||
# creator should be able to send aliases
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_alias_event(RoomVersions.V1, creator),
|
||||
auth_events,
|
||||
)
|
||||
|
||||
# Reject an event with no state key.
|
||||
with self.assertRaises(AuthError):
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_alias_event(RoomVersions.V1, creator, state_key=""),
|
||||
auth_events,
|
||||
)
|
||||
|
||||
# If the domain of the sender does not match the state key, reject.
|
||||
with self.assertRaises(AuthError):
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_alias_event(RoomVersions.V1, creator, state_key="test.com"),
|
||||
auth_events,
|
||||
)
|
||||
|
||||
# Note that the member does *not* need to be in the room.
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_alias_event(RoomVersions.V1, other),
|
||||
auth_events,
|
||||
)
|
||||
|
@ -175,24 +216,24 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
]
|
||||
|
||||
# creator should be able to send aliases
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_alias_event(RoomVersions.V6, creator),
|
||||
auth_events,
|
||||
)
|
||||
|
||||
# No particular checks are done on the state key.
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_alias_event(RoomVersions.V6, creator, state_key=""),
|
||||
auth_events,
|
||||
)
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_alias_event(RoomVersions.V6, creator, state_key="test.com"),
|
||||
auth_events,
|
||||
)
|
||||
|
||||
# Per standard auth rules, the member must be in the room.
|
||||
with self.assertRaises(AuthError):
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_alias_event(RoomVersions.V6, other),
|
||||
auth_events,
|
||||
)
|
||||
|
@ -220,12 +261,12 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
|
||||
# on room V1, pleb should be able to modify the notifications power level.
|
||||
if allow_modification:
|
||||
event_auth.check_auth_rules_for_event(pl_event, auth_events)
|
||||
event_auth.check_state_dependent_auth_rules(pl_event, auth_events)
|
||||
|
||||
else:
|
||||
# But an MSC2209 room rejects this change.
|
||||
with self.assertRaises(AuthError):
|
||||
event_auth.check_auth_rules_for_event(pl_event, auth_events)
|
||||
event_auth.check_state_dependent_auth_rules(pl_event, auth_events)
|
||||
|
||||
def test_join_rules_public(self):
|
||||
"""
|
||||
|
@ -243,14 +284,14 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
}
|
||||
|
||||
# Check join.
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_join_event(RoomVersions.V6, pleb),
|
||||
auth_events.values(),
|
||||
)
|
||||
|
||||
# A user cannot be force-joined to a room.
|
||||
with self.assertRaises(AuthError):
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_member_event(RoomVersions.V6, pleb, "join", sender=creator),
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -260,7 +301,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
RoomVersions.V6, pleb, "ban"
|
||||
)
|
||||
with self.assertRaises(AuthError):
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_join_event(RoomVersions.V6, pleb),
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -269,7 +310,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
auth_events[("m.room.member", pleb)] = _member_event(
|
||||
RoomVersions.V6, pleb, "leave"
|
||||
)
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_join_event(RoomVersions.V6, pleb),
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -278,7 +319,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
auth_events[("m.room.member", pleb)] = _member_event(
|
||||
RoomVersions.V6, pleb, "join"
|
||||
)
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_join_event(RoomVersions.V6, pleb),
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -287,7 +328,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
auth_events[("m.room.member", pleb)] = _member_event(
|
||||
RoomVersions.V6, pleb, "invite", sender=creator
|
||||
)
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_join_event(RoomVersions.V6, pleb),
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -309,14 +350,14 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
|
||||
# A join without an invite is rejected.
|
||||
with self.assertRaises(AuthError):
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_join_event(RoomVersions.V6, pleb),
|
||||
auth_events.values(),
|
||||
)
|
||||
|
||||
# A user cannot be force-joined to a room.
|
||||
with self.assertRaises(AuthError):
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_member_event(RoomVersions.V6, pleb, "join", sender=creator),
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -326,7 +367,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
RoomVersions.V6, pleb, "ban"
|
||||
)
|
||||
with self.assertRaises(AuthError):
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_join_event(RoomVersions.V6, pleb),
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -336,7 +377,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
RoomVersions.V6, pleb, "leave"
|
||||
)
|
||||
with self.assertRaises(AuthError):
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_join_event(RoomVersions.V6, pleb),
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -345,7 +386,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
auth_events[("m.room.member", pleb)] = _member_event(
|
||||
RoomVersions.V6, pleb, "join"
|
||||
)
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_join_event(RoomVersions.V6, pleb),
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -354,7 +395,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
auth_events[("m.room.member", pleb)] = _member_event(
|
||||
RoomVersions.V6, pleb, "invite", sender=creator
|
||||
)
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_join_event(RoomVersions.V6, pleb),
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -376,7 +417,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
}
|
||||
|
||||
with self.assertRaises(AuthError):
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_join_event(RoomVersions.V6, pleb),
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -413,7 +454,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
EventContentFields.AUTHORISING_USER: "@creator:example.com"
|
||||
},
|
||||
)
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
authorised_join_event,
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -429,7 +470,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
pl_auth_events[("m.room.member", "@inviter:foo.test")] = _join_event(
|
||||
RoomVersions.V8, "@inviter:foo.test"
|
||||
)
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_join_event(
|
||||
RoomVersions.V8,
|
||||
pleb,
|
||||
|
@ -442,7 +483,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
|
||||
# A join which is missing an authorised server is rejected.
|
||||
with self.assertRaises(AuthError):
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_join_event(RoomVersions.V8, pleb),
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -455,7 +496,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
{"invite": 100, "users": {"@other:example.com": 150}},
|
||||
)
|
||||
with self.assertRaises(AuthError):
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_join_event(
|
||||
RoomVersions.V8,
|
||||
pleb,
|
||||
|
@ -469,7 +510,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
# A user cannot be force-joined to a room. (This uses an event which
|
||||
# *would* be valid, but is sent be a different user.)
|
||||
with self.assertRaises(AuthError):
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_member_event(
|
||||
RoomVersions.V8,
|
||||
pleb,
|
||||
|
@ -487,7 +528,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
RoomVersions.V8, pleb, "ban"
|
||||
)
|
||||
with self.assertRaises(AuthError):
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
authorised_join_event,
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -496,7 +537,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
auth_events[("m.room.member", pleb)] = _member_event(
|
||||
RoomVersions.V8, pleb, "leave"
|
||||
)
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
authorised_join_event,
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -506,7 +547,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
auth_events[("m.room.member", pleb)] = _member_event(
|
||||
RoomVersions.V8, pleb, "join"
|
||||
)
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_join_event(RoomVersions.V8, pleb),
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -516,7 +557,7 @@ class EventAuthTestCase(unittest.TestCase):
|
|||
auth_events[("m.room.member", pleb)] = _member_event(
|
||||
RoomVersions.V8, pleb, "invite", sender=creator
|
||||
)
|
||||
event_auth.check_auth_rules_for_event(
|
||||
event_auth.check_state_dependent_auth_rules(
|
||||
_join_event(RoomVersions.V8, pleb),
|
||||
auth_events.values(),
|
||||
)
|
||||
|
@ -539,6 +580,7 @@ def _create_event(
|
|||
"state_key": "",
|
||||
"sender": user_id,
|
||||
"content": {"creator": user_id},
|
||||
"auth_events": [],
|
||||
},
|
||||
room_version=room_version,
|
||||
)
|
||||
|
@ -559,6 +601,7 @@ def _member_event(
|
|||
"sender": sender or user_id,
|
||||
"state_key": user_id,
|
||||
"content": {"membership": membership, **(additional_content or {})},
|
||||
"auth_events": [],
|
||||
"prev_events": [],
|
||||
},
|
||||
room_version=room_version,
|
||||
|
@ -609,7 +652,22 @@ def _alias_event(room_version: RoomVersion, sender: str, **kwargs) -> EventBase:
|
|||
return make_event_from_dict(data, room_version=room_version)
|
||||
|
||||
|
||||
def _random_state_event(room_version: RoomVersion, sender: str) -> EventBase:
|
||||
def _build_auth_dict_for_room_version(
|
||||
room_version: RoomVersion, auth_events: Iterable[EventBase]
|
||||
) -> List:
|
||||
if room_version.event_format == EventFormatVersions.V1:
|
||||
return [(e.event_id, "not_used") for e in auth_events]
|
||||
else:
|
||||
return [e.event_id for e in auth_events]
|
||||
|
||||
|
||||
def _random_state_event(
|
||||
room_version: RoomVersion,
|
||||
sender: str,
|
||||
auth_events: Optional[Iterable[EventBase]] = None,
|
||||
) -> EventBase:
|
||||
if auth_events is None:
|
||||
auth_events = []
|
||||
return make_event_from_dict(
|
||||
{
|
||||
"room_id": TEST_ROOM_ID,
|
||||
|
@ -618,6 +676,7 @@ def _random_state_event(room_version: RoomVersion, sender: str) -> EventBase:
|
|||
"sender": sender,
|
||||
"state_key": "",
|
||||
"content": {"membership": "join"},
|
||||
"auth_events": _build_auth_dict_for_room_version(room_version, auth_events),
|
||||
},
|
||||
room_version=room_version,
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue