Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
matrix:
include:
- homeserver: Synapse
tags: synapse_blacklist,msc3083
tags: synapse_blacklist,msc3083,msc3787

- homeserver: Dendrite
tags: msc2836 dendrite_blacklist
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 @@ -34,7 +34,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 @@ -48,13 +48,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 @@ -70,7 +70,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 @@ -142,7 +142,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 @@ -158,7 +158,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 @@ -174,13 +174,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 @@ -189,18 +189,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) {
deployment := Deploy(t, b.BlueprintFederationTwoLocalOneRemote)
defer deployment.Destroy(t)

Expand All @@ -217,13 +221,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 @@ -322,6 +326,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) {
deployment := Deploy(t, b.Blueprint{
Name: "federation_three_homeservers",
Homeservers: []b.Homeserver{
Expand Down Expand Up @@ -357,7 +365,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