From 6ea69d2f1a35ec5e75c7a0544a86d985ca962fcb Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Thu, 1 Jul 2021 10:43:11 -0400 Subject: [PATCH 1/5] Additional tests for restricted rooms based on updates to MSC3083. --- tests/msc3083_test.go | 124 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/tests/msc3083_test.go b/tests/msc3083_test.go index 410e9a52..6fe72da5 100644 --- a/tests/msc3083_test.go +++ b/tests/msc3083_test.go @@ -181,6 +181,130 @@ func TestRestrictedRoomsRemoteJoin(t *testing.T) { checkRestrictedRoom(t, alice, bob, space, room) } +// Not all servers can issue join events for a restricted room. Ensure a join +// completes successfully when a server is in a room, but unable to issue joins +// for it. +func TestRestrictedRoomsLimitedJoin(t *testing.T) { + deployment := Deploy(t, b.BlueprintFederationTwoLocalOneRemote) + defer deployment.Destroy(t) + + // Charlie sets up the space so it is on the other server. + charlie := deployment.Client(t, "hs2", "@charlie:hs2") + space := charlie.CreateRoom(t, map[string]interface{}{ + "preset": "public_chat", + "name": "Space", + "creation_content": map[string]interface{}{ + "type": "m.space", + }, + }) + // The room is an unstable room version which supports the restricted join_rule. + room := charlie.CreateRoom(t, map[string]interface{}{ + "preset": "public_chat", + "name": "Room", + "room_version": "org.matrix.msc3083", + "initial_state": []map[string]interface{}{ + { + "type": "m.room.join_rules", + "state_key": "", + "content": map[string]interface{}{ + "join_rule": "restricted", + "allow": []map[string]interface{}{ + { + "type": "m.room_membership", + "room_id": &space, + "via": []string{"hs2"}, + }, + }, + }, + }, + }, + }) + charlie.SendEventSynced(t, space, b.Event{ + Type: "m.space.child", + StateKey: &room, + Content: map[string]interface{}{ + "via": []string{"hs2"}, + }, + }) + + // Invite alice manually and accept it. + alice := deployment.Client(t, "hs1", "@alice:hs1") + charlie.InviteRoom(t, room, alice.UserID) + alice.JoinRoom(t, room, []string{"hs2"}) + + // Alice should not be able to issue invites. + bob := deployment.Client(t, "hs1", "@bob:hs1") + body := map[string]interface{}{ + "user_id": bob.UserID, + } + res := alice.DoFunc( + t, + "POST", + []string{"_matrix", "client", "r0", "rooms", room, "invite"}, + client.WithJSONBody(t, body), + ) + must.MatchResponse(t, res, match.HTTPResponse{ + StatusCode: 403, + }) + + // Bob cannot join the room. + failJoinRoom(t, bob, room, "hs1") + + // Join the space, joining the room should work, but will bounce through hs2. + bob.JoinRoom(t, space, []string{"hs2"}) + bob.JoinRoom(t, room, []string{"hs1"}) + + // Ensure that the join comes down sync on hs2. Note that we want to ensure hs2 + // accepted the event. + charlie.SyncUntilTimelineHas( + t, + room, + func(ev gjson.Result) bool { + if ev.Get("type").Str != "m.room.member" || ev.Get("state_key").Str != bob.UserID { + return false + } + must.EqualStr(t, ev.Get("sender").Str, bob.UserID, "Bob should have joined by himself") + must.EqualStr(t, ev.Get("content").Get("membership").Str, "join", "Bob failed to join the room") + + return true + }, + ) + + // Raise the power level so that users on hs1 can invite people and then leave + // the room. + state_key := "" + charlie.SendEventSynced(t, room, b.Event{ + Type: "m.room.power_levels", + StateKey: &state_key, + Content: map[string]interface{}{ + "invite": 0, + "users": map[string]interface{}{ + charlie.UserID: 100, + }, + }, + }) + charlie.LeaveRoom(t, room) + + // Ensure the events have synced to hs1. + alice.SyncUntilTimelineHas( + t, + room, + func(ev gjson.Result) bool { + if ev.Get("type").Str != "m.room.member" || ev.Get("state_key").Str != charlie.UserID { + return false + } + must.EqualStr(t, ev.Get("content").Get("membership").Str, "leave", "Charlie failed to leave the room") + + return true + }, + ) + + // Have bob leave and rejoin. This should still work even though hs2 isn't in + // the room anymore! + bob.LeaveRoom(t, room) + bob.JoinRoom(t, room, []string{"hs1"}) +} + // Request the room summary and ensure the expected rooms are in the response. func requestAndAssertSummary(t *testing.T, user *client.CSAPI, space string, expected_rooms []interface{}) { t.Helper() From 490138c437f5f97672b251b28758a4feee54900d Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Thu, 1 Jul 2021 12:56:15 -0400 Subject: [PATCH 2/5] Update the room version per the MSC. --- tests/msc3083_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/msc3083_test.go b/tests/msc3083_test.go index 6fe72da5..c54bcd11 100644 --- a/tests/msc3083_test.go +++ b/tests/msc3083_test.go @@ -52,7 +52,7 @@ func setupRestrictedRoom(t *testing.T, deployment *docker.Deployment) (*client.C room := alice.CreateRoom(t, map[string]interface{}{ "preset": "public_chat", "name": "Room", - "room_version": "org.matrix.msc3083", + "room_version": "org.matrix.msc3083.v2", "initial_state": []map[string]interface{}{ { "type": "m.room.join_rules", @@ -201,7 +201,7 @@ func TestRestrictedRoomsLimitedJoin(t *testing.T) { room := charlie.CreateRoom(t, map[string]interface{}{ "preset": "public_chat", "name": "Room", - "room_version": "org.matrix.msc3083", + "room_version": "org.matrix.msc3083.v2", "initial_state": []map[string]interface{}{ { "type": "m.room.join_rules", @@ -353,7 +353,7 @@ func TestRestrictedRoomsSpacesSummary(t *testing.T) { room := alice.CreateRoom(t, map[string]interface{}{ "preset": "public_chat", "name": "Room", - "room_version": "org.matrix.msc3083", + "room_version": "org.matrix.msc3083.v2", "initial_state": []map[string]interface{}{ { "type": "m.room.join_rules", @@ -436,7 +436,7 @@ func TestRestrictedRoomsSpacesSummaryFederation(t *testing.T) { room := charlie.CreateRoom(t, map[string]interface{}{ "preset": "public_chat", "name": "Room", - "room_version": "org.matrix.msc3083", + "room_version": "org.matrix.msc3083.v2", "initial_state": []map[string]interface{}{ { "type": "m.room.join_rules", From 2a154dce9c859e5068648287e1025a3d0fe8d3b1 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Thu, 15 Jul 2021 08:08:18 -0400 Subject: [PATCH 3/5] A user should be able to join again to update their info. --- tests/msc3083_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/msc3083_test.go b/tests/msc3083_test.go index c54bcd11..7b67231f 100644 --- a/tests/msc3083_test.go +++ b/tests/msc3083_test.go @@ -90,6 +90,9 @@ func checkRestrictedRoom(t *testing.T, alice *client.CSAPI, bob *client.CSAPI, s bob.JoinRoom(t, space, []string{"hs1"}) bob.JoinRoom(t, room, []string{"hs1"}) + // Joining the same room again should work fine (e.g. to change your display name). + bob.JoinRoom(t, room, []string{"hs1"}) + // Leaving the room works and the user is unable to re-join. bob.LeaveRoom(t, room) bob.LeaveRoom(t, space) From 140da16e7b13e000a7cdda236a1f84773e23ba05 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Wed, 21 Jul 2021 14:02:10 -0400 Subject: [PATCH 4/5] Clarify comments. --- tests/msc3083_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/msc3083_test.go b/tests/msc3083_test.go index 7b67231f..fd1ca0e2 100644 --- a/tests/msc3083_test.go +++ b/tests/msc3083_test.go @@ -235,7 +235,7 @@ func TestRestrictedRoomsLimitedJoin(t *testing.T) { charlie.InviteRoom(t, room, alice.UserID) alice.JoinRoom(t, room, []string{"hs2"}) - // Alice should not be able to issue invites. + // Confirm that Alice cannot issue invites (due to the default power levels). bob := deployment.Client(t, "hs1", "@bob:hs1") body := map[string]interface{}{ "user_id": bob.UserID, @@ -253,8 +253,10 @@ func TestRestrictedRoomsLimitedJoin(t *testing.T) { // Bob cannot join the room. failJoinRoom(t, bob, room, "hs1") - // Join the space, joining the room should work, but will bounce through hs2. + // Join the space via hs2. bob.JoinRoom(t, space, []string{"hs2"}) + // Joining the room should work, although we're joining via hs1, it will end up + // as a remote join through hs2. bob.JoinRoom(t, room, []string{"hs1"}) // Ensure that the join comes down sync on hs2. Note that we want to ensure hs2 From 2905d727e740185c0b82fb6683cee7327354a2f6 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Wed, 21 Jul 2021 10:07:29 -0400 Subject: [PATCH 5/5] Rename a test. --- tests/msc3083_test.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/msc3083_test.go b/tests/msc3083_test.go index fd1ca0e2..9da71271 100644 --- a/tests/msc3083_test.go +++ b/tests/msc3083_test.go @@ -184,10 +184,9 @@ func TestRestrictedRoomsRemoteJoin(t *testing.T) { checkRestrictedRoom(t, alice, bob, space, room) } -// Not all servers can issue join events for a restricted room. Ensure a join -// completes successfully when a server is in a room, but unable to issue joins -// for it. -func TestRestrictedRoomsLimitedJoin(t *testing.T) { +// A server will do a remote join for a local user if it is unable to to issue +// joins in a restricted room it is already participating in. +func TestRestrictedRoomsRemoteJoinLocalUser(t *testing.T) { deployment := Deploy(t, b.BlueprintFederationTwoLocalOneRemote) defer deployment.Destroy(t)