Add relationship_room_id|servers to the unsigned section of events

This commit is contained in:
Kegan Dougal 2020-11-17 14:34:27 +00:00
parent 435dbf2bde
commit f33e2258f6
6 changed files with 105 additions and 39 deletions

View file

@ -48,6 +48,7 @@ type FederationSenderInternalAPI interface {
// Query the server names of the joined hosts in a room. // Query the server names of the joined hosts in a room.
// Unlike QueryJoinedHostsInRoom, this function returns a de-duplicated slice // Unlike QueryJoinedHostsInRoom, this function returns a de-duplicated slice
// containing only the server names (without information for membership events). // containing only the server names (without information for membership events).
// The response will include this server if they are joined to the room.
QueryJoinedHostServerNamesInRoom( QueryJoinedHostServerNamesInRoom(
ctx context.Context, ctx context.Context,
request *QueryJoinedHostServerNamesInRoomRequest, request *QueryJoinedHostServerNamesInRoomRequest,

View file

@ -4,7 +4,6 @@ import (
"context" "context"
"github.com/matrix-org/dendrite/federationsender/api" "github.com/matrix-org/dendrite/federationsender/api"
"github.com/matrix-org/gomatrixserverlib"
) )
// QueryJoinedHostServerNamesInRoom implements api.FederationSenderInternalAPI // QueryJoinedHostServerNamesInRoom implements api.FederationSenderInternalAPI
@ -13,17 +12,11 @@ func (f *FederationSenderInternalAPI) QueryJoinedHostServerNamesInRoom(
request *api.QueryJoinedHostServerNamesInRoomRequest, request *api.QueryJoinedHostServerNamesInRoomRequest,
response *api.QueryJoinedHostServerNamesInRoomResponse, response *api.QueryJoinedHostServerNamesInRoomResponse,
) (err error) { ) (err error) {
joinedHosts, err := f.db.GetJoinedHosts(ctx, request.RoomID) joinedHosts, err := f.db.GetJoinedHostsForRooms(ctx, []string{request.RoomID})
if err != nil { if err != nil {
return return
} }
response.ServerNames = joinedHosts
response.ServerNames = make([]gomatrixserverlib.ServerName, 0, len(joinedHosts))
for _, host := range joinedHosts {
response.ServerNames = append(response.ServerNames, host.ServerName)
}
// TODO: remove duplicates?
return return
} }

View file

@ -24,6 +24,15 @@ const (
// Usage: // Usage:
// hooks.Attach(hooks.KindNewEvent, func(headeredEvent interface{}) { ... }) // hooks.Attach(hooks.KindNewEvent, func(headeredEvent interface{}) { ... })
KindNewEvent = "new_event" KindNewEvent = "new_event"
// KindModifyNewEvent is a hook which is called with *gomatrixserverlib.HeaderedEvent
// It is run before a new event is processed by the roomserver. This hook can be used
// to modify the event before it is persisted by adding data to `unsigned`.
// Usage:
// hooks.Attach(hooks.KindModifyNewEvent, func(headeredEvent interface{}) {
// ev := headeredEvent.(*gomatrixserverlib.HeaderedEvent)
// _ = ev.SetUnsignedField("key", "val")
// })
KindModifyNewEvent = "modify_new_event"
) )
var ( var (

View file

@ -22,6 +22,7 @@ import (
"net/http" "net/http"
"github.com/matrix-org/dendrite/clientapi/jsonerror" "github.com/matrix-org/dendrite/clientapi/jsonerror"
fs "github.com/matrix-org/dendrite/federationsender/api"
"github.com/matrix-org/dendrite/internal/hooks" "github.com/matrix-org/dendrite/internal/hooks"
"github.com/matrix-org/dendrite/internal/httputil" "github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/dendrite/internal/setup" "github.com/matrix-org/dendrite/internal/setup"
@ -31,7 +32,11 @@ import (
"github.com/matrix-org/util" "github.com/matrix-org/util"
) )
const constRelType = "m.reference" const (
constRelType = "m.reference"
constRoomIDKey = "relationship_room_id"
constRoomServers = "relationship_servers"
)
type EventRelationshipRequest struct { type EventRelationshipRequest struct {
EventID string `json:"event_id"` EventID string `json:"event_id"`
@ -83,7 +88,7 @@ type EventRelationshipResponse struct {
} }
// Enable this MSC // Enable this MSC
func Enable(base *setup.BaseDendrite, rsAPI roomserver.RoomserverInternalAPI, userAPI userapi.UserInternalAPI) error { func Enable(base *setup.BaseDendrite, rsAPI roomserver.RoomserverInternalAPI, fsAPI fs.FederationSenderInternalAPI, userAPI userapi.UserInternalAPI) error {
db, err := NewDatabase(&base.Cfg.MSCs.Database) db, err := NewDatabase(&base.Cfg.MSCs.Database)
if err != nil { if err != nil {
return fmt.Errorf("Cannot enable MSC2836: %w", err) return fmt.Errorf("Cannot enable MSC2836: %w", err)
@ -98,6 +103,55 @@ func Enable(base *setup.BaseDendrite, rsAPI roomserver.RoomserverInternalAPI, us
) )
} }
}) })
hooks.Attach(hooks.KindModifyNewEvent, func(headeredEvent interface{}) {
he := headeredEvent.(*gomatrixserverlib.HeaderedEvent)
ctx := context.Background()
// we only inject metadata for events our server sends
userID := he.Sender()
_, domain, err := gomatrixserverlib.SplitID('@', userID)
if err != nil {
return
}
if domain != base.Cfg.Global.ServerName {
return
}
// if this event has an m.relationship, add on the room_id and servers to unsigned
parent, child, relType := parentChildEventIDs(he)
if parent == "" || child == "" || relType == "" {
return
}
event, joinedToRoom := getEventIfVisible(ctx, rsAPI, parent, userID)
if !joinedToRoom {
return
}
err = he.SetUnsignedField(constRoomIDKey, event.RoomID())
if err != nil {
util.GetLogger(context.Background()).WithError(err).Warn("Failed to SetUnsignedField")
return
}
var servers []gomatrixserverlib.ServerName
if fsAPI != nil {
var res fs.QueryJoinedHostServerNamesInRoomResponse
err = fsAPI.QueryJoinedHostServerNamesInRoom(ctx, &fs.QueryJoinedHostServerNamesInRoomRequest{
RoomID: event.RoomID(),
}, &res)
if err != nil {
util.GetLogger(context.Background()).WithError(err).Warn("Failed to QueryJoinedHostServerNamesInRoom")
return
}
servers = res.ServerNames
} else {
servers = []gomatrixserverlib.ServerName{
base.Cfg.Global.ServerName,
}
}
err = he.SetUnsignedField(constRoomServers, servers)
if err != nil {
util.GetLogger(context.Background()).WithError(err).Warn("Failed to SetUnsignedField")
return
}
})
base.PublicClientAPIMux.Handle("/unstable/event_relationships", base.PublicClientAPIMux.Handle("/unstable/event_relationships",
httputil.MakeAuthAPI("eventRelationships", userAPI, eventRelationshipHandler(db, rsAPI)), httputil.MakeAuthAPI("eventRelationships", userAPI, eventRelationshipHandler(db, rsAPI)),
@ -264,34 +318,12 @@ func walkThread(
} }
func (rc *reqCtx) getEventIfVisible(eventID string) *gomatrixserverlib.HeaderedEvent { func (rc *reqCtx) getEventIfVisible(eventID string) *gomatrixserverlib.HeaderedEvent {
var queryEventsRes roomserver.QueryEventsByIDResponse event, joinedToRoom := getEventIfVisible(rc.ctx, rc.rsAPI, eventID, rc.userID)
err := rc.rsAPI.QueryEventsByID(rc.ctx, &roomserver.QueryEventsByIDRequest{ if event == nil {
EventIDs: []string{eventID},
}, &queryEventsRes)
if err != nil {
util.GetLogger(rc.ctx).WithError(err).Error("getEventIfVisible: failed to QueryEventsByID")
return nil return nil
} }
if len(queryEventsRes.Events) == 0 { if joinedToRoom {
util.GetLogger(rc.ctx).Infof("event does not exist") return event
return nil // event does not exist
}
event := queryEventsRes.Events[0]
// Allow events if the member is in the room
// TODO: This does not honour history_visibility
// TODO: This does not honour m.room.create content
var queryMembershipRes roomserver.QueryMembershipForUserResponse
err = rc.rsAPI.QueryMembershipForUser(rc.ctx, &roomserver.QueryMembershipForUserRequest{
RoomID: event.RoomID(),
UserID: rc.userID,
}, &queryMembershipRes)
if err != nil {
util.GetLogger(rc.ctx).WithError(err).Error("getEventIfVisible: failed to QueryMembershipForUser")
return nil
}
if queryMembershipRes.IsInRoom {
return &event
} }
if rc.req.AutoJoin { if rc.req.AutoJoin {
var joinRes roomserver.PerformJoinResponse var joinRes roomserver.PerformJoinResponse
@ -305,12 +337,42 @@ func (rc *reqCtx) getEventIfVisible(eventID string) *gomatrixserverlib.HeaderedE
util.GetLogger(rc.ctx).WithError(joinRes.Error).WithField("room_id", event.RoomID()).Error("Failed to auto-join room") util.GetLogger(rc.ctx).WithError(joinRes.Error).WithField("room_id", event.RoomID()).Error("Failed to auto-join room")
return nil return nil
} }
return &event return event
} }
util.GetLogger(rc.ctx).Infof("user not in room and auto_join disabled") util.GetLogger(rc.ctx).Infof("user not in room and auto_join disabled")
return nil return nil
} }
func getEventIfVisible(ctx context.Context, rsAPI roomserver.RoomserverInternalAPI, eventID, userID string) (*gomatrixserverlib.HeaderedEvent, bool) {
var queryEventsRes roomserver.QueryEventsByIDResponse
err := rsAPI.QueryEventsByID(ctx, &roomserver.QueryEventsByIDRequest{
EventIDs: []string{eventID},
}, &queryEventsRes)
if err != nil {
util.GetLogger(ctx).WithError(err).Error("getEventIfVisible: failed to QueryEventsByID")
return nil, false
}
if len(queryEventsRes.Events) == 0 {
util.GetLogger(ctx).Infof("event does not exist")
return nil, false // event does not exist
}
event := queryEventsRes.Events[0]
// Allow events if the member is in the room
// TODO: This does not honour history_visibility
// TODO: This does not honour m.room.create content
var queryMembershipRes roomserver.QueryMembershipForUserResponse
err = rsAPI.QueryMembershipForUser(ctx, &roomserver.QueryMembershipForUserRequest{
RoomID: event.RoomID(),
UserID: userID,
}, &queryMembershipRes)
if err != nil {
util.GetLogger(ctx).WithError(err).Error("getEventIfVisible: failed to QueryMembershipForUser")
return nil, false
}
return &event, queryMembershipRes.IsInRoom
}
type walkInfo struct { type walkInfo struct {
eventInfo eventInfo
SiblingNumber int SiblingNumber int

View file

@ -35,7 +35,7 @@ func Enable(base *setup.BaseDendrite, monolith *setup.Monolith) error {
func EnableMSC(base *setup.BaseDendrite, monolith *setup.Monolith, msc string) error { func EnableMSC(base *setup.BaseDendrite, monolith *setup.Monolith, msc string) error {
switch msc { switch msc {
case "msc2836": case "msc2836":
return msc2836.Enable(base, monolith.RoomserverAPI, monolith.UserAPI) return msc2836.Enable(base, monolith.RoomserverAPI, monolith.FederationSenderAPI, monolith.UserAPI)
default: default:
return fmt.Errorf("EnableMSC: unknown msc '%s'", msc) return fmt.Errorf("EnableMSC: unknown msc '%s'", msc)
} }

View file

@ -62,6 +62,7 @@ func (w *inputWorker) start() {
for { for {
select { select {
case task := <-w.input: case task := <-w.input:
hooks.Run(hooks.KindModifyNewEvent, &task.event.Event)
_, task.err = w.r.processRoomEvent(task.ctx, task.event) _, task.err = w.r.processRoomEvent(task.ctx, task.event)
if task.err == nil { if task.err == nil {
hooks.Run(hooks.KindNewEvent, &task.event.Event) hooks.Run(hooks.KindNewEvent, &task.event.Event)