mirror of
https://github.com/matrix-org/dendrite.git
synced 2026-01-20 04:23:09 -06:00
Add kickUsers test, add possibility to set guest_access event
This commit is contained in:
parent
b15d5cb4cc
commit
bc1b50f17d
|
|
@ -831,7 +831,7 @@ func (r *Inputer) kickGuests(ctx context.Context, event *gomatrixserverlib.Event
|
||||||
|
|
||||||
inputReq := &api.InputRoomEventsRequest{
|
inputReq := &api.InputRoomEventsRequest{
|
||||||
InputRoomEvents: inputEvents,
|
InputRoomEvents: inputEvents,
|
||||||
Asynchronous: true,
|
Asynchronous: true, // Needs to be async, as we otherwise create a deadlock
|
||||||
}
|
}
|
||||||
inputRes := &api.InputRoomEventsResponse{}
|
inputRes := &api.InputRoomEventsResponse{}
|
||||||
return r.InputRoomEvents(ctx, inputReq, inputRes)
|
return r.InputRoomEvents(ctx, inputReq, inputRes)
|
||||||
|
|
|
||||||
|
|
@ -2,27 +2,43 @@ package roomserver_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/matrix-org/dendrite/userapi"
|
||||||
|
|
||||||
|
userAPI "github.com/matrix-org/dendrite/userapi/api"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/roomserver"
|
"github.com/matrix-org/dendrite/roomserver"
|
||||||
"github.com/matrix-org/dendrite/roomserver/api"
|
"github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage"
|
|
||||||
"github.com/matrix-org/dendrite/setup/base"
|
|
||||||
"github.com/matrix-org/dendrite/test"
|
"github.com/matrix-org/dendrite/test"
|
||||||
"github.com/matrix-org/dendrite/test/testrig"
|
"github.com/matrix-org/dendrite/test/testrig"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func mustCreateDatabase(t *testing.T, dbType test.DBType) (*base.BaseDendrite, storage.Database, func()) {
|
func TestUsers(t *testing.T) {
|
||||||
base, close := testrig.CreateBaseDendrite(t, dbType)
|
|
||||||
db, err := storage.Open(base, &base.Cfg.KeyServer.Database, base.Caches)
|
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
|
||||||
if err != nil {
|
base, close := testrig.CreateBaseDendrite(t, dbType)
|
||||||
t.Fatalf("failed to create Database: %v", err)
|
defer close()
|
||||||
}
|
rsAPI := roomserver.NewInternalAPI(base)
|
||||||
return base, db, close
|
// SetFederationAPI starts the room event input consumer
|
||||||
|
rsAPI.SetFederationAPI(nil, nil)
|
||||||
|
|
||||||
|
t.Run("shared users", func(t *testing.T) {
|
||||||
|
testSharedUsers(t, rsAPI)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("kick users", func(t *testing.T) {
|
||||||
|
usrAPI := userapi.NewInternalAPI(base, &base.Cfg.UserAPI, nil, nil, rsAPI, nil)
|
||||||
|
rsAPI.SetUserAPI(usrAPI)
|
||||||
|
testKickUsers(t, rsAPI, usrAPI)
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_SharedUsers(t *testing.T) {
|
func testSharedUsers(t *testing.T, rsAPI api.RoomserverInternalAPI) {
|
||||||
alice := test.NewUser(t)
|
alice := test.NewUser(t)
|
||||||
bob := test.NewUser(t)
|
bob := test.NewUser(t)
|
||||||
room := test.NewRoom(t, alice, test.RoomPreset(test.PresetTrustedPrivateChat))
|
room := test.NewRoom(t, alice, test.RoomPreset(test.PresetTrustedPrivateChat))
|
||||||
|
|
@ -36,34 +52,91 @@ func Test_SharedUsers(t *testing.T) {
|
||||||
}, test.WithStateKey(bob.ID))
|
}, test.WithStateKey(bob.ID))
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
|
|
||||||
base, _, close := mustCreateDatabase(t, dbType)
|
|
||||||
defer close()
|
|
||||||
|
|
||||||
rsAPI := roomserver.NewInternalAPI(base)
|
// Create the room
|
||||||
// SetFederationAPI starts the room event input consumer
|
if err := api.SendEvents(ctx, rsAPI, api.KindNew, room.Events(), "test", "test", "test", nil, false); err != nil {
|
||||||
rsAPI.SetFederationAPI(nil, nil)
|
t.Errorf("failed to send events: %v", err)
|
||||||
// Create the room
|
}
|
||||||
if err := api.SendEvents(ctx, rsAPI, api.KindNew, room.Events(), "test", "test", "test", nil, false); err != nil {
|
|
||||||
t.Fatalf("failed to send events: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Query the shared users for Alice, there should only be Bob.
|
// Query the shared users for Alice, there should only be Bob.
|
||||||
// This is used by the SyncAPI keychange consumer.
|
// This is used by the SyncAPI keychange consumer.
|
||||||
res := &api.QuerySharedUsersResponse{}
|
res := &api.QuerySharedUsersResponse{}
|
||||||
if err := rsAPI.QuerySharedUsers(ctx, &api.QuerySharedUsersRequest{UserID: alice.ID}, res); err != nil {
|
if err := rsAPI.QuerySharedUsers(ctx, &api.QuerySharedUsersRequest{UserID: alice.ID}, res); err != nil {
|
||||||
t.Fatalf("unable to query known users: %v", err)
|
t.Errorf("unable to query known users: %v", err)
|
||||||
}
|
}
|
||||||
if _, ok := res.UserIDsToCount[bob.ID]; !ok {
|
if _, ok := res.UserIDsToCount[bob.ID]; !ok {
|
||||||
t.Fatalf("expected to find %s in shared users, but didn't: %+v", bob.ID, res.UserIDsToCount)
|
t.Errorf("expected to find %s in shared users, but didn't: %+v", bob.ID, res.UserIDsToCount)
|
||||||
}
|
}
|
||||||
// Also verify that we get the expected result when specifying OtherUserIDs.
|
// Also verify that we get the expected result when specifying OtherUserIDs.
|
||||||
// This is used by the SyncAPI when getting device list changes.
|
// This is used by the SyncAPI when getting device list changes.
|
||||||
if err := rsAPI.QuerySharedUsers(ctx, &api.QuerySharedUsersRequest{UserID: alice.ID, OtherUserIDs: []string{bob.ID}}, res); err != nil {
|
if err := rsAPI.QuerySharedUsers(ctx, &api.QuerySharedUsersRequest{UserID: alice.ID, OtherUserIDs: []string{bob.ID}}, res); err != nil {
|
||||||
t.Fatalf("unable to query known users: %v", err)
|
t.Errorf("unable to query known users: %v", err)
|
||||||
}
|
}
|
||||||
if _, ok := res.UserIDsToCount[bob.ID]; !ok {
|
if _, ok := res.UserIDsToCount[bob.ID]; !ok {
|
||||||
t.Fatalf("expected to find %s in shared users, but didn't: %+v", bob.ID, res.UserIDsToCount)
|
t.Errorf("expected to find %s in shared users, but didn't: %+v", bob.ID, res.UserIDsToCount)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
func testKickUsers(t *testing.T, rsAPI api.RoomserverInternalAPI, usrAPI userAPI.UserInternalAPI) {
|
||||||
|
// Create users and room; Bob is going to be the guest and kicked on revocation of guest access
|
||||||
|
alice := test.NewUser(t, test.WithAccountType(userAPI.AccountTypeUser))
|
||||||
|
bob := test.NewUser(t, test.WithAccountType(userAPI.AccountTypeGuest))
|
||||||
|
|
||||||
|
room := test.NewRoom(t, alice, test.RoomPreset(test.PresetPublicChat), test.GuestsCanJoin(true))
|
||||||
|
|
||||||
|
// Join with the guest user
|
||||||
|
room.CreateAndInsert(t, bob, gomatrixserverlib.MRoomMember, map[string]interface{}{
|
||||||
|
"membership": "join",
|
||||||
|
}, test.WithStateKey(bob.ID))
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
// Create the users in the userapi, so the RSAPI can query the account type later
|
||||||
|
for _, u := range []*test.User{alice, bob} {
|
||||||
|
localpart, serverName, _ := gomatrixserverlib.SplitID('@', u.ID)
|
||||||
|
userRes := &userAPI.PerformAccountCreationResponse{}
|
||||||
|
if err := usrAPI.PerformAccountCreation(ctx, &userAPI.PerformAccountCreationRequest{
|
||||||
|
AccountType: u.AccountType,
|
||||||
|
Localpart: localpart,
|
||||||
|
ServerName: serverName,
|
||||||
|
Password: "someRandomPassword",
|
||||||
|
}, userRes); err != nil {
|
||||||
|
t.Errorf("failed to create account: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the room in the database
|
||||||
|
if err := api.SendEvents(ctx, rsAPI, api.KindNew, room.Events(), "test", "test", "test", nil, false); err != nil {
|
||||||
|
t.Errorf("failed to send events: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the membership events BEFORE revoking guest access
|
||||||
|
membershipRes := &api.QueryMembershipsForRoomResponse{}
|
||||||
|
if err := rsAPI.QueryMembershipsForRoom(ctx, &api.QueryMembershipsForRoomRequest{LocalOnly: true, JoinedOnly: true, RoomID: room.ID}, membershipRes); err != nil {
|
||||||
|
t.Errorf("failed to query membership for room: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// revoke guest access
|
||||||
|
revokeEvent := room.CreateAndInsert(t, alice, gomatrixserverlib.MRoomGuestAccess, map[string]string{"guest_access": "forbidden"}, test.WithStateKey(""))
|
||||||
|
if err := api.SendEvents(ctx, rsAPI, api.KindNew, []*gomatrixserverlib.HeaderedEvent{revokeEvent}, "test", "test", "test", nil, false); err != nil {
|
||||||
|
t.Errorf("failed to send events: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Even though we are sending the events sync, the "kickUsers" function is sending the events async, so we need
|
||||||
|
// to loop and wait for the events to be processed by the roomserver.
|
||||||
|
for i := 0; i <= 20; i++ {
|
||||||
|
// Get the membership events AFTER revoking guest access
|
||||||
|
membershipRes2 := &api.QueryMembershipsForRoomResponse{}
|
||||||
|
if err := rsAPI.QueryMembershipsForRoom(ctx, &api.QueryMembershipsForRoomRequest{LocalOnly: true, JoinedOnly: true, RoomID: room.ID}, membershipRes2); err != nil {
|
||||||
|
t.Errorf("failed to query membership for room: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The membership events should NOT match, as Bob (guest user) should now be kicked from the room
|
||||||
|
if !reflect.DeepEqual(membershipRes, membershipRes2) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
time.Sleep(time.Millisecond * 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Errorf("memberships didn't change in time")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
test/room.go
22
test/room.go
|
|
@ -38,11 +38,12 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Room struct {
|
type Room struct {
|
||||||
ID string
|
ID string
|
||||||
Version gomatrixserverlib.RoomVersion
|
Version gomatrixserverlib.RoomVersion
|
||||||
preset Preset
|
preset Preset
|
||||||
visibility gomatrixserverlib.HistoryVisibility
|
guestCanJoin bool
|
||||||
creator *User
|
visibility gomatrixserverlib.HistoryVisibility
|
||||||
|
creator *User
|
||||||
|
|
||||||
authEvents gomatrixserverlib.AuthEvents
|
authEvents gomatrixserverlib.AuthEvents
|
||||||
currentState map[string]*gomatrixserverlib.HeaderedEvent
|
currentState map[string]*gomatrixserverlib.HeaderedEvent
|
||||||
|
|
@ -120,6 +121,11 @@ func (r *Room) insertCreateEvents(t *testing.T) {
|
||||||
r.CreateAndInsert(t, r.creator, gomatrixserverlib.MRoomPowerLevels, plContent, WithStateKey(""))
|
r.CreateAndInsert(t, r.creator, gomatrixserverlib.MRoomPowerLevels, plContent, WithStateKey(""))
|
||||||
r.CreateAndInsert(t, r.creator, gomatrixserverlib.MRoomJoinRules, joinRule, WithStateKey(""))
|
r.CreateAndInsert(t, r.creator, gomatrixserverlib.MRoomJoinRules, joinRule, WithStateKey(""))
|
||||||
r.CreateAndInsert(t, r.creator, gomatrixserverlib.MRoomHistoryVisibility, hisVis, WithStateKey(""))
|
r.CreateAndInsert(t, r.creator, gomatrixserverlib.MRoomHistoryVisibility, hisVis, WithStateKey(""))
|
||||||
|
if r.guestCanJoin {
|
||||||
|
r.CreateAndInsert(t, r.creator, gomatrixserverlib.MRoomGuestAccess, map[string]string{
|
||||||
|
"guest_access": "can_join",
|
||||||
|
}, WithStateKey(""))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an event in this room but do not insert it. Does not modify the room in any way (depth, fwd extremities, etc) so is thread-safe.
|
// Create an event in this room but do not insert it. Does not modify the room in any way (depth, fwd extremities, etc) so is thread-safe.
|
||||||
|
|
@ -268,3 +274,9 @@ func RoomVersion(ver gomatrixserverlib.RoomVersion) roomModifier {
|
||||||
r.Version = ver
|
r.Version = ver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GuestsCanJoin(canJoin bool) roomModifier {
|
||||||
|
return func(t *testing.T, r *Room) {
|
||||||
|
r.guestCanJoin = canJoin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ var (
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID string
|
ID string
|
||||||
accountType api.AccountType
|
AccountType api.AccountType
|
||||||
// key ID and private key of the server who has this user, if known.
|
// key ID and private key of the server who has this user, if known.
|
||||||
keyID gomatrixserverlib.KeyID
|
keyID gomatrixserverlib.KeyID
|
||||||
privKey ed25519.PrivateKey
|
privKey ed25519.PrivateKey
|
||||||
|
|
@ -66,7 +66,7 @@ func WithSigningServer(srvName gomatrixserverlib.ServerName, keyID gomatrixserve
|
||||||
|
|
||||||
func WithAccountType(accountType api.AccountType) UserOpt {
|
func WithAccountType(accountType api.AccountType) UserOpt {
|
||||||
return func(u *User) {
|
return func(u *User) {
|
||||||
u.accountType = accountType
|
u.AccountType = accountType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue