1// Copyright 2017 Vector Creations Ltd 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package api 16 17import ( 18 "github.com/matrix-org/gomatrixserverlib" 19) 20 21// An OutputType is a type of roomserver output. 22type OutputType string 23 24const ( 25 // OutputTypeNewRoomEvent indicates that the event is an OutputNewRoomEvent 26 OutputTypeNewRoomEvent OutputType = "new_room_event" 27 // OutputTypeOldRoomEvent indicates that the event is an OutputOldRoomEvent 28 OutputTypeOldRoomEvent OutputType = "old_room_event" 29 // OutputTypeNewInviteEvent indicates that the event is an OutputNewInviteEvent 30 OutputTypeNewInviteEvent OutputType = "new_invite_event" 31 // OutputTypeRetireInviteEvent indicates that the event is an OutputRetireInviteEvent 32 OutputTypeRetireInviteEvent OutputType = "retire_invite_event" 33 // OutputTypeRedactedEvent indicates that the event is an OutputRedactedEvent 34 // 35 // This event is emitted when a redaction has been 'validated' (meaning both the redaction and the event to redact are known). 36 // Redaction validation happens when the roomserver receives either: 37 // - A redaction for which we have the event to redact. 38 // - Any event for which we have a redaction. 39 // When the roomserver receives an event, it will check against the redactions table to see if there is a matching redaction 40 // for the event. If there is, it will mark the redaction as validated and emit this event. In the common case of a redaction 41 // happening after receiving the event to redact, the roomserver will emit a OutputTypeNewRoomEvent of m.room.redaction 42 // immediately followed by a OutputTypeRedactedEvent. In the uncommon case of receiving the redaction BEFORE the event to redact, 43 // the roomserver will emit a OutputTypeNewRoomEvent of the event to redact immediately followed by a OutputTypeRedactedEvent. 44 // 45 // In order to honour redactions correctly, downstream components must ignore m.room.redaction events emitted via OutputTypeNewRoomEvent. 46 // When downstream components receive an OutputTypeRedactedEvent they must: 47 // - Pull out the event to redact from the database. They should have this because the redaction is validated. 48 // - Redact the event and set the corresponding `unsigned` fields to indicate it as redacted. 49 // - Replace the event in the database. 50 OutputTypeRedactedEvent OutputType = "redacted_event" 51 52 // OutputTypeNewPeek indicates that the kafka event is an OutputNewPeek 53 OutputTypeNewPeek OutputType = "new_peek" 54 // OutputTypeNewInboundPeek indicates that the kafka event is an OutputNewInboundPeek 55 OutputTypeNewInboundPeek OutputType = "new_inbound_peek" 56 // OutputTypeRetirePeek indicates that the kafka event is an OutputRetirePeek 57 OutputTypeRetirePeek OutputType = "retire_peek" 58) 59 60// An OutputEvent is an entry in the roomserver output kafka log. 61// Consumers should check the type field when consuming this event. 62type OutputEvent struct { 63 // What sort of event this is. 64 Type OutputType `json:"type"` 65 // The content of event with type OutputTypeNewRoomEvent 66 NewRoomEvent *OutputNewRoomEvent `json:"new_room_event,omitempty"` 67 // The content of event with type OutputTypeOldRoomEvent 68 OldRoomEvent *OutputOldRoomEvent `json:"old_room_event,omitempty"` 69 // The content of event with type OutputTypeNewInviteEvent 70 NewInviteEvent *OutputNewInviteEvent `json:"new_invite_event,omitempty"` 71 // The content of event with type OutputTypeRetireInviteEvent 72 RetireInviteEvent *OutputRetireInviteEvent `json:"retire_invite_event,omitempty"` 73 // The content of event with type OutputTypeRedactedEvent 74 RedactedEvent *OutputRedactedEvent `json:"redacted_event,omitempty"` 75 // The content of event with type OutputTypeNewPeek 76 NewPeek *OutputNewPeek `json:"new_peek,omitempty"` 77 // The content of event with type OutputTypeNewInboundPeek 78 NewInboundPeek *OutputNewInboundPeek `json:"new_inbound_peek,omitempty"` 79 // The content of event with type OutputTypeRetirePeek 80 RetirePeek *OutputRetirePeek `json:"retire_peek,omitempty"` 81} 82 83// Type of the OutputNewRoomEvent. 84type OutputRoomEventType int 85 86const ( 87 // The event is a timeline event and likely just happened. 88 OutputRoomTimeline OutputRoomEventType = iota 89 90 // The event is a state event and quite possibly happened in the past. 91 OutputRoomState 92) 93 94// An OutputNewRoomEvent is written when the roomserver receives a new event. 95// It contains the full matrix room event and enough information for a 96// consumer to construct the current state of the room and the state before the 97// event. 98// 99// When we talk about state in a matrix room we are talking about the state 100// after a list of events. The current state is the state after the latest 101// event IDs in the room. The state before an event is the state after its 102// prev_events. 103type OutputNewRoomEvent struct { 104 // The Event. 105 Event *gomatrixserverlib.HeaderedEvent `json:"event"` 106 // Does the event completely rewrite the room state? If so, then AddsStateEventIDs 107 // will contain the entire room state. 108 RewritesState bool `json:"rewrites_state"` 109 // The latest events in the room after this event. 110 // This can be used to set the prev events for new events in the room. 111 // This also can be used to get the full current state after this event. 112 LatestEventIDs []string `json:"latest_event_ids"` 113 // The state event IDs that were added to the state of the room by this event. 114 // Together with RemovesStateEventIDs this allows the receiver to keep an up to date 115 // view of the current state of the room. 116 AddsStateEventIDs []string `json:"adds_state_event_ids"` 117 // All extra newly added state events. This is only set if there are *extra* events 118 // other than `Event`. This can happen when forks get merged because state resolution 119 // may decide a bunch of state events on one branch are now valid, so they will be 120 // present in this list. This is useful when trying to maintain the current state of a room 121 // as to do so you need to include both these events and `Event`. 122 AddStateEvents []*gomatrixserverlib.HeaderedEvent `json:"adds_state_events"` 123 124 // The state event IDs that were removed from the state of the room by this event. 125 RemovesStateEventIDs []string `json:"removes_state_event_ids"` 126 // The ID of the event that was output before this event. 127 // Or the empty string if this is the first event output for this room. 128 // This is used by consumers to check if they can safely update their 129 // current state using the delta supplied in AddsStateEventIDs and 130 // RemovesStateEventIDs. 131 // 132 // If the LastSentEventID doesn't match what they were expecting it to be 133 // they can use the LatestEventIDs to request the full current state. 134 LastSentEventID string `json:"last_sent_event_id"` 135 // The state event IDs that are part of the state at the event, but not 136 // part of the current state. Together with the StateBeforeRemovesEventIDs 137 // this can be used to construct the state before the event from the 138 // current state. The StateBeforeAddsEventIDs and StateBeforeRemovesEventIDs 139 // delta is applied after the AddsStateEventIDs and RemovesStateEventIDs. 140 // 141 // Consumers need to know the state at each event in order to determine 142 // which users and servers are allowed to see the event. This information 143 // is needed to apply the history visibility rules and to tell which 144 // servers we need to push events to over federation. 145 // 146 // The state is given as a delta against the current state because they are 147 // usually either the same state, or differ by just a couple of events. 148 StateBeforeAddsEventIDs []string `json:"state_before_adds_event_ids"` 149 // The state event IDs that are part of the current state, but not part 150 // of the state at the event. 151 StateBeforeRemovesEventIDs []string `json:"state_before_removes_event_ids"` 152 // The server name to use to push this event to other servers. 153 // Or empty if this event shouldn't be pushed to other servers. 154 // 155 // This is used by the federation sender component. We need to tell it what 156 // event it needs to send because it can't tell on its own. Normally if an 157 // event was created on this server then we are responsible for sending it. 158 // However there are a couple of exceptions. The first is that when the 159 // server joins a remote room through another matrix server, it is the job 160 // of the other matrix server to send the event over federation. The second 161 // is the reverse of the first, that is when a remote server joins a room 162 // that we are in over federation using our server it is our responsibility 163 // to send the join event to other matrix servers. 164 // 165 // We encode the server name that the event should be sent using here to 166 // future proof the API for virtual hosting. 167 SendAsServer string `json:"send_as_server"` 168 // The transaction ID of the send request if sent by a local user and one 169 // was specified 170 TransactionID *TransactionID `json:"transaction_id"` 171} 172 173// AddsState returns all added state events from this event. 174// 175// This function is needed because `AddStateEvents` will not include a copy of 176// the original event to save space, so you cannot use that slice alone. 177// Instead, use this function which will add the original event if it is present 178// in `AddsStateEventIDs`. 179func (ore *OutputNewRoomEvent) AddsState() []*gomatrixserverlib.HeaderedEvent { 180 includeOutputEvent := false 181 for _, id := range ore.AddsStateEventIDs { 182 if id == ore.Event.EventID() { 183 includeOutputEvent = true 184 break 185 } 186 } 187 if !includeOutputEvent { 188 return ore.AddStateEvents 189 } 190 return append(ore.AddStateEvents, ore.Event) 191} 192 193// An OutputOldRoomEvent is written when the roomserver receives an old event. 194// This will typically happen as a result of getting either missing events 195// or backfilling. Downstream components may wish to send these events to 196// clients when it is advantageous to do so, but with the consideration that 197// the event is likely a historic event. 198// 199// Old events do not update forward extremities or the current room state, 200// therefore they must not be treated as if they do. Downstream components 201// should build their current room state up from OutputNewRoomEvents only. 202type OutputOldRoomEvent struct { 203 // The Event. 204 Event *gomatrixserverlib.HeaderedEvent `json:"event"` 205} 206 207// An OutputNewInviteEvent is written whenever an invite becomes active. 208// Invite events can be received outside of an existing room so have to be 209// tracked separately from the room events themselves. 210type OutputNewInviteEvent struct { 211 // The room version of the invited room. 212 RoomVersion gomatrixserverlib.RoomVersion `json:"room_version"` 213 // The "m.room.member" invite event. 214 Event *gomatrixserverlib.HeaderedEvent `json:"event"` 215} 216 217// An OutputRetireInviteEvent is written whenever an existing invite is no longer 218// active. An invite stops being active if the user joins the room or if the 219// invite is rejected by the user. 220type OutputRetireInviteEvent struct { 221 // The ID of the "m.room.member" invite event. 222 EventID string 223 // The target user ID of the "m.room.member" invite event that was retired. 224 TargetUserID string 225 // Optional event ID of the event that replaced the invite. 226 // This can be empty if the invite was rejected locally and we were unable 227 // to reach the server that originally sent the invite. 228 RetiredByEventID string 229 // The "membership" of the user after retiring the invite. One of "join" 230 // "leave" or "ban". 231 Membership string 232} 233 234// An OutputRedactedEvent is written whenever a redaction has been /validated/. 235// Downstream components MUST redact the given event ID if they have stored the 236// event JSON. It is guaranteed that this event ID has been seen before. 237type OutputRedactedEvent struct { 238 // The event ID that was redacted 239 RedactedEventID string 240 // The value of `unsigned.redacted_because` - the redaction event itself 241 RedactedBecause *gomatrixserverlib.HeaderedEvent 242} 243 244// An OutputNewPeek is written whenever a user starts peeking into a room 245// using a given device. 246type OutputNewPeek struct { 247 RoomID string 248 UserID string 249 DeviceID string 250} 251 252// An OutputNewInboundPeek is written whenever a server starts peeking into a room 253type OutputNewInboundPeek struct { 254 RoomID string 255 PeekID string 256 // the event ID at which the peek begins (so we can avoid 257 // a race between tracking the state returned by /peek and emitting subsequent 258 // peeked events) 259 LatestEventID string 260 ServerName gomatrixserverlib.ServerName 261 // how often we told the peeking server to renew the peek 262 RenewalInterval int64 263} 264 265// An OutputRetirePeek is written whenever a user stops peeking into a room. 266type OutputRetirePeek struct { 267 RoomID string 268 UserID string 269 DeviceID string 270} 271