-
Notifications
You must be signed in to change notification settings - Fork 61
Test failover logic for MSC3083 #172
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a3dc950
a818c33
4dba467
11ddf9c
24ecdb8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,7 +17,7 @@ import ( | |
| "github.com/tidwall/gjson" | ||
| ) | ||
|
|
||
| func failJoinRoom(t *testing.T, c *client.CSAPI, roomIDOrAlias string, serverName string) { | ||
| func failJoinRoom(t *testing.T, c *client.CSAPI, roomIDOrAlias string, serverName string, expectedErrorCode int) { | ||
| t.Helper() | ||
|
|
||
| // This is copied from Client.JoinRoom to test a join failure. | ||
|
|
@@ -30,7 +30,7 @@ func failJoinRoom(t *testing.T, c *client.CSAPI, roomIDOrAlias string, serverNam | |
| client.WithQueries(query), | ||
| ) | ||
| must.MatchResponse(t, res, match.HTTPResponse{ | ||
| StatusCode: 403, | ||
| StatusCode: expectedErrorCode, | ||
| }) | ||
| } | ||
|
|
||
|
|
@@ -84,7 +84,7 @@ func setupRestrictedRoom(t *testing.T, deployment *docker.Deployment) (*client.C | |
| func checkRestrictedRoom(t *testing.T, alice *client.CSAPI, bob *client.CSAPI, space string, room string) { | ||
| t.Helper() | ||
|
|
||
| failJoinRoom(t, bob, room, "hs1") | ||
| failJoinRoom(t, bob, room, "hs1", 403) | ||
|
|
||
| // Join the space, attempt to join the room again, which now should succeed. | ||
| bob.JoinRoom(t, space, []string{"hs1"}) | ||
|
|
@@ -108,7 +108,7 @@ func checkRestrictedRoom(t *testing.T, alice *client.CSAPI, bob *client.CSAPI, s | |
| return ev.Get("content").Get("membership").Str == "leave" | ||
| }) | ||
|
|
||
| failJoinRoom(t, bob, room, "hs1") | ||
| failJoinRoom(t, bob, room, "hs1", 403) | ||
|
|
||
| // Invite the user and joining should work. | ||
| alice.InviteRoom(t, room, bob.UserID) | ||
|
|
@@ -135,7 +135,7 @@ func checkRestrictedRoom(t *testing.T, alice *client.CSAPI, bob *client.CSAPI, s | |
| }, | ||
| ) | ||
| // Fails since invalid values get filtered out of allow. | ||
| failJoinRoom(t, bob, room, "hs1") | ||
| failJoinRoom(t, bob, room, "hs1", 403) | ||
|
|
||
| alice.SendEventSynced( | ||
| t, | ||
|
|
@@ -151,7 +151,7 @@ func checkRestrictedRoom(t *testing.T, alice *client.CSAPI, bob *client.CSAPI, s | |
| }, | ||
| ) | ||
| // Fails since a fully invalid allow key requires an invite. | ||
| failJoinRoom(t, bob, room, "hs1") | ||
| failJoinRoom(t, bob, room, "hs1", 403) | ||
| } | ||
|
|
||
| // Test joining a room with join rules restricted to membership in a space. | ||
|
|
@@ -250,7 +250,7 @@ func TestRestrictedRoomsRemoteJoinLocalUser(t *testing.T) { | |
| }) | ||
|
|
||
| // Bob cannot join the room. | ||
| failJoinRoom(t, bob, room, "hs1") | ||
| failJoinRoom(t, bob, room, "hs1", 403) | ||
|
|
||
| // Join the space via hs2. | ||
| bob.JoinRoom(t, space, []string{"hs2"}) | ||
|
|
@@ -309,6 +309,150 @@ func TestRestrictedRoomsRemoteJoinLocalUser(t *testing.T) { | |
| bob.JoinRoom(t, room, []string{"hs1"}) | ||
| } | ||
|
|
||
| // A server will request a failover if asked to /make_join and it does not have | ||
| // the appropriate authorisation to complete the request. | ||
| // | ||
| // Setup 3 homeservers: | ||
| // * hs1 creates the space/room. | ||
| // * hs2 joins the room | ||
| // * hs3 attempts to join via hs2 (should fail) and hs1 (should work) | ||
| func TestRestrictedRoomsRemoteJoinFailOver(t *testing.T) { | ||
| deployment := Deploy(t, b.Blueprint{ | ||
| Name: "federation_three_homeservers", | ||
| Homeservers: []b.Homeserver{ | ||
| { | ||
| Name: "hs1", | ||
| Users: []b.User{ | ||
| { | ||
| Localpart: "alice", | ||
| DisplayName: "Alice", | ||
| }, | ||
| }, | ||
| }, | ||
| { | ||
| Name: "hs2", | ||
| Users: []b.User{ | ||
| { | ||
| Localpart: "bob", | ||
| DisplayName: "Bob", | ||
| }, | ||
| }, | ||
| }, | ||
| { | ||
| Name: "hs3", | ||
| Users: []b.User{ | ||
| { | ||
| Localpart: "charlie", | ||
| DisplayName: "Charlie", | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| }) | ||
| defer deployment.Destroy(t) | ||
|
|
||
| // Setup the user, space, and restricted room. | ||
| alice, space, room := setupRestrictedRoom(t, deployment) | ||
|
|
||
| // Raise the power level so that only alice can invite. | ||
| state_key := "" | ||
| alice.SendEventSynced(t, room, b.Event{ | ||
| Type: "m.room.power_levels", | ||
| StateKey: &state_key, | ||
| Content: map[string]interface{}{ | ||
| "invite": 100, | ||
| "users": map[string]interface{}{ | ||
| alice.UserID: 100, | ||
| }, | ||
| }, | ||
| }) | ||
|
|
||
| // Create a second user on a different homeserver. | ||
| bob := deployment.Client(t, "hs2", "@bob:hs2") | ||
|
|
||
| // Bob joins the room and space. | ||
| bob.JoinRoom(t, space, []string{"hs1"}) | ||
| bob.JoinRoom(t, room, []string{"hs1"}) | ||
|
||
|
|
||
| // Charlie should join the space (which gives access to the room). | ||
| charlie := deployment.Client(t, "hs3", "@charlie:hs3") | ||
| charlie.JoinRoom(t, space, []string{"hs1"}) | ||
|
|
||
| // hs2 doesn't have anyone to invite from, so the join fails. | ||
| failJoinRoom(t, charlie, room, "hs2", 502) | ||
|
||
|
|
||
| // Including hs1 (and failing over to it) allows the join to succeed. | ||
| charlie.JoinRoom(t, room, []string{"hs2", "hs1"}) | ||
|
|
||
| // Double check that the join was authorised via hs1. | ||
| bob.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, "join", "Charlie failed to join the room") | ||
| must.EqualStr(t, ev.Get("content").Get("join_authorised_via_users_server").Str, alice.UserID, "Join authorised via incorrect server") | ||
|
|
||
| return true | ||
| }, | ||
| ) | ||
|
|
||
| // Bump the power-level of bob. | ||
| alice.SendEventSynced(t, room, b.Event{ | ||
| Type: "m.room.power_levels", | ||
| StateKey: &state_key, | ||
| Content: map[string]interface{}{ | ||
| "invite": 100, | ||
| "users": map[string]interface{}{ | ||
| alice.UserID: 100, | ||
| bob.UserID: 100, | ||
| }, | ||
| }, | ||
| }) | ||
|
|
||
| // Charlie leaves the room (so they can rejoin). | ||
| charlie.LeaveRoom(t, room) | ||
|
|
||
| // Ensure the events have synced to hs2. | ||
| bob.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 | ||
| } | ||
| return ev.Get("content").Get("membership").Str == "leave" | ||
| }, | ||
| ) | ||
|
|
||
| // Bob leaves the space so that hs2 doesn't know if Charlie is in the space or not. | ||
| bob.LeaveRoom(t, space) | ||
|
|
||
| // hs2 cannot complete the join since they do not know if Charlie meets the | ||
| // requirements (since it is no longer in the space). | ||
| failJoinRoom(t, charlie, room, "hs2", 502) | ||
|
|
||
| // Including hs1 (and failing over to it) allows the join to succeed. | ||
| charlie.JoinRoom(t, room, []string{"hs2", "hs1"}) | ||
|
|
||
| // Double check that the join was authorised via hs1. | ||
| bob.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, "join", "Charlie failed to join the room") | ||
| must.EqualStr(t, ev.Get("content").Get("join_authorised_via_users_server").Str, alice.UserID, "Join authorised via incorrect server") | ||
|
|
||
| return true | ||
| }, | ||
| ) | ||
| } | ||
|
|
||
| // 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() | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't you use
setupRestrictedRoomin the previous test?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The joiners need to be on the same server while the creator needs to be on a separate server. Unfortunately
BlueprintFederationTwoLocalOneRemotehas alice and bob on one server and charlie on another.