Skip to content
74 changes: 74 additions & 0 deletions tests/restricted_rooms_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -446,3 +446,77 @@ func doTestRestrictedRoomsRemoteJoinFailOver(t *testing.T, roomVersion string, j
return true
}))
}

// A server will attempt to perform a local join to a room with creators (v12),
// using a creator as the authorising user, but falling back to power levels if
// an appropriate creator cannot be found.
//
// ref: https://github.com/element-hq/synapse/issues/19120
func TestRestrictedRoomsLocalJoinNoCreatorsUsesPowerLevels(t *testing.T) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking the time to write a test! It looks great overall 🤩

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tested to make sure it fails with the latest develop with Synapse and passes with element-hq/synapse#19321

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested again to make sure all of the new tests pass locally ✅ :

  1. Checkout Complement:
    1. Switch to the correct branch (this PR):
    2. git fetch origin refs/pull/836/head:pr-836
    3. git checkout pr-836
  2. Checkout Synapse:
    1. Switch to the correct branch (Fall back to checking power levels when sourcing local restricted join users element-hq/synapse#19321):
    2. git fetch origin refs/pull/19321/head:pr-19321
    3. git checkout pr-19321
  3. COMPLEMENT_DIR=../complement ./scripts-dev/complement.sh ./tests -run TestRestrictedRoomsLocalJoinNoCreatorsUsesPowerLevelsV
  4. COMPLEMENT_DIR=../complement ./scripts-dev/complement.sh ./tests -run TestKnockRestrictedRoomsLocalJoinNoCreatorsUsesPowerLevelsV

doTestRestrictedRoomsLocalJoinNoCreatorsUsesPowerLevels(t, "12", "restricted")
}

func doTestRestrictedRoomsLocalJoinNoCreatorsUsesPowerLevels(t *testing.T, roomVersion string, joinRule string) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the reason other tests are written this way is so that it can be shared with tests/knock_restricted_test.go. I'm guessing we should also have knock_restricted test there.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(needs change)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added knock variants in 3cb69dd. Do you want them all to have docstrings or is TestRestrictedRoomsLocalJoinNoCreatorsUsesPowerLevelsV12's just being within view fine?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can say this:

// See docstring on `TestRestrictedRoomsLocalJoinNoCreatorsUsesPowerLevelsV12`

deployment := complement.Deploy(t, 2)
defer deployment.Destroy(t)
// Create the room
alice, allowed_room, room := setupRestrictedRoom(t, deployment, roomVersion, joinRule)
// Create two users on the other homeserver.
bob := deployment.Register(t, "hs2", helpers.RegistrationOpts{})
charlie := deployment.Register(t, "hs2", helpers.RegistrationOpts{})

// Bob joins the allowed room.
bob.JoinRoom(t, allowed_room, []spec.ServerName{
deployment.GetFullyQualifiedHomeserverName(t, "hs1"),
})
// Bob joins the restricted room. This join should go remotely
// and consequently be authorised by Alice as she is the only
// member.
bob.JoinRoom(t, room, []spec.ServerName{
deployment.GetFullyQualifiedHomeserverName(t, "hs1"),
})
// Ensure the join was authorised by alice
bob.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, room, func(ev gjson.Result) bool {
must.MatchGJSON(t, ev,
match.JSONKeyEqual("content.join_authorised_via_users_server", alice.UserID),
)
return true
}))

// Alice restricts the invite power level to moderators and promotes Bob to
// moderator.
state_key := ""
alice.SendEventSynced(t, room, b.Event{
Type: "m.room.power_levels",
StateKey: &state_key,
Content: map[string]interface{}{
"invite": 50,
"users": map[string]interface{}{
bob.UserID: 50,
},
},
})

// Charlie joins the allowed room.
charlie.JoinRoom(t, allowed_room, []spec.ServerName{
deployment.GetFullyQualifiedHomeserverName(t, "hs1"),
})
// Charlie attempts to join the restricted room.
// hs2 should attempt to find a creator to authorise the room join,
// but can't as the only creator is remote. It should then fall back
// to checking the power levels for a user that can authorise the join.
// The end result should be that charlie is allowed to join.
charlie.JoinRoom(t, room, []spec.ServerName{
deployment.GetFullyQualifiedHomeserverName(t, "hs2"),
})

// Ensure the join was authorised by bob. The join should not be
// authorised by alice as hs2 should not have attempted a remote
// join given bob is a local user that can authorise the join.
bob.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(charlie.UserID, room, func(ev gjson.Result) bool {
must.MatchGJSON(t, ev,
match.JSONKeyEqual("content.join_authorised_via_users_server", bob.UserID),
)
return true
}))
}
Loading