Skip to content

Commit a234d6d

Browse files
authored
Add a way to set custom room version impls (#455)
We have this lovely room version abstraction, but... no one can actually use it without getting it into this map. Let's fix that.
1 parent 904c8f0 commit a234d6d

File tree

4 files changed

+66
-25
lines changed

4 files changed

+66
-25
lines changed

eventauth.go

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,7 +1158,12 @@ func (m *membershipAllower) membershipAllowedSelf() error { // nolint: gocyclo
11581158
switch m.newMember.Membership {
11591159
case spec.Knock:
11601160
// Check if the given roomVersionImpl allows knocking.
1161-
return m.roomVersionImpl.CheckKnockingAllowed(m)
1161+
return m.roomVersionImpl.CheckKnockingAllowed(
1162+
string(m.roomVersionImpl.Version()),
1163+
m.senderID, m.targetID,
1164+
m.joinRule.JoinRule,
1165+
m.oldMember.Membership,
1166+
)
11621167
case spec.Join:
11631168
if m.joinRule.JoinRule == spec.Restricted || m.joinRule.JoinRule == spec.KnockRestricted {
11641169
if err := m.membershipAllowedSelfForRestrictedJoin(); err != nil {
@@ -1227,11 +1232,17 @@ func disallowRestrictedJoins() error {
12271232
return errorf("restricted joins are not supported in this room version")
12281233
}
12291234

1230-
func disallowKnocking(m *membershipAllower) error {
1231-
return m.membershipFailed(
1232-
"room version %q does not support knocking on rooms with join rule %q",
1233-
m.roomVersionImpl.Version(),
1234-
m.joinRule.JoinRule,
1235+
func disallowKnocking(roomVer, sender, target, joinRule, prevMembership string) error {
1236+
if sender == target {
1237+
return errorf(
1238+
"%q is not allowed to change their membership from %q as room version %q does not support knocking on rooms with join rule %q",
1239+
sender, prevMembership, roomVer, joinRule,
1240+
)
1241+
}
1242+
1243+
return errorf(
1244+
"%q is not allowed to change the membership of %q from %q as room version %q does not support knocking on rooms with join rule %q",
1245+
sender, target, prevMembership, roomVer, joinRule,
12351246
)
12361247
}
12371248

@@ -1242,23 +1253,25 @@ func disallowKnocking(m *membershipAllower) error {
12421253
// MSC3787 extends this: the behaviour above is also permitted if the
12431254
// join rules are "knock_restricted"
12441255
// Spec: https://github.com/matrix-org/matrix-spec-proposals/pull/3787
1245-
func checkKnocking(m *membershipAllower) error {
1256+
func checkKnocking(roomVer, sender, target, joinRule, prevMembership string) error {
12461257
// If the join_rule is anything other than knock or knock_restricted, reject.
1247-
supported := m.joinRule.JoinRule == spec.Knock || m.joinRule.JoinRule == spec.KnockRestricted
1258+
supported := joinRule == spec.Knock || joinRule == spec.KnockRestricted
12481259
if !supported {
1249-
return m.membershipFailed(
1250-
"room version %q does not support knocking on rooms with join rule %q",
1251-
m.roomVersionImpl.Version(),
1252-
m.joinRule.JoinRule,
1260+
return errorf(
1261+
"%q is not allowed to change the membership of %q from %q as room version %q does not support knocking on rooms with join rule %q",
1262+
sender, target, prevMembership,
1263+
roomVer,
1264+
joinRule,
12531265
)
12541266
}
1255-
switch m.oldMember.Membership {
1267+
switch prevMembership {
12561268

12571269
case spec.Join, spec.Invite, spec.Ban:
12581270
// The user is already joined, invited or banned, therefore they
12591271
// can't knock.
1260-
return m.membershipFailed(
1261-
"sender is already joined/invited/banned",
1272+
return errorf(
1273+
"%q is not allowed to change the membership of %q from %q as sender is already joined/invited/banned",
1274+
sender, target, prevMembership,
12621275
)
12631276
}
12641277
// A non-joined, non-invited, non-banned user is allowed to knock.

eventauth_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,3 +1999,21 @@ func TestJoinRuleKnockRestricted(t *testing.T) {
19991999
}]
20002000
}`, RoomVersionV10)
20012001
}
2002+
2003+
type CustomVer struct {
2004+
IRoomVersion
2005+
}
2006+
2007+
func (v CustomVer) Version() RoomVersion {
2008+
return "hello"
2009+
}
2010+
2011+
func TestSetRoomVersion(t *testing.T) {
2012+
// ensure we can set and get custom room versions.
2013+
// GMSL doesn't use this but users of GMSL do.
2014+
v := CustomVer{
2015+
IRoomVersion: MustGetRoomVersion("10"),
2016+
}
2017+
SetRoomVersion(v)
2018+
MustGetRoomVersion("hello")
2019+
}

eventcontent.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -581,11 +581,11 @@ type RelatesTo struct {
581581
RelationType string `json:"rel_type"`
582582
}
583583

584-
func noCheckCreateEvent(event PDU, knownRoomVersion knownRoomVersionFunc) error {
584+
func noCheckCreateEvent(event PDU, knownRoomVersion KnownRoomVersionFunc) error {
585585
return nil
586586
}
587587

588-
func checkCreateEvent(event PDU, knownRoomVersion knownRoomVersionFunc) error {
588+
func checkCreateEvent(event PDU, knownRoomVersion KnownRoomVersionFunc) error {
589589
c := struct {
590590
Creator *string `json:"creator"`
591591
RoomVersion *RoomVersion `json:"room_version"`

eventversion.go

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import (
1212
// RoomVersion refers to the room version for a specific room.
1313
type RoomVersion string
1414

15+
// The interface which needs to be implemented to register a room version with gomatrixserverlib.
16+
// All types should be public to allow for extensibility.
1517
type IRoomVersion interface {
1618
Version() RoomVersion
1719
Stable() bool
@@ -29,14 +31,14 @@ type IRoomVersion interface {
2931

3032
RestrictedJoinServername(content []byte) (spec.ServerName, error)
3133
CheckRestrictedJoinsAllowed() error
32-
CheckKnockingAllowed(m *membershipAllower) error
34+
CheckKnockingAllowed(roomVer, sender, target, joinRule, prevMembership string) error
3335
CheckNotificationLevels(senderLevel int64, oldPowerLevels, newPowerLevels PowerLevelContent) error
3436
CheckCanonicalJSON(input []byte) error
3537
ParsePowerLevels(contentBytes []byte, c *PowerLevelContent) error
36-
CheckCreateEvent(event PDU, knownRoomVersion knownRoomVersionFunc) error
38+
CheckCreateEvent(event PDU, knownRoomVersion KnownRoomVersionFunc) error
3739
}
3840

39-
type knownRoomVersionFunc func(RoomVersion) bool
41+
type KnownRoomVersionFunc func(RoomVersion) bool
4042

4143
// StateResAlgorithm refers to a version of the state resolution algorithm.
4244
type StateResAlgorithm int
@@ -416,6 +418,14 @@ func StableRoomVersions() map[RoomVersion]IRoomVersion {
416418
return versions
417419
}
418420

421+
// SetRoomVersion sets a room version implementation so it is recognised by gomatrixserverlib.
422+
// This is useful when you are testing custom room versions which gomatrixserverlib may be unaware of,
423+
// e.g for Complement usage. Full room version impls should be defined in gomatrixserverlib, but
424+
// partial impls for testing can be set here.
425+
func SetRoomVersion(ver IRoomVersion) {
426+
roomVersionMeta[ver.Version()] = ver
427+
}
428+
419429
// RoomVersionDescription contains information about a room version,
420430
// namely whether it is marked as supported or stable in this server
421431
// version, along with the state resolution algorithm, event ID etc
@@ -440,8 +450,8 @@ type RoomVersionImpl struct {
440450
checkRestrictedJoin restrictedJoinCheckFunc
441451
restrictedJoinServernameFunc func(content []byte) (spec.ServerName, error)
442452
checkRestrictedJoinAllowedFunc func() error
443-
checkKnockingAllowedFunc func(m *membershipAllower) error
444-
checkCreateEvent func(e PDU, knownRoomVersion knownRoomVersionFunc) error
453+
checkKnockingAllowedFunc func(roomVer, sender, target, joinRule, prevMembership string) error
454+
checkCreateEvent func(e PDU, knownRoomVersion KnownRoomVersionFunc) error
445455
newEventFromUntrustedJSONFunc func(eventJSON []byte, roomVersion IRoomVersion) (result PDU, err error)
446456
newEventFromTrustedJSONFunc func(eventJSON []byte, redacted bool, roomVersion IRoomVersion) (result PDU, err error)
447457
newEventFromTrustedJSONWithEventIDFunc func(eventID string, eventJSON []byte, redacted bool, roomVersion IRoomVersion) (result PDU, err error)
@@ -483,8 +493,8 @@ func (v RoomVersionImpl) CheckNotificationLevels(senderLevel int64, oldPowerLeve
483493
}
484494

485495
// CheckKnockingAllowed checks if this room version supports knocking on rooms.
486-
func (v RoomVersionImpl) CheckKnockingAllowed(m *membershipAllower) error {
487-
return v.checkKnockingAllowedFunc(m)
496+
func (v RoomVersionImpl) CheckKnockingAllowed(roomVer, sender, target, joinRule, prevMembership string) error {
497+
return v.checkKnockingAllowedFunc(roomVer, sender, target, joinRule, prevMembership)
488498
}
489499

490500
// CheckRestrictedJoinsAllowed checks if this room version allows restricted joins.
@@ -508,7 +518,7 @@ func (v RoomVersionImpl) ParsePowerLevels(contentBytes []byte, c *PowerLevelCont
508518
return v.parsePowerLevelsFunc(contentBytes, c)
509519
}
510520

511-
func (v RoomVersionImpl) CheckCreateEvent(event PDU, knownRoomVersion knownRoomVersionFunc) error {
521+
func (v RoomVersionImpl) CheckCreateEvent(event PDU, knownRoomVersion KnownRoomVersionFunc) error {
512522
return v.checkCreateEvent(event, knownRoomVersion)
513523
}
514524

0 commit comments

Comments
 (0)