From 2b34f88fde6b3aa633c8f23ff424a5db4951efd3 Mon Sep 17 00:00:00 2001 From: kegsay Date: Thu, 4 May 2023 11:17:42 +0100 Subject: [PATCH] Use ProtoEvent where needed instead of EventBuilder (#3075) They are fundamentally different concepts, so should be represented as such. Proto events are exchanged in /make_xxx calls over federation, and made as "fledgling" events in /createRoom and general event sending. *Building* events is a reasonably complex VERSION SPECIFIC process which needs amongst other things, auth event providers, prev events, signing keys, etc. Requires https://github.com/matrix-org/gomatrixserverlib/pull/379 --- clientapi/routing/createroom.go | 18 +++++-- clientapi/routing/membership.go | 6 +-- clientapi/routing/profile.go | 6 +-- clientapi/routing/redaction.go | 8 ++-- clientapi/routing/sendevent.go | 8 ++-- clientapi/threepid/invites.go | 6 +-- federationapi/federationapi_test.go | 4 +- federationapi/internal/perform.go | 11 +++-- federationapi/routing/join.go | 8 ++-- federationapi/routing/leave.go | 10 ++-- federationapi/routing/threepid.go | 48 +++++++++++-------- go.mod | 2 +- go.sum | 2 + internal/eventutil/events.go | 28 ++++++----- roomserver/internal/alias.go | 6 +-- roomserver/internal/input/input_events.go | 4 +- roomserver/internal/perform/perform_admin.go | 12 ++--- roomserver/internal/perform/perform_join.go | 8 ++-- roomserver/internal/perform/perform_leave.go | 12 ++--- .../internal/perform/perform_upgrade.go | 37 +++++++++----- roomserver/roomserver_test.go | 7 +-- setup/mscs/msc2836/msc2836_test.go | 6 +-- test/room.go | 14 ++---- 23 files changed, 152 insertions(+), 119 deletions(-) diff --git a/clientapi/routing/createroom.go b/clientapi/routing/createroom.go index c586474d..abf5b4f4 100644 --- a/clientapi/routing/createroom.go +++ b/clientapi/routing/createroom.go @@ -433,18 +433,26 @@ func createRoom( // TODO: invite events // TODO: 3pid invite events + verImpl, err := gomatrixserverlib.GetRoomVersion(roomVersion) + if err != nil { + return util.JSONResponse{ + Code: http.StatusBadRequest, + JSON: jsonerror.BadJSON("unknown room version"), + } + } + var builtEvents []*types.HeaderedEvent authEvents := gomatrixserverlib.NewAuthEvents(nil) for i, e := range eventsToMake { depth := i + 1 // depth starts at 1 - builder := gomatrixserverlib.EventBuilder{ + builder := verImpl.NewEventBuilderFromProtoEvent(&gomatrixserverlib.ProtoEvent{ Sender: userID, RoomID: roomID, Type: e.Type, StateKey: &e.StateKey, Depth: int64(depth), - } + }) err = builder.SetContent(e.Content) if err != nil { util.GetLogger(ctx).WithError(err).Error("builder.SetContent failed") @@ -454,7 +462,11 @@ func createRoom( builder.PrevEvents = []gomatrixserverlib.EventReference{builtEvents[i-1].EventReference()} } var ev gomatrixserverlib.PDU - ev, err = builder.AddAuthEventsAndBuild(userDomain, &authEvents, evTime, roomVersion, cfg.Matrix.KeyID, cfg.Matrix.PrivateKey) + if err = builder.AddAuthEvents(&authEvents); err != nil { + util.GetLogger(ctx).WithError(err).Error("AddAuthEvents failed") + return jsonerror.InternalServerError() + } + ev, err = builder.Build(evTime, userDomain, cfg.Matrix.KeyID, cfg.Matrix.PrivateKey) if err != nil { util.GetLogger(ctx).WithError(err).Error("buildEvent failed") return jsonerror.InternalServerError() diff --git a/clientapi/routing/membership.go b/clientapi/routing/membership.go index a4aa963a..d696f2b1 100644 --- a/clientapi/routing/membership.go +++ b/clientapi/routing/membership.go @@ -313,7 +313,7 @@ func buildMembershipEvent( return nil, err } - builder := gomatrixserverlib.EventBuilder{ + proto := gomatrixserverlib.ProtoEvent{ Sender: device.UserID, RoomID: roomID, Type: "m.room.member", @@ -328,7 +328,7 @@ func buildMembershipEvent( IsDirect: isDirect, } - if err = builder.SetContent(content); err != nil { + if err = proto.SetContent(content); err != nil { return nil, err } @@ -337,7 +337,7 @@ func buildMembershipEvent( return nil, err } - return eventutil.QueryAndBuildEvent(ctx, &builder, cfg.Matrix, identity, evTime, rsAPI, nil) + return eventutil.QueryAndBuildEvent(ctx, &proto, cfg.Matrix, identity, evTime, rsAPI, nil) } // loadProfile lookups the profile of a given user from the database and returns diff --git a/clientapi/routing/profile.go b/clientapi/routing/profile.go index 9ccd1be2..765ad7cb 100644 --- a/clientapi/routing/profile.go +++ b/clientapi/routing/profile.go @@ -339,7 +339,7 @@ func buildMembershipEvents( evs := []*types.HeaderedEvent{} for _, roomID := range roomIDs { - builder := gomatrixserverlib.EventBuilder{ + proto := gomatrixserverlib.ProtoEvent{ Sender: userID, RoomID: roomID, Type: "m.room.member", @@ -353,7 +353,7 @@ func buildMembershipEvents( content.DisplayName = newProfile.DisplayName content.AvatarURL = newProfile.AvatarURL - if err := builder.SetContent(content); err != nil { + if err := proto.SetContent(content); err != nil { return nil, err } @@ -362,7 +362,7 @@ func buildMembershipEvents( return nil, err } - event, err := eventutil.QueryAndBuildEvent(ctx, &builder, cfg.Matrix, identity, evTime, rsAPI, nil) + event, err := eventutil.QueryAndBuildEvent(ctx, &proto, cfg.Matrix, identity, evTime, rsAPI, nil) if err != nil { return nil, err } diff --git a/clientapi/routing/redaction.go b/clientapi/routing/redaction.go index c433110e..a65cf673 100644 --- a/clientapi/routing/redaction.go +++ b/clientapi/routing/redaction.go @@ -113,15 +113,15 @@ func SendRedaction( } // create the new event and set all the fields we can - builder := gomatrixserverlib.EventBuilder{ + proto := gomatrixserverlib.ProtoEvent{ Sender: device.UserID, RoomID: roomID, Type: spec.MRoomRedaction, Redacts: eventID, } - err := builder.SetContent(r) + err := proto.SetContent(r) if err != nil { - util.GetLogger(req.Context()).WithError(err).Error("builder.SetContent failed") + util.GetLogger(req.Context()).WithError(err).Error("proto.SetContent failed") return jsonerror.InternalServerError() } @@ -131,7 +131,7 @@ func SendRedaction( } var queryRes roomserverAPI.QueryLatestEventsAndStateResponse - e, err := eventutil.QueryAndBuildEvent(req.Context(), &builder, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes) + e, err := eventutil.QueryAndBuildEvent(req.Context(), &proto, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes) if err == eventutil.ErrRoomNoExists { return util.JSONResponse{ Code: http.StatusNotFound, diff --git a/clientapi/routing/sendevent.go b/clientapi/routing/sendevent.go index 2d22d801..7e5918f2 100644 --- a/clientapi/routing/sendevent.go +++ b/clientapi/routing/sendevent.go @@ -264,15 +264,15 @@ func generateSendEvent( userID := device.UserID // create the new event and set all the fields we can - builder := gomatrixserverlib.EventBuilder{ + proto := gomatrixserverlib.ProtoEvent{ Sender: userID, RoomID: roomID, Type: eventType, StateKey: stateKey, } - err := builder.SetContent(r) + err := proto.SetContent(r) if err != nil { - util.GetLogger(ctx).WithError(err).Error("builder.SetContent failed") + util.GetLogger(ctx).WithError(err).Error("proto.SetContent failed") resErr := jsonerror.InternalServerError() return nil, &resErr } @@ -284,7 +284,7 @@ func generateSendEvent( } var queryRes api.QueryLatestEventsAndStateResponse - e, err := eventutil.QueryAndBuildEvent(ctx, &builder, cfg.Matrix, identity, evTime, rsAPI, &queryRes) + e, err := eventutil.QueryAndBuildEvent(ctx, &proto, cfg.Matrix, identity, evTime, rsAPI, &queryRes) if err == eventutil.ErrRoomNoExists { return nil, &util.JSONResponse{ Code: http.StatusNotFound, diff --git a/clientapi/threepid/invites.go b/clientapi/threepid/invites.go index 21940575..2e9c1261 100644 --- a/clientapi/threepid/invites.go +++ b/clientapi/threepid/invites.go @@ -335,7 +335,7 @@ func emit3PIDInviteEvent( rsAPI api.ClientRoomserverAPI, evTime time.Time, ) error { - builder := &gomatrixserverlib.EventBuilder{ + proto := &gomatrixserverlib.ProtoEvent{ Sender: device.UserID, RoomID: roomID, Type: "m.room.third_party_invite", @@ -350,7 +350,7 @@ func emit3PIDInviteEvent( PublicKeys: res.PublicKeys, } - if err := builder.SetContent(content); err != nil { + if err := proto.SetContent(content); err != nil { return err } @@ -360,7 +360,7 @@ func emit3PIDInviteEvent( } queryRes := api.QueryLatestEventsAndStateResponse{} - event, err := eventutil.QueryAndBuildEvent(ctx, builder, cfg.Matrix, identity, evTime, rsAPI, &queryRes) + event, err := eventutil.QueryAndBuildEvent(ctx, proto, cfg.Matrix, identity, evTime, rsAPI, &queryRes) if err != nil { return err } diff --git a/federationapi/federationapi_test.go b/federationapi/federationapi_test.go index aa96dacc..bd49c530 100644 --- a/federationapi/federationapi_test.go +++ b/federationapi/federationapi_test.go @@ -113,7 +113,7 @@ func (f *fedClient) MakeJoin(ctx context.Context, origin, s spec.ServerName, roo for _, r := range f.allowJoins { if r.ID == roomID { res.RoomVersion = r.Version - res.JoinEvent = gomatrixserverlib.EventBuilder{ + res.JoinEvent = gomatrixserverlib.ProtoEvent{ Sender: userID, RoomID: roomID, Type: "m.room.member", @@ -122,7 +122,7 @@ func (f *fedClient) MakeJoin(ctx context.Context, origin, s spec.ServerName, roo PrevEvents: r.ForwardExtremities(), } var needed gomatrixserverlib.StateNeeded - needed, err = gomatrixserverlib.StateNeededForEventBuilder(&res.JoinEvent) + needed, err = gomatrixserverlib.StateNeededForProtoEvent(&res.JoinEvent) if err != nil { f.t.Errorf("StateNeededForEventBuilder: %v", err) return diff --git a/federationapi/internal/perform.go b/federationapi/internal/perform.go index f55995ca..99943d86 100644 --- a/federationapi/internal/perform.go +++ b/federationapi/internal/perform.go @@ -439,7 +439,7 @@ func (r *FederationInternalAPI) PerformLeave( // Work out if we support the room version that has been supplied in // the make_leave response. - _, err = gomatrixserverlib.GetRoomVersion(respMakeLeave.RoomVersion) + verImpl, err := gomatrixserverlib.GetRoomVersion(respMakeLeave.RoomVersion) if err != nil { return err } @@ -451,27 +451,28 @@ func (r *FederationInternalAPI) PerformLeave( respMakeLeave.LeaveEvent.StateKey = &request.UserID respMakeLeave.LeaveEvent.RoomID = request.RoomID respMakeLeave.LeaveEvent.Redacts = "" + leaveEB := verImpl.NewEventBuilderFromProtoEvent(&respMakeLeave.LeaveEvent) + if respMakeLeave.LeaveEvent.Content == nil { content := map[string]interface{}{ "membership": "leave", } - if err = respMakeLeave.LeaveEvent.SetContent(content); err != nil { + if err = leaveEB.SetContent(content); err != nil { logrus.WithError(err).Warnf("respMakeLeave.LeaveEvent.SetContent failed") continue } } - if err = respMakeLeave.LeaveEvent.SetUnsigned(struct{}{}); err != nil { + if err = leaveEB.SetUnsigned(struct{}{}); err != nil { logrus.WithError(err).Warnf("respMakeLeave.LeaveEvent.SetUnsigned failed") continue } // Build the leave event. - event, err := respMakeLeave.LeaveEvent.Build( + event, err := leaveEB.Build( time.Now(), origin, r.cfg.Matrix.KeyID, r.cfg.Matrix.PrivateKey, - respMakeLeave.RoomVersion, ) if err != nil { logrus.WithError(err).Warnf("respMakeLeave.LeaveEvent.Build failed") diff --git a/federationapi/routing/join.go b/federationapi/routing/join.go index a67262da..c68a6f0c 100644 --- a/federationapi/routing/join.go +++ b/federationapi/routing/join.go @@ -118,7 +118,7 @@ func MakeJoin( } // Try building an event for the server - builder := gomatrixserverlib.EventBuilder{ + proto := gomatrixserverlib.ProtoEvent{ Sender: userID, RoomID: roomID, Type: "m.room.member", @@ -128,7 +128,7 @@ func MakeJoin( Membership: spec.Join, AuthorisedVia: authorisedVia, } - if err = builder.SetContent(content); err != nil { + if err = proto.SetContent(content); err != nil { util.GetLogger(httpReq.Context()).WithError(err).Error("builder.SetContent failed") return jsonerror.InternalServerError() } @@ -146,7 +146,7 @@ func MakeJoin( queryRes := api.QueryLatestEventsAndStateResponse{ RoomVersion: roomVersion, } - event, err := eventutil.QueryAndBuildEvent(httpReq.Context(), &builder, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes) + event, err := eventutil.QueryAndBuildEvent(httpReq.Context(), &proto, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes) if err == eventutil.ErrRoomNoExists { return util.JSONResponse{ Code: http.StatusNotFound, @@ -179,7 +179,7 @@ func MakeJoin( return util.JSONResponse{ Code: http.StatusOK, JSON: map[string]interface{}{ - "event": builder, + "event": proto, "room_version": roomVersion, }, } diff --git a/federationapi/routing/leave.go b/federationapi/routing/leave.go index da677d5d..f4936d4a 100644 --- a/federationapi/routing/leave.go +++ b/federationapi/routing/leave.go @@ -52,15 +52,15 @@ func MakeLeave( } // Try building an event for the server - builder := gomatrixserverlib.EventBuilder{ + proto := gomatrixserverlib.ProtoEvent{ Sender: userID, RoomID: roomID, Type: "m.room.member", StateKey: &userID, } - err = builder.SetContent(map[string]interface{}{"membership": spec.Leave}) + err = proto.SetContent(map[string]interface{}{"membership": spec.Leave}) if err != nil { - util.GetLogger(httpReq.Context()).WithError(err).Error("builder.SetContent failed") + util.GetLogger(httpReq.Context()).WithError(err).Error("proto.SetContent failed") return jsonerror.InternalServerError() } @@ -75,7 +75,7 @@ func MakeLeave( } var queryRes api.QueryLatestEventsAndStateResponse - event, err := eventutil.QueryAndBuildEvent(httpReq.Context(), &builder, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes) + event, err := eventutil.QueryAndBuildEvent(httpReq.Context(), &proto, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes) if err == eventutil.ErrRoomNoExists { return util.JSONResponse{ Code: http.StatusNotFound, @@ -126,7 +126,7 @@ func MakeLeave( Code: http.StatusOK, JSON: map[string]interface{}{ "room_version": event.Version(), - "event": builder, + "event": proto, }, } } diff --git a/federationapi/routing/threepid.go b/federationapi/routing/threepid.go index 8f26d53d..244553ba 100644 --- a/federationapi/routing/threepid.go +++ b/federationapi/routing/threepid.go @@ -121,8 +121,8 @@ func ExchangeThirdPartyInvite( cfg *config.FederationAPI, federation fclient.FederationClient, ) util.JSONResponse { - var builder gomatrixserverlib.EventBuilder - if err := json.Unmarshal(request.Content(), &builder); err != nil { + var proto gomatrixserverlib.ProtoEvent + if err := json.Unmarshal(request.Content(), &proto); err != nil { return util.JSONResponse{ Code: http.StatusBadRequest, JSON: jsonerror.NotJSON("The request body could not be decoded into valid JSON. " + err.Error()), @@ -130,14 +130,14 @@ func ExchangeThirdPartyInvite( } // Check that the room ID is correct. - if builder.RoomID != roomID { + if proto.RoomID != roomID { return util.JSONResponse{ Code: http.StatusBadRequest, JSON: jsonerror.BadJSON("The room ID in the request path must match the room ID in the invite event JSON"), } } - _, senderDomain, err := cfg.Matrix.SplitLocalID('@', builder.Sender) + _, senderDomain, err := cfg.Matrix.SplitLocalID('@', proto.Sender) if err != nil { return util.JSONResponse{ Code: http.StatusBadRequest, @@ -146,7 +146,7 @@ func ExchangeThirdPartyInvite( } // Check that the state key is correct. - _, targetDomain, err := gomatrixserverlib.SplitID('@', *builder.StateKey) + _, targetDomain, err := gomatrixserverlib.SplitID('@', *proto.StateKey) if err != nil { return util.JSONResponse{ Code: http.StatusBadRequest, @@ -171,7 +171,7 @@ func ExchangeThirdPartyInvite( } // Auth and build the event from what the remote server sent us - event, err := buildMembershipEvent(httpReq.Context(), &builder, rsAPI, cfg) + event, err := buildMembershipEvent(httpReq.Context(), &proto, rsAPI, cfg) if err == errNotInRoom { return util.JSONResponse{ Code: http.StatusNotFound, @@ -248,7 +248,7 @@ func createInviteFrom3PIDInvite( } // Build the event - builder := &gomatrixserverlib.EventBuilder{ + proto := &gomatrixserverlib.ProtoEvent{ Type: "m.room.member", Sender: inv.Sender, RoomID: inv.RoomID, @@ -269,13 +269,13 @@ func createInviteFrom3PIDInvite( }, } - if err = builder.SetContent(content); err != nil { + if err = proto.SetContent(content); err != nil { return nil, err } - event, err := buildMembershipEvent(ctx, builder, rsAPI, cfg) + event, err := buildMembershipEvent(ctx, proto, rsAPI, cfg) if err == errNotInRoom { - return nil, sendToRemoteServer(ctx, inv, federation, cfg, *builder) + return nil, sendToRemoteServer(ctx, inv, federation, cfg, *proto) } if err != nil { return nil, err @@ -291,10 +291,10 @@ func createInviteFrom3PIDInvite( // Returns an error if something failed during the process. func buildMembershipEvent( ctx context.Context, - builder *gomatrixserverlib.EventBuilder, rsAPI api.FederationRoomserverAPI, + protoEvent *gomatrixserverlib.ProtoEvent, rsAPI api.FederationRoomserverAPI, cfg *config.FederationAPI, ) (gomatrixserverlib.PDU, error) { - eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(builder) + eventsNeeded, err := gomatrixserverlib.StateNeededForProtoEvent(protoEvent) if err != nil { return nil, err } @@ -305,7 +305,7 @@ func buildMembershipEvent( // Ask the roomserver for information about this room queryReq := api.QueryLatestEventsAndStateRequest{ - RoomID: builder.RoomID, + RoomID: protoEvent.RoomID, StateToFetch: eventsNeeded.Tuples(), } var queryRes api.QueryLatestEventsAndStateResponse @@ -319,8 +319,8 @@ func buildMembershipEvent( } // Auth the event locally - builder.Depth = queryRes.Depth - builder.PrevEvents = queryRes.LatestEvents + protoEvent.Depth = queryRes.Depth + protoEvent.PrevEvents = queryRes.LatestEvents authEvents := gomatrixserverlib.NewAuthEvents(nil) @@ -331,7 +331,7 @@ func buildMembershipEvent( } } - if err = fillDisplayName(builder, authEvents); err != nil { + if err = fillDisplayName(protoEvent, authEvents); err != nil { return nil, err } @@ -339,11 +339,17 @@ func buildMembershipEvent( if err != nil { return nil, err } - builder.AuthEvents = refs + protoEvent.AuthEvents = refs + + verImpl, err := gomatrixserverlib.GetRoomVersion(queryRes.RoomVersion) + if err != nil { + return nil, err + } + builder := verImpl.NewEventBuilderFromProtoEvent(protoEvent) event, err := builder.Build( time.Now(), cfg.Matrix.ServerName, cfg.Matrix.KeyID, - cfg.Matrix.PrivateKey, queryRes.RoomVersion, + cfg.Matrix.PrivateKey, ) return event, err @@ -357,7 +363,7 @@ func buildMembershipEvent( func sendToRemoteServer( ctx context.Context, inv invite, federation fclient.FederationClient, cfg *config.FederationAPI, - builder gomatrixserverlib.EventBuilder, + proto gomatrixserverlib.ProtoEvent, ) (err error) { remoteServers := make([]spec.ServerName, 2) _, remoteServers[0], err = gomatrixserverlib.SplitID('@', inv.Sender) @@ -372,7 +378,7 @@ func sendToRemoteServer( } for _, server := range remoteServers { - err = federation.ExchangeThirdPartyInvite(ctx, cfg.Matrix.ServerName, server, builder) + err = federation.ExchangeThirdPartyInvite(ctx, cfg.Matrix.ServerName, server, proto) if err == nil { return } @@ -393,7 +399,7 @@ func sendToRemoteServer( // found. Returning an error isn't necessary in this case as the event will be // rejected by gomatrixserverlib. func fillDisplayName( - builder *gomatrixserverlib.EventBuilder, authEvents gomatrixserverlib.AuthEvents, + builder *gomatrixserverlib.ProtoEvent, authEvents gomatrixserverlib.AuthEvents, ) error { var content gomatrixserverlib.MemberContent if err := json.Unmarshal(builder.Content, &content); err != nil { diff --git a/go.mod b/go.mod index 0ea75ad3..c418faa4 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/matrix-org/dugong v0.0.0-20210921133753-66e6b1c67e2e github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 - github.com/matrix-org/gomatrixserverlib v0.0.0-20230503081352-9e29bff996eb + github.com/matrix-org/gomatrixserverlib v0.0.0-20230504085954-69034410deb1 github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 github.com/mattn/go-sqlite3 v1.14.16 diff --git a/go.sum b/go.sum index 123ec6e3..502dcea3 100644 --- a/go.sum +++ b/go.sum @@ -333,6 +333,8 @@ github.com/matrix-org/gomatrixserverlib v0.0.0-20230502133856-ad26780a085c h1:5x github.com/matrix-org/gomatrixserverlib v0.0.0-20230502133856-ad26780a085c/go.mod h1:7HTbSZe+CIdmeqVyFMekwD5dFU8khWQyngKATvd12FU= github.com/matrix-org/gomatrixserverlib v0.0.0-20230503081352-9e29bff996eb h1:qg9iR39ctvB7A4hBcddjxmHQO/t3y4mpQnpmEc3xvNI= github.com/matrix-org/gomatrixserverlib v0.0.0-20230503081352-9e29bff996eb/go.mod h1:7HTbSZe+CIdmeqVyFMekwD5dFU8khWQyngKATvd12FU= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230504085954-69034410deb1 h1:K0wM4rUNdqzWVQ54am8IeQn1q6f03sTNvhUW+ZaK1Zs= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230504085954-69034410deb1/go.mod h1:7HTbSZe+CIdmeqVyFMekwD5dFU8khWQyngKATvd12FU= github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a h1:awrPDf9LEFySxTLKYBMCiObelNx/cBuv/wzllvCCH3A= github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a/go.mod h1:HchJX9oKMXaT2xYFs0Ha/6Zs06mxLU8k6F1ODnrGkeQ= github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y= diff --git a/internal/eventutil/events.go b/internal/eventutil/events.go index 1d727ec4..dff45968 100644 --- a/internal/eventutil/events.go +++ b/internal/eventutil/events.go @@ -41,7 +41,7 @@ var ErrRoomNoExists = errors.New("room does not exist") // Returns an error if something else went wrong func QueryAndBuildEvent( ctx context.Context, - builder *gomatrixserverlib.EventBuilder, cfg *config.Global, + proto *gomatrixserverlib.ProtoEvent, cfg *config.Global, identity *fclient.SigningIdentity, evTime time.Time, rsAPI api.QueryLatestEventsAndStateAPI, queryRes *api.QueryLatestEventsAndStateResponse, ) (*types.HeaderedEvent, error) { @@ -49,29 +49,35 @@ func QueryAndBuildEvent( queryRes = &api.QueryLatestEventsAndStateResponse{} } - eventsNeeded, err := queryRequiredEventsForBuilder(ctx, builder, rsAPI, queryRes) + eventsNeeded, err := queryRequiredEventsForBuilder(ctx, proto, rsAPI, queryRes) if err != nil { // This can pass through a ErrRoomNoExists to the caller return nil, err } - return BuildEvent(ctx, builder, cfg, identity, evTime, eventsNeeded, queryRes) + return BuildEvent(ctx, proto, cfg, identity, evTime, eventsNeeded, queryRes) } // BuildEvent builds a Matrix event from the builder and QueryLatestEventsAndStateResponse // provided. func BuildEvent( ctx context.Context, - builder *gomatrixserverlib.EventBuilder, cfg *config.Global, + proto *gomatrixserverlib.ProtoEvent, cfg *config.Global, identity *fclient.SigningIdentity, evTime time.Time, eventsNeeded *gomatrixserverlib.StateNeeded, queryRes *api.QueryLatestEventsAndStateResponse, ) (*types.HeaderedEvent, error) { - if err := addPrevEventsToEvent(builder, eventsNeeded, queryRes); err != nil { + if err := addPrevEventsToEvent(proto, eventsNeeded, queryRes); err != nil { return nil, err } + verImpl, err := gomatrixserverlib.GetRoomVersion(queryRes.RoomVersion) + if err != nil { + return nil, err + } + builder := verImpl.NewEventBuilderFromProtoEvent(proto) + event, err := builder.Build( evTime, identity.ServerName, identity.KeyID, - identity.PrivateKey, queryRes.RoomVersion, + identity.PrivateKey, ) if err != nil { return nil, err @@ -83,12 +89,12 @@ func BuildEvent( // queryRequiredEventsForBuilder queries the roomserver for auth/prev events needed for this builder. func queryRequiredEventsForBuilder( ctx context.Context, - builder *gomatrixserverlib.EventBuilder, + proto *gomatrixserverlib.ProtoEvent, rsAPI api.QueryLatestEventsAndStateAPI, queryRes *api.QueryLatestEventsAndStateResponse, ) (*gomatrixserverlib.StateNeeded, error) { - eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(builder) + eventsNeeded, err := gomatrixserverlib.StateNeededForProtoEvent(proto) if err != nil { - return nil, fmt.Errorf("gomatrixserverlib.StateNeededForEventBuilder: %w", err) + return nil, fmt.Errorf("gomatrixserverlib.StateNeededForProtoEvent: %w", err) } if len(eventsNeeded.Tuples()) == 0 { @@ -97,7 +103,7 @@ func queryRequiredEventsForBuilder( // Ask the roomserver for information about this room queryReq := api.QueryLatestEventsAndStateRequest{ - RoomID: builder.RoomID, + RoomID: proto.RoomID, StateToFetch: eventsNeeded.Tuples(), } return &eventsNeeded, rsAPI.QueryLatestEventsAndState(ctx, &queryReq, queryRes) @@ -105,7 +111,7 @@ func queryRequiredEventsForBuilder( // addPrevEventsToEvent fills out the prev_events and auth_events fields in builder func addPrevEventsToEvent( - builder *gomatrixserverlib.EventBuilder, + builder *gomatrixserverlib.ProtoEvent, eventsNeeded *gomatrixserverlib.StateNeeded, queryRes *api.QueryLatestEventsAndStateResponse, ) error { diff --git a/roomserver/internal/alias.go b/roomserver/internal/alias.go index d3ab10f0..4d2de9a5 100644 --- a/roomserver/internal/alias.go +++ b/roomserver/internal/alias.go @@ -187,7 +187,7 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias( return err } - builder := &gomatrixserverlib.EventBuilder{ + proto := &gomatrixserverlib.ProtoEvent{ Sender: sender, RoomID: ev.RoomID(), Type: ev.Type(), @@ -195,7 +195,7 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias( Content: res, } - eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(builder) + eventsNeeded, err := gomatrixserverlib.StateNeededForProtoEvent(proto) if err != nil { return fmt.Errorf("gomatrixserverlib.StateNeededForEventBuilder: %w", err) } @@ -208,7 +208,7 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias( return err } - newEvent, err := eventutil.BuildEvent(ctx, builder, &r.Cfg.Global, identity, time.Now(), &eventsNeeded, stateRes) + newEvent, err := eventutil.BuildEvent(ctx, proto, &r.Cfg.Global, identity, time.Now(), &eventsNeeded, stateRes) if err != nil { return err } diff --git a/roomserver/internal/input/input_events.go b/roomserver/internal/input/input_events.go index 1a472eb9..9ae29c54 100644 --- a/roomserver/internal/input/input_events.go +++ b/roomserver/internal/input/input_events.go @@ -852,7 +852,7 @@ func (r *Inputer) kickGuests(ctx context.Context, event gomatrixserverlib.PDU, r memberContent.Membership = spec.Leave stateKey := *memberEvent.StateKey() - fledglingEvent := &gomatrixserverlib.EventBuilder{ + fledglingEvent := &gomatrixserverlib.ProtoEvent{ RoomID: event.RoomID(), Type: spec.MRoomMember, StateKey: &stateKey, @@ -864,7 +864,7 @@ func (r *Inputer) kickGuests(ctx context.Context, event gomatrixserverlib.PDU, r return err } - eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(fledglingEvent) + eventsNeeded, err := gomatrixserverlib.StateNeededForProtoEvent(fledglingEvent) if err != nil { return err } diff --git a/roomserver/internal/perform/perform_admin.go b/roomserver/internal/perform/perform_admin.go index 59675cd9..70668a20 100644 --- a/roomserver/internal/perform/perform_admin.go +++ b/roomserver/internal/perform/perform_admin.go @@ -92,7 +92,7 @@ func (r *Admin) PerformAdminEvacuateRoom( memberContent.Membership = spec.Leave stateKey := *memberEvent.StateKey() - fledglingEvent := &gomatrixserverlib.EventBuilder{ + fledglingEvent := &gomatrixserverlib.ProtoEvent{ RoomID: roomID, Type: spec.MRoomMember, StateKey: &stateKey, @@ -109,7 +109,7 @@ func (r *Admin) PerformAdminEvacuateRoom( return nil, err } - eventsNeeded, err = gomatrixserverlib.StateNeededForEventBuilder(fledglingEvent) + eventsNeeded, err = gomatrixserverlib.StateNeededForProtoEvent(fledglingEvent) if err != nil { return nil, err } @@ -283,16 +283,16 @@ func (r *Admin) PerformAdminDownloadState( stateIDs = append(stateIDs, stateEvent.EventID()) } - builder := &gomatrixserverlib.EventBuilder{ + proto := &gomatrixserverlib.ProtoEvent{ Type: "org.matrix.dendrite.state_download", Sender: userID, RoomID: roomID, Content: spec.RawJSON("{}"), } - eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(builder) + eventsNeeded, err := gomatrixserverlib.StateNeededForProtoEvent(proto) if err != nil { - return fmt.Errorf("gomatrixserverlib.StateNeededForEventBuilder: %w", err) + return fmt.Errorf("gomatrixserverlib.StateNeededForProtoEvent: %w", err) } queryRes := &api.QueryLatestEventsAndStateResponse{ @@ -308,7 +308,7 @@ func (r *Admin) PerformAdminDownloadState( return err } - ev, err := eventutil.BuildEvent(ctx, builder, r.Cfg.Matrix, identity, time.Now(), &eventsNeeded, queryRes) + ev, err := eventutil.BuildEvent(ctx, proto, r.Cfg.Matrix, identity, time.Now(), &eventsNeeded, queryRes) if err != nil { return fmt.Errorf("eventutil.BuildEvent: %w", err) } diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go index 06cc0d67..d676bd4b 100644 --- a/roomserver/internal/perform/perform_join.go +++ b/roomserver/internal/perform/perform_join.go @@ -180,14 +180,14 @@ func (r *Joiner) performJoinRoomByID( if err != nil { return "", "", rsAPI.ErrInvalidID{Err: fmt.Errorf("user ID %q is invalid: %w", userID, err)} } - eb := gomatrixserverlib.EventBuilder{ + proto := gomatrixserverlib.ProtoEvent{ Type: spec.MRoomMember, Sender: userID, StateKey: &userID, RoomID: req.RoomIDOrAlias, Redacts: "", } - if err = eb.SetUnsigned(struct{}{}); err != nil { + if err = proto.SetUnsigned(struct{}{}); err != nil { return "", "", fmt.Errorf("eb.SetUnsigned: %w", err) } @@ -203,7 +203,7 @@ func (r *Joiner) performJoinRoomByID( } else if authorisedVia != "" { req.Content["join_authorised_via_users_server"] = authorisedVia } - if err = eb.SetContent(req.Content); err != nil { + if err = proto.SetContent(req.Content); err != nil { return "", "", fmt.Errorf("eb.SetContent: %w", err) } @@ -284,7 +284,7 @@ func (r *Joiner) performJoinRoomByID( if err != nil { return "", "", fmt.Errorf("error joining local room: %q", err) } - event, err := eventutil.QueryAndBuildEvent(ctx, &eb, r.Cfg.Matrix, identity, time.Now(), r.RSAPI, &buildRes) + event, err := eventutil.QueryAndBuildEvent(ctx, &proto, r.Cfg.Matrix, identity, time.Now(), r.RSAPI, &buildRes) switch err { case nil: diff --git a/roomserver/internal/perform/perform_leave.go b/roomserver/internal/perform/perform_leave.go index 1db5707d..f0e95811 100644 --- a/roomserver/internal/perform/perform_leave.go +++ b/roomserver/internal/perform/perform_leave.go @@ -154,24 +154,24 @@ func (r *Leaver) performLeaveRoomByID( // Prepare the template for the leave event. userID := req.UserID - eb := gomatrixserverlib.EventBuilder{ + proto := gomatrixserverlib.ProtoEvent{ Type: spec.MRoomMember, Sender: userID, StateKey: &userID, RoomID: req.RoomID, Redacts: "", } - if err = eb.SetContent(map[string]interface{}{"membership": "leave"}); err != nil { + if err = proto.SetContent(map[string]interface{}{"membership": "leave"}); err != nil { return nil, fmt.Errorf("eb.SetContent: %w", err) } - if err = eb.SetUnsigned(struct{}{}); err != nil { + if err = proto.SetUnsigned(struct{}{}); err != nil { return nil, fmt.Errorf("eb.SetUnsigned: %w", err) } // Get the sender domain. - _, senderDomain, serr := r.Cfg.Matrix.SplitLocalID('@', eb.Sender) + _, senderDomain, serr := r.Cfg.Matrix.SplitLocalID('@', proto.Sender) if serr != nil { - return nil, fmt.Errorf("sender %q is invalid", eb.Sender) + return nil, fmt.Errorf("sender %q is invalid", proto.Sender) } // We know that the user is in the room at this point so let's build @@ -184,7 +184,7 @@ func (r *Leaver) performLeaveRoomByID( if err != nil { return nil, fmt.Errorf("SigningIdentityFor: %w", err) } - event, err := eventutil.QueryAndBuildEvent(ctx, &eb, r.Cfg.Matrix, identity, time.Now(), r.RSAPI, &buildRes) + event, err := eventutil.QueryAndBuildEvent(ctx, &proto, r.Cfg.Matrix, identity, time.Now(), r.RSAPI, &buildRes) if err != nil { return nil, fmt.Errorf("eventutil.QueryAndBuildEvent: %w", err) } diff --git a/roomserver/internal/perform/perform_upgrade.go b/roomserver/internal/perform/perform_upgrade.go index 2085fb37..e88cb1dc 100644 --- a/roomserver/internal/perform/perform_upgrade.go +++ b/roomserver/internal/perform/perform_upgrade.go @@ -459,22 +459,33 @@ func (r *Upgrader) sendInitialEvents(ctx context.Context, evTime time.Time, user for i, e := range eventsToMake { depth := i + 1 // depth starts at 1 - builder := gomatrixserverlib.EventBuilder{ + proto := gomatrixserverlib.ProtoEvent{ Sender: userID, RoomID: newRoomID, Type: e.Type, StateKey: &e.StateKey, Depth: int64(depth), } - err = builder.SetContent(e.Content) + err = proto.SetContent(e.Content) if err != nil { - return fmt.Errorf("failed to set content of new %q event: %w", builder.Type, err) + return fmt.Errorf("failed to set content of new %q event: %w", proto.Type, err) } if i > 0 { - builder.PrevEvents = []gomatrixserverlib.EventReference{builtEvents[i-1].EventReference()} + proto.PrevEvents = []gomatrixserverlib.EventReference{builtEvents[i-1].EventReference()} } + + var verImpl gomatrixserverlib.IRoomVersion + verImpl, err = gomatrixserverlib.GetRoomVersion(newVersion) + if err != nil { + return err + } + builder := verImpl.NewEventBuilderFromProtoEvent(&proto) + if err = builder.AddAuthEvents(&authEvents); err != nil { + return err + } + var event gomatrixserverlib.PDU - event, err = builder.AddAuthEventsAndBuild(userDomain, &authEvents, evTime, newVersion, r.Cfg.Matrix.KeyID, r.Cfg.Matrix.PrivateKey) + event, err = builder.Build(evTime, userDomain, r.Cfg.Matrix.KeyID, r.Cfg.Matrix.PrivateKey) if err != nil { return fmt.Errorf("failed to build new %q event: %w", builder.Type, err) @@ -524,27 +535,27 @@ func (r *Upgrader) makeTombstoneEvent( } func (r *Upgrader) makeHeaderedEvent(ctx context.Context, evTime time.Time, userID, roomID string, event fledglingEvent) (*types.HeaderedEvent, error) { - builder := gomatrixserverlib.EventBuilder{ + proto := gomatrixserverlib.ProtoEvent{ Sender: userID, RoomID: roomID, Type: event.Type, StateKey: &event.StateKey, } - err := builder.SetContent(event.Content) + err := proto.SetContent(event.Content) if err != nil { - return nil, fmt.Errorf("failed to set new %q event content: %w", builder.Type, err) + return nil, fmt.Errorf("failed to set new %q event content: %w", proto.Type, err) } // Get the sender domain. - _, senderDomain, serr := r.Cfg.Matrix.SplitLocalID('@', builder.Sender) + _, senderDomain, serr := r.Cfg.Matrix.SplitLocalID('@', proto.Sender) if serr != nil { - return nil, fmt.Errorf("Failed to split user ID %q: %w", builder.Sender, err) + return nil, fmt.Errorf("Failed to split user ID %q: %w", proto.Sender, err) } identity, err := r.Cfg.Matrix.SigningIdentityFor(senderDomain) if err != nil { return nil, fmt.Errorf("failed to get signing identity for %q: %w", senderDomain, err) } var queryRes api.QueryLatestEventsAndStateResponse - headeredEvent, err := eventutil.QueryAndBuildEvent(ctx, &builder, r.Cfg.Matrix, identity, evTime, r.URSAPI, &queryRes) + headeredEvent, err := eventutil.QueryAndBuildEvent(ctx, &proto, r.Cfg.Matrix, identity, evTime, r.URSAPI, &queryRes) if err == eventutil.ErrRoomNoExists { return nil, err } else if e, ok := err.(gomatrixserverlib.BadJSONError); ok { @@ -552,7 +563,7 @@ func (r *Upgrader) makeHeaderedEvent(ctx context.Context, evTime time.Time, user } else if e, ok := err.(gomatrixserverlib.EventValidationError); ok { return nil, e } else if err != nil { - return nil, fmt.Errorf("failed to build new %q event: %w", builder.Type, err) + return nil, fmt.Errorf("failed to build new %q event: %w", proto.Type, err) } // check to see if this user can perform this operation stateEvents := make([]gomatrixserverlib.PDU, len(queryRes.StateEvents)) @@ -561,7 +572,7 @@ func (r *Upgrader) makeHeaderedEvent(ctx context.Context, evTime time.Time, user } provider := gomatrixserverlib.NewAuthEvents(stateEvents) if err = gomatrixserverlib.Allowed(headeredEvent.PDU, &provider); err != nil { - return nil, api.ErrNotAllowed{Err: fmt.Errorf("failed to auth new %q event: %w", builder.Type, err)} // TODO: Is this error string comprehensible to the client? + return nil, api.ErrNotAllowed{Err: fmt.Errorf("failed to auth new %q event: %w", proto.Type, err)} // TODO: Is this error string comprehensible to the client? } return headeredEvent, nil diff --git a/roomserver/roomserver_test.go b/roomserver/roomserver_test.go index 702432b1..c0f3e12d 100644 --- a/roomserver/roomserver_test.go +++ b/roomserver/roomserver_test.go @@ -404,7 +404,7 @@ func mustCreateEvent(t *testing.T, ev fledglingEvent) (result *types.HeaderedEve roomVer := gomatrixserverlib.RoomVersionV9 seed := make([]byte, ed25519.SeedSize) // zero seed key := ed25519.NewKeyFromSeed(seed) - eb := gomatrixserverlib.EventBuilder{ + eb := gomatrixserverlib.MustGetRoomVersion(roomVer).NewEventBuilderFromProtoEvent(&gomatrixserverlib.ProtoEvent{ Sender: ev.Sender, Type: ev.Type, StateKey: ev.StateKey, @@ -412,12 +412,13 @@ func mustCreateEvent(t *testing.T, ev fledglingEvent) (result *types.HeaderedEve Redacts: ev.Redacts, Depth: ev.Depth, PrevEvents: ev.PrevEvents, - } + }) err := eb.SetContent(map[string]interface{}{}) if err != nil { t.Fatalf("mustCreateEvent: failed to marshal event content %v", err) } - signedEvent, err := eb.Build(time.Now(), "localhost", "ed25519:test", key, roomVer) + + signedEvent, err := eb.Build(time.Now(), "localhost", "ed25519:test", key) if err != nil { t.Fatalf("mustCreateEvent: failed to sign event: %s", err) } diff --git a/setup/mscs/msc2836/msc2836_test.go b/setup/mscs/msc2836/msc2836_test.go index f235cfef..2c6f63d4 100644 --- a/setup/mscs/msc2836/msc2836_test.go +++ b/setup/mscs/msc2836/msc2836_test.go @@ -585,20 +585,20 @@ func mustCreateEvent(t *testing.T, ev fledglingEvent) (result *types.HeaderedEve roomVer := gomatrixserverlib.RoomVersionV6 seed := make([]byte, ed25519.SeedSize) // zero seed key := ed25519.NewKeyFromSeed(seed) - eb := gomatrixserverlib.EventBuilder{ + eb := gomatrixserverlib.MustGetRoomVersion(roomVer).NewEventBuilderFromProtoEvent(&gomatrixserverlib.ProtoEvent{ Sender: ev.Sender, Depth: 999, Type: ev.Type, StateKey: ev.StateKey, RoomID: ev.RoomID, - } + }) err := eb.SetContent(ev.Content) if err != nil { t.Fatalf("mustCreateEvent: failed to marshal event content %+v", ev.Content) } // make sure the origin_server_ts changes so we can test recency time.Sleep(1 * time.Millisecond) - signedEvent, err := eb.Build(time.Now(), spec.ServerName("localhost"), "ed25519:test", key, roomVer) + signedEvent, err := eb.Build(time.Now(), spec.ServerName("localhost"), "ed25519:test", key) if err != nil { t.Fatalf("mustCreateEvent: failed to sign event: %s", err) } diff --git a/test/room.go b/test/room.go index 918123aa..1c0f01e4 100644 --- a/test/room.go +++ b/test/room.go @@ -163,14 +163,14 @@ func (r *Room) CreateEvent(t *testing.T, creator *User, eventType string, conten } } - builder := &gomatrixserverlib.EventBuilder{ + builder := gomatrixserverlib.MustGetRoomVersion(r.Version).NewEventBuilderFromProtoEvent(&gomatrixserverlib.ProtoEvent{ Sender: creator.ID, RoomID: r.ID, Type: eventType, StateKey: mod.stateKey, Depth: int64(depth), Unsigned: unsigned, - } + }) err = builder.SetContent(content) if err != nil { t.Fatalf("CreateEvent[%s]: failed to SetContent: %s", eventType, err) @@ -179,16 +179,10 @@ func (r *Room) CreateEvent(t *testing.T, creator *User, eventType string, conten builder.PrevEvents = []gomatrixserverlib.EventReference{r.events[len(r.events)-1].EventReference()} } - eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(builder) - if err != nil { - t.Fatalf("CreateEvent[%s]: failed to StateNeededForEventBuilder: %s", eventType, err) - } - - refs, err := eventsNeeded.AuthEventReferences(&r.authEvents) + err = builder.AddAuthEvents(&r.authEvents) if err != nil { t.Fatalf("CreateEvent[%s]: failed to AuthEventReferences: %s", eventType, err) } - builder.AuthEvents = refs if len(mod.authEvents) > 0 { builder.AuthEvents = mod.authEvents @@ -196,7 +190,7 @@ func (r *Room) CreateEvent(t *testing.T, creator *User, eventType string, conten ev, err := builder.Build( mod.originServerTS, mod.origin, mod.keyID, - mod.privKey, r.Version, + mod.privKey, ) if err != nil { t.Fatalf("CreateEvent[%s]: failed to build event: %s", eventType, err)