Skip to content

Commit 162387a

Browse files
S7evinKdevonh
andauthored
Support for room version v11 (#418)
Co-authored-by: Devon Hudson <[email protected]>
1 parent 0466775 commit 162387a

File tree

6 files changed

+229
-30
lines changed

6 files changed

+229
-30
lines changed

eventV2.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ var lenientByteLimitRoomVersions = map[RoomVersion]struct{}{
196196
RoomVersionV8: {},
197197
RoomVersionV9: {},
198198
RoomVersionV10: {},
199+
RoomVersionV11: {},
199200
RoomVersionPseudoIDs: {},
200201
"org.matrix.msc3787": {},
201202
"org.matrix.msc3667": {},

eventauth.go

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,11 @@ func (a *allowerContext) update(provider AuthEventProvider) {
370370
}
371371
}
372372
if e, _ := provider.PowerLevels(); a.powerLevelsEvent == nil || a.powerLevelsEvent != e {
373-
if p, err := NewPowerLevelContentFromAuthEvents(provider, a.create.Creator); err == nil {
373+
creator := ""
374+
if a.createEvent != nil {
375+
creator = string(a.createEvent.SenderID())
376+
}
377+
if p, err := NewPowerLevelContentFromAuthEvents(provider, creator); err == nil {
374378
a.powerLevelsEvent = e
375379
a.powerLevels = p
376380
}
@@ -431,21 +435,15 @@ func (a *allowerContext) createEventAllowed(event PDU) error {
431435
if sender.Domain() != event.RoomID().Domain() {
432436
return errorf("create event room ID domain does not match sender: %q != %q", event.RoomID().Domain(), sender.String())
433437
}
434-
c := struct {
435-
Creator *string `json:"creator"`
436-
RoomVersion *RoomVersion `json:"room_version"`
437-
}{}
438-
if err := json.Unmarshal(event.Content(), &c); err != nil {
439-
return errorf("create event has invalid content: %s", err.Error())
440-
}
441-
if c.Creator == nil {
442-
return errorf("create event has no creator field")
438+
439+
verImpl, err := GetRoomVersion(event.Version())
440+
if err != nil {
441+
return nil
443442
}
444-
if c.RoomVersion != nil {
445-
if !KnownRoomVersion(*c.RoomVersion) {
446-
return errorf("create event has unrecognised room version %q", *c.RoomVersion)
447-
}
443+
if err = verImpl.CheckCreateEvent(event, KnownRoomVersion); err != nil {
444+
return err
448445
}
446+
449447
return nil
450448
}
451449

@@ -1013,7 +1011,7 @@ func (m *membershipAllower) membershipAllowed(event PDU) error { // nolint: gocy
10131011

10141012
// Special case the first join event in the room to allow the creator to join.
10151013
// https://github.com/matrix-org/synapse/blob/v0.18.5/synapse/api/auth.py#L328
1016-
if m.targetID == m.create.Creator &&
1014+
if m.targetID == string(m.createEvent.SenderID()) &&
10171015
m.newMember.Membership == spec.Join &&
10181016
m.senderID == m.targetID &&
10191017
len(event.PrevEventIDs()) == 1 {

eventcontent.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,3 +575,27 @@ type RelatesTo struct {
575575
EventID string `json:"event_id"`
576576
RelationType string `json:"rel_type"`
577577
}
578+
579+
func noCheckCreateEvent(event PDU, knownRoomVersion knownRoomVersionFunc) error {
580+
return nil
581+
}
582+
583+
func checkCreateEvent(event PDU, knownRoomVersion knownRoomVersionFunc) error {
584+
c := struct {
585+
Creator *string `json:"creator"`
586+
RoomVersion *RoomVersion `json:"room_version"`
587+
}{}
588+
if err := json.Unmarshal(event.Content(), &c); err != nil {
589+
return errorf("create event has invalid content: %s", err.Error())
590+
}
591+
if c.Creator == nil {
592+
return errorf("create event has no creator field")
593+
}
594+
if c.RoomVersion != nil {
595+
if !knownRoomVersion(*c.RoomVersion) {
596+
return errorf("create event has unrecognised room version %q", *c.RoomVersion)
597+
}
598+
}
599+
600+
return nil
601+
}

eventversion.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ type IRoomVersion interface {
3333
CheckNotificationLevels(senderLevel int64, oldPowerLevels, newPowerLevels PowerLevelContent) error
3434
CheckCanonicalJSON(input []byte) error
3535
ParsePowerLevels(contentBytes []byte, c *PowerLevelContent) error
36+
CheckCreateEvent(event PDU, knownRoomVersion knownRoomVersionFunc) error
3637
}
3738

39+
type knownRoomVersionFunc func(RoomVersion) bool
40+
3841
// StateResAlgorithm refers to a version of the state resolution algorithm.
3942
type StateResAlgorithm int
4043

@@ -58,6 +61,7 @@ const (
5861
RoomVersionV8 RoomVersion = "8"
5962
RoomVersionV9 RoomVersion = "9"
6063
RoomVersionV10 RoomVersion = "10"
64+
RoomVersionV11 RoomVersion = "11"
6165
RoomVersionPseudoIDs RoomVersion = "org.matrix.msc4014"
6266
)
6367

@@ -96,6 +100,7 @@ var roomVersionMeta = map[RoomVersion]IRoomVersion{
96100
parsePowerLevelsFunc: parsePowerLevels,
97101
checkKnockingAllowedFunc: disallowKnocking,
98102
checkRestrictedJoinAllowedFunc: disallowRestrictedJoins,
103+
checkCreateEvent: checkCreateEvent,
99104
newEventFromUntrustedJSONFunc: newEventFromUntrustedJSONV1,
100105
newEventFromTrustedJSONFunc: newEventFromTrustedJSONV1,
101106
newEventFromTrustedJSONWithEventIDFunc: newEventFromTrustedJSONWithEventIDV1,
@@ -115,6 +120,7 @@ var roomVersionMeta = map[RoomVersion]IRoomVersion{
115120
parsePowerLevelsFunc: parsePowerLevels,
116121
checkKnockingAllowedFunc: disallowKnocking,
117122
checkRestrictedJoinAllowedFunc: disallowRestrictedJoins,
123+
checkCreateEvent: checkCreateEvent,
118124
newEventFromUntrustedJSONFunc: newEventFromUntrustedJSONV1,
119125
newEventFromTrustedJSONFunc: newEventFromTrustedJSONV1,
120126
newEventFromTrustedJSONWithEventIDFunc: newEventFromTrustedJSONWithEventIDV1,
@@ -134,6 +140,7 @@ var roomVersionMeta = map[RoomVersion]IRoomVersion{
134140
parsePowerLevelsFunc: parsePowerLevels,
135141
checkKnockingAllowedFunc: disallowKnocking,
136142
checkRestrictedJoinAllowedFunc: disallowRestrictedJoins,
143+
checkCreateEvent: checkCreateEvent,
137144
newEventFromUntrustedJSONFunc: newEventFromUntrustedJSONV2,
138145
newEventFromTrustedJSONFunc: newEventFromTrustedJSONV2,
139146
newEventFromTrustedJSONWithEventIDFunc: newEventFromTrustedJSONWithEventIDV2,
@@ -153,6 +160,7 @@ var roomVersionMeta = map[RoomVersion]IRoomVersion{
153160
parsePowerLevelsFunc: parsePowerLevels,
154161
checkKnockingAllowedFunc: disallowKnocking,
155162
checkRestrictedJoinAllowedFunc: disallowRestrictedJoins,
163+
checkCreateEvent: checkCreateEvent,
156164
newEventFromUntrustedJSONFunc: newEventFromUntrustedJSONV2,
157165
newEventFromTrustedJSONFunc: newEventFromTrustedJSONV2,
158166
newEventFromTrustedJSONWithEventIDFunc: newEventFromTrustedJSONWithEventIDV2,
@@ -172,6 +180,7 @@ var roomVersionMeta = map[RoomVersion]IRoomVersion{
172180
parsePowerLevelsFunc: parsePowerLevels,
173181
checkKnockingAllowedFunc: disallowKnocking,
174182
checkRestrictedJoinAllowedFunc: disallowRestrictedJoins,
183+
checkCreateEvent: checkCreateEvent,
175184
newEventFromUntrustedJSONFunc: newEventFromUntrustedJSONV2,
176185
newEventFromTrustedJSONFunc: newEventFromTrustedJSONV2,
177186
newEventFromTrustedJSONWithEventIDFunc: newEventFromTrustedJSONWithEventIDV2,
@@ -191,6 +200,7 @@ var roomVersionMeta = map[RoomVersion]IRoomVersion{
191200
parsePowerLevelsFunc: parsePowerLevels,
192201
checkKnockingAllowedFunc: disallowKnocking,
193202
checkRestrictedJoinAllowedFunc: disallowRestrictedJoins,
203+
checkCreateEvent: checkCreateEvent,
194204
newEventFromUntrustedJSONFunc: newEventFromUntrustedJSONV2,
195205
newEventFromTrustedJSONFunc: newEventFromTrustedJSONV2,
196206
newEventFromTrustedJSONWithEventIDFunc: newEventFromTrustedJSONWithEventIDV2,
@@ -210,6 +220,7 @@ var roomVersionMeta = map[RoomVersion]IRoomVersion{
210220
parsePowerLevelsFunc: parsePowerLevels,
211221
checkKnockingAllowedFunc: checkKnocking,
212222
checkRestrictedJoinAllowedFunc: disallowRestrictedJoins,
223+
checkCreateEvent: checkCreateEvent,
213224
newEventFromUntrustedJSONFunc: newEventFromUntrustedJSONV2,
214225
newEventFromTrustedJSONFunc: newEventFromTrustedJSONV2,
215226
newEventFromTrustedJSONWithEventIDFunc: newEventFromTrustedJSONWithEventIDV2,
@@ -229,6 +240,7 @@ var roomVersionMeta = map[RoomVersion]IRoomVersion{
229240
parsePowerLevelsFunc: parsePowerLevels,
230241
checkKnockingAllowedFunc: checkKnocking,
231242
checkRestrictedJoinAllowedFunc: allowRestrictedJoins,
243+
checkCreateEvent: checkCreateEvent,
232244
newEventFromUntrustedJSONFunc: newEventFromUntrustedJSONV2,
233245
newEventFromTrustedJSONFunc: newEventFromTrustedJSONV2,
234246
newEventFromTrustedJSONWithEventIDFunc: newEventFromTrustedJSONWithEventIDV2,
@@ -248,6 +260,7 @@ var roomVersionMeta = map[RoomVersion]IRoomVersion{
248260
parsePowerLevelsFunc: parsePowerLevels,
249261
checkKnockingAllowedFunc: checkKnocking,
250262
checkRestrictedJoinAllowedFunc: allowRestrictedJoins,
263+
checkCreateEvent: checkCreateEvent,
251264
newEventFromUntrustedJSONFunc: newEventFromUntrustedJSONV2,
252265
newEventFromTrustedJSONFunc: newEventFromTrustedJSONV2,
253266
newEventFromTrustedJSONWithEventIDFunc: newEventFromTrustedJSONWithEventIDV2,
@@ -267,6 +280,27 @@ var roomVersionMeta = map[RoomVersion]IRoomVersion{
267280
parsePowerLevelsFunc: parseIntegerPowerLevels,
268281
checkKnockingAllowedFunc: checkKnocking,
269282
checkRestrictedJoinAllowedFunc: allowRestrictedJoins,
283+
checkCreateEvent: checkCreateEvent,
284+
newEventFromUntrustedJSONFunc: newEventFromUntrustedJSONV2,
285+
newEventFromTrustedJSONFunc: newEventFromTrustedJSONV2,
286+
newEventFromTrustedJSONWithEventIDFunc: newEventFromTrustedJSONWithEventIDV2,
287+
},
288+
RoomVersionV11: RoomVersionImpl{
289+
ver: RoomVersionV11,
290+
stable: true,
291+
stateResAlgorithm: StateResV2,
292+
eventFormat: EventFormatV2,
293+
eventIDFormat: EventIDFormatV3,
294+
redactionAlgorithm: redactEventJSONV5,
295+
signatureValidityCheckFunc: StrictValiditySignatureCheck,
296+
canonicalJSONCheck: verifyEnforcedCanonicalJSON,
297+
notificationLevelCheck: checkNotificationLevels,
298+
restrictedJoinServernameFunc: extractAuthorisedViaServerName,
299+
checkRestrictedJoin: checkRestrictedJoin,
300+
parsePowerLevelsFunc: parseIntegerPowerLevels,
301+
checkKnockingAllowedFunc: checkKnocking,
302+
checkRestrictedJoinAllowedFunc: allowRestrictedJoins,
303+
checkCreateEvent: noCheckCreateEvent,
270304
newEventFromUntrustedJSONFunc: newEventFromUntrustedJSONV2,
271305
newEventFromTrustedJSONFunc: newEventFromTrustedJSONV2,
272306
newEventFromTrustedJSONWithEventIDFunc: newEventFromTrustedJSONWithEventIDV2,
@@ -286,6 +320,7 @@ var roomVersionMeta = map[RoomVersion]IRoomVersion{
286320
parsePowerLevelsFunc: parseIntegerPowerLevels,
287321
checkKnockingAllowedFunc: checkKnocking,
288322
checkRestrictedJoinAllowedFunc: allowRestrictedJoins,
323+
checkCreateEvent: checkCreateEvent,
289324
newEventFromUntrustedJSONFunc: newEventFromUntrustedJSONV2,
290325
newEventFromTrustedJSONFunc: newEventFromTrustedJSONV2,
291326
newEventFromTrustedJSONWithEventIDFunc: newEventFromTrustedJSONWithEventIDV2,
@@ -305,6 +340,7 @@ var roomVersionMeta = map[RoomVersion]IRoomVersion{
305340
parsePowerLevelsFunc: parseIntegerPowerLevels,
306341
checkKnockingAllowedFunc: checkKnocking,
307342
checkRestrictedJoinAllowedFunc: disallowRestrictedJoins,
343+
checkCreateEvent: checkCreateEvent,
308344
newEventFromUntrustedJSONFunc: newEventFromUntrustedJSONV2,
309345
newEventFromTrustedJSONFunc: newEventFromTrustedJSONV2,
310346
newEventFromTrustedJSONWithEventIDFunc: newEventFromTrustedJSONWithEventIDV2,
@@ -323,6 +359,7 @@ var roomVersionMeta = map[RoomVersion]IRoomVersion{
323359
checkRestrictedJoin: checkRestrictedJoin,
324360
parsePowerLevelsFunc: parsePowerLevels,
325361
checkKnockingAllowedFunc: checkKnocking,
362+
checkCreateEvent: checkCreateEvent,
326363
newEventFromUntrustedJSONFunc: newEventFromUntrustedJSONV2,
327364
newEventFromTrustedJSONFunc: newEventFromTrustedJSONV2,
328365
newEventFromTrustedJSONWithEventIDFunc: newEventFromTrustedJSONWithEventIDV2,
@@ -404,6 +441,7 @@ type RoomVersionImpl struct {
404441
restrictedJoinServernameFunc func(content []byte) (spec.ServerName, error)
405442
checkRestrictedJoinAllowedFunc func() error
406443
checkKnockingAllowedFunc func(m *membershipAllower) error
444+
checkCreateEvent func(e PDU, knownRoomVersion knownRoomVersionFunc) error
407445
newEventFromUntrustedJSONFunc func(eventJSON []byte, roomVersion IRoomVersion) (result PDU, err error)
408446
newEventFromTrustedJSONFunc func(eventJSON []byte, redacted bool, roomVersion IRoomVersion) (result PDU, err error)
409447
newEventFromTrustedJSONWithEventIDFunc func(eventID string, eventJSON []byte, redacted bool, roomVersion IRoomVersion) (result PDU, err error)
@@ -470,6 +508,10 @@ func (v RoomVersionImpl) ParsePowerLevels(contentBytes []byte, c *PowerLevelCont
470508
return v.parsePowerLevelsFunc(contentBytes, c)
471509
}
472510

511+
func (v RoomVersionImpl) CheckCreateEvent(event PDU, knownRoomVersion knownRoomVersionFunc) error {
512+
return v.checkCreateEvent(event, knownRoomVersion)
513+
}
514+
473515
func (v RoomVersionImpl) CheckRestrictedJoin(
474516
ctx context.Context,
475517
localServerName spec.ServerName,

redactevent.go

Lines changed: 82 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
)
88

99
// For satisfying "Upon receipt of a redaction event, the server must strip off any keys not in the following list:"
10-
type unredactableEventFields struct {
10+
type unredactableEventFieldsV1 struct {
1111
EventID spec.RawJSON `json:"event_id,omitempty"`
1212
Type string `json:"type"`
1313
RoomID spec.RawJSON `json:"room_id,omitempty"`
@@ -25,6 +25,46 @@ type unredactableEventFields struct {
2525
Membership spec.RawJSON `json:"membership,omitempty"`
2626
}
2727

28+
func (u *unredactableEventFieldsV1) GetType() string {
29+
return u.Type
30+
}
31+
32+
func (u *unredactableEventFieldsV1) GetContent() map[string]interface{} {
33+
return u.Content
34+
}
35+
36+
func (u *unredactableEventFieldsV1) SetContent(content map[string]interface{}) {
37+
u.Content = content
38+
}
39+
40+
// For satisfying "Upon receipt of a redaction event, the server must strip off any keys not in the following list:"
41+
type unredactableEventFieldsV2 struct {
42+
EventID spec.RawJSON `json:"event_id,omitempty"`
43+
Type string `json:"type"`
44+
RoomID spec.RawJSON `json:"room_id,omitempty"`
45+
Sender spec.RawJSON `json:"sender,omitempty"`
46+
StateKey spec.RawJSON `json:"state_key,omitempty"`
47+
Content map[string]interface{} `json:"content"`
48+
Hashes spec.RawJSON `json:"hashes,omitempty"`
49+
Signatures spec.RawJSON `json:"signatures,omitempty"`
50+
Depth spec.RawJSON `json:"depth,omitempty"`
51+
PrevEvents spec.RawJSON `json:"prev_events,omitempty"`
52+
AuthEvents spec.RawJSON `json:"auth_events,omitempty"`
53+
OriginServerTS spec.RawJSON `json:"origin_server_ts,omitempty"`
54+
}
55+
56+
func (u *unredactableEventFieldsV2) GetType() string {
57+
return u.Type
58+
}
59+
60+
func (u *unredactableEventFieldsV2) GetContent() map[string]interface{} {
61+
return u.Content
62+
}
63+
64+
func (u *unredactableEventFieldsV2) SetContent(content map[string]interface{}) {
65+
u.Content = content
66+
}
67+
2868
// For satisfying "The content object must also be stripped of all keys, unless it is one of one of the following event types:"
2969
var (
3070
unredactableContentFieldsV1 = map[string][]string{
@@ -56,52 +96,79 @@ var (
5696
"m.room.power_levels": {"ban", "events", "events_default", "kick", "redact", "state_default", "users", "users_default"},
5797
"m.room.history_visibility": {"history_visibility"},
5898
}
99+
unredactableContentFieldsV5 = map[string][]string{
100+
"m.room.member": {"membership", "join_authorised_via_users_server"},
101+
"m.room.create": {}, // NOTE: Keep all fields
102+
"m.room.join_rules": {"join_rule", "allow"},
103+
"m.room.power_levels": {"ban", "events", "events_default", "kick", "redact", "state_default", "users", "users_default", "invite"},
104+
"m.room.history_visibility": {"history_visibility"},
105+
"m.room.redaction": {"redacts"},
106+
}
59107
)
60108

109+
// RedactEvent strips the user controlled fields from an event, but leaves the
110+
// fields necessary for authenticating the event. Implements https://spec.matrix.org/unstable/rooms/v9/#redactions
111+
// which protects membership 'join_authorised_via_users_server' key
112+
func redactEventJSONV5(eventJSON []byte) ([]byte, error) {
113+
return redactEventJSON(eventJSON, &unredactableEventFieldsV2{}, unredactableContentFieldsV5)
114+
}
115+
61116
// RedactEvent strips the user controlled fields from an event, but leaves the
62117
// fields necessary for authenticating the event. Implements https://spec.matrix.org/unstable/rooms/v9/#redactions
63118
// which protects membership 'join_authorised_via_users_server' key
64119
func redactEventJSONV4(eventJSON []byte) ([]byte, error) {
65-
return redactEventJSON(eventJSON, unredactableContentFieldsV4)
120+
return redactEventJSON(eventJSON, &unredactableEventFieldsV1{}, unredactableContentFieldsV4)
66121
}
67122

68123
// RedactEvent strips the user controlled fields from an event, but leaves the
69124
// fields necessary for authenticating the event. Implements https://spec.matrix.org/unstable/rooms/v8/#redactions
70125
// which protects join rules 'allow' key
71126
func redactEventJSONV3(eventJSON []byte) ([]byte, error) {
72-
return redactEventJSON(eventJSON, unredactableContentFieldsV3)
127+
return redactEventJSON(eventJSON, &unredactableEventFieldsV1{}, unredactableContentFieldsV3)
73128
}
74129

75130
// RedactEvent strips the user controlled fields from an event, but leaves the
76131
// fields necessary for authenticating the event. Implements https://spec.matrix.org/unstable/rooms/v6/#redactions
77132
// which has no special meaning for m.room.aliases
78133
func redactEventJSONV2(eventJSON []byte) ([]byte, error) {
79-
return redactEventJSON(eventJSON, unredactableContentFieldsV2)
134+
return redactEventJSON(eventJSON, &unredactableEventFieldsV1{}, unredactableContentFieldsV2)
80135
}
81136

82137
// RedactEvent strips the user controlled fields from an event, but leaves the
83138
// fields necessary for authenticating the event. Implements https://spec.matrix.org/unstable/rooms/v1/#redactions
84139
func redactEventJSONV1(eventJSON []byte) ([]byte, error) {
85-
return redactEventJSON(eventJSON, unredactableContentFieldsV1)
140+
return redactEventJSON(eventJSON, &unredactableEventFieldsV1{}, unredactableContentFieldsV1)
141+
}
142+
143+
type unredactableEvent interface {
144+
*unredactableEventFieldsV1 | *unredactableEventFieldsV2
145+
GetType() string
146+
GetContent() map[string]interface{}
147+
SetContent(map[string]interface{})
86148
}
87149

88-
func redactEventJSON(eventJSON []byte, eventTypeToKeepContentFields map[string][]string) ([]byte, error) {
89-
var event unredactableEventFields
150+
func redactEventJSON[T unredactableEvent](eventJSON []byte, unredactableEvent T, eventTypeToKeepContentFields map[string][]string) ([]byte, error) {
90151
// Unmarshalling into a struct will discard any extra fields from the event.
91-
if err := json.Unmarshal(eventJSON, &event); err != nil {
152+
if err := json.Unmarshal(eventJSON, &unredactableEvent); err != nil {
92153
return nil, err
93154
}
94155
newContent := map[string]interface{}{}
95-
keepContentFields := eventTypeToKeepContentFields[event.Type]
96-
for _, contentKey := range keepContentFields {
97-
val, ok := event.Content[contentKey]
98-
if ok {
99-
newContent[contentKey] = val
156+
keepContentFields, ok := eventTypeToKeepContentFields[unredactableEvent.GetType()]
157+
if ok && len(keepContentFields) == 0 {
158+
// An unredactable content entry with no provided fields should keep all fields.
159+
newContent = unredactableEvent.GetContent()
160+
} else {
161+
for _, contentKey := range keepContentFields {
162+
val, ok := unredactableEvent.GetContent()[contentKey]
163+
if ok {
164+
newContent[contentKey] = val
165+
}
100166
}
101167
}
168+
102169
// Replace the content with our new filtered content.
103170
// This will zero out any keys that weren't copied in the loop above.
104-
event.Content = newContent
171+
unredactableEvent.SetContent(newContent)
105172
// Return the redacted event encoded as JSON.
106-
return json.Marshal(&event)
173+
return json.Marshal(&unredactableEvent)
107174
}

0 commit comments

Comments
 (0)