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
		},
	)
}
// 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)
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)
// 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)
	alice, space, room := setupRestrictedRoom(t, deployment)
	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,
			},
		},
	})
	bob := deployment.Client(t, "hs2", "@bob:hs2")
	bob.JoinRoom(t, space, []string{"hs1"})
	bob.JoinRoom(t, room, []string{"hs1"})
	charlie := deployment.Client(t, "hs3", "@charlie:hs3")
	charlie.JoinRoom(t, space, []string{"hs1"})
	failJoinRoom(t, charlie, room, "hs2", 502)
	charlie.JoinRoom(t, room, []string{"hs2", "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
		},
	)
	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.LeaveRoom(t, room)
	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.LeaveRoom(t, space)
	failJoinRoom(t, charlie, room, "hs2", 502)
	charlie.JoinRoom(t, room, []string{"hs2", "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
		},
	)
}
func TestRestrictedRoomsRemoteJoinFailOver ( t * testing . T ) { deployment := Deploy ( t , b . Blueprint { Name : " " , Homeservers : [ ] b . Homeserver { { Name : " " , Users : [ ] b . User { { Localpart : " " , DisplayName : " " , } , } , } , { Name : " " , Users : [ ] b . User { { Localpart : " " , DisplayName : " " , } , } , } , { Name : " " , Users : [ ] b . User { { Localpart : " " , DisplayName : " " , } , } , } , } , } ) defer deployment . Destroy ( t ) alice , space , room := setupRestrictedRoom ( t , deployment ) state_key := " " alice . SendEventSynced ( t , room , b . Event { Type : " " , StateKey : & state_key , Content : map [ string ] interface { } { " " : 100 , " " : map [ string ] interface { } { alice . UserID : 100 , } , } , } ) bob := deployment . Client ( t , " " , " " ) bob . JoinRoom ( t , space , [ ] string { " " } ) bob . JoinRoom ( t , room , [ ] string { " " } ) charlie := deployment . Client ( t , " " , " " ) charlie . JoinRoom ( t , space , [ ] string { " " } ) failJoinRoom ( t , charlie , room , " " , 502 ) charlie . JoinRoom ( t , room , [ ] string { " " , " " } ) bob . SyncUntilTimelineHas ( t , room , func ( ev gjson . Result ) bool { if ev . Get ( " " ) . Str != " " || ev . Get ( " " ) . Str != charlie . UserID { return false } must . EqualStr ( t , ev . Get ( " " ) . Get ( " " ) . Str , " " , " " ) must . EqualStr ( t , ev . Get ( " " ) . Get ( " " ) . Str , alice . UserID , " " ) return true } , ) alice . SendEventSynced ( t , room , b . Event { Type : " " , StateKey : & state_key , Content : map [ string ] interface { } { " " : 100 , " " : map [ string ] interface { } { alice . UserID : 100 , bob . UserID : 100 , } , } , } ) charlie . LeaveRoom ( t , room ) bob . SyncUntilTimelineHas ( t , room , func ( ev gjson . Result ) bool { if ev . Get ( " " ) . Str != " " || ev . Get ( " " ) . Str != charlie . UserID { return false } return ev . Get ( " " ) . Get ( " " ) . Str == " " } , ) bob . LeaveRoom ( t , space ) failJoinRoom ( t , charlie , room , " " , 502 ) charlie . JoinRoom ( t , room , [ ] string { " " , " " } ) bob . SyncUntilTimelineHas ( t , room , func ( ev gjson . Result ) bool { if ev . Get ( " " ) . Str != " " || ev . Get ( " " ) . Str != charlie . UserID { return false } must . EqualStr ( t , ev . Get ( " " ) . Get ( " " ) . Str , " " , " " ) must . EqualStr ( t , ev . Get ( " " ) . Get ( " " ) . Str , alice . UserID , " " ) return true } , ) }
A server will request a failover if asked to /make_join and it does not have
the appropriate authorisation to complete the request.
A server will request a failover if asked to / make_join and it does not have the appropriate authorisation to complete the request .
// Setup the user, space, and restricted room. // Raise the power level so that only alice can invite. // Create a second user on a different homeserver. // Bob joins the room and space. // Charlie should join the space (which gives access to the room). // hs2 doesn't have anyone to invite from, so the join fails. // Including hs1 (and failing over to it) allows the join to succeed. // Double check that the join was authorised via hs1. // Bump the power-level of bob. // Charlie leaves the room (so they can rejoin). // Ensure the events have synced to hs2. // Bob leaves the space so that hs2 doesn't know if Charlie is in the space or not. // hs2 cannot complete the join since they do not know if Charlie meets the // requirements (since it is no longer in the space). // Including hs1 (and failing over to it) allows the join to succeed. // Double check that the join was authorised via hs1.