Handle event_format federation in /sync responses (#3192)
This commit is contained in:
parent
11fd2f019b
commit
bb2ab62cbf
16 changed files with 739 additions and 84 deletions
|
|
@ -16,12 +16,21 @@
|
|||
package synctypes
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// PrevEventRef represents a reference to a previous event in a state event upgrade
|
||||
type PrevEventRef struct {
|
||||
PrevContent json.RawMessage `json:"prev_content"`
|
||||
ReplacesState string `json:"replaces_state"`
|
||||
PrevSenderID string `json:"prev_sender"`
|
||||
}
|
||||
|
||||
type ClientEventFormat int
|
||||
|
||||
const (
|
||||
|
|
@ -30,8 +39,21 @@ const (
|
|||
// FormatSync will include only the event keys required by the /sync API. Notably, this
|
||||
// means the 'room_id' will be missing from the events.
|
||||
FormatSync
|
||||
// FormatSyncFederation will include all event keys normally included in federated events.
|
||||
// This allows clients to request federated formatted events via the /sync API.
|
||||
FormatSyncFederation
|
||||
)
|
||||
|
||||
// ClientFederationFields extends a ClientEvent to contain the additional fields present in a
|
||||
// federation event. Used when the client requests `event_format` of type `federation`.
|
||||
type ClientFederationFields struct {
|
||||
Depth int64 `json:"depth,omitempty"`
|
||||
PrevEvents []string `json:"prev_events,omitempty"`
|
||||
AuthEvents []string `json:"auth_events,omitempty"`
|
||||
Signatures spec.RawJSON `json:"signatures,omitempty"`
|
||||
Hashes spec.RawJSON `json:"hashes,omitempty"`
|
||||
}
|
||||
|
||||
// ClientEvent is an event which is fit for consumption by clients, in accordance with the specification.
|
||||
type ClientEvent struct {
|
||||
Content spec.RawJSON `json:"content"`
|
||||
|
|
@ -44,6 +66,9 @@ type ClientEvent struct {
|
|||
Type string `json:"type"`
|
||||
Unsigned spec.RawJSON `json:"unsigned,omitempty"`
|
||||
Redacts string `json:"redacts,omitempty"`
|
||||
|
||||
// Only sent to clients when `event_format` == `federation`.
|
||||
ClientFederationFields
|
||||
}
|
||||
|
||||
// ToClientEvents converts server events to client events.
|
||||
|
|
@ -53,6 +78,11 @@ func ToClientEvents(serverEvs []gomatrixserverlib.PDU, format ClientEventFormat,
|
|||
if se == nil {
|
||||
continue // TODO: shouldn't happen?
|
||||
}
|
||||
if format == FormatSyncFederation {
|
||||
evs = append(evs, ToClientEvent(se, format, string(se.SenderID()), se.StateKey(), spec.RawJSON(se.Unsigned())))
|
||||
continue
|
||||
}
|
||||
|
||||
sender := spec.UserID{}
|
||||
validRoomID, err := spec.NewRoomID(se.RoomID())
|
||||
if err != nil {
|
||||
|
|
@ -71,28 +101,61 @@ func ToClientEvents(serverEvs []gomatrixserverlib.PDU, format ClientEventFormat,
|
|||
sk = &skString
|
||||
}
|
||||
}
|
||||
evs = append(evs, ToClientEvent(se, format, sender, sk))
|
||||
|
||||
unsigned := se.Unsigned()
|
||||
var prev PrevEventRef
|
||||
if err := json.Unmarshal(se.Unsigned(), &prev); err == nil && prev.PrevSenderID != "" {
|
||||
prevUserID, err := userIDForSender(*validRoomID, spec.SenderID(prev.PrevSenderID))
|
||||
if err == nil && userID != nil {
|
||||
prev.PrevSenderID = prevUserID.String()
|
||||
} else {
|
||||
errString := "userID unknown"
|
||||
if err != nil {
|
||||
errString = err.Error()
|
||||
}
|
||||
logrus.Warnf("Failed to find userID for prev_sender in ClientEvent: %s", errString)
|
||||
// NOTE: Not much can be done here, so leave the previous value in place.
|
||||
}
|
||||
unsigned, err = json.Marshal(prev)
|
||||
if err != nil {
|
||||
logrus.Errorf("Failed to marshal unsigned content for ClientEvent: %s", err.Error())
|
||||
continue
|
||||
}
|
||||
}
|
||||
evs = append(evs, ToClientEvent(se, format, sender.String(), sk, spec.RawJSON(unsigned)))
|
||||
}
|
||||
return evs
|
||||
}
|
||||
|
||||
// ToClientEvent converts a single server event to a client event.
|
||||
func ToClientEvent(se gomatrixserverlib.PDU, format ClientEventFormat, sender spec.UserID, stateKey *string) ClientEvent {
|
||||
func ToClientEvent(se gomatrixserverlib.PDU, format ClientEventFormat, sender string, stateKey *string, unsigned spec.RawJSON) ClientEvent {
|
||||
ce := ClientEvent{
|
||||
Content: spec.RawJSON(se.Content()),
|
||||
Sender: sender.String(),
|
||||
Sender: sender,
|
||||
Type: se.Type(),
|
||||
StateKey: stateKey,
|
||||
Unsigned: spec.RawJSON(se.Unsigned()),
|
||||
Unsigned: unsigned,
|
||||
OriginServerTS: se.OriginServerTS(),
|
||||
EventID: se.EventID(),
|
||||
Redacts: se.Redacts(),
|
||||
}
|
||||
if format == FormatAll {
|
||||
|
||||
switch format {
|
||||
case FormatAll:
|
||||
ce.RoomID = se.RoomID()
|
||||
case FormatSync:
|
||||
case FormatSyncFederation:
|
||||
ce.RoomID = se.RoomID()
|
||||
ce.AuthEvents = se.AuthEventIDs()
|
||||
ce.PrevEvents = se.PrevEventIDs()
|
||||
ce.Depth = se.Depth()
|
||||
// TODO: Set Signatures & Hashes fields
|
||||
}
|
||||
if se.Version() == gomatrixserverlib.RoomVersionPseudoIDs {
|
||||
ce.SenderKey = se.SenderID()
|
||||
|
||||
if format != FormatSyncFederation {
|
||||
if se.Version() == gomatrixserverlib.RoomVersionPseudoIDs {
|
||||
ce.SenderKey = se.SenderID()
|
||||
}
|
||||
}
|
||||
return ce
|
||||
}
|
||||
|
|
@ -118,7 +181,7 @@ func ToClientEventDefault(userIDQuery spec.UserIDForSender, event gomatrixserver
|
|||
sk = &skString
|
||||
}
|
||||
}
|
||||
return ToClientEvent(event, FormatAll, sender, sk)
|
||||
return ToClientEvent(event, FormatAll, sender.String(), sk, event.Unsigned())
|
||||
}
|
||||
|
||||
// If provided state key is a user ID (state keys beginning with @ are reserved for this purpose)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue