Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
44 changes: 30 additions & 14 deletions tests/csapi/apidoc_room_alias_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/matrix-org/complement/match"
"github.com/matrix-org/complement/must"
"github.com/matrix-org/complement/should"
"github.com/matrix-org/gomatrixserverlib"
)

func setRoomAliasResp(t *testing.T, c *client.CSAPI, roomID, roomAlias string) *http.Response {
Expand Down Expand Up @@ -192,6 +193,8 @@ func TestRoomDeleteAlias(t *testing.T) {
alice := deployment.Register(t, "hs1", helpers.RegistrationOpts{})
bob := deployment.Register(t, "hs1", helpers.RegistrationOpts{})

defaultRoomVersion := alice.GetDefaultRoomVersion(t)

t.Run("Parallel", func(t *testing.T) {
// sytest: Alias creators can delete alias with no ops
t.Run("Alias creators can delete alias with no ops", func(t *testing.T) {
Expand Down Expand Up @@ -352,14 +355,21 @@ func TestRoomDeleteAlias(t *testing.T) {
alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.power_levels",
StateKey: b.Ptr(""),
Content: map[string]interface{}{
"users": map[string]int64{
alice.UserID: 100,
},
"events": map[string]int64{
"m.room.aliases": 50,
},
},
Content: func() map[string]interface{} {
content := map[string]interface{}{
"events": map[string]int64{
"m.room.aliases": 50,
},
"users": map[string]int64{
alice.UserID: 100,
},
}
// Room v12+ prohibits the room creator in the `users` object
if gomatrixserverlib.MustGetRoomVersion(defaultRoomVersion).PrivilegedCreators() {
delete(content["users"].(map[string]int64), alice.UserID)
}
return content
}(),
})

res := setRoomAliasResp(t, bob, roomID, randomAlias)
Expand Down Expand Up @@ -428,12 +438,18 @@ func TestRoomDeleteAlias(t *testing.T) {
alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.power_levels",
StateKey: b.Ptr(""),
Content: map[string]interface{}{
"users": map[string]int64{
alice.UserID: 100,
bob.UserID: 100,
},
},
Content: func() map[string]interface{} {
content := map[string]interface{}{
"users": map[string]int64{
alice.UserID: 100,
bob.UserID: 100,
},
}
if gomatrixserverlib.MustGetRoomVersion(defaultRoomVersion).PrivilegedCreators() {
delete(content["users"].(map[string]int64), alice.UserID)
}
return content
}(),
})

res := setRoomAliasResp(t, alice, roomID, randomAlias)
Expand Down
22 changes: 15 additions & 7 deletions tests/csapi/apidoc_room_members_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/matrix-org/complement/helpers"
"github.com/matrix-org/complement/match"
"github.com/matrix-org/complement/must"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/spec"
)

Expand Down Expand Up @@ -84,6 +85,7 @@ func TestRoomMembers(t *testing.T) {
// sytest: Test that we can be reinvited to a room we created
t.Run("Test that we can be reinvited to a room we created", func(t *testing.T) {
t.Parallel()
defaultRoomVersion := alice.GetDefaultRoomVersion(t)
roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "private_chat",
})
Expand All @@ -101,13 +103,19 @@ func TestRoomMembers(t *testing.T) {
alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.power_levels",
StateKey: &stateKey,
Content: map[string]interface{}{
"invite": 100,
"users": map[string]interface{}{
alice.UserID: 100,
bob.UserID: 100,
},
},
Content: func() map[string]interface{} {
content := map[string]interface{}{
"invite": 100,
"users": map[string]int64{
bob.UserID: 100,
alice.UserID: 100,
},
}
if gomatrixserverlib.MustGetRoomVersion(defaultRoomVersion).PrivilegedCreators() {
delete(content["users"].(map[string]int64), alice.UserID)
}
return content
}(),
})

alice.MustLeaveRoom(t, roomID)
Expand Down
164 changes: 119 additions & 45 deletions tests/csapi/power_levels_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"github.com/matrix-org/complement/helpers"
"github.com/matrix-org/complement/match"
"github.com/matrix-org/complement/must"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/spec"
)

// This test ensures that an authorised (PL 100) user is able to modify the users_default value
Expand All @@ -22,30 +24,53 @@ func TestDemotingUsersViaUsersDefault(t *testing.T) {
defer deployment.Destroy(t)

alice := deployment.Register(t, "hs1", helpers.RegistrationOpts{})
bob := deployment.Register(t, "hs1", helpers.RegistrationOpts{})

defaultRoomVersion := alice.GetDefaultRoomVersion(t)

roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat",
"power_level_content_override": map[string]interface{}{
"users_default": 100, // the default is 0
"users": map[string]interface{}{
alice.UserID: 100,
},
"events": map[string]int64{},
"notifications": map[string]int64{},
},
"power_level_content_override": func() map[string]interface{} {
power_level_content := map[string]interface{}{
"users_default": 100, // the default is 0
"users": map[string]int64{
alice.UserID: 100,
bob.UserID: 100,
},
"events": map[string]int64{},
"notifications": map[string]int64{},
}
// Remove the room creator if this is a v12+ room
if gomatrixserverlib.MustGetRoomVersion(defaultRoomVersion).PrivilegedCreators() {
delete(power_level_content["users"].(map[string]int64), alice.UserID)
}
return power_level_content
}(),
})

bob.MustJoinRoom(t, roomID, []spec.ServerName{
deployment.GetFullyQualifiedHomeserverName(t, "hs1"),
})

alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.power_levels",
bob.SendEventSynced(t, roomID, b.Event{
Type: spec.MRoomPowerLevels,
StateKey: b.Ptr(""),
Content: map[string]interface{}{
"users_default": 40, // we change the default to 40. We should be able to do this.
"users": map[string]interface{}{
alice.UserID: 100,
},
"events": map[string]int64{},
"notifications": map[string]int64{},
},
Content: func() map[string]interface{} {
content := map[string]interface{}{
"users_default": 40, // we change the default to 40. We should be able to do this.
"users": map[string]int64{
alice.UserID: 100,
bob.UserID: 100,
},
"events": map[string]int64{},
"notifications": map[string]int64{},
}
// Remove the room creator if this is a v12+ room
if gomatrixserverlib.MustGetRoomVersion(defaultRoomVersion).PrivilegedCreators() {
delete(content["users"].(map[string]int64), alice.UserID)
}
return content
}(),
})
}

Expand All @@ -55,6 +80,8 @@ func TestPowerLevels(t *testing.T) {

alice := deployment.Register(t, "hs1", helpers.RegistrationOpts{})

defaultRoomVersion := alice.GetDefaultRoomVersion(t)

roomID := alice.MustCreateRoom(t, map[string]interface{}{})

// sytest: GET /rooms/:room_id/state/m.room.power_levels can fetch levels
Expand All @@ -65,7 +92,11 @@ func TestPowerLevels(t *testing.T) {
// However, for this test, we control the test environment,
// and we will assume the server is sane and give us powerlevels as numbers,
// and if it doesn't, that's an offense worthy of a frown.
content := alice.MustGetStateEventContent(t, roomID, "m.room.power_levels", "")
// note 2: before v12 the `users` object had to explicitly define the room creator, if they
// should have some power level other than the room's default. Starting with v12, this user
// is to be excluded from the `users` object, as they have an infinite power level that is
// not representable in JSON
content := alice.MustGetStateEventContent(t, roomID, spec.MRoomPowerLevels, "")
must.MatchGJSON(t, content,
match.JSONKeyTypeEqual("ban", gjson.Number),
match.JSONKeyTypeEqual("kick", gjson.Number),
Expand All @@ -91,13 +122,18 @@ func TestPowerLevels(t *testing.T) {
}),

func(body gjson.Result) error {
userDefault := int(body.Get("users_default").Num)
thisUser := int(body.Get("users." + client.GjsonEscape(alice.UserID)).Num)

if thisUser > userDefault {
// This key should be missing for room v12+
if gomatrixserverlib.MustGetRoomVersion(defaultRoomVersion).PrivilegedCreators() {
match.JSONKeyMissing("users." + client.GjsonEscape(alice.UserID))
return nil
} else {
Comment on lines +125 to 129
return fmt.Errorf("expected room creator (%d) to have a higher-than-default powerlevel (which is %d)", thisUser, userDefault)
userDefault := int(body.Get("users_default").Num)
thisUser := int(body.Get("users." + client.GjsonEscape(alice.UserID)).Num)
if thisUser > userDefault {
return nil
} else {
return fmt.Errorf("expected room creator (%d) to have a higher-than-default powerlevel (which is %d)", thisUser, userDefault)
}
}
},
)
Expand All @@ -114,8 +150,13 @@ func TestPowerLevels(t *testing.T) {
},
}

// Rooms versioned 12+ do not allow having the room creator in the 'users' object, so just remove it
if gomatrixserverlib.MustGetRoomVersion(defaultRoomVersion).PrivilegedCreators() {
delete(PLContent["users"].(map[string]interface{}), alice.UserID)
}

eventId := alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.power_levels",
Type: spec.MRoomPowerLevels,
StateKey: b.Ptr(""),
Content: PLContent,
})
Expand All @@ -137,37 +178,70 @@ func TestPowerLevels(t *testing.T) {
t.Run("PUT power_levels should not explode if the old power levels were empty", func(t *testing.T) {
// Absence of an "events" key
alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.power_levels",
Type: spec.MRoomPowerLevels,
StateKey: b.Ptr(""),
Content: map[string]interface{}{
"users": map[string]interface{}{
alice.UserID: 100,
},
},
Content: func() map[string]interface{} {
PLContent := map[string]interface{}{
"users": map[string]int64{
alice.UserID: 100,
},
}
// Rooms versioned 12+ do not allow having the room creator in the 'users' object, so just remove the
// single user so the empty `users` object is present
if gomatrixserverlib.MustGetRoomVersion(defaultRoomVersion).PrivilegedCreators() {
delete(PLContent["users"].(map[string]int64), alice.UserID)
}
return PLContent
}(),
})

// Absence of a "users" key
alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.power_levels",
Type: spec.MRoomPowerLevels,
StateKey: b.Ptr(""),
Content: map[string]interface{}{},
})

// This should give a 403 (not a 500)
res := alice.Do(
t,
"PUT",
[]string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.power_levels"},
client.WithJSONBody(t, map[string]interface{}{
"users": map[string]string{},
}),
)
must.MatchResponse(t, res, match.HTTPResponse{
StatusCode: 403,
})
// This part of the test should check that sending a power_levels event fails. As then the previous
// power_levels event should not have changed. Depending on the room version, this can be done in one
// of two different ways:
if gomatrixserverlib.MustGetRoomVersion(defaultRoomVersion).PrivilegedCreators() {
// For rooms with privileged creators(MSC4289), try and send an event with the room creator in the
// `users` object, which should be prohibited with a 400 error code. An empty `users` object appears
// to be allowed, hence the difference from the below condition for other room versions.
res := alice.Do(
t,
"PUT",
[]string{"_matrix", "client", "v3", "rooms", roomID, "state", spec.MRoomPowerLevels},
client.WithJSONBody(t, map[string]interface{}{
"users": map[string]int64{
alice.UserID: 100,
},
}),
)
must.MatchResponse(t, res, match.HTTPResponse{
StatusCode: 400,
})

} else {
// Prior to rooms using privileged creators, an empty `users` object would be prohibited and should
// give a 403 (not a 500)
res := alice.Do(
t,
"PUT",
[]string{"_matrix", "client", "v3", "rooms", roomID, "state", spec.MRoomPowerLevels},
client.WithJSONBody(t, map[string]interface{}{
"users": map[string]int64{},
}),
)
must.MatchResponse(t, res, match.HTTPResponse{
StatusCode: 403,
})

}

// Test if the old state still exists
content := alice.MustGetStateEventContent(t, roomID, "m.room.power_levels", "")
content := alice.MustGetStateEventContent(t, roomID, spec.MRoomPowerLevels, "")
must.MatchGJSON(t, content, match.JSONKeyMissing("users"))
})
}
Loading
Loading