Skip to content

Commit 449b1a4

Browse files
MSC4311: invites and knocks should contain the create event (#19722)
Part of MSC4311: invites and knocks should contain the create event (stripped state for the client API) Part of #19414
1 parent 2e9d6f7 commit 449b1a4

4 files changed

Lines changed: 92 additions & 7 deletions

File tree

changelog.d/19722.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Partial [MSC4311](https://github.com/matrix-org/matrix-spec-proposals/pull/4311) implementation: `m.room.create` is now a required part of stripped `invite_state`/`knock_state` . Contributed by @FrenchGithubUser @Famedly.

synapse/config/api.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ def _get_prejoin_state_entries(
4848
self, config: JsonDict
4949
) -> Iterable[tuple[str, str | None]]:
5050
"""Get the event types and state keys to include in the prejoin state."""
51+
# MSC4311: the create event must always be included in invite/knock state.
52+
yield EventTypes.Create, ""
53+
5154
room_prejoin_state_config = config.get("room_prejoin_state") or {}
5255

5356
# backwards-compatibility support for room_invite_state_types

tests/config/test_api.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from synapse.config import ConfigError
66
from synapse.config._base import RootConfig
77
from synapse.config.api import ApiConfig
8-
from synapse.types.state import StateFilter
98

109
DEFAULT_PREJOIN_STATE_PAIRS = {
1110
("m.room.join_rules", ""),
@@ -38,7 +37,11 @@ def test_disable_default_event_types(self) -> None:
3837
disable_default_event_types: true
3938
"""
4039
)
41-
self.assertEqual(config.room_prejoin_state, StateFilter.none())
40+
# MSC4311: m.room.create is always included even when defaults are disabled
41+
self.assertEqual(
42+
set(config.room_prejoin_state.concrete_types()),
43+
{("m.room.create", "")},
44+
)
4245

4346
def test_event_without_state_key(self) -> None:
4447
config = self.read_config(
@@ -50,7 +53,11 @@ def test_event_without_state_key(self) -> None:
5053
"""
5154
)
5255
self.assertEqual(config.room_prejoin_state.wildcard_types(), ["foo"])
53-
self.assertEqual(config.room_prejoin_state.concrete_types(), [])
56+
# MSC4311: m.room.create is always included
57+
self.assertEqual(
58+
set(config.room_prejoin_state.concrete_types()),
59+
{("m.room.create", "")},
60+
)
5461

5562
def test_event_with_specific_state_key(self) -> None:
5663
config = self.read_config(
@@ -62,9 +69,10 @@ def test_event_with_specific_state_key(self) -> None:
6269
"""
6370
)
6471
self.assertFalse(config.room_prejoin_state.has_wildcards())
72+
# MSC4311: m.room.create is always included
6573
self.assertEqual(
6674
set(config.room_prejoin_state.concrete_types()),
67-
{("foo", "bar")},
75+
{("foo", "bar"), ("m.room.create", "")},
6876
)
6977

7078
def test_repeated_event_with_specific_state_key(self) -> None:
@@ -78,9 +86,10 @@ def test_repeated_event_with_specific_state_key(self) -> None:
7886
"""
7987
)
8088
self.assertFalse(config.room_prejoin_state.has_wildcards())
89+
# MSC4311: m.room.create is always included
8190
self.assertEqual(
8291
set(config.room_prejoin_state.concrete_types()),
83-
{("foo", "bar"), ("foo", "baz")},
92+
{("foo", "bar"), ("foo", "baz"), ("m.room.create", "")},
8493
)
8594

8695
def test_no_specific_state_key_overrides_specific_state_key(self) -> None:
@@ -94,7 +103,11 @@ def test_no_specific_state_key_overrides_specific_state_key(self) -> None:
94103
"""
95104
)
96105
self.assertEqual(config.room_prejoin_state.wildcard_types(), ["foo"])
97-
self.assertEqual(config.room_prejoin_state.concrete_types(), [])
106+
# MSC4311: m.room.create is always included
107+
self.assertEqual(
108+
set(config.room_prejoin_state.concrete_types()),
109+
{("m.room.create", "")},
110+
)
98111

99112
config = self.read_config(
100113
"""
@@ -106,7 +119,11 @@ def test_no_specific_state_key_overrides_specific_state_key(self) -> None:
106119
"""
107120
)
108121
self.assertEqual(config.room_prejoin_state.wildcard_types(), ["foo"])
109-
self.assertEqual(config.room_prejoin_state.concrete_types(), [])
122+
# MSC4311: m.room.create is always included
123+
self.assertEqual(
124+
set(config.room_prejoin_state.concrete_types()),
125+
{("m.room.create", "")},
126+
)
110127

111128
def test_bad_event_type_entry_raises(self) -> None:
112129
with self.assertRaises(ConfigError):

tests/rest/client/test_sync.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from synapse.api.constants import (
3030
EventContentFields,
3131
EventTypes,
32+
JoinRules,
3233
ReceiptTypes,
3334
RelationTypes,
3435
)
@@ -394,6 +395,69 @@ def test_knock_room_state(self) -> None:
394395
)
395396

396397

398+
class SyncCreateEventInPrejoinStateTestCase(unittest.HomeserverTestCase):
399+
"""MSC4311: Tests that m.room.create is present in invite_state and knock_state"""
400+
401+
servlets = [
402+
synapse.rest.admin.register_servlets,
403+
login.register_servlets,
404+
room.register_servlets,
405+
sync.register_servlets,
406+
knock.register_servlets,
407+
]
408+
409+
def default_config(self) -> JsonDict:
410+
config = super().default_config()
411+
return config
412+
413+
def test_create_event_present_in_invite_state(self) -> None:
414+
"""m.room.create must appear in invite_state."""
415+
inviter = self.register_user("inviter", "pass")
416+
inviter_tok = self.login("inviter", "pass")
417+
invitee = self.register_user("invitee", "pass")
418+
invitee_tok = self.login("invitee", "pass")
419+
420+
room_id = self.helper.create_room_as(inviter, tok=inviter_tok)
421+
self.helper.invite(room=room_id, src=inviter, targ=invitee, tok=inviter_tok)
422+
423+
channel = self.make_request("GET", "/sync", access_token=invitee_tok)
424+
self.assertEqual(channel.code, 200, channel.json_body)
425+
426+
invite_state_events = channel.json_body["rooms"]["invite"][room_id][
427+
"invite_state"
428+
]["events"]
429+
event_types = {stripped_event["type"] for stripped_event in invite_state_events}
430+
self.assertIn(EventTypes.Create, event_types)
431+
432+
def test_create_event_present_in_knock_state(self) -> None:
433+
"""m.room.create must appear in knock_state."""
434+
host = self.register_user("host", "pass")
435+
host_tok = self.login("host", "pass")
436+
knocker = self.register_user("knocker", "pass")
437+
knocker_tok = self.login("knocker", "pass")
438+
439+
room_id = self.helper.create_room_as(
440+
host, is_public=False, room_version="7", tok=host_tok
441+
)
442+
self.helper.send_state(
443+
room_id,
444+
EventTypes.JoinRules,
445+
{"join_rule": JoinRules.KNOCK},
446+
tok=host_tok,
447+
)
448+
449+
self.helper.knock(room_id, knocker, tok=knocker_tok)
450+
451+
channel = self.make_request("GET", "/sync", access_token=knocker_tok)
452+
self.assertEqual(channel.code, 200, channel.json_body)
453+
454+
knock_state_events = channel.json_body["rooms"]["knock"][room_id][
455+
"knock_state"
456+
]["events"]
457+
event_types = {stripped_event["type"] for stripped_event in knock_state_events}
458+
self.assertIn(EventTypes.Create, event_types)
459+
460+
397461
class UnreadMessagesTestCase(unittest.HomeserverTestCase):
398462
servlets = [
399463
synapse.rest.admin.register_servlets,

0 commit comments

Comments
 (0)