From 25adcae601732a79843aca7e8c5006eb0c11ac5e Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 27 May 2022 04:52:04 -0600 Subject: [PATCH] Add tests for MSC3787 (#367) Co-authored-by: Erik Johnston Co-authored-by: David Robertson Co-authored-by: Kegan Dougal --- .github/workflows/ci.yaml | 4 +- go.mod | 4 +- go.sum | 8 ++++ tests/knocking_test.go | 29 +++++++----- tests/msc3787_test.go | 81 ++++++++++++++++++++++++++++++++++ tests/restricted_rooms_test.go | 34 ++++++++------ 6 files changed, 133 insertions(+), 27 deletions(-) create mode 100644 tests/msc3787_test.go diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a024138f..e1944653 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -30,8 +30,8 @@ jobs: matrix: include: - homeserver: Synapse - tags: synapse_blacklist msc3083 faster_joins - + tags: synapse_blacklist msc3083 msc3787 faster_joins + - homeserver: Dendrite tags: msc2836 dendrite_blacklist diff --git a/go.mod b/go.mod index 1621c9ad..4400d7b3 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/gorilla/mux v1.8.0 github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16 - github.com/matrix-org/gomatrixserverlib v0.0.0-20220524100759-f98e737f8f9c + github.com/matrix-org/gomatrixserverlib v0.0.0-20220526140030-dcfbb70ff32d github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4 github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect github.com/morikuni/aec v1.0.0 // indirect @@ -21,7 +21,7 @@ require ( github.com/sirupsen/logrus v1.8.1 github.com/tidwall/gjson v1.14.1 github.com/tidwall/sjson v1.2.4 - golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898 // indirect + golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 // indirect golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 // indirect golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 // indirect diff --git a/go.sum b/go.sum index eef71e63..333697af 100644 --- a/go.sum +++ b/go.sum @@ -76,8 +76,14 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/matrix-org/gomatrix v0.0.0-20190528120928-7df988a63f26/go.mod h1:3fxX6gUjWyI/2Bt7J1OLhpCzOfO/bB3AiX0cJtEKud0= github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16 h1:ZtO5uywdd5dLDCud4r0r55eP4j9FuUNpl60Gmntcop4= github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= +github.com/matrix-org/gomatrixserverlib v0.0.0-20220519174812-8904a93b5a99 h1:JsIMDWZl2B9bReq/yNlLSsBk2Zvx+JO8Ci8B+eZDHzM= +github.com/matrix-org/gomatrixserverlib v0.0.0-20220519174812-8904a93b5a99/go.mod h1:V5eO8rn/C3rcxig37A/BCeKerLFS+9Avg/77FIeTZ48= github.com/matrix-org/gomatrixserverlib v0.0.0-20220524100759-f98e737f8f9c h1:J9krMtVgo4mV/G+mRA1u3GL6nNxdNnuPcs891uIQGic= github.com/matrix-org/gomatrixserverlib v0.0.0-20220524100759-f98e737f8f9c/go.mod h1:V5eO8rn/C3rcxig37A/BCeKerLFS+9Avg/77FIeTZ48= +github.com/matrix-org/gomatrixserverlib v0.0.0-20220526125151-b6f33bc40ed8 h1:5cdzTYzcwWxp7TvYtHi5WpMHarPddpFDxHnkLtgGgdE= +github.com/matrix-org/gomatrixserverlib v0.0.0-20220526125151-b6f33bc40ed8/go.mod h1:V5eO8rn/C3rcxig37A/BCeKerLFS+9Avg/77FIeTZ48= +github.com/matrix-org/gomatrixserverlib v0.0.0-20220526140030-dcfbb70ff32d h1:IwyG/58rFn0/ugD0A/IdSIo7D/oLJ4+k3NznlYhzyHs= +github.com/matrix-org/gomatrixserverlib v0.0.0-20220526140030-dcfbb70ff32d/go.mod h1:jX38yp3SSLJNftBg3PXU1ayd0PCLIiDHQ4xAc9DIixk= github.com/matrix-org/util v0.0.0-20190711121626-527ce5ddefc7/go.mod h1:vVQlW/emklohkZnOPwD3LrZUBqdfsbiyO3p1lNV8F6U= github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4 h1:eCEHXWDv9Rm335MSuB49mFUK44bwZPFSDde3ORE3syk= github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4/go.mod h1:vVQlW/emklohkZnOPwD3LrZUBqdfsbiyO3p1lNV8F6U= @@ -138,6 +144,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898 h1:SLP7Q4Di66FONjDJbCYrCRrh97focO6sLogHO7/g8F0= golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= diff --git a/tests/knocking_test.go b/tests/knocking_test.go index 258306fa..ad0ded38 100644 --- a/tests/knocking_test.go +++ b/tests/knocking_test.go @@ -15,7 +15,6 @@ import ( "time" "github.com/matrix-org/gomatrixserverlib" - "github.com/tidwall/gjson" "github.com/matrix-org/complement/internal/b" @@ -32,6 +31,11 @@ const testKnockReason string = "Let me in... LET ME IN!!!" // Knocking is currently an experimental feature and not in the matrix spec. // This function tests knocking on local and remote room. func TestKnocking(t *testing.T) { + // v7 is required for knocking support + doTestKnocking(t, "7", "knock") +} + +func doTestKnocking(t *testing.T, roomVersion string, joinRule string) { deployment := Deploy(t, b.BlueprintFederationTwoLocalOneRemote) defer deployment.Destroy(t) @@ -67,14 +71,14 @@ func TestKnocking(t *testing.T) { RoomVersion string `json:"room_version"` }{ "private_chat", // Set to private in order to get an invite-only room - "7", // Room version required for knocking. + roomVersion, }) alice.InviteRoom(t, roomIDOne, david) inviteWaiter.Wait(t, 5*time.Second) serverRoomOne := srv.MustJoinRoom(t, deployment, "hs1", roomIDOne, david) // Test knocking between two users on the same homeserver - knockingBetweenTwoUsersTest(t, roomIDOne, alice, bob, serverRoomOne, false) + knockingBetweenTwoUsersTest(t, roomIDOne, alice, bob, serverRoomOne, false, joinRule) // Create a room for alice and charlie to test knocking with roomIDTwo := alice.CreateRoom(t, struct { @@ -82,7 +86,7 @@ func TestKnocking(t *testing.T) { RoomVersion string `json:"room_version"` }{ "private_chat", // Set to private in order to get an invite-only room - "7", // Room version required for knocking. + roomVersion, }) inviteWaiter = NewWaiter() alice.InviteRoom(t, roomIDTwo, david) @@ -90,10 +94,10 @@ func TestKnocking(t *testing.T) { serverRoomTwo := srv.MustJoinRoom(t, deployment, "hs1", roomIDTwo, david) // Test knocking between two users, each on a separate homeserver - knockingBetweenTwoUsersTest(t, roomIDTwo, alice, charlie, serverRoomTwo, true) + knockingBetweenTwoUsersTest(t, roomIDTwo, alice, charlie, serverRoomTwo, true, joinRule) } -func knockingBetweenTwoUsersTest(t *testing.T, roomID string, inRoomUser, knockingUser *client.CSAPI, serverRoom *federation.ServerRoom, testFederation bool) { +func knockingBetweenTwoUsersTest(t *testing.T, roomID string, inRoomUser, knockingUser *client.CSAPI, serverRoom *federation.ServerRoom, testFederation bool, joinRule string) { t.Run("Knocking on a room with a join rule other than 'knock' should fail", func(t *testing.T) { knockOnRoomWithStatus(t, knockingUser, roomID, "Can I knock anyways?", []string{"hs1"}, 403) }) @@ -105,7 +109,7 @@ func knockingBetweenTwoUsersTest(t *testing.T, roomID string, inRoomUser, knocki Sender: inRoomUser.UserID, StateKey: &emptyStateKey, Content: map[string]interface{}{ - "join_rule": "knock", + "join_rule": joinRule, }, }) }) @@ -367,6 +371,11 @@ func knockOnRoomWithStatus(t *testing.T, c *client.CSAPI, roomID, reason string, // representing a knock room. For sanity-checking, this test will also create a public room and ensure it has a // 'join_rule' representing a publicly-joinable room. func TestKnockRoomsInPublicRoomsDirectory(t *testing.T) { + // v7 is required for knocking + doTestKnockRoomsInPublicRoomsDirectory(t, "7", "knock") +} + +func doTestKnockRoomsInPublicRoomsDirectory(t *testing.T, roomVersion string, joinRule string) { deployment := Deploy(t, b.BlueprintAlice) defer deployment.Destroy(t) @@ -380,7 +389,7 @@ func TestKnockRoomsInPublicRoomsDirectory(t *testing.T) { RoomVersion string `json:"room_version"` }{ "private_chat", // Set to private in order to get an invite-only room - "7", // Room version required for knocking. + roomVersion, }) // Change the join_rule to allow knocking @@ -390,12 +399,12 @@ func TestKnockRoomsInPublicRoomsDirectory(t *testing.T) { Sender: alice.UserID, StateKey: &emptyStateKey, Content: map[string]interface{}{ - "join_rule": "knock", + "join_rule": joinRule, }, }) // Publish the room to the public room directory and check that the 'join_rule' key is knock - publishAndCheckRoomJoinRule(t, alice, roomID, "knock") + publishAndCheckRoomJoinRule(t, alice, roomID, joinRule) // Create a public room roomID = alice.CreateRoom(t, struct { diff --git a/tests/msc3787_test.go b/tests/msc3787_test.go new file mode 100644 index 00000000..6c8c7272 --- /dev/null +++ b/tests/msc3787_test.go @@ -0,0 +1,81 @@ +//go:build msc3787 +// +build msc3787 + +// This file contains tests for a join rule which mixes concepts of restricted joins +// and knocking. This is currently experimental and defined by MSC3787, found here: +// /~https://github.com/matrix-org/matrix-spec-proposals/pull/3787 +// +// Generally, this is a combination of knocking_test and restricted_rooms_test. + +package tests + +import ( + "testing" + + "github.com/matrix-org/complement/internal/b" +) + +var ( + msc3787RoomVersion = "org.matrix.msc3787" + msc3787JoinRule = "knock_restricted" +) + +// See TestKnocking +func TestKnockingInMSC3787Room(t *testing.T) { + doTestKnocking(t, msc3787RoomVersion, msc3787JoinRule) +} + +// See TestKnockRoomsInPublicRoomsDirectory +func TestKnockRoomsInPublicRoomsDirectoryInMSC3787Room(t *testing.T) { + doTestKnockRoomsInPublicRoomsDirectory(t, msc3787RoomVersion, msc3787JoinRule) +} + +// See TestCannotSendKnockViaSendKnock +func TestCannotSendKnockViaSendKnockInMSC3787Room(t *testing.T) { + testValidationForSendMembershipEndpoint(t, "/_matrix/federation/v1/send_knock", "knock", + map[string]interface{}{ + "preset": "public_chat", + "room_version": msc3787RoomVersion, + }, + ) +} + +// See TestRestrictedRoomsLocalJoin +func TestRestrictedRoomsLocalJoinInMSC3787Room(t *testing.T) { + deployment := Deploy(t, b.BlueprintOneToOneRoom) + defer deployment.Destroy(t) + + // Setup the user, allowed room, and restricted room. + alice, allowed_room, room := setupRestrictedRoom(t, deployment, msc3787RoomVersion, msc3787JoinRule) + + // Create a second user on the same homeserver. + bob := deployment.Client(t, "hs1", "@bob:hs1") + + // Execute the checks. + checkRestrictedRoom(t, alice, bob, allowed_room, room, msc3787JoinRule) +} + +// See TestRestrictedRoomsRemoteJoin +func TestRestrictedRoomsRemoteJoinInMSC3787Room(t *testing.T) { + deployment := Deploy(t, b.BlueprintFederationOneToOneRoom) + defer deployment.Destroy(t) + + // Setup the user, allowed room, and restricted room. + alice, allowed_room, room := setupRestrictedRoom(t, deployment, msc3787RoomVersion, msc3787JoinRule) + + // Create a second user on a different homeserver. + bob := deployment.Client(t, "hs2", "@bob:hs2") + + // Execute the checks. + checkRestrictedRoom(t, alice, bob, allowed_room, room, msc3787JoinRule) +} + +// See TestRestrictedRoomsRemoteJoinLocalUser +func TestRestrictedRoomsRemoteJoinLocalUserInMSC3787Room(t *testing.T) { + doTestRestrictedRoomsRemoteJoinLocalUser(t, msc3787RoomVersion, msc3787JoinRule) +} + +// See TestRestrictedRoomsRemoteJoinFailOver +func TestRestrictedRoomsRemoteJoinFailOverInMSC3787Room(t *testing.T) { + doTestRestrictedRoomsRemoteJoinFailOver(t, msc3787RoomVersion, msc3787JoinRule) +} diff --git a/tests/restricted_rooms_test.go b/tests/restricted_rooms_test.go index ae88a96a..487aa883 100644 --- a/tests/restricted_rooms_test.go +++ b/tests/restricted_rooms_test.go @@ -33,7 +33,7 @@ func failJoinRoom(t *testing.T, c *client.CSAPI, roomIDOrAlias string, serverNam // Creates two rooms on room version 8 and sets the second room to have // restricted join rules with allow set to the first room. -func setupRestrictedRoom(t *testing.T, deployment *docker.Deployment) (*client.CSAPI, string, string) { +func setupRestrictedRoom(t *testing.T, deployment *docker.Deployment, roomVersion string, joinRule string) (*client.CSAPI, string, string) { t.Helper() alice := deployment.Client(t, "hs1", "@alice:hs1") @@ -47,13 +47,13 @@ func setupRestrictedRoom(t *testing.T, deployment *docker.Deployment) (*client.C room := alice.CreateRoom(t, map[string]interface{}{ "preset": "public_chat", "name": "Room", - "room_version": "8", + "room_version": roomVersion, "initial_state": []map[string]interface{}{ { "type": "m.room.join_rules", "state_key": "", "content": map[string]interface{}{ - "join_rule": "restricted", + "join_rule": joinRule, "allow": []map[string]interface{}{ { "type": "m.room_membership", @@ -69,7 +69,7 @@ func setupRestrictedRoom(t *testing.T, deployment *docker.Deployment) (*client.C return alice, allowed_room, room } -func checkRestrictedRoom(t *testing.T, alice *client.CSAPI, bob *client.CSAPI, allowed_room string, room string) { +func checkRestrictedRoom(t *testing.T, alice *client.CSAPI, bob *client.CSAPI, allowed_room string, room string, joinRule string) { t.Helper() t.Run("Join should fail initially", func(t *testing.T) { @@ -141,7 +141,7 @@ func checkRestrictedRoom(t *testing.T, alice *client.CSAPI, bob *client.CSAPI, a Sender: alice.UserID, StateKey: &emptyStateKey, Content: map[string]interface{}{ - "join_rule": "restricted", + "join_rule": joinRule, "allow": []string{"invalid"}, }, }, @@ -157,7 +157,7 @@ func checkRestrictedRoom(t *testing.T, alice *client.CSAPI, bob *client.CSAPI, a Sender: alice.UserID, StateKey: &emptyStateKey, Content: map[string]interface{}{ - "join_rule": "restricted", + "join_rule": joinRule, "allow": "invalid", }, }, @@ -173,13 +173,13 @@ func TestRestrictedRoomsLocalJoin(t *testing.T) { defer deployment.Destroy(t) // Setup the user, allowed room, and restricted room. - alice, allowed_room, room := setupRestrictedRoom(t, deployment) + alice, allowed_room, room := setupRestrictedRoom(t, deployment, "8", "restricted") // Create a second user on the same homeserver. bob := deployment.Client(t, "hs1", "@bob:hs1") // Execute the checks. - checkRestrictedRoom(t, alice, bob, allowed_room, room) + checkRestrictedRoom(t, alice, bob, allowed_room, room, "restricted") } // Test joining a room with join rules restricted to membership in another room. @@ -188,18 +188,22 @@ func TestRestrictedRoomsRemoteJoin(t *testing.T) { defer deployment.Destroy(t) // Setup the user, allowed room, and restricted room. - alice, allowed_room, room := setupRestrictedRoom(t, deployment) + alice, allowed_room, room := setupRestrictedRoom(t, deployment, "8", "restricted") // Create a second user on a different homeserver. bob := deployment.Client(t, "hs2", "@bob:hs2") // Execute the checks. - checkRestrictedRoom(t, alice, bob, allowed_room, room) + checkRestrictedRoom(t, alice, bob, allowed_room, room, "restricted") } // 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) { + doTestRestrictedRoomsRemoteJoinLocalUser(t, "8", "restricted") +} + +func doTestRestrictedRoomsRemoteJoinLocalUser(t *testing.T, roomVersion string, joinRule string) { runtime.SkipIf(t, runtime.Dendrite) // requires more debugging deployment := Deploy(t, b.BlueprintFederationTwoLocalOneRemote) @@ -218,13 +222,13 @@ func TestRestrictedRoomsRemoteJoinLocalUser(t *testing.T) { room := charlie.CreateRoom(t, map[string]interface{}{ "preset": "public_chat", "name": "Room", - "room_version": "8", + "room_version": roomVersion, "initial_state": []map[string]interface{}{ { "type": "m.room.join_rules", "state_key": "", "content": map[string]interface{}{ - "join_rule": "restricted", + "join_rule": joinRule, "allow": []map[string]interface{}{ { "type": "m.room_membership", @@ -323,6 +327,10 @@ func TestRestrictedRoomsRemoteJoinLocalUser(t *testing.T) { // * hs2 joins the room // * hs3 attempts to join via hs2 (should fail) and hs1 (should work) func TestRestrictedRoomsRemoteJoinFailOver(t *testing.T) { + doTestRestrictedRoomsRemoteJoinFailOver(t, "8", "restricted") +} + +func doTestRestrictedRoomsRemoteJoinFailOver(t *testing.T, roomVersion string, joinRule string) { runtime.SkipIf(t, runtime.Dendrite) // requires more debugging deployment := Deploy(t, b.Blueprint{ @@ -360,7 +368,7 @@ func TestRestrictedRoomsRemoteJoinFailOver(t *testing.T) { defer deployment.Destroy(t) // Setup the user, allowed room, and restricted room. - alice, allowed_room, room := setupRestrictedRoom(t, deployment) + alice, allowed_room, room := setupRestrictedRoom(t, deployment, roomVersion, joinRule) // Raise the power level so that only alice can invite. state_key := ""