mirror of
https://github.com/hoernschen/dendrite.git
synced 2025-04-03 18:43:39 +00:00
1040 lines
24 KiB
Go
1040 lines
24 KiB
Go
/* Copyright 2016-2017 Vector Creations Ltd
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package gomatrixserverlib
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
)
|
|
|
|
func stateNeededEquals(a, b StateNeeded) bool {
|
|
if a.Create != b.Create {
|
|
return false
|
|
}
|
|
if a.JoinRules != b.JoinRules {
|
|
return false
|
|
}
|
|
if a.PowerLevels != b.PowerLevels {
|
|
return false
|
|
}
|
|
if len(a.Member) != len(b.Member) {
|
|
return false
|
|
}
|
|
if len(a.ThirdPartyInvite) != len(b.ThirdPartyInvite) {
|
|
return false
|
|
}
|
|
for i := range a.Member {
|
|
if a.Member[i] != b.Member[i] {
|
|
return false
|
|
}
|
|
}
|
|
for i := range a.ThirdPartyInvite {
|
|
if a.ThirdPartyInvite[i] != b.ThirdPartyInvite[i] {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
type testEventList []Event
|
|
|
|
func (tel *testEventList) UnmarshalJSON(data []byte) error {
|
|
var eventJSONs []RawJSON
|
|
var events []Event
|
|
if err := json.Unmarshal([]byte(data), &eventJSONs); err != nil {
|
|
return err
|
|
}
|
|
for _, eventJSON := range eventJSONs {
|
|
event, err := NewEventFromTrustedJSON([]byte(eventJSON), false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
events = append(events, event)
|
|
}
|
|
*tel = testEventList(events)
|
|
return nil
|
|
}
|
|
|
|
func testStateNeededForAuth(t *testing.T, eventdata string, builder *EventBuilder, want StateNeeded) {
|
|
var events testEventList
|
|
if err := json.Unmarshal([]byte(eventdata), &events); err != nil {
|
|
panic(err)
|
|
}
|
|
got := StateNeededForAuth(events)
|
|
if !stateNeededEquals(got, want) {
|
|
t.Errorf("Testing StateNeededForAuth(%#v), wanted %#v got %#v", events, want, got)
|
|
}
|
|
if builder != nil {
|
|
got, err := StateNeededForEventBuilder(builder)
|
|
if !stateNeededEquals(got, want) {
|
|
t.Errorf("Testing StateNeededForEventBuilder(%#v), wanted %#v got %#v", events, want, got)
|
|
}
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestStateNeededForCreate(t *testing.T) {
|
|
// Create events don't need anything.
|
|
skey := ""
|
|
testStateNeededForAuth(t, `[{"type": "m.room.create"}]`, &EventBuilder{
|
|
Type: "m.room.create",
|
|
StateKey: &skey,
|
|
}, StateNeeded{})
|
|
}
|
|
|
|
func TestStateNeededForMessage(t *testing.T) {
|
|
// Message events need the create event, the sender and the power_levels.
|
|
testStateNeededForAuth(t, `[{
|
|
"type": "m.room.message",
|
|
"sender": "@u1:a"
|
|
}]`, &EventBuilder{
|
|
Type: "m.room.message",
|
|
Sender: "@u1:a",
|
|
}, StateNeeded{
|
|
Create: true,
|
|
PowerLevels: true,
|
|
Member: []string{"@u1:a"},
|
|
})
|
|
}
|
|
|
|
func TestStateNeededForAlias(t *testing.T) {
|
|
// Alias events need only the create event.
|
|
testStateNeededForAuth(t, `[{"type": "m.room.aliases"}]`, &EventBuilder{
|
|
Type: "m.room.aliases",
|
|
}, StateNeeded{
|
|
Create: true,
|
|
})
|
|
}
|
|
|
|
func TestStateNeededForJoin(t *testing.T) {
|
|
skey := "@u1:a"
|
|
b := EventBuilder{
|
|
Type: "m.room.member",
|
|
StateKey: &skey,
|
|
Sender: "@u1:a",
|
|
}
|
|
if err := b.SetContent(memberContent{"join", nil}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
testStateNeededForAuth(t, `[{
|
|
"type": "m.room.member",
|
|
"state_key": "@u1:a",
|
|
"sender": "@u1:a",
|
|
"content": {"membership": "join"}
|
|
}]`, &b, StateNeeded{
|
|
Create: true,
|
|
JoinRules: true,
|
|
PowerLevels: true,
|
|
Member: []string{"@u1:a"},
|
|
})
|
|
}
|
|
|
|
func TestStateNeededForInvite(t *testing.T) {
|
|
skey := "@u2:b"
|
|
b := EventBuilder{
|
|
Type: "m.room.member",
|
|
StateKey: &skey,
|
|
Sender: "@u1:a",
|
|
}
|
|
if err := b.SetContent(memberContent{"invite", nil}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
testStateNeededForAuth(t, `[{
|
|
"type": "m.room.member",
|
|
"state_key": "@u2:b",
|
|
"sender": "@u1:a",
|
|
"content": {"membership": "invite"}
|
|
}]`, &b, StateNeeded{
|
|
Create: true,
|
|
PowerLevels: true,
|
|
Member: []string{"@u1:a", "@u2:b"},
|
|
})
|
|
}
|
|
|
|
func TestStateNeededForInvite3PID(t *testing.T) {
|
|
skey := "@u2:b"
|
|
b := EventBuilder{
|
|
Type: "m.room.member",
|
|
StateKey: &skey,
|
|
Sender: "@u1:a",
|
|
}
|
|
|
|
if err := b.SetContent(memberContent{"invite", &memberThirdPartyInvite{
|
|
Signed: memberThirdPartyInviteSigned{
|
|
Token: "my_token",
|
|
},
|
|
}}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
testStateNeededForAuth(t, `[{
|
|
"type": "m.room.member",
|
|
"state_key": "@u2:b",
|
|
"sender": "@u1:a",
|
|
"content": {
|
|
"membership": "invite",
|
|
"third_party_invite": {
|
|
"signed": {
|
|
"token": "my_token"
|
|
}
|
|
}
|
|
}
|
|
}]`, &b, StateNeeded{
|
|
Create: true,
|
|
PowerLevels: true,
|
|
Member: []string{"@u1:a", "@u2:b"},
|
|
ThirdPartyInvite: []string{"my_token"},
|
|
})
|
|
}
|
|
|
|
type testAuthEvents struct {
|
|
CreateJSON json.RawMessage `json:"create"`
|
|
JoinRulesJSON json.RawMessage `json:"join_rules"`
|
|
PowerLevelsJSON json.RawMessage `json:"power_levels"`
|
|
MemberJSON map[string]json.RawMessage `json:"member"`
|
|
ThirdPartyInviteJSON map[string]json.RawMessage `json:"third_party_invite"`
|
|
}
|
|
|
|
func (tae *testAuthEvents) Create() (*Event, error) {
|
|
if len(tae.CreateJSON) == 0 {
|
|
return nil, nil
|
|
}
|
|
var event Event
|
|
event, err := NewEventFromTrustedJSON(tae.CreateJSON, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &event, nil
|
|
}
|
|
|
|
func (tae *testAuthEvents) JoinRules() (*Event, error) {
|
|
if len(tae.JoinRulesJSON) == 0 {
|
|
return nil, nil
|
|
}
|
|
event, err := NewEventFromTrustedJSON(tae.JoinRulesJSON, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &event, nil
|
|
}
|
|
|
|
func (tae *testAuthEvents) PowerLevels() (*Event, error) {
|
|
if len(tae.PowerLevelsJSON) == 0 {
|
|
return nil, nil
|
|
}
|
|
event, err := NewEventFromTrustedJSON(tae.PowerLevelsJSON, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &event, nil
|
|
}
|
|
|
|
func (tae *testAuthEvents) Member(stateKey string) (*Event, error) {
|
|
if len(tae.MemberJSON[stateKey]) == 0 {
|
|
return nil, nil
|
|
}
|
|
event, err := NewEventFromTrustedJSON(tae.MemberJSON[stateKey], false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &event, nil
|
|
}
|
|
|
|
func (tae *testAuthEvents) ThirdPartyInvite(stateKey string) (*Event, error) {
|
|
if len(tae.ThirdPartyInviteJSON[stateKey]) == 0 {
|
|
return nil, nil
|
|
}
|
|
event, err := NewEventFromTrustedJSON(tae.ThirdPartyInviteJSON[stateKey], false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &event, nil
|
|
}
|
|
|
|
type testCase struct {
|
|
AuthEvents testAuthEvents `json:"auth_events"`
|
|
Allowed []json.RawMessage `json:"allowed"`
|
|
NotAllowed []json.RawMessage `json:"not_allowed"`
|
|
}
|
|
|
|
func testEventAllowed(t *testing.T, testCaseJSON string) {
|
|
var tc testCase
|
|
if err := json.Unmarshal([]byte(testCaseJSON), &tc); err != nil {
|
|
panic(err)
|
|
}
|
|
for _, data := range tc.Allowed {
|
|
event, err := NewEventFromTrustedJSON(data, false)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if err = Allowed(event, &tc.AuthEvents); err != nil {
|
|
t.Fatalf("Expected %q to be allowed but it was not: %q", string(data), err)
|
|
}
|
|
}
|
|
for _, data := range tc.NotAllowed {
|
|
event, err := NewEventFromTrustedJSON(data, false)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if err := Allowed(event, &tc.AuthEvents); err == nil {
|
|
t.Fatalf("Expected %q to not be allowed but it was", string(data))
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAllowedEmptyRoom(t *testing.T) {
|
|
// Test that only m.room.create events can be sent without auth events.
|
|
// TODO: Test the events that aren't m.room.create
|
|
testEventAllowed(t, `{
|
|
"auth_events": {},
|
|
"allowed": [{
|
|
"type": "m.room.create",
|
|
"state_key": "",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e1:a",
|
|
"content": {"creator": "@u1:a"}
|
|
}],
|
|
"not_allowed": [{
|
|
"type": "m.room.create",
|
|
"state_key": "",
|
|
"sender": "@u1:b",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e2:a",
|
|
"content": {"creator": "@u1:b"},
|
|
"unsigned": {
|
|
"not_allowed": "Sent by a different server than the one which made the room_id"
|
|
}
|
|
}, {
|
|
"type": "m.room.create",
|
|
"state_key": "",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e3:a",
|
|
"prev_events": [["$e1", {}]],
|
|
"content": {"creator": "@u1:a"},
|
|
"unsigned": {
|
|
"not_allowed": "Was not the first event in the room"
|
|
}
|
|
}, {
|
|
"type": "m.room.message",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e4:a",
|
|
"content": {"body": "Test"},
|
|
"unsigned": {
|
|
"not_allowed": "No create event"
|
|
}
|
|
}, {
|
|
"type": "m.room.member",
|
|
"state_key": "@u1:a",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e4:a",
|
|
"content": {"membership": "join"},
|
|
"unsigned": {
|
|
"not_allowed": "No create event"
|
|
}
|
|
}, {
|
|
"type": "m.room.create",
|
|
"state_key": "",
|
|
"sender": "not_a_user_id",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e5:a",
|
|
"content": {"creator": "@u1:a"},
|
|
"unsigned": {
|
|
"not_allowed": "Sender is not a valid user ID"
|
|
}
|
|
}, {
|
|
"type": "m.room.create",
|
|
"state_key": "",
|
|
"sender": "@u1:a",
|
|
"room_id": "not_a_room_id",
|
|
"event_id": "$e6:a",
|
|
"content": {"creator": "@u1:a"},
|
|
"unsigned": {
|
|
"not_allowed": "Room is not a valid room ID"
|
|
}
|
|
}, {
|
|
"type": "m.room.create",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e7:a",
|
|
"content": {"creator": "@u1:a"},
|
|
"unsigned": {
|
|
"not_allowed": "Missing state_key"
|
|
}
|
|
}, {
|
|
"type": "m.room.create",
|
|
"state_key": "not_empty",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e7:a",
|
|
"content": {"creator": "@u1:a"},
|
|
"unsigned": {
|
|
"not_allowed": "The state_key is not empty"
|
|
}
|
|
}]
|
|
}`)
|
|
}
|
|
|
|
func TestAllowedFirstJoin(t *testing.T) {
|
|
testEventAllowed(t, `{
|
|
"auth_events": {
|
|
"create": {
|
|
"type": "m.room.create",
|
|
"state_key": "",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e1:a",
|
|
"content": {"creator": "@u1:a"}
|
|
}
|
|
},
|
|
"allowed": [{
|
|
"type": "m.room.member",
|
|
"state_key": "@u1:a",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e2:a",
|
|
"prev_events": [["$e1:a", {}]],
|
|
"content": {"membership": "join"}
|
|
}],
|
|
"not_allowed": [{
|
|
"type": "m.room.message",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e3:a",
|
|
"content": {"body": "test"},
|
|
"unsigned": {
|
|
"not_allowed": "Sender is not in the room"
|
|
}
|
|
}, {
|
|
"type": "m.room.member",
|
|
"state_key": "@u2:a",
|
|
"sender": "@u2:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e4:a",
|
|
"prev_events": [["$e1:a", {}]],
|
|
"content": {"membership": "join"},
|
|
"unsigned": {
|
|
"not_allowed": "Only the creator can join the room"
|
|
}
|
|
}, {
|
|
"type": "m.room.member",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e4:a",
|
|
"prev_events": [["$e1:a", {}]],
|
|
"content": {"membership": "join"},
|
|
"unsigned": {
|
|
"not_allowed": "Missing state_key"
|
|
}
|
|
}, {
|
|
"type": "m.room.member",
|
|
"state_key": "@u1:a",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e4:a",
|
|
"prev_events": [["$e2:a", {}]],
|
|
"content": {"membership": "join"},
|
|
"unsigned": {
|
|
"not_allowed": "The prev_event is not the create event"
|
|
}
|
|
}, {
|
|
"type": "m.room.member",
|
|
"state_key": "@u1:a",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e4:a",
|
|
"content": {"membership": "join"},
|
|
"unsigned": {
|
|
"not_allowed": "There are no prev_events"
|
|
}
|
|
}, {
|
|
"type": "m.room.member",
|
|
"state_key": "@u1:a",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e4:a",
|
|
"content": {"membership": "join"},
|
|
"prev_events": [["$e1:a", {}], ["$e2:a", {}]],
|
|
"unsigned": {
|
|
"not_allowed": "There are too many prev_events"
|
|
}
|
|
}, {
|
|
"type": "m.room.member",
|
|
"state_key": "@u1:a",
|
|
"sender": "@u2:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e4:a",
|
|
"content": {"membership": "join"},
|
|
"prev_events": [["$e1:a", {}]],
|
|
"unsigned": {
|
|
"not_allowed": "The sender doesn't match the joining user"
|
|
}
|
|
}, {
|
|
"type": "m.room.member",
|
|
"state_key": "@u1:a",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e4:a",
|
|
"content": {"membership": "invite"},
|
|
"prev_events": [["$e1:a", {}]],
|
|
"unsigned": {
|
|
"not_allowed": "The membership is not 'join'"
|
|
}
|
|
}]
|
|
}`)
|
|
}
|
|
|
|
func TestAllowedWithNoPowerLevels(t *testing.T) {
|
|
testEventAllowed(t, `{
|
|
"auth_events": {
|
|
"create": {
|
|
"type": "m.room.create",
|
|
"state_key": "",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e1:a",
|
|
"content": {"creator": "@u1:a"}
|
|
},
|
|
"member": {
|
|
"@u1:a": {
|
|
"type": "m.room.member",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"state_key": "@u1:a",
|
|
"event_id": "$e2:a",
|
|
"content": {"membership": "join"}
|
|
}
|
|
}
|
|
},
|
|
"allowed": [{
|
|
"type": "m.room.message",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e3:a",
|
|
"content": {"body": "Test"}
|
|
}],
|
|
"not_allowed": [{
|
|
"type": "m.room.message",
|
|
"sender": "@u2:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e4:a",
|
|
"content": {"body": "Test"},
|
|
"unsigned": {
|
|
"not_allowed": "Sender is not in room"
|
|
}
|
|
}]
|
|
}`)
|
|
}
|
|
|
|
func TestAllowedInviteFrom3PID(t *testing.T) {
|
|
testEventAllowed(t, `{
|
|
"auth_events": {
|
|
"create": {
|
|
"type": "m.room.create",
|
|
"state_key": "",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e1:a",
|
|
"content": {"creator": "@u1:a"}
|
|
},
|
|
"member": {
|
|
"@u1:a": {
|
|
"type": "m.room.member",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"state_key": "@u1:a",
|
|
"event_id": "$e2:a",
|
|
"content": {"membership": "join"}
|
|
}
|
|
},
|
|
"third_party_invite": {
|
|
"my_token": {
|
|
"type": "m.room.third_party_invite",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"state_key": "my_token",
|
|
"event_id": "$e3:a",
|
|
"content": {
|
|
"display_name": "foo...@bar...",
|
|
"public_key": "pubkey",
|
|
"key_validity_url": "https://example.tld/isvalid",
|
|
"public_keys": [
|
|
{
|
|
"public_key": "mrV51jApZKahGjfMhlevp+QtSSTDKCLaLVCzYc4HELY",
|
|
"key_validity_url": "https://example.tld/isvalid"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"allowed": [{
|
|
"type": "m.room.member",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"state_key": "@u2:a",
|
|
"event_id": "$e4:a",
|
|
"content": {
|
|
"membership": "invite",
|
|
"third_party_invite": {
|
|
"display_name": "foo...@bar...",
|
|
"signed": {
|
|
"token": "my_token",
|
|
"mxid": "@u2:a",
|
|
"signatures": {
|
|
"example.tld": {
|
|
"ed25519:0": "CibGFS0vX93quJFppsQbYQKJFIwxiYEK87lNmekS/fdetUMXPdR2wwNDd09J1jJ28GCH3GogUTuFDB1ScPFxBg"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}],
|
|
"not_allowed": [{
|
|
"type": "m.room.member",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"state_key": "@u2:a",
|
|
"event_id": "$e4:a",
|
|
"content": {
|
|
"membership": "invite",
|
|
"third_party_invite": {
|
|
"display_name": "foo...@bar...",
|
|
"signed": {
|
|
"token": "my_token",
|
|
"mxid": "@u2:a",
|
|
"signatures": {
|
|
"example.tld": {
|
|
"ed25519:0": "some_signature"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"unsigned": {
|
|
"not_allowed": "Bad signature"
|
|
}
|
|
}, {
|
|
"type": "m.room.member",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"state_key": "@u2:a",
|
|
"event_id": "$e5:a",
|
|
"content": {
|
|
"membership": "invite",
|
|
"third_party_invite": {
|
|
"display_name": "foo...@bar...",
|
|
"signed": {
|
|
"token": "my_token",
|
|
"mxid": "@u3:a",
|
|
"signatures": {
|
|
"example.tld": {
|
|
"ed25519:0": "CibGFS0vX93quJFppsQbYQKJFIwxiYEK87lNmekS/fdetUMXPdR2wwNDd09J1jJ28GCH3GogUTuFDB1ScPFxBg"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"unsigned": {
|
|
"not_allowed": "MXID doesn't match state key"
|
|
}
|
|
}, {
|
|
"type": "m.room.member",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"state_key": "@u2:a",
|
|
"event_id": "$e6:a",
|
|
"content": {
|
|
"membership": "invite",
|
|
"third_party_invite": {
|
|
"display_name": "foo...@bar...",
|
|
"signed": {
|
|
"token": "my_other_token",
|
|
"mxid": "@u2:a",
|
|
"signatures": {
|
|
"example.tld": {
|
|
"ed25519:0": "CibGFS0vX93quJFppsQbYQKJFIwxiYEK87lNmekS/fdetUMXPdR2wwNDd09J1jJ28GCH3GogUTuFDB1ScPFxBg"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"unsigned": {
|
|
"not_allowed": "Token doesn't refer to a known third-party invite"
|
|
}
|
|
}]
|
|
}`)
|
|
}
|
|
|
|
func TestAllowedNoFederation(t *testing.T) {
|
|
testEventAllowed(t, `{
|
|
"auth_events": {
|
|
"create": {
|
|
"type": "m.room.create",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e1:a",
|
|
"content": {
|
|
"creator": "@u1:a",
|
|
"m.federate": false
|
|
}
|
|
},
|
|
"member": {
|
|
"@u1:a": {
|
|
"type": "m.room.member",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"state_key": "@u1:a",
|
|
"event_id": "$e2:a",
|
|
"content": {"membership": "join"}
|
|
}
|
|
}
|
|
},
|
|
"allowed": [{
|
|
"type": "m.room.message",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e3:a",
|
|
"content": {"body": "Test"}
|
|
}],
|
|
"not_allowed": [{
|
|
"type": "m.room.message",
|
|
"sender": "@u1:b",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e4:a",
|
|
"content": {"body": "Test"},
|
|
"unsigned": {
|
|
"not_allowed": "Sender is from a different server."
|
|
}
|
|
}]
|
|
}`)
|
|
}
|
|
|
|
func TestAllowedWithPowerLevels(t *testing.T) {
|
|
testEventAllowed(t, `{
|
|
"auth_events": {
|
|
"create": {
|
|
"type": "m.room.create",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e1:a",
|
|
"content": {"creator": "@u1:a"}
|
|
},
|
|
"member": {
|
|
"@u1:a": {
|
|
"type": "m.room.member",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"state_key": "@u1:a",
|
|
"event_id": "$e2:a",
|
|
"content": {"membership": "join"}
|
|
},
|
|
"@u2:a": {
|
|
"type": "m.room.member",
|
|
"sender": "@u2:a",
|
|
"room_id": "!r1:a",
|
|
"state_key": "@u2:a",
|
|
"event_id": "$e3:a",
|
|
"content": {"membership": "join"}
|
|
},
|
|
"@u3:b": {
|
|
"type": "m.room.member",
|
|
"sender": "@u3:b",
|
|
"room_id": "!r1:a",
|
|
"state_key": "@u3:b",
|
|
"event_id": "$e4:a",
|
|
"content": {"membership": "join"}
|
|
}
|
|
},
|
|
"power_levels": {
|
|
"type": "m.room.power_levels",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e5:a",
|
|
"content": {
|
|
"users": {
|
|
"@u1:a": 100,
|
|
"@u2:a": 50
|
|
},
|
|
"users_default": 0,
|
|
"events": {
|
|
"m.room.join_rules": 100
|
|
},
|
|
"state_default": 50,
|
|
"events_default": 0
|
|
}
|
|
}
|
|
},
|
|
"allowed": [{
|
|
"type": "m.room.message",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e6:a",
|
|
"content": {"body": "Test from @u1:a"}
|
|
}, {
|
|
"type": "m.room.message",
|
|
"sender": "@u2:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e7:a",
|
|
"content": {"body": "Test from @u2:a"}
|
|
}, {
|
|
"type": "m.room.message",
|
|
"sender": "@u3:b",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e8:a",
|
|
"content": {"body": "Test from @u3:b"}
|
|
},{
|
|
"type": "m.room.name",
|
|
"state_key": "",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e9:a",
|
|
"content": {"name": "Name set by @u1:a"}
|
|
}, {
|
|
"type": "m.room.name",
|
|
"state_key": "",
|
|
"sender": "@u2:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e10:a",
|
|
"content": {"name": "Name set by @u2:a"}
|
|
}, {
|
|
"type": "m.room.join_rules",
|
|
"state_key": "",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e11:a",
|
|
"content": {"join_rule": "public"}
|
|
}, {
|
|
"type": "my.custom.state",
|
|
"state_key": "@u2:a",
|
|
"sender": "@u2:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "@e12:a",
|
|
"content": {}
|
|
}],
|
|
"not_allowed": [{
|
|
"type": "m.room.name",
|
|
"state_key": "",
|
|
"sender": "@u3:b",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e13:a",
|
|
"content": {"name": "Name set by @u3:b"},
|
|
"unsigned": {
|
|
"not_allowed": "User @u3:b's level is too low to send a state event"
|
|
}
|
|
}, {
|
|
"type": "m.room.join_rules",
|
|
"sender": "@u2:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e14:a",
|
|
"content": {"name": "Name set by @u3:b"},
|
|
"unsigned": {
|
|
"not_allowed": "User @u2:a's level is too low to send m.room.join_rules"
|
|
}
|
|
}, {
|
|
"type": "m.room.message",
|
|
"sender": "@u4:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e15:a",
|
|
"content": {"Body": "Test from @u4:a"},
|
|
"unsigned": {
|
|
"not_allowed": "User @u4:a is not in the room"
|
|
}
|
|
}, {
|
|
"type": "m.room.message",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r2:a",
|
|
"event_id": "$e16:a",
|
|
"content": {"body": "Test from @u4:a"},
|
|
"unsigned": {
|
|
"not_allowed": "Sent from a different room to the create event"
|
|
}
|
|
}, {
|
|
"type": "my.custom.state",
|
|
"state_key": "@u2:a",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "@e17:a",
|
|
"content": {},
|
|
"unsigned": {
|
|
"not_allowed": "State key starts with '@' and is for a different user"
|
|
}
|
|
}]
|
|
}`)
|
|
}
|
|
|
|
func TestRedactAllowed(t *testing.T) {
|
|
// Test if redacts are allowed correctly in a room with a power level event.
|
|
testEventAllowed(t, `{
|
|
"auth_events": {
|
|
"create": {
|
|
"type": "m.room.create",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e1:a",
|
|
"content": {"creator": "@u1:a"}
|
|
},
|
|
"member": {
|
|
"@u1:a": {
|
|
"type": "m.room.member",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"state_key": "@u1:a",
|
|
"event_id": "$e2:a",
|
|
"content": {"membership": "join"}
|
|
},
|
|
"@u2:a": {
|
|
"type": "m.room.member",
|
|
"sender": "@u2:a",
|
|
"room_id": "!r1:a",
|
|
"state_key": "@u2:a",
|
|
"event_id": "$e3:a",
|
|
"content": {"membership": "join"}
|
|
},
|
|
"@u1:b": {
|
|
"type": "m.room.member",
|
|
"sender": "@u1:b",
|
|
"room_id": "!r1:a",
|
|
"state_key": "@u1:b",
|
|
"event_id": "$e4:a",
|
|
"content": {"membership": "join"}
|
|
}
|
|
},
|
|
"power_levels": {
|
|
"type": "m.room.power_levels",
|
|
"state_key": "",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e5:a",
|
|
"content": {
|
|
"users": {
|
|
"@u1:a": 100
|
|
},
|
|
"redact": 100
|
|
}
|
|
}
|
|
},
|
|
"allowed": [{
|
|
"type": "m.room.redaction",
|
|
"sender": "@u1:b",
|
|
"room_id": "!r1:a",
|
|
"redacts": "$event_sent_by_b:b",
|
|
"event_id": "$e6:b",
|
|
"content": {"reason": ""}
|
|
}, {
|
|
"type": "m.room.redaction",
|
|
"sender": "@u2:a",
|
|
"room_id": "!r1:a",
|
|
"redacts": "$event_sent_by_a:a",
|
|
"event_id": "$e7:a",
|
|
"content": {"reason": ""}
|
|
}, {
|
|
"type": "m.room.redaction",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"redacts": "$event_sent_by_b:b",
|
|
"event_id": "$e8:a",
|
|
"content": {"reason": ""}
|
|
}],
|
|
"not_allowed": [{
|
|
"type": "m.room.redaction",
|
|
"sender": "@u2:a",
|
|
"room_id": "!r1:a",
|
|
"redacts": "$event_sent_by_b:b",
|
|
"event_id": "$e9:a",
|
|
"content": {"reason": ""},
|
|
"unsigned": {
|
|
"not_allowed": "User power level is too low and event is from different server"
|
|
}
|
|
}, {
|
|
"type": "m.room.redaction",
|
|
"sender": "@u1:c",
|
|
"room_id": "!r1:a",
|
|
"redacts": "$event_sent_by_c:c",
|
|
"event_id": "$e10:a",
|
|
"content": {"reason": ""},
|
|
"unsigned": {
|
|
"not_allowed": "User is not in the room"
|
|
}
|
|
}, {
|
|
"type": "m.room.redaction",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"redacts": "not_a_valid_event_id",
|
|
"event_id": "$e11:a",
|
|
"content": {"reason": ""},
|
|
"unsigned": {
|
|
"not_allowed": "Invalid redacts event ID"
|
|
}
|
|
}, {
|
|
"type": "m.room.redaction",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e11:a",
|
|
"content": {"reason": ""},
|
|
"unsigned": {
|
|
"not_allowed": "Missing redacts event ID"
|
|
}
|
|
}]
|
|
}`)
|
|
}
|
|
|
|
func TestAuthEvents(t *testing.T) {
|
|
power, err := NewEventFromTrustedJSON(RawJSON(`{
|
|
"type": "m.room.power_levels",
|
|
"state_key": "",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e5:a",
|
|
"content": {
|
|
"users": {
|
|
"@u1:a": 100
|
|
},
|
|
"redact": 100
|
|
}
|
|
}`), false)
|
|
if err != nil {
|
|
t.Fatalf("TestAuthEvents: failed to create power_levels event: %s", err)
|
|
}
|
|
a := NewAuthEvents([]*Event{&power})
|
|
var e *Event
|
|
if e, err = a.PowerLevels(); err != nil || e != &power {
|
|
t.Errorf("TestAuthEvents: failed to get same power_levels event")
|
|
}
|
|
create, err := NewEventFromTrustedJSON(RawJSON(`{
|
|
"type": "m.room.create",
|
|
"state_key": "",
|
|
"sender": "@u1:a",
|
|
"room_id": "!r1:a",
|
|
"event_id": "$e1:a",
|
|
"content": {
|
|
"creator": "@u1:a"
|
|
}
|
|
}`), false)
|
|
if err != nil {
|
|
t.Fatalf("TestAuthEvents: failed to create create event: %s", err)
|
|
}
|
|
if err = a.AddEvent(&create); err != nil {
|
|
t.Errorf("TestAuthEvents: Failed to AddEvent: %s", err)
|
|
}
|
|
if e, err = a.Create(); err != nil || e != &create {
|
|
t.Errorf("TestAuthEvents: failed to get same create event")
|
|
}
|
|
}
|