Skip to content

Commit 390dbaa

Browse files
committed
Add missing file
1 parent d38d280 commit 390dbaa

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

eventV3.go

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
package gomatrixserverlib
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"fmt"
7+
"strings"
8+
9+
"github.com/matrix-org/gomatrixserverlib/spec"
10+
"github.com/tidwall/gjson"
11+
"github.com/tidwall/sjson"
12+
)
13+
14+
type eventV3 struct {
15+
eventV2
16+
}
17+
18+
func (e *eventV3) RoomID() spec.RoomID {
19+
roomIDStr := e.eventFields.RoomID
20+
isCreateEvent := e.Type() == spec.MRoomCreate && e.StateKeyEquals("")
21+
if isCreateEvent {
22+
roomIDStr = fmt.Sprintf("!%s", e.EventID()[1:])
23+
}
24+
roomID, err := spec.NewRoomID(roomIDStr)
25+
if err != nil {
26+
panic(fmt.Errorf("RoomID is invalid: %w", err))
27+
}
28+
return *roomID
29+
}
30+
31+
func (e *eventV3) AuthEventIDs() []string {
32+
isCreateEvent := e.Type() == spec.MRoomCreate && e.StateKeyEquals("")
33+
if isCreateEvent {
34+
return []string{}
35+
}
36+
createEventID := fmt.Sprintf("$%s", e.eventFields.RoomID[1:])
37+
if len(e.AuthEvents) > 0 {
38+
// always include the create event
39+
return append([]string{createEventID}, e.AuthEvents...)
40+
}
41+
return []string{createEventID}
42+
}
43+
44+
func newEventFromUntrustedJSONV3(eventJSON []byte, roomVersion IRoomVersion) (PDU, error) {
45+
if r := gjson.GetBytes(eventJSON, "_*"); r.Exists() {
46+
return nil, fmt.Errorf("gomatrixserverlib NewEventFromUntrustedJSON: found top-level '_' key, is this a headered event: %v", string(eventJSON))
47+
}
48+
if err := roomVersion.CheckCanonicalJSON(eventJSON); err != nil {
49+
return nil, BadJSONError{err}
50+
}
51+
52+
res := &eventV3{}
53+
var err error
54+
// Synapse removes these keys from events in case a server accidentally added them.
55+
// https://github.com/matrix-org/synapse/blob/v0.18.5/synapse/crypto/event_signing.py#L57-L62
56+
for _, key := range []string{"outlier", "destinations", "age_ts", "unsigned", "event_id"} {
57+
if eventJSON, err = sjson.DeleteBytes(eventJSON, key); err != nil {
58+
return nil, err
59+
}
60+
}
61+
62+
if err = json.Unmarshal(eventJSON, &res); err != nil {
63+
return nil, err
64+
}
65+
66+
// v3 events have room IDs as the create event ID.
67+
// TODO: allow validation to be enhanced/relaxed to help users like Complement.
68+
if err := checkRoomID(res); err != nil {
69+
return nil, err
70+
}
71+
72+
res.roomVersion = roomVersion.Version()
73+
74+
// We know the JSON must be valid here.
75+
eventJSON = CanonicalJSONAssumeValid(eventJSON)
76+
res.eventJSON = eventJSON
77+
78+
if err = checkEventContentHash(eventJSON); err != nil {
79+
res.redacted = true
80+
81+
// If the content hash doesn't match then we have to discard all non-essential fields
82+
// because they've been tampered with.
83+
var redactedJSON []byte
84+
if redactedJSON, err = roomVersion.RedactEventJSON(eventJSON); err != nil {
85+
return nil, err
86+
}
87+
88+
redactedJSON = CanonicalJSONAssumeValid(redactedJSON)
89+
90+
// We need to ensure that `result` is the redacted event.
91+
// If redactedJSON is the same as eventJSON then `result` is already
92+
// correct. If not then we need to reparse.
93+
//
94+
// Yes, this means that for some events we parse twice (which is slow),
95+
// but means that parsing unredacted events is fast.
96+
if !bytes.Equal(redactedJSON, eventJSON) {
97+
result, err := roomVersion.NewEventFromTrustedJSON(redactedJSON, true)
98+
if err != nil {
99+
return nil, err
100+
}
101+
err = CheckFields(result)
102+
return result, err
103+
}
104+
}
105+
106+
err = CheckFields(res)
107+
108+
return res, err
109+
}
110+
111+
func newEventFromTrustedJSONV3(eventJSON []byte, redacted bool, roomVersion IRoomVersion) (PDU, error) {
112+
res := eventV3{}
113+
if err := json.Unmarshal(eventJSON, &res); err != nil {
114+
return nil, err
115+
}
116+
117+
// v3 events have room IDs as the create event ID.
118+
// TODO: allow validation to be enhanced/relaxed to help users like Complement.
119+
// TODO: feels weird to only have this validation here and not length checks etc :S
120+
if err := checkRoomID(&res); err != nil {
121+
return nil, err
122+
}
123+
124+
res.roomVersion = roomVersion.Version()
125+
res.redacted = redacted
126+
res.eventJSON = eventJSON
127+
return &res, nil
128+
}
129+
130+
func newEventFromTrustedJSONWithEventIDV3(eventID string, eventJSON []byte, redacted bool, roomVersion IRoomVersion) (PDU, error) {
131+
res := &eventV3{}
132+
if err := json.Unmarshal(eventJSON, &res); err != nil {
133+
return nil, err
134+
}
135+
136+
// v3 events have room IDs as the create event ID.
137+
// TODO: allow validation to be enhanced/relaxed to help users like Complement.
138+
if err := checkRoomID(res); err != nil {
139+
return nil, err
140+
}
141+
142+
res.roomVersion = roomVersion.Version()
143+
res.eventJSON = eventJSON
144+
res.EventIDRaw = eventID
145+
res.redacted = redacted
146+
return res, nil
147+
}
148+
149+
func checkRoomID(res *eventV3) error {
150+
isCreateEvent := res.Type() == spec.MRoomCreate && res.StateKeyEquals("")
151+
// TODO: We can't do this so long as we support partial Hydra impls in Complement
152+
// because otherwise if MSC4291=0 and MSC4289=1 then this check fails as the create
153+
// event will have a room_id.
154+
if isCreateEvent && res.eventFields.RoomID != "" {
155+
//return fmt.Errorf("gomatrixserverlib: room_id must not exist on create event")
156+
}
157+
if !isCreateEvent && !strings.HasPrefix(res.eventFields.RoomID, "!") {
158+
return fmt.Errorf("gomatrixserverlib: room_id must start with !")
159+
}
160+
return nil
161+
}

0 commit comments

Comments
 (0)