Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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-20220526125151-b6f33bc40ed8
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
Expand All @@ -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
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,12 @@ 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/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=
Expand Down Expand Up @@ -138,6 +142,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=
Expand Down
29 changes: 19 additions & 10 deletions tests/knocking_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"time"

"github.com/matrix-org/gomatrixserverlib"

"github.com/tidwall/gjson"

"github.com/matrix-org/complement/internal/b"
Expand All @@ -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)

Expand Down Expand Up @@ -67,33 +71,33 @@ 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 {
Preset string `json:"preset"`
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)
inviteWaiter.Wait(t, 5*time.Second)
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)
})
Expand All @@ -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,
},
})
})
Expand Down Expand Up @@ -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)

Expand All @@ -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
Expand All @@ -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 {
Expand Down
81 changes: 81 additions & 0 deletions tests/msc3787_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
34 changes: 21 additions & 13 deletions tests/restricted_rooms_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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",
Expand All @@ -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) {
Expand Down Expand Up @@ -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"},
},
},
Expand All @@ -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",
},
},
Expand All @@ -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.
Expand All @@ -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)
Expand All @@ -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",
Expand Down Expand Up @@ -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{
Expand Down Expand Up @@ -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 := ""
Expand Down