From d63685af4c5677c3faee657e0c6dea43faf7eeb3 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Tue, 13 Jun 2023 18:05:28 +0200 Subject: [PATCH 01/21] Add MXIDMapping for pseudoID rooms, also sign with the pseudoIDKey --- .../internal/perform/perform_create_room.go | 101 ++++++++++++------ 1 file changed, 67 insertions(+), 34 deletions(-) diff --git a/roomserver/internal/perform/perform_create_room.go b/roomserver/internal/perform/perform_create_room.go index 121b257edc..d051140bba 100644 --- a/roomserver/internal/perform/perform_create_room.go +++ b/roomserver/internal/perform/perform_create_room.go @@ -16,9 +16,12 @@ package perform import ( "context" + "crypto/ed25519" + "encoding/base64" "encoding/json" "fmt" "net/http" + "strings" "github.com/getsentry/sentry-go" "github.com/matrix-org/dendrite/internal/eventutil" @@ -30,6 +33,7 @@ import ( "github.com/matrix-org/gomatrixserverlib/fclient" "github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/util" + "github.com/sirupsen/logrus" ) const ( @@ -93,6 +97,15 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo } } + _, err = c.DB.AssignRoomNID(ctx, roomID, createRequest.RoomVersion) + if err != nil { + util.GetLogger(ctx).WithError(err).Error("failed to assign roomNID") + return "", &util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{}, + } + } + var guestsCanJoin bool switch createRequest.StatePreset { case spec.PresetPrivateChat: @@ -130,13 +143,59 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo membershipEvent := gomatrixserverlib.FledglingEvent{ Type: spec.MRoomMember, StateKey: string(senderID), - Content: gomatrixserverlib.MemberContent{ - Membership: spec.Join, - DisplayName: createRequest.UserDisplayName, - AvatarURL: createRequest.UserAvatarURL, - }, } + memberContent := gomatrixserverlib.MemberContent{ + Membership: spec.Join, + DisplayName: createRequest.UserDisplayName, + AvatarURL: createRequest.UserAvatarURL, + } + + // get the signing identity + identity, err := c.Cfg.Matrix.SigningIdentityFor(userID.Domain()) + if err != nil { + logrus.WithError(err).WithField("domain", userID.Domain()).Error("unable to find signing identity for domain") + return "", &util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{}, + } + } + + // If we are creating a room with pseudo IDs, create and sign the MXIDMapping + if createRequest.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs { + var pseudoIDKey ed25519.PrivateKey + pseudoIDKey, err = c.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, userID, roomID) + if err != nil { + util.GetLogger(ctx).WithError(err).Error("GetOrCreateUserRoomPrivateKey failed") + return "", &util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{}, + } + } + + mapping := &gomatrixserverlib.MXIDMapping{ + UserRoomKey: strings.ToLower(base64.StdEncoding.WithPadding(base64.NoPadding).EncodeToString(pseudoIDKey.Public().(ed25519.PublicKey))), + UserID: userID.String(), + } + + // Sign the mapping with the server identity + if err = mapping.Sign(identity.ServerName, identity.KeyID, identity.PrivateKey); err != nil { + return "", &util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{}, + } + } + memberContent.MXIDMapping = mapping + + // sign all events with the pseudo ID key + identity = &fclient.SigningIdentity{ + ServerName: userID.Domain(), + KeyID: "self", + PrivateKey: pseudoIDKey, + } + } + membershipEvent.Content = memberContent + var nameEvent *gomatrixserverlib.FledglingEvent var topicEvent *gomatrixserverlib.FledglingEvent var guestAccessEvent *gomatrixserverlib.FledglingEvent @@ -314,7 +373,7 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo JSON: spec.InternalServerError{}, } } - ev, err = builder.Build(createRequest.EventTime, userID.Domain(), createRequest.KeyID, createRequest.PrivateKey) + ev, err = builder.Build(createRequest.EventTime, identity.ServerName, identity.KeyID, identity.PrivateKey) if err != nil { util.GetLogger(ctx).WithError(err).Error("buildEvent failed") return "", &util.JSONResponse{ @@ -355,29 +414,8 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo }) } - // first send the `m.room.create` event, so we have a roomNID - if err = api.SendInputRoomEvents(ctx, c.RSAPI, userID.Domain(), inputs[:1], false); err != nil { - util.GetLogger(ctx).WithError(err).Error("roomserverAPI.SendInputRoomEvents failed") - return "", &util.JSONResponse{ - Code: http.StatusInternalServerError, - JSON: spec.InternalServerError{}, - } - } - - // create user room key if needed - if createRequest.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs { - _, err = c.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, userID, roomID) - if err != nil { - util.GetLogger(ctx).WithError(err).Error("GetOrCreateUserRoomPrivateKey failed") - return "", &util.JSONResponse{ - Code: http.StatusInternalServerError, - JSON: spec.InternalServerError{}, - } - } - } - - // send the remaining events - if err = api.SendInputRoomEvents(ctx, c.RSAPI, userID.Domain(), inputs[1:], false); err != nil { + // send the events to the roomserver + if err = api.SendInputRoomEvents(ctx, c.RSAPI, userID.Domain(), inputs, false); err != nil { util.GetLogger(ctx).WithError(err).Error("roomserverAPI.SendInputRoomEvents failed") return "", &util.JSONResponse{ Code: http.StatusInternalServerError, @@ -487,11 +525,6 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo } // Build the invite event. - identity := &fclient.SigningIdentity{ - ServerName: userID.Domain(), - KeyID: createRequest.KeyID, - PrivateKey: createRequest.PrivateKey, - } inviteEvent, err = eventutil.QueryAndBuildEvent(ctx, &proto, identity, createRequest.EventTime, c.RSAPI, nil) if err != nil { From 781bd80c2ccbf1a8d1f13868c2f1198c85b6bfe7 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Tue, 13 Jun 2023 18:10:39 +0200 Subject: [PATCH 02/21] Update GMSL --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2fbae31482..048b0137cf 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-20230612110349-8e7766804077 + github.com/matrix-org/gomatrixserverlib v0.0.0-20230613155116-96519f6cf88a 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 ef8c298abf..daa3a98a58 100644 --- a/go.sum +++ b/go.sum @@ -323,8 +323,8 @@ github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 h1:s7fexw github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230612110349-8e7766804077 h1:AmKkAUjy9rZA2K+qHXm/O/dPEPnUYfRE2I6SL+Dj+LU= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230612110349-8e7766804077/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230613155116-96519f6cf88a h1:wC3e4IAsjhTnHnxfz4LoxO5Q03YCL7TlMa+EKLQqjOs= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230613155116-96519f6cf88a/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= 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= From 50615c76090b670e651d03a3e1590945dc6d39a5 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Wed, 14 Jun 2023 09:39:32 +0200 Subject: [PATCH 03/21] Sign MXIDMapping for join events --- go.mod | 2 +- go.sum | 4 +- roomserver/api/query.go | 2 + .../internal/perform/perform_create_room.go | 4 +- roomserver/internal/perform/perform_join.go | 48 ++++++++++++++----- roomserver/internal/query/query.go | 3 ++ roomserver/storage/shared/storage.go | 1 + 7 files changed, 46 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 048b0137cf..932c16e667 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-20230613155116-96519f6cf88a + github.com/matrix-org/gomatrixserverlib v0.0.0-20230614073341-8d0345fcba4e 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 daa3a98a58..ce790551af 100644 --- a/go.sum +++ b/go.sum @@ -323,8 +323,8 @@ github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 h1:s7fexw github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230613155116-96519f6cf88a h1:wC3e4IAsjhTnHnxfz4LoxO5Q03YCL7TlMa+EKLQqjOs= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230613155116-96519f6cf88a/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230614073341-8d0345fcba4e h1:ZCPgtte0nLiqzS9x7Et4jVAnOGLEszijsH0Xi9h/CJA= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230614073341-8d0345fcba4e/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= 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/roomserver/api/query.go b/roomserver/api/query.go index 684a5b0e3d..b6140afd56 100644 --- a/roomserver/api/query.go +++ b/roomserver/api/query.go @@ -174,6 +174,8 @@ type QueryServerJoinedToRoomResponse struct { RoomExists bool `json:"room_exists"` // True if we still believe that the server is participating in the room IsInRoom bool `json:"is_in_room"` + // The roomversion if joined to room + RoomVersion gomatrixserverlib.RoomVersion } // QueryServerAllowedToSeeEventRequest is a request to QueryServerAllowedToSeeEvent diff --git a/roomserver/internal/perform/perform_create_room.go b/roomserver/internal/perform/perform_create_room.go index d051140bba..02ea6edd57 100644 --- a/roomserver/internal/perform/perform_create_room.go +++ b/roomserver/internal/perform/perform_create_room.go @@ -17,11 +17,9 @@ package perform import ( "context" "crypto/ed25519" - "encoding/base64" "encoding/json" "fmt" "net/http" - "strings" "github.com/getsentry/sentry-go" "github.com/matrix-org/dendrite/internal/eventutil" @@ -174,7 +172,7 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo } mapping := &gomatrixserverlib.MXIDMapping{ - UserRoomKey: strings.ToLower(base64.StdEncoding.WithPadding(base64.NoPadding).EncodeToString(pseudoIDKey.Public().(ed25519.PublicKey))), + UserRoomKey: spec.UserRoomKey(pseudoIDKey), UserID: userID.String(), } diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go index 74ed87c744..b99cc56e8b 100644 --- a/roomserver/internal/perform/perform_join.go +++ b/roomserver/internal/perform/perform_join.go @@ -16,6 +16,7 @@ package perform import ( "context" + "crypto/ed25519" "database/sql" "errors" "fmt" @@ -24,7 +25,9 @@ import ( "github.com/getsentry/sentry-go" "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/gomatrixserverlib/fclient" "github.com/matrix-org/gomatrixserverlib/spec" + "github.com/matrix-org/util" "github.com/sirupsen/logrus" "github.com/tidwall/gjson" @@ -208,9 +211,6 @@ func (r *Joiner) performJoinRoomByID( } else if authorisedVia != "" { req.Content["join_authorised_via_users_server"] = authorisedVia } - if err = proto.SetContent(req.Content); err != nil { - return "", "", fmt.Errorf("eb.SetContent: %w", err) - } // Force a federated join if we aren't in the room and we've been // given some server names to try joining by. @@ -289,19 +289,43 @@ func (r *Joiner) performJoinRoomByID( if err != nil { return "", "", fmt.Errorf("error joining local room: %q", err) } + + // at this point we know we have an existing room + if inRoomRes.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs { + var pseudoIDKey ed25519.PrivateKey + pseudoIDKey, err = r.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, *userID, *roomID) + if err != nil { + util.GetLogger(ctx).WithError(err).Error("GetOrCreateUserRoomPrivateKey failed") + return "", "", err + } + + mapping := &gomatrixserverlib.MXIDMapping{ + UserRoomKey: spec.UserRoomKey(pseudoIDKey), + UserID: userID.String(), + } + + // Sign the mapping with the server identity + if err = mapping.Sign(identity.ServerName, identity.KeyID, identity.PrivateKey); err != nil { + return "", "", err + } + req.Content["mxid_mapping"] = mapping + + // sign the event with the pseudo ID key + identity = &fclient.SigningIdentity{ + ServerName: userID.Domain(), + KeyID: "self", + PrivateKey: pseudoIDKey, + } + } + + if err = proto.SetContent(req.Content); err != nil { + return "", "", fmt.Errorf("eb.SetContent: %w", err) + } + event, err := eventutil.QueryAndBuildEvent(ctx, &proto, identity, time.Now(), r.RSAPI, &buildRes) switch err.(type) { case nil: - // create user room key if needed - if buildRes.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs { - _, err = r.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, *userID, *roomID) - if err != nil { - logrus.WithError(err).Error("GetOrCreateUserRoomPrivateKey failed") - return "", "", fmt.Errorf("failed to get user room private key: %w", err) - } - } - // The room join is local. Send the new join event into the // roomserver. First of all check that the user isn't already // a member of the room. This is best-effort (as in we won't diff --git a/roomserver/internal/query/query.go b/roomserver/internal/query/query.go index caea6b526d..e7ad214b98 100644 --- a/roomserver/internal/query/query.go +++ b/roomserver/internal/query/query.go @@ -477,6 +477,9 @@ func (r *Queryer) QueryServerJoinedToRoom( if err != nil { return fmt.Errorf("r.DB.RoomInfo: %w", err) } + if info != nil { + response.RoomVersion = info.RoomVersion + } if info == nil || info.IsStub() { return nil } diff --git a/roomserver/storage/shared/storage.go b/roomserver/storage/shared/storage.go index bda51da819..492cd1ab6a 100644 --- a/roomserver/storage/shared/storage.go +++ b/roomserver/storage/shared/storage.go @@ -1692,6 +1692,7 @@ func (d *Database) InsertUserRoomPublicKey(ctx context.Context, userID spec.User // SelectUserRoomPrivateKey queries the users room private key. // If no key exists, returns no key and no error. Otherwise returns // the key and a database error, if any. +// TODO: Cache this? func (d *Database) SelectUserRoomPrivateKey(ctx context.Context, userID spec.UserID, roomID spec.RoomID) (key ed25519.PrivateKey, err error) { uID := userID.String() stateKeyNIDMap, sErr := d.eventStateKeyNIDs(ctx, nil, []string{uID}) From 34ab4d11ed684b46ff9726cda28dfc5b4a61aa5b Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Wed, 14 Jun 2023 16:52:48 +0200 Subject: [PATCH 04/21] Get signing identity depending on the room version --- clientapi/routing/membership.go | 16 +++++--- clientapi/routing/profile.go | 25 ++++++++---- clientapi/routing/redaction.go | 12 +++++- clientapi/routing/sendevent.go | 15 +++++-- clientapi/routing/server_notices.go | 4 +- federationapi/routing/join.go | 10 ++++- federationapi/routing/leave.go | 10 ++++- roomserver/api/api.go | 4 +- roomserver/internal/alias.go | 11 ++++-- roomserver/internal/api.go | 39 ++++++++++++++++--- roomserver/internal/input/input.go | 2 +- roomserver/internal/input/input_events.go | 17 +++++++- .../internal/perform/perform_create_room.go | 7 ++-- roomserver/internal/perform/perform_join.go | 10 ++--- roomserver/internal/perform/perform_leave.go | 9 ++++- 15 files changed, 143 insertions(+), 48 deletions(-) diff --git a/clientapi/routing/membership.go b/clientapi/routing/membership.go index 03e85edbf9..d74b3b52b8 100644 --- a/clientapi/routing/membership.go +++ b/clientapi/routing/membership.go @@ -419,11 +419,6 @@ func buildMembershipEvent( return nil, err } - identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain()) - if err != nil { - return nil, err - } - userID, err := spec.NewUserID(device.UserID, true) if err != nil { return nil, err @@ -441,6 +436,17 @@ func buildMembershipEvent( if err != nil { return nil, err } + + validRoomID, err := spec.NewRoomID(roomID) + if err != nil { + return nil, err + } + + identity, err := rsAPI.SigningIdentityFor(ctx, *validRoomID, *userID) + if err != nil { + return nil, err + } + return buildMembershipEventDirect(ctx, targetSenderID, reason, profile.DisplayName, profile.AvatarURL, senderID, device.UserDomain(), membership, roomID, isDirect, identity.KeyID, identity.PrivateKey, evTime, rsAPI) } diff --git a/clientapi/routing/profile.go b/clientapi/routing/profile.go index e734e2e4fc..bda9183842 100644 --- a/clientapi/routing/profile.go +++ b/clientapi/routing/profile.go @@ -151,7 +151,7 @@ func SetAvatarURL( } } - response, err := updateProfile(req.Context(), rsAPI, device, profile, userID, cfg, evTime) + response, err := updateProfile(req.Context(), rsAPI, device, profile, userID, evTime) if err != nil { return response } @@ -246,7 +246,7 @@ func SetDisplayName( } } - response, err := updateProfile(req.Context(), rsAPI, device, profile, userID, cfg, evTime) + response, err := updateProfile(req.Context(), rsAPI, device, profile, userID, evTime) if err != nil { return response } @@ -260,7 +260,7 @@ func SetDisplayName( func updateProfile( ctx context.Context, rsAPI api.ClientRoomserverAPI, device *userapi.Device, profile *authtypes.Profile, - userID string, cfg *config.ClientAPI, evTime time.Time, + userID string, evTime time.Time, ) (util.JSONResponse, error) { var res api.QueryRoomsForUserResponse err := rsAPI.QueryRoomsForUser(ctx, &api.QueryRoomsForUserRequest{ @@ -285,7 +285,7 @@ func updateProfile( } events, err := buildMembershipEvents( - ctx, device, res.RoomIDs, *profile, userID, cfg, evTime, rsAPI, + ctx, res.RoomIDs, *profile, userID, evTime, rsAPI, ) switch e := err.(type) { case nil: @@ -356,9 +356,8 @@ func getProfile( func buildMembershipEvents( ctx context.Context, - device *userapi.Device, roomIDs []string, - newProfile authtypes.Profile, userID string, cfg *config.ClientAPI, + newProfile authtypes.Profile, userID string, evTime time.Time, rsAPI api.ClientRoomserverAPI, ) ([]*types.HeaderedEvent, error) { evs := []*types.HeaderedEvent{} @@ -391,12 +390,22 @@ func buildMembershipEvents( return nil, err } - identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain()) + validRoomID, err := spec.NewRoomID(roomID) if err != nil { return nil, err } - event, err := eventutil.QueryAndBuildEvent(ctx, &proto, identity, evTime, rsAPI, nil) + user, err := spec.NewUserID(userID, true) + if err != nil { + return nil, err + } + + identity, err := rsAPI.SigningIdentityFor(ctx, *validRoomID, *user) + if err != nil { + return nil, err + } + + event, err := eventutil.QueryAndBuildEvent(ctx, &proto, &identity, evTime, rsAPI, nil) if err != nil { return nil, err } diff --git a/clientapi/routing/redaction.go b/clientapi/routing/redaction.go index da48e84dea..ce4c17c9f4 100644 --- a/clientapi/routing/redaction.go +++ b/clientapi/routing/redaction.go @@ -143,7 +143,15 @@ func SendRedaction( } } - identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain()) + validRoomID, err := spec.NewRoomID(roomID) + if err != nil { + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{}, + } + } + + identity, err := rsAPI.SigningIdentityFor(req.Context(), *validRoomID, *deviceUserID) if err != nil { return util.JSONResponse{ Code: http.StatusInternalServerError, @@ -152,7 +160,7 @@ func SendRedaction( } var queryRes roomserverAPI.QueryLatestEventsAndStateResponse - e, err := eventutil.QueryAndBuildEvent(req.Context(), &proto, identity, time.Now(), rsAPI, &queryRes) + e, err := eventutil.QueryAndBuildEvent(req.Context(), &proto, &identity, time.Now(), rsAPI, &queryRes) if errors.Is(err, eventutil.ErrRoomNoExists{}) { return util.JSONResponse{ Code: http.StatusNotFound, diff --git a/clientapi/routing/sendevent.go b/clientapi/routing/sendevent.go index 4d0a9f24a5..c6e8fbde8f 100644 --- a/clientapi/routing/sendevent.go +++ b/clientapi/routing/sendevent.go @@ -129,7 +129,7 @@ func SendEvent( } } - e, resErr := generateSendEvent(req.Context(), r, device, roomID, eventType, stateKey, cfg, rsAPI, evTime) + e, resErr := generateSendEvent(req.Context(), r, device, roomID, eventType, stateKey, rsAPI, evTime) if resErr != nil { return *resErr } @@ -261,7 +261,6 @@ func generateSendEvent( r map[string]interface{}, device *userapi.Device, roomID, eventType string, stateKey *string, - cfg *config.ClientAPI, rsAPI api.ClientRoomserverAPI, evTime time.Time, ) (gomatrixserverlib.PDU, *util.JSONResponse) { @@ -297,7 +296,15 @@ func generateSendEvent( } } - identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain()) + validRoomID, err := spec.NewRoomID(roomID) + if err != nil { + return nil, &util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{}, + } + } + + identity, err := rsAPI.SigningIdentityFor(ctx, *validRoomID, *fullUserID) if err != nil { return nil, &util.JSONResponse{ Code: http.StatusInternalServerError, @@ -306,7 +313,7 @@ func generateSendEvent( } var queryRes api.QueryLatestEventsAndStateResponse - e, err := eventutil.QueryAndBuildEvent(ctx, &proto, identity, evTime, rsAPI, &queryRes) + e, err := eventutil.QueryAndBuildEvent(ctx, &proto, &identity, evTime, rsAPI, &queryRes) switch specificErr := err.(type) { case nil: case eventutil.ErrRoomNoExists: diff --git a/clientapi/routing/server_notices.go b/clientapi/routing/server_notices.go index 7006ced46c..66258a68ac 100644 --- a/clientapi/routing/server_notices.go +++ b/clientapi/routing/server_notices.go @@ -221,7 +221,7 @@ func SendServerNotice( "body": r.Content.Body, "msgtype": r.Content.MsgType, } - e, resErr := generateSendEvent(ctx, request, senderDevice, roomID, "m.room.message", nil, cfgClient, rsAPI, time.Now()) + e, resErr := generateSendEvent(ctx, request, senderDevice, roomID, "m.room.message", nil, rsAPI, time.Now()) if resErr != nil { logrus.Errorf("failed to send message: %+v", resErr) return *resErr @@ -350,7 +350,7 @@ func getSenderDevice( if len(deviceRes.Devices) > 0 { // If there were changes to the profile, create a new membership event if displayNameChanged || avatarChanged { - _, err = updateProfile(ctx, rsAPI, &deviceRes.Devices[0], profile, accRes.Account.UserID, cfg, time.Now()) + _, err = updateProfile(ctx, rsAPI, &deviceRes.Devices[0], profile, accRes.Account.UserID, time.Now()) if err != nil { return nil, err } diff --git a/federationapi/routing/join.go b/federationapi/routing/join.go index d14801921c..2a6d854772 100644 --- a/federationapi/routing/join.go +++ b/federationapi/routing/join.go @@ -64,7 +64,13 @@ func MakeJoin( } createJoinTemplate := func(proto *gomatrixserverlib.ProtoEvent) (gomatrixserverlib.PDU, []gomatrixserverlib.PDU, error) { - identity, signErr := cfg.Matrix.SigningIdentityFor(request.Destination()) + // TODO: remove this once the join dance understands pseudo IDs + var dummyUserID *spec.UserID + dummyUserID, err = spec.NewUserID(fmt.Sprintf("@dummy:%s", request.Destination()), true) + if err != nil { + return nil, nil, err + } + identity, signErr := rsAPI.SigningIdentityFor(httpReq.Context(), roomID, *dummyUserID) if signErr != nil { util.GetLogger(httpReq.Context()).WithError(signErr).Errorf("obtaining signing identity for %s failed", request.Destination()) return nil, nil, spec.NotFound(fmt.Sprintf("Server name %q does not exist", request.Destination())) @@ -73,7 +79,7 @@ func MakeJoin( queryRes := api.QueryLatestEventsAndStateResponse{ RoomVersion: roomVersion, } - event, signErr := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, identity, time.Now(), rsAPI, &queryRes) + event, signErr := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, &identity, time.Now(), rsAPI, &queryRes) switch e := signErr.(type) { case nil: case eventutil.ErrRoomNoExists: diff --git a/federationapi/routing/leave.go b/federationapi/routing/leave.go index 716276bec4..fdcd5819c3 100644 --- a/federationapi/routing/leave.go +++ b/federationapi/routing/leave.go @@ -59,14 +59,20 @@ func MakeLeave( } createLeaveTemplate := func(proto *gomatrixserverlib.ProtoEvent) (gomatrixserverlib.PDU, []gomatrixserverlib.PDU, error) { - identity, signErr := cfg.Matrix.SigningIdentityFor(request.Destination()) + // TODO: remove this once the leave dance understands pseudo IDs + var dummyUserID *spec.UserID + dummyUserID, err = spec.NewUserID(fmt.Sprintf("@dummy:%s", request.Destination()), true) + if err != nil { + return nil, nil, err + } + identity, signErr := rsAPI.SigningIdentityFor(httpReq.Context(), roomID, *dummyUserID) if signErr != nil { util.GetLogger(httpReq.Context()).WithError(signErr).Errorf("obtaining signing identity for %s failed", request.Destination()) return nil, nil, spec.NotFound(fmt.Sprintf("Server name %q does not exist", request.Destination())) } queryRes := api.QueryLatestEventsAndStateResponse{} - event, buildErr := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, identity, time.Now(), rsAPI, &queryRes) + event, buildErr := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, &identity, time.Now(), rsAPI, &queryRes) switch e := buildErr.(type) { case nil: case eventutil.ErrRoomNoExists: diff --git a/roomserver/api/api.go b/roomserver/api/api.go index fec28841e0..99a68efae0 100644 --- a/roomserver/api/api.go +++ b/roomserver/api/api.go @@ -5,6 +5,7 @@ import ( "crypto/ed25519" "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/gomatrixserverlib/fclient" "github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/util" @@ -210,6 +211,7 @@ type ClientRoomserverAPI interface { PerformForget(ctx context.Context, req *PerformForgetRequest, resp *PerformForgetResponse) error SetRoomAlias(ctx context.Context, req *SetRoomAliasRequest, res *SetRoomAliasResponse) error RemoveRoomAlias(ctx context.Context, req *RemoveRoomAliasRequest, res *RemoveRoomAliasResponse) error + SigningIdentityFor(ctx context.Context, roomID spec.RoomID, senderID spec.UserID) (fclient.SigningIdentity, error) } type UserRoomserverAPI interface { @@ -228,7 +230,7 @@ type FederationRoomserverAPI interface { QueryLatestEventsAndStateAPI QueryBulkStateContentAPI QuerySenderIDAPI - + SigningIdentityFor(ctx context.Context, roomID spec.RoomID, senderID spec.UserID) (fclient.SigningIdentity, error) // QueryServerBannedFromRoom returns whether a server is banned from a room by server ACLs. QueryServerBannedFromRoom(ctx context.Context, req *QueryServerBannedFromRoomRequest, res *QueryServerBannedFromRoomResponse) error QueryMembershipForUser(ctx context.Context, req *QueryMembershipForUserRequest, res *QueryMembershipForUserResponse) error diff --git a/roomserver/internal/alias.go b/roomserver/internal/alias.go index c950024adc..41de52fc26 100644 --- a/roomserver/internal/alias.go +++ b/roomserver/internal/alias.go @@ -114,6 +114,7 @@ func (r *RoomserverInternalAPI) GetAliasesForRoomID( } // RemoveRoomAlias implements alias.RoomserverInternalAPI +// nolint: gocyclo func (r *RoomserverInternalAPI) RemoveRoomAlias( ctx context.Context, request *api.RemoveRoomAliasRequest, @@ -182,9 +183,11 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias( return err } - senderDomain := sender.Domain() - - identity, err := r.Cfg.Global.SigningIdentityFor(senderDomain) + validRoomID, err := spec.NewRoomID(roomID) + if err != nil { + return err + } + identity, err := r.SigningIdentityFor(ctx, *validRoomID, *sender) if err != nil { return err } @@ -210,7 +213,7 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias( return err } - newEvent, err := eventutil.BuildEvent(ctx, proto, identity, time.Now(), &eventsNeeded, stateRes) + newEvent, err := eventutil.BuildEvent(ctx, proto, &identity, time.Now(), &eventsNeeded, stateRes) if err != nil { return err } diff --git a/roomserver/internal/api.go b/roomserver/internal/api.go index 4bcd3f3ede..97b35764fd 100644 --- a/roomserver/internal/api.go +++ b/roomserver/internal/api.go @@ -6,6 +6,7 @@ import ( "github.com/getsentry/sentry-go" "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/gomatrixserverlib/fclient" "github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/util" "github.com/nats-io/nats.go" @@ -110,11 +111,6 @@ func (r *RoomserverInternalAPI) SetFederationAPI(fsAPI fsAPI.RoomserverFederatio r.fsAPI = fsAPI r.KeyRing = keyRing - identity, err := r.Cfg.Global.SigningIdentityFor(r.ServerName) - if err != nil { - logrus.Panic(err) - } - r.Inputer = &input.Inputer{ Cfg: &r.Cfg.RoomServer, ProcessContext: r.ProcessContext, @@ -125,7 +121,7 @@ func (r *RoomserverInternalAPI) SetFederationAPI(fsAPI fsAPI.RoomserverFederatio NATSClient: r.NATSClient, Durable: nats.Durable(r.Durable), ServerName: r.ServerName, - SigningIdentity: identity, + SigningIdentity: r.SigningIdentityFor, FSAPI: fsAPI, KeyRing: keyRing, ACLs: r.ServerACLs, @@ -291,3 +287,34 @@ func (r *RoomserverInternalAPI) GetOrCreateUserRoomPrivateKey(ctx context.Contex } return key, nil } + +func (r *RoomserverInternalAPI) SigningIdentityFor(ctx context.Context, roomID spec.RoomID, senderID spec.UserID) (fclient.SigningIdentity, error) { + roomVersion, ok := r.Cache.GetRoomVersion(roomID.String()) + if !ok { + roomInfo, err := r.DB.RoomInfo(ctx, roomID.String()) + if err != nil { + return fclient.SigningIdentity{}, err + } + if roomInfo != nil { + roomVersion = roomInfo.RoomVersion + } + } + if roomVersion == gomatrixserverlib.RoomVersionPseudoIDs { + privKey, err := r.GetOrCreateUserRoomPrivateKey(ctx, senderID, roomID) + if err != nil { + return fclient.SigningIdentity{}, err + } + logrus.Infof("XXX: using user signing key") + return fclient.SigningIdentity{ + PrivateKey: privKey, + KeyID: "ed25519", + ServerName: "self", + }, nil + } + logrus.Infof("XXX: using config signing key") + identity, err := r.Cfg.Global.SigningIdentityFor(senderID.Domain()) + if err != nil { + return fclient.SigningIdentity{}, err + } + return *identity, err +} diff --git a/roomserver/internal/input/input.go b/roomserver/internal/input/input.go index 3db2d0a67a..dea8f8c878 100644 --- a/roomserver/internal/input/input.go +++ b/roomserver/internal/input/input.go @@ -81,7 +81,7 @@ type Inputer struct { JetStream nats.JetStreamContext Durable nats.SubOpt ServerName spec.ServerName - SigningIdentity *fclient.SigningIdentity + SigningIdentity func(ctx context.Context, roomID spec.RoomID, senderID spec.UserID) (fclient.SigningIdentity, error) FSAPI fedapi.RoomserverFederationAPI KeyRing gomatrixserverlib.JSONVerifier ACLs *acls.ServerACLs diff --git a/roomserver/internal/input/input_events.go b/roomserver/internal/input/input_events.go index 7bb4016328..8ee32b3c24 100644 --- a/roomserver/internal/input/input_events.go +++ b/roomserver/internal/input/input_events.go @@ -886,7 +886,22 @@ func (r *Inputer) kickGuests(ctx context.Context, event gomatrixserverlib.PDU, r return err } - event, err := eventutil.BuildEvent(ctx, fledglingEvent, r.SigningIdentity, time.Now(), &eventsNeeded, latestRes) + validRoomID, err := spec.NewRoomID(event.RoomID()) + if err != nil { + return err + } + + userID, err := spec.NewUserID(stateKey, true) + if err != nil { + return err + } + + signingIdentity, err := r.SigningIdentity(ctx, *validRoomID, *userID) + if err != nil { + return err + } + + event, err := eventutil.BuildEvent(ctx, fledglingEvent, &signingIdentity, time.Now(), &eventsNeeded, latestRes) if err != nil { return err } diff --git a/roomserver/internal/perform/perform_create_room.go b/roomserver/internal/perform/perform_create_room.go index 02ea6edd57..2c08f363ad 100644 --- a/roomserver/internal/perform/perform_create_room.go +++ b/roomserver/internal/perform/perform_create_room.go @@ -150,7 +150,7 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo } // get the signing identity - identity, err := c.Cfg.Matrix.SigningIdentityFor(userID.Domain()) + identity, err := c.Cfg.Matrix.SigningIdentityFor(userID.Domain()) // we MUST use the server signing mxid_mapping if err != nil { logrus.WithError(err).WithField("domain", userID.Domain()).Error("unable to find signing identity for domain") return "", &util.JSONResponse{ @@ -187,8 +187,8 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo // sign all events with the pseudo ID key identity = &fclient.SigningIdentity{ - ServerName: userID.Domain(), - KeyID: "self", + ServerName: "self", + KeyID: "ed25519", PrivateKey: pseudoIDKey, } } @@ -404,6 +404,7 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo inputs := make([]api.InputRoomEvent, 0, len(builtEvents)) for _, event := range builtEvents { + logrus.Infof("XXX: built event: %s", string(event.JSON())) inputs = append(inputs, api.InputRoomEvent{ Kind: api.KindNew, Event: event, diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go index b99cc56e8b..63c8ced855 100644 --- a/roomserver/internal/perform/perform_join.go +++ b/roomserver/internal/perform/perform_join.go @@ -285,7 +285,7 @@ func (r *Joiner) performJoinRoomByID( // but everyone has since left. I suspect it does the wrong thing. var buildRes rsAPI.QueryLatestEventsAndStateResponse - identity, err := r.Cfg.Matrix.SigningIdentityFor(userDomain) + identity, err := r.RSAPI.SigningIdentityFor(ctx, *roomID, *userID) if err != nil { return "", "", fmt.Errorf("error joining local room: %q", err) } @@ -311,9 +311,9 @@ func (r *Joiner) performJoinRoomByID( req.Content["mxid_mapping"] = mapping // sign the event with the pseudo ID key - identity = &fclient.SigningIdentity{ - ServerName: userID.Domain(), - KeyID: "self", + identity = fclient.SigningIdentity{ + ServerName: "self", + KeyID: "ed25519", PrivateKey: pseudoIDKey, } } @@ -322,7 +322,7 @@ func (r *Joiner) performJoinRoomByID( return "", "", fmt.Errorf("eb.SetContent: %w", err) } - event, err := eventutil.QueryAndBuildEvent(ctx, &proto, identity, time.Now(), r.RSAPI, &buildRes) + event, err := eventutil.QueryAndBuildEvent(ctx, &proto, &identity, time.Now(), r.RSAPI, &buildRes) switch err.(type) { case nil: diff --git a/roomserver/internal/perform/perform_leave.go b/roomserver/internal/perform/perform_leave.go index 1b23cc1ffe..2c4da2606e 100644 --- a/roomserver/internal/perform/perform_leave.go +++ b/roomserver/internal/perform/perform_leave.go @@ -173,12 +173,17 @@ func (r *Leaver) performLeaveRoomByID( // TODO: Check what happens if the room exists on the server // but everyone has since left. I suspect it does the wrong thing. + validRoomID, err := spec.NewRoomID(req.RoomID) + if err != nil { + return nil, err + } + var buildRes rsAPI.QueryLatestEventsAndStateResponse - identity, err := r.Cfg.Matrix.SigningIdentityFor(req.Leaver.Domain()) + identity, err := r.RSAPI.SigningIdentityFor(ctx, *validRoomID, req.Leaver) if err != nil { return nil, fmt.Errorf("SigningIdentityFor: %w", err) } - event, err := eventutil.QueryAndBuildEvent(ctx, &proto, identity, time.Now(), r.RSAPI, &buildRes) + event, err := eventutil.QueryAndBuildEvent(ctx, &proto, &identity, time.Now(), r.RSAPI, &buildRes) if err != nil { return nil, fmt.Errorf("eventutil.QueryAndBuildEvent: %w", err) } From fd999253ef5279831ff00982c3f91b450884c107 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Thu, 15 Jun 2023 09:37:07 +0200 Subject: [PATCH 05/21] Correctly resolve userID --- federationapi/consumers/roomserver.go | 15 ++++++++++----- federationapi/internal/perform.go | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/federationapi/consumers/roomserver.go b/federationapi/consumers/roomserver.go index c6ad3f7485..19bf3730b3 100644 --- a/federationapi/consumers/roomserver.go +++ b/federationapi/consumers/roomserver.go @@ -192,7 +192,7 @@ func (s *OutputRoomEventConsumer) processMessage(ore api.OutputNewRoomEvent, rew evs[i] = addsStateEvents[i].PDU } - addsJoinedHosts, err := JoinedHostsFromEvents(evs) + addsJoinedHosts, err := JoinedHostsFromEvents(s.ctx, evs, s.rsAPI) if err != nil { return err } @@ -345,7 +345,7 @@ func (s *OutputRoomEventConsumer) joinedHostsAtEvent( return nil, err } - combinedAddsJoinedHosts, err := JoinedHostsFromEvents(combinedAddsEvents) + combinedAddsJoinedHosts, err := JoinedHostsFromEvents(s.ctx, combinedAddsEvents, s.rsAPI) if err != nil { return nil, err } @@ -394,7 +394,7 @@ func (s *OutputRoomEventConsumer) joinedHostsAtEvent( // JoinedHostsFromEvents turns a list of state events into a list of joined hosts. // This errors if one of the events was invalid. // It should be impossible for an invalid event to get this far in the pipeline. -func JoinedHostsFromEvents(evs []gomatrixserverlib.PDU) ([]types.JoinedHost, error) { +func JoinedHostsFromEvents(ctx context.Context, evs []gomatrixserverlib.PDU, rsAPI api.FederationRoomserverAPI) ([]types.JoinedHost, error) { var joinedHosts []types.JoinedHost for _, ev := range evs { if ev.Type() != "m.room.member" || ev.StateKey() == nil { @@ -407,12 +407,17 @@ func JoinedHostsFromEvents(evs []gomatrixserverlib.PDU) ([]types.JoinedHost, err if membership != spec.Join { continue } - _, serverName, err := gomatrixserverlib.SplitID('@', *ev.StateKey()) + validRoomID, err := spec.NewRoomID(ev.RoomID()) if err != nil { return nil, err } + userID, err := rsAPI.QueryUserIDForSender(ctx, *validRoomID, ev.SenderID()) + if err != nil { + return nil, err + } + joinedHosts = append(joinedHosts, types.JoinedHost{ - MemberEventID: ev.EventID(), ServerName: serverName, + MemberEventID: ev.EventID(), ServerName: userID.Domain(), }) } return joinedHosts, nil diff --git a/federationapi/internal/perform.go b/federationapi/internal/perform.go index 7f61dba411..74d9e1af52 100644 --- a/federationapi/internal/perform.go +++ b/federationapi/internal/perform.go @@ -200,7 +200,7 @@ func (r *FederationInternalAPI) performJoinUsingServer( // joining a room, waiting for 200 OK then changing device keys and have those keys not be sent // to other servers (this was a cause of a flakey sytest "Local device key changes get to remote servers") // The events are trusted now as we performed auth checks above. - joinedHosts, err := consumers.JoinedHostsFromEvents(response.StateSnapshot.GetStateEvents().TrustedEvents(response.JoinEvent.Version(), false)) + joinedHosts, err := consumers.JoinedHostsFromEvents(ctx, response.StateSnapshot.GetStateEvents().TrustedEvents(response.JoinEvent.Version(), false), r.rsAPI) if err != nil { return fmt.Errorf("JoinedHostsFromEvents: failed to get joined hosts: %s", err) } From b655017b07dcaec58de4f049eb9c1bc2fbfc21c9 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Thu, 15 Jun 2023 13:19:51 +0200 Subject: [PATCH 06/21] Workaround problem with senderID/userID --- roomserver/types/headered_event.go | 5 ++ syncapi/consumers/roomserver.go | 69 +++++++++++++------ syncapi/routing/search_test.go | 3 +- .../postgres/current_room_state_table.go | 4 +- syncapi/storage/postgres/memberships_table.go | 2 +- .../postgres/output_room_events_table.go | 2 +- .../sqlite3/current_room_state_table.go | 4 +- syncapi/storage/sqlite3/memberships_table.go | 2 +- .../sqlite3/output_room_events_table.go | 2 +- syncapi/sync/requestpool.go | 2 + 10 files changed, 66 insertions(+), 29 deletions(-) diff --git a/roomserver/types/headered_event.go b/roomserver/types/headered_event.go index 52d006bd90..7839998222 100644 --- a/roomserver/types/headered_event.go +++ b/roomserver/types/headered_event.go @@ -18,6 +18,7 @@ import ( "unsafe" "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/gomatrixserverlib/spec" ) // HeaderedEvent is an Event which serialises to the headered form, which includes @@ -25,6 +26,10 @@ import ( type HeaderedEvent struct { gomatrixserverlib.PDU Visibility gomatrixserverlib.HistoryVisibility + // TODO: Remove this. This is a temporary workaround to store the userID in the syncAPI. + // It really should be the userKey instead. + UserID spec.UserID + StateKeyResolved *string } func (h *HeaderedEvent) CacheCost() int { diff --git a/syncapi/consumers/roomserver.go b/syncapi/consumers/roomserver.go index d468dfc98b..785676755e 100644 --- a/syncapi/consumers/roomserver.go +++ b/syncapi/consumers/roomserver.go @@ -256,16 +256,19 @@ func (s *OutputRoomEventConsumer) onNewRoomEvent( } } - pduPos, err := s.db.WriteEvent( - ctx, - ev, - addsStateEvents, - msg.AddsStateEventIDs, - msg.RemovesStateEventIDs, - msg.TransactionID, - false, - msg.HistoryVisibility, - ) + validRoomID, err := spec.NewRoomID(ev.RoomID()) + if err != nil { + return err + } + + userID, err := s.rsAPI.QueryUserIDForSender(ctx, *validRoomID, ev.SenderID()) + if err != nil { + return err + } + + ev.UserID = *userID + + pduPos, err := s.db.WriteEvent(ctx, ev, addsStateEvents, msg.AddsStateEventIDs, msg.RemovesStateEventIDs, msg.TransactionID, false, msg.HistoryVisibility) if err != nil { // panic rather than continue with an inconsistent database log.WithFields(log.Fields{ @@ -315,16 +318,19 @@ func (s *OutputRoomEventConsumer) onOldRoomEvent( // hack but until we have some better strategy for dealing with // old events in the sync API, this should at least prevent us // from confusing clients into thinking they've joined/left rooms. - pduPos, err := s.db.WriteEvent( - ctx, - ev, - []*rstypes.HeaderedEvent{}, - []string{}, // adds no state - []string{}, // removes no state - nil, // no transaction - ev.StateKey() != nil, // exclude from sync?, - msg.HistoryVisibility, - ) + + validRoomID, err := spec.NewRoomID(ev.RoomID()) + if err != nil { + return err + } + + userID, err := s.rsAPI.QueryUserIDForSender(ctx, *validRoomID, ev.SenderID()) + if err != nil { + return err + } + ev.UserID = *userID + + pduPos, err := s.db.WriteEvent(ctx, ev, []*rstypes.HeaderedEvent{}, []string{}, []string{}, nil, ev.StateKey() != nil, msg.HistoryVisibility) if err != nil { // panic rather than continue with an inconsistent database log.WithFields(log.Fields{ @@ -537,6 +543,7 @@ func (s *OutputRoomEventConsumer) onPurgeRoom( } func (s *OutputRoomEventConsumer) updateStateEvent(event *rstypes.HeaderedEvent) (*rstypes.HeaderedEvent, error) { + event.StateKeyResolved = event.StateKey() if event.StateKey() == nil { return event, nil } @@ -556,6 +563,28 @@ func (s *OutputRoomEventConsumer) updateStateEvent(event *rstypes.HeaderedEvent) return event, err } + validRoomID, err := spec.NewRoomID(event.RoomID()) + if err != nil { + return event, err + } + + if event.StateKey() != nil { + if *event.StateKey() != "" { + sku, err := s.rsAPI.QueryUserIDForSender(s.ctx, *validRoomID, spec.SenderID(stateKey)) + if err == nil && sku != nil { + sKey := sku.String() + event.StateKeyResolved = &sKey + } + } + } + + userID, err := s.rsAPI.QueryUserIDForSender(s.ctx, *validRoomID, event.SenderID()) + if err != nil { + return event, err + } + + event.UserID = *userID + if prevEvent == nil || prevEvent.EventID() == event.EventID() { return event, nil } diff --git a/syncapi/routing/search_test.go b/syncapi/routing/search_test.go index f6d7fb4ebe..c70abbd1be 100644 --- a/syncapi/routing/search_test.go +++ b/syncapi/routing/search_test.go @@ -230,7 +230,8 @@ func TestSearch(t *testing.T) { stateEvents = append(stateEvents, x) stateEventIDs = append(stateEventIDs, x.EventID()) } - sp, err = db.WriteEvent(processCtx.Context(), x, stateEvents, stateEventIDs, nil, nil, false, gomatrixserverlib.HistoryVisibilityShared) + + sp, err = db.WriteEvent(processCtx.Context(), x, spec.UserID{}, stateEvents, stateEventIDs, nil, nil, false, gomatrixserverlib.HistoryVisibilityShared) assert.NoError(t, err) if x.Type() != "m.room.message" { continue diff --git a/syncapi/storage/postgres/current_room_state_table.go b/syncapi/storage/postgres/current_room_state_table.go index bfe5e9bdda..112fa9d4a9 100644 --- a/syncapi/storage/postgres/current_room_state_table.go +++ b/syncapi/storage/postgres/current_room_state_table.go @@ -343,9 +343,9 @@ func (s *currentRoomStateStatements) UpsertRoomState( event.RoomID(), event.EventID(), event.Type(), - event.SenderID(), + event.UserID.String(), containsURL, - *event.StateKey(), + *event.StateKeyResolved, headeredJSON, membership, addedAt, diff --git a/syncapi/storage/postgres/memberships_table.go b/syncapi/storage/postgres/memberships_table.go index 3905f9abb2..6bf9f61a1b 100644 --- a/syncapi/storage/postgres/memberships_table.go +++ b/syncapi/storage/postgres/memberships_table.go @@ -109,7 +109,7 @@ func (s *membershipsStatements) UpsertMembership( _, err = sqlutil.TxStmt(txn, s.upsertMembershipStmt).ExecContext( ctx, event.RoomID(), - *event.StateKey(), + event.UserID.String(), membership, event.EventID(), streamPos, diff --git a/syncapi/storage/postgres/output_room_events_table.go b/syncapi/storage/postgres/output_room_events_table.go index e068afab1b..b58cf59f04 100644 --- a/syncapi/storage/postgres/output_room_events_table.go +++ b/syncapi/storage/postgres/output_room_events_table.go @@ -407,7 +407,7 @@ func (s *outputRoomEventsStatements) InsertEvent( event.EventID(), headeredJSON, event.Type(), - event.SenderID(), + event.UserID.String(), containsURL, pq.StringArray(addState), pq.StringArray(removeState), diff --git a/syncapi/storage/sqlite3/current_room_state_table.go b/syncapi/storage/sqlite3/current_room_state_table.go index e432e483b9..3bd19b3676 100644 --- a/syncapi/storage/sqlite3/current_room_state_table.go +++ b/syncapi/storage/sqlite3/current_room_state_table.go @@ -342,9 +342,9 @@ func (s *currentRoomStateStatements) UpsertRoomState( event.RoomID(), event.EventID(), event.Type(), - event.SenderID(), + event.UserID.String(), containsURL, - *event.StateKey(), + *event.StateKeyResolved, headeredJSON, membership, addedAt, diff --git a/syncapi/storage/sqlite3/memberships_table.go b/syncapi/storage/sqlite3/memberships_table.go index c09fa1510d..6218ea6603 100644 --- a/syncapi/storage/sqlite3/memberships_table.go +++ b/syncapi/storage/sqlite3/memberships_table.go @@ -112,7 +112,7 @@ func (s *membershipsStatements) UpsertMembership( _, err = sqlutil.TxStmt(txn, s.upsertMembershipStmt).ExecContext( ctx, event.RoomID(), - *event.StateKey(), + event.UserID.String(), membership, event.EventID(), streamPos, diff --git a/syncapi/storage/sqlite3/output_room_events_table.go b/syncapi/storage/sqlite3/output_room_events_table.go index 5a47aec44e..06c65419af 100644 --- a/syncapi/storage/sqlite3/output_room_events_table.go +++ b/syncapi/storage/sqlite3/output_room_events_table.go @@ -348,7 +348,7 @@ func (s *outputRoomEventsStatements) InsertEvent( event.EventID(), headeredJSON, event.Type(), - event.SenderID(), + event.UserID.String(), containsURL, string(addStateJSON), string(removeStateJSON), diff --git a/syncapi/sync/requestpool.go b/syncapi/sync/requestpool.go index 5a92c70e1c..cb5205d7f1 100644 --- a/syncapi/sync/requestpool.go +++ b/syncapi/sync/requestpool.go @@ -503,6 +503,8 @@ func (rp *RequestPool) OnIncomingSyncRequest(req *http.Request, device *userapi. } } + logrus.Infof("%#v", syncReq.Response.Rooms.Join) + return util.JSONResponse{ Code: http.StatusOK, JSON: syncReq.Response, From 8f967e5f52599be5b35f7dce3b9044de90f9b87a Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Thu, 15 Jun 2023 13:23:07 +0200 Subject: [PATCH 07/21] Partially working pseudo IDs --- federationapi/internal/perform.go | 2 +- .../internal/perform/perform_create_room.go | 23 ++++++++++--------- roomserver/internal/perform/perform_join.go | 4 ++-- roomserver/internal/query/query.go | 2 +- syncapi/consumers/roomserver.go | 3 ++- syncapi/routing/search_test.go | 2 +- 6 files changed, 19 insertions(+), 17 deletions(-) diff --git a/federationapi/internal/perform.go b/federationapi/internal/perform.go index 74d9e1af52..5a98cd2180 100644 --- a/federationapi/internal/perform.go +++ b/federationapi/internal/perform.go @@ -176,7 +176,7 @@ func (r *FederationInternalAPI) performJoinUsingServer( return "", keyErr } - return spec.SenderID(spec.Base64Bytes(key).Encode()), nil + return spec.SenderIDFromPseudoIDKey(key), nil }, } response, joinErr := gomatrixserverlib.PerformJoin(ctx, r, joinInput) diff --git a/roomserver/internal/perform/perform_create_room.go b/roomserver/internal/perform/perform_create_room.go index 965c128a6b..9316c1290d 100644 --- a/roomserver/internal/perform/perform_create_room.go +++ b/roomserver/internal/perform/perform_create_room.go @@ -65,6 +65,16 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo } } } + + _, err = c.DB.AssignRoomNID(ctx, roomID, createRequest.RoomVersion) + if err != nil { + util.GetLogger(ctx).WithError(err).Error("failed to assign roomNID") + return "", &util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{}, + } + } + var senderID spec.SenderID if createRequest.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs { // create user room key if needed @@ -76,7 +86,7 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo JSON: spec.InternalServerError{}, } } - senderID = spec.SenderID(spec.Base64Bytes(key).Encode()) + senderID = spec.SenderIDFromPseudoIDKey(key) } else { senderID = spec.SenderID(userID.String()) } @@ -102,15 +112,6 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo } } - _, err = c.DB.AssignRoomNID(ctx, roomID, createRequest.RoomVersion) - if err != nil { - util.GetLogger(ctx).WithError(err).Error("failed to assign roomNID") - return "", &util.JSONResponse{ - Code: http.StatusInternalServerError, - JSON: spec.InternalServerError{}, - } - } - var guestsCanJoin bool switch createRequest.StatePreset { case spec.PresetPrivateChat: @@ -179,7 +180,7 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo } mapping := &gomatrixserverlib.MXIDMapping{ - UserRoomKey: spec.UserRoomKey(pseudoIDKey), + UserRoomKey: spec.SenderIDFromPseudoIDKey(pseudoIDKey), UserID: userID.String(), } diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go index 759c577b02..092567ca6f 100644 --- a/roomserver/internal/perform/perform_join.go +++ b/roomserver/internal/perform/perform_join.go @@ -211,7 +211,7 @@ func (r *Joiner) performJoinRoomByID( util.GetLogger(ctx).WithError(keyErr).Error("GetOrCreateUserRoomPrivateKey failed") return "", "", fmt.Errorf("GetOrCreateUserRoomPrivateKey failed: %w", keyErr) } - senderID = spec.SenderID(spec.Base64Bytes(key).Encode()) + senderID = spec.SenderIDFromPseudoIDKey(key) } default: checkInvitePending = true @@ -300,7 +300,7 @@ func (r *Joiner) performJoinRoomByID( } mapping := &gomatrixserverlib.MXIDMapping{ - UserRoomKey: spec.UserRoomKey(pseudoIDKey), + UserRoomKey: spec.SenderIDFromPseudoIDKey(pseudoIDKey), UserID: userID.String(), } diff --git a/roomserver/internal/query/query.go b/roomserver/internal/query/query.go index 918619e5e3..1b5637266f 100644 --- a/roomserver/internal/query/query.go +++ b/roomserver/internal/query/query.go @@ -1029,7 +1029,7 @@ func (r *Queryer) QueryUserIDForSender(ctx context.Context, roomID spec.RoomID, } if userKeys, ok := result[roomID]; ok { - if userID, ok := userKeys[string(senderID)]; ok { + if userID, ok := userKeys[string(bytes)]; ok { return spec.NewUserID(userID, true) } } diff --git a/syncapi/consumers/roomserver.go b/syncapi/consumers/roomserver.go index 785676755e..6f6cda0aa0 100644 --- a/syncapi/consumers/roomserver.go +++ b/syncapi/consumers/roomserver.go @@ -570,7 +570,8 @@ func (s *OutputRoomEventConsumer) updateStateEvent(event *rstypes.HeaderedEvent) if event.StateKey() != nil { if *event.StateKey() != "" { - sku, err := s.rsAPI.QueryUserIDForSender(s.ctx, *validRoomID, spec.SenderID(stateKey)) + var sku *spec.UserID + sku, err = s.rsAPI.QueryUserIDForSender(s.ctx, *validRoomID, spec.SenderID(stateKey)) if err == nil && sku != nil { sKey := sku.String() event.StateKeyResolved = &sKey diff --git a/syncapi/routing/search_test.go b/syncapi/routing/search_test.go index c70abbd1be..939650a951 100644 --- a/syncapi/routing/search_test.go +++ b/syncapi/routing/search_test.go @@ -231,7 +231,7 @@ func TestSearch(t *testing.T) { stateEventIDs = append(stateEventIDs, x.EventID()) } - sp, err = db.WriteEvent(processCtx.Context(), x, spec.UserID{}, stateEvents, stateEventIDs, nil, nil, false, gomatrixserverlib.HistoryVisibilityShared) + sp, err = db.WriteEvent(processCtx.Context(), x, stateEvents, stateEventIDs, nil, nil, false, gomatrixserverlib.HistoryVisibilityShared) assert.NoError(t, err) if x.Type() != "m.room.message" { continue From 7f41a6a3f07925aca7ec19473ad7200ccef3aac2 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Thu, 15 Jun 2023 13:25:02 +0200 Subject: [PATCH 08/21] Update GMSL --- go.mod | 2 +- go.sum | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 3cf23cc888..83b83b625b 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-20230614145931-12a52cd26821 + github.com/matrix-org/gomatrixserverlib v0.0.0-20230615111912-faa3f2ede7d6 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 d206928222..97c55b1828 100644 --- a/go.sum +++ b/go.sum @@ -248,7 +248,6 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -324,10 +323,8 @@ github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 h1:s7fexw github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230614140620-4dea2171c8f1 h1:k75Fy0iQVbDjvddip/x898+BdyopBNAfL1BMNx0awA0= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230614140620-4dea2171c8f1/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230614145931-12a52cd26821 h1:MRouiZMQ3WrYROnflU9cvcUdmDrC8yN1DuljJBOhqEk= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230614145931-12a52cd26821/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230615111912-faa3f2ede7d6 h1:OPINB/pCmcjTvHKEJUq2uEmx8lgrqHCwFUHQaHdw+Ao= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230615111912-faa3f2ede7d6/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= 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= From 07960a5efcdb77fcb7de2c638226e006c64e8084 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Thu, 15 Jun 2023 14:05:26 +0200 Subject: [PATCH 09/21] Cleanup, fix test --- syncapi/storage/tables/current_room_state_test.go | 8 +++++++- syncapi/sync/requestpool.go | 2 -- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/syncapi/storage/tables/current_room_state_test.go b/syncapi/storage/tables/current_room_state_test.go index 7d4ec812ce..2df111a267 100644 --- a/syncapi/storage/tables/current_room_state_test.go +++ b/syncapi/storage/tables/current_room_state_test.go @@ -54,7 +54,13 @@ func TestCurrentRoomStateTable(t *testing.T) { events := room.CurrentState() err := sqlutil.WithTransaction(db, func(txn *sql.Tx) error { for i, ev := range events { - err := tab.UpsertRoomState(ctx, txn, ev, nil, types.StreamPosition(i)) + ev.StateKeyResolved = ev.StateKey() + userID, err := spec.NewUserID(string(ev.SenderID()), true) + if err != nil { + return err + } + ev.UserID = *userID + err = tab.UpsertRoomState(ctx, txn, ev, nil, types.StreamPosition(i)) if err != nil { return fmt.Errorf("failed to UpsertRoomState: %w", err) } diff --git a/syncapi/sync/requestpool.go b/syncapi/sync/requestpool.go index cb5205d7f1..5a92c70e1c 100644 --- a/syncapi/sync/requestpool.go +++ b/syncapi/sync/requestpool.go @@ -503,8 +503,6 @@ func (rp *RequestPool) OnIncomingSyncRequest(req *http.Request, device *userapi. } } - logrus.Infof("%#v", syncReq.Response.Rooms.Join) - return util.JSONResponse{ Code: http.StatusOK, JSON: syncReq.Response, From e6fd65b8fca00e1d85e1a76499e6f56964181255 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Thu, 15 Jun 2023 14:05:56 +0200 Subject: [PATCH 10/21] Fix empty senderID --- federationapi/consumers/roomserver.go | 2 +- roomserver/internal/perform/perform_join.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/federationapi/consumers/roomserver.go b/federationapi/consumers/roomserver.go index 19bf3730b3..6dd2fd345a 100644 --- a/federationapi/consumers/roomserver.go +++ b/federationapi/consumers/roomserver.go @@ -411,7 +411,7 @@ func JoinedHostsFromEvents(ctx context.Context, evs []gomatrixserverlib.PDU, rsA if err != nil { return nil, err } - userID, err := rsAPI.QueryUserIDForSender(ctx, *validRoomID, ev.SenderID()) + userID, err := rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(*ev.StateKey())) if err != nil { return nil, err } diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go index 092567ca6f..3883a5b964 100644 --- a/roomserver/internal/perform/perform_join.go +++ b/roomserver/internal/perform/perform_join.go @@ -204,7 +204,8 @@ func (r *Joiner) performJoinRoomByID( senderID, err = r.Queryer.QuerySenderIDForUser(ctx, *roomID, *userID) if err == nil { checkInvitePending = true - } else { + } + if senderID == "" { // create user room key if needed key, keyErr := r.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, *userID, *roomID) if keyErr != nil { From 4406c85c98e685348f2858b89485ad539dff8405 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Thu, 15 Jun 2023 14:48:21 +0200 Subject: [PATCH 11/21] Merge main, fix issues --- mediaapi/routing/download.go | 5 +++-- roomserver/internal/query/query.go | 2 +- roomserver/storage/postgres/user_room_keys_table.go | 3 ++- roomserver/storage/shared/storage_test.go | 2 +- roomserver/storage/sqlite3/user_room_keys_table.go | 3 ++- roomserver/storage/tables/user_room_keys_table_test.go | 5 +++-- syncapi/routing/search_test.go | 2 +- syncapi/storage/postgres/memberships_table.go | 2 +- syncapi/storage/sqlite3/memberships_table.go | 2 +- syncapi/storage/tables/memberships_test.go | 2 ++ 10 files changed, 17 insertions(+), 11 deletions(-) diff --git a/mediaapi/routing/download.go b/mediaapi/routing/download.go index e9f161a3c2..8fb1b6534e 100644 --- a/mediaapi/routing/download.go +++ b/mediaapi/routing/download.go @@ -341,6 +341,7 @@ func (r *downloadRequest) addDownloadFilenameToHeaders( } if len(filename) == 0 { + w.Header().Set("Content-Disposition", "attachment") return nil } @@ -376,13 +377,13 @@ func (r *downloadRequest) addDownloadFilenameToHeaders( // that would otherwise be parsed as a control character in the // Content-Disposition header w.Header().Set("Content-Disposition", fmt.Sprintf( - `inline; filename=%s%s%s`, + `attachment; filename=%s%s%s`, quote, unescaped, quote, )) } else { // For UTF-8 filenames, we quote always, as that's the standard w.Header().Set("Content-Disposition", fmt.Sprintf( - `inline; filename*=utf-8''%s`, + `attachment; filename*=utf-8''%s`, url.QueryEscape(unescaped), )) } diff --git a/roomserver/internal/query/query.go b/roomserver/internal/query/query.go index 1b5637266f..918619e5e3 100644 --- a/roomserver/internal/query/query.go +++ b/roomserver/internal/query/query.go @@ -1029,7 +1029,7 @@ func (r *Queryer) QueryUserIDForSender(ctx context.Context, roomID spec.RoomID, } if userKeys, ok := result[roomID]; ok { - if userID, ok := userKeys[string(bytes)]; ok { + if userID, ok := userKeys[string(senderID)]; ok { return spec.NewUserID(userID, true) } } diff --git a/roomserver/storage/postgres/user_room_keys_table.go b/roomserver/storage/postgres/user_room_keys_table.go index dbb4af34a0..202b0abc10 100644 --- a/roomserver/storage/postgres/user_room_keys_table.go +++ b/roomserver/storage/postgres/user_room_keys_table.go @@ -25,6 +25,7 @@ import ( "github.com/matrix-org/dendrite/internal/sqlutil" "github.com/matrix-org/dendrite/roomserver/storage/tables" "github.com/matrix-org/dendrite/roomserver/types" + "github.com/matrix-org/gomatrixserverlib/spec" ) const userRoomKeysSchema = ` @@ -145,7 +146,7 @@ func (s *userRoomKeysStatements) BulkSelectUserNIDs(ctx context.Context, txn *sq if err = rows.Scan(&userRoomKeyPair.EventStateKeyNID, &userRoomKeyPair.RoomNID, &publicKey); err != nil { return nil, err } - result[string(publicKey)] = userRoomKeyPair + result[spec.Base64Bytes(publicKey).Encode()] = userRoomKeyPair } return result, rows.Err() } diff --git a/roomserver/storage/shared/storage_test.go b/roomserver/storage/shared/storage_test.go index c7b915c7d4..612e4ef069 100644 --- a/roomserver/storage/shared/storage_test.go +++ b/roomserver/storage/shared/storage_test.go @@ -183,7 +183,7 @@ func TestUserRoomKeys(t *testing.T) { assert.NoError(t, err) wantKeys := map[spec.RoomID]map[string]string{ *roomID: { - string(key.Public().(ed25519.PublicKey)): userID.String(), + spec.Base64Bytes(key.Public().(ed25519.PublicKey)).Encode(): userID.String(), }, } assert.Equal(t, wantKeys, userIDs) diff --git a/roomserver/storage/sqlite3/user_room_keys_table.go b/roomserver/storage/sqlite3/user_room_keys_table.go index 84c8b54ec5..d58b8ac3fe 100644 --- a/roomserver/storage/sqlite3/user_room_keys_table.go +++ b/roomserver/storage/sqlite3/user_room_keys_table.go @@ -25,6 +25,7 @@ import ( "github.com/matrix-org/dendrite/internal/sqlutil" "github.com/matrix-org/dendrite/roomserver/storage/tables" "github.com/matrix-org/dendrite/roomserver/types" + "github.com/matrix-org/gomatrixserverlib/spec" ) const userRoomKeysSchema = ` @@ -159,7 +160,7 @@ func (s *userRoomKeysStatements) BulkSelectUserNIDs(ctx context.Context, txn *sq if err = rows.Scan(&userRoomKeyPair.EventStateKeyNID, &userRoomKeyPair.RoomNID, &publicKey); err != nil { return nil, err } - result[string(publicKey)] = userRoomKeyPair + result[spec.Base64Bytes(publicKey).Encode()] = userRoomKeyPair } return result, rows.Err() } diff --git a/roomserver/storage/tables/user_room_keys_table_test.go b/roomserver/storage/tables/user_room_keys_table_test.go index 8802a3c6ee..2809771b4c 100644 --- a/roomserver/storage/tables/user_room_keys_table_test.go +++ b/roomserver/storage/tables/user_room_keys_table_test.go @@ -13,6 +13,7 @@ import ( "github.com/matrix-org/dendrite/roomserver/types" "github.com/matrix-org/dendrite/setup/config" "github.com/matrix-org/dendrite/test" + "github.com/matrix-org/gomatrixserverlib/spec" "github.com/stretchr/testify/assert" ed255192 "golang.org/x/crypto/ed25519" ) @@ -101,8 +102,8 @@ func TestUserRoomKeysTable(t *testing.T) { assert.NotNil(t, gotKeys) wantKeys := map[string]types.UserRoomKeyPair{ - string(key2.Public().(ed25519.PublicKey)): {RoomNID: roomNID, EventStateKeyNID: userNID}, - string(key3.Public().(ed25519.PublicKey)): {RoomNID: roomNID, EventStateKeyNID: userNID2}, + string(spec.Base64Bytes(key2.Public().(ed25519.PublicKey)).Encode()): {RoomNID: roomNID, EventStateKeyNID: userNID}, + string(spec.Base64Bytes(key3.Public().(ed25519.PublicKey)).Encode()): {RoomNID: roomNID, EventStateKeyNID: userNID2}, } assert.Equal(t, wantKeys, gotKeys) diff --git a/syncapi/routing/search_test.go b/syncapi/routing/search_test.go index 939650a951..905a9a1ac3 100644 --- a/syncapi/routing/search_test.go +++ b/syncapi/routing/search_test.go @@ -230,7 +230,7 @@ func TestSearch(t *testing.T) { stateEvents = append(stateEvents, x) stateEventIDs = append(stateEventIDs, x.EventID()) } - + x.StateKeyResolved = x.StateKey() sp, err = db.WriteEvent(processCtx.Context(), x, stateEvents, stateEventIDs, nil, nil, false, gomatrixserverlib.HistoryVisibilityShared) assert.NoError(t, err) if x.Type() != "m.room.message" { diff --git a/syncapi/storage/postgres/memberships_table.go b/syncapi/storage/postgres/memberships_table.go index 6bf9f61a1b..09b47432b7 100644 --- a/syncapi/storage/postgres/memberships_table.go +++ b/syncapi/storage/postgres/memberships_table.go @@ -109,7 +109,7 @@ func (s *membershipsStatements) UpsertMembership( _, err = sqlutil.TxStmt(txn, s.upsertMembershipStmt).ExecContext( ctx, event.RoomID(), - event.UserID.String(), + event.StateKeyResolved, membership, event.EventID(), streamPos, diff --git a/syncapi/storage/sqlite3/memberships_table.go b/syncapi/storage/sqlite3/memberships_table.go index 6218ea6603..a9e880d2a4 100644 --- a/syncapi/storage/sqlite3/memberships_table.go +++ b/syncapi/storage/sqlite3/memberships_table.go @@ -112,7 +112,7 @@ func (s *membershipsStatements) UpsertMembership( _, err = sqlutil.TxStmt(txn, s.upsertMembershipStmt).ExecContext( ctx, event.RoomID(), - event.UserID.String(), + event.StateKeyResolved, membership, event.EventID(), streamPos, diff --git a/syncapi/storage/tables/memberships_test.go b/syncapi/storage/tables/memberships_test.go index 4afa2ac5b2..a421a97727 100644 --- a/syncapi/storage/tables/memberships_test.go +++ b/syncapi/storage/tables/memberships_test.go @@ -80,6 +80,7 @@ func TestMembershipsTable(t *testing.T) { defer cancel() for _, ev := range userEvents { + ev.StateKeyResolved = ev.StateKey() if err := table.UpsertMembership(ctx, nil, ev, types.StreamPosition(ev.Depth()), 1); err != nil { t.Fatalf("failed to upsert membership: %s", err) } @@ -134,6 +135,7 @@ func testUpsert(t *testing.T, ctx context.Context, table tables.Memberships, mem ev := room.CreateAndInsert(t, user, spec.MRoomMember, map[string]interface{}{ "membership": spec.Join, }, test.WithStateKey(user.ID)) + ev.StateKeyResolved = ev.StateKey() // Insert the same event again, but with different positions, which should get updated if err = table.UpsertMembership(ctx, nil, ev, 2, 2); err != nil { t.Fatalf("failed to upsert membership: %s", err) From b4d5c837ddd40cc51d6c5a28c682a1058ea09000 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Thu, 15 Jun 2023 15:02:40 +0200 Subject: [PATCH 12/21] Update test --- syncapi/storage/storage_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/syncapi/storage/storage_test.go b/syncapi/storage/storage_test.go index bc64aa50fa..530ecc68ff 100644 --- a/syncapi/storage/storage_test.go +++ b/syncapi/storage/storage_test.go @@ -41,6 +41,7 @@ func MustWriteEvents(t *testing.T, db storage.Database, events []*rstypes.Header var addStateEventIDs []string var removeStateEventIDs []string if ev.StateKey() != nil { + ev.StateKeyResolved = ev.StateKey() addStateEvents = append(addStateEvents, ev) addStateEventIDs = append(addStateEventIDs, ev.EventID()) } From 31609d62fe524d2082056557267882f6cd8c94e4 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Thu, 15 Jun 2023 18:04:31 +0200 Subject: [PATCH 13/21] Replace senderID with userID in powerlevel events, workaround invites --- clientapi/routing/membership.go | 24 ++++++-- roomserver/api/api.go | 1 + syncapi/consumers/roomserver.go | 2 + syncapi/storage/postgres/invites_table.go | 2 +- syncapi/storage/sqlite3/invites_table.go | 2 +- syncapi/streams/stream_pdu.go | 73 +++++++++++++++++++++++ 6 files changed, 98 insertions(+), 6 deletions(-) diff --git a/clientapi/routing/membership.go b/clientapi/routing/membership.go index 29ee2b1e52..c0aad98405 100644 --- a/clientapi/routing/membership.go +++ b/clientapi/routing/membership.go @@ -22,10 +22,6 @@ import ( "time" "github.com/getsentry/sentry-go" - "github.com/matrix-org/gomatrixserverlib" - "github.com/matrix-org/gomatrixserverlib/fclient" - "github.com/matrix-org/gomatrixserverlib/spec" - appserviceAPI "github.com/matrix-org/dendrite/appservice/api" "github.com/matrix-org/dendrite/clientapi/auth/authtypes" "github.com/matrix-org/dendrite/clientapi/httputil" @@ -36,6 +32,9 @@ import ( "github.com/matrix-org/dendrite/roomserver/types" "github.com/matrix-org/dendrite/setup/config" userapi "github.com/matrix-org/dendrite/userapi/api" + "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/gomatrixserverlib/fclient" + "github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/util" ) @@ -455,6 +454,23 @@ func buildMembershipEvent( return nil, err } + // If we're inviting a local user, we can generate the needed key here. + if targetSenderID == "" && cfg.Matrix.IsLocalServerName(targetID.Domain()) { // todo: remove + roomVersion, err := rsAPI.QueryRoomVersionForRoom(ctx, roomID) + if err != nil { + return nil, err + } + switch roomVersion { + case gomatrixserverlib.RoomVersionPseudoIDs: + key, err := rsAPI.GetOrCreateUserRoomPrivateKey(ctx, *targetID, *validRoomID) + if err != nil { + return nil, err + } + targetSenderID = spec.SenderIDFromPseudoIDKey(key) + } + + } + identity, err := rsAPI.SigningIdentityFor(ctx, *validRoomID, *userID) if err != nil { return nil, err diff --git a/roomserver/api/api.go b/roomserver/api/api.go index ce6594b7d8..5d7728bd47 100644 --- a/roomserver/api/api.go +++ b/roomserver/api/api.go @@ -185,6 +185,7 @@ type ClientRoomserverAPI interface { QueryBulkStateContentAPI QueryEventsAPI QuerySenderIDAPI + UserRoomPrivateKeyCreator QueryMembershipForUser(ctx context.Context, req *QueryMembershipForUserRequest, res *QueryMembershipForUserResponse) error QueryMembershipsForRoom(ctx context.Context, req *QueryMembershipsForRoomRequest, res *QueryMembershipsForRoomResponse) error QueryRoomsForUser(ctx context.Context, req *QueryRoomsForUserRequest, res *QueryRoomsForUserResponse) error diff --git a/syncapi/consumers/roomserver.go b/syncapi/consumers/roomserver.go index 6f6cda0aa0..fed35b95f7 100644 --- a/syncapi/consumers/roomserver.go +++ b/syncapi/consumers/roomserver.go @@ -426,6 +426,8 @@ func (s *OutputRoomEventConsumer) onNewInviteEvent( return } + msg.Event.UserID = *userID + pduPos, err := s.db.AddInviteEvent(ctx, msg.Event) if err != nil { sentry.CaptureException(err) diff --git a/syncapi/storage/postgres/invites_table.go b/syncapi/storage/postgres/invites_table.go index 267209bba6..7b8d2d7336 100644 --- a/syncapi/storage/postgres/invites_table.go +++ b/syncapi/storage/postgres/invites_table.go @@ -101,7 +101,7 @@ func (s *inviteEventsStatements) InsertInviteEvent( ctx, inviteEvent.RoomID(), inviteEvent.EventID(), - *inviteEvent.StateKey(), + inviteEvent.UserID.String(), headeredJSON, ).Scan(&streamPos) return diff --git a/syncapi/storage/sqlite3/invites_table.go b/syncapi/storage/sqlite3/invites_table.go index 347523cf79..7e0d895f12 100644 --- a/syncapi/storage/sqlite3/invites_table.go +++ b/syncapi/storage/sqlite3/invites_table.go @@ -108,7 +108,7 @@ func (s *inviteEventsStatements) InsertInviteEvent( streamPos, inviteEvent.RoomID(), inviteEvent.EventID(), - *inviteEvent.StateKey(), + inviteEvent.UserID.String(), headeredJSON, ) return diff --git a/syncapi/streams/stream_pdu.go b/syncapi/streams/stream_pdu.go index 7939dd8fad..545cbd9637 100644 --- a/syncapi/streams/stream_pdu.go +++ b/syncapi/streams/stream_pdu.go @@ -3,6 +3,7 @@ package streams import ( "context" "database/sql" + "encoding/json" "fmt" "time" @@ -15,6 +16,7 @@ import ( "github.com/matrix-org/dendrite/syncapi/types" userapi "github.com/matrix-org/dendrite/userapi/api" "github.com/matrix-org/gomatrixserverlib/spec" + "github.com/tidwall/sjson" "github.com/matrix-org/dendrite/syncapi/notifier" "github.com/matrix-org/gomatrixserverlib" @@ -346,6 +348,42 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse( // Now that we've filtered the timeline, work out which state events are still // left. Anything that appears in the filtered timeline will be removed from the // "state" section and kept in "timeline". + + for i, ev := range events { + if ev.Version() != gomatrixserverlib.RoomVersionPseudoIDs { + continue + } + if ev.Type() != spec.MRoomPowerLevels || !ev.StateKeyEquals("") { + continue + } + pls, err := gomatrixserverlib.NewPowerLevelContentFromEvent(ev) + if err != nil { + return r.From, err + } + newPls := make(map[string]int64) + for user, level := range pls.Users { + validRoomID, _ := spec.NewRoomID(ev.RoomID()) + userID, err := p.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(user)) + if err != nil { + return r.From, err + } + newPls[userID.String()] = level + } + newPlBytes, err := json.Marshal(newPls) + if err != nil { + return r.From, err + } + newEv, err := sjson.SetRawBytes(ev.JSON(), "content.users", newPlBytes) + if err != nil { + return r.From, err + } + evNew, err := gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionPseudoIDs).NewEventFromTrustedJSON(newEv, false) + if err != nil { + return r.From, err + } + events[i] = &rstypes.HeaderedEvent{PDU: evNew} + } + sEvents := gomatrixserverlib.HeaderedReverseTopologicalOrdering( gomatrixserverlib.ToPDUs(removeDuplicates(delta.StateEvents, events)), gomatrixserverlib.TopologicalOrderByAuthEvents, @@ -563,6 +601,41 @@ func (p *PDUStreamProvider) getJoinResponseForCompleteSync( prevBatch.Decrement() } + for i, ev := range events { + if ev.Version() != gomatrixserverlib.RoomVersionPseudoIDs { + continue + } + if ev.Type() != spec.MRoomPowerLevels || !ev.StateKeyEquals("") { + continue + } + pls, err := gomatrixserverlib.NewPowerLevelContentFromEvent(ev) + if err != nil { + return nil, err + } + newPls := make(map[string]int64) + for user, level := range pls.Users { + validRoomID, _ := spec.NewRoomID(ev.RoomID()) + userID, err := p.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(user)) + if err != nil { + return nil, err + } + newPls[userID.String()] = level + } + newPlBytes, err := json.Marshal(newPls) + if err != nil { + return nil, err + } + newEv, err := sjson.SetRawBytes(ev.JSON(), "content.users", newPlBytes) + if err != nil { + return nil, err + } + evNew, err := gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionPseudoIDs).NewEventFromTrustedJSON(newEv, false) + if err != nil { + return nil, err + } + events[i] = &rstypes.HeaderedEvent{PDU: evNew} + } + jr.Timeline.PrevBatch = prevBatch jr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), synctypes.FormatSync, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) { return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID) From 708e95090ae72f4bfafc78890fca14216a28df13 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Thu, 15 Jun 2023 18:05:40 +0200 Subject: [PATCH 14/21] Update GMSL --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 83b83b625b..faa7c47db3 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-20230615111912-faa3f2ede7d6 + github.com/matrix-org/gomatrixserverlib v0.0.0-20230615155745-0c9f18717a12 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 97c55b1828..db58a3b55b 100644 --- a/go.sum +++ b/go.sum @@ -323,8 +323,8 @@ github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 h1:s7fexw github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230615111912-faa3f2ede7d6 h1:OPINB/pCmcjTvHKEJUq2uEmx8lgrqHCwFUHQaHdw+Ao= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230615111912-faa3f2ede7d6/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230615155745-0c9f18717a12 h1:KqEEv5zDBgsLV/dkQPBpuMg65U8Us7AK2T8uQMKyu4k= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230615155745-0c9f18717a12/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= 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= From 75ffbc6aa7633100e04019787a09f92d509c9b94 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Thu, 15 Jun 2023 18:11:10 +0200 Subject: [PATCH 15/21] Linter --- clientapi/routing/membership.go | 6 ++++-- syncapi/streams/stream_pdu.go | 18 ++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/clientapi/routing/membership.go b/clientapi/routing/membership.go index c0aad98405..c6744ed855 100644 --- a/clientapi/routing/membership.go +++ b/clientapi/routing/membership.go @@ -456,13 +456,15 @@ func buildMembershipEvent( // If we're inviting a local user, we can generate the needed key here. if targetSenderID == "" && cfg.Matrix.IsLocalServerName(targetID.Domain()) { // todo: remove - roomVersion, err := rsAPI.QueryRoomVersionForRoom(ctx, roomID) + var roomVersion gomatrixserverlib.RoomVersion + roomVersion, err = rsAPI.QueryRoomVersionForRoom(ctx, roomID) if err != nil { return nil, err } switch roomVersion { case gomatrixserverlib.RoomVersionPseudoIDs: - key, err := rsAPI.GetOrCreateUserRoomPrivateKey(ctx, *targetID, *validRoomID) + var key ed25519.PrivateKey + key, err = rsAPI.GetOrCreateUserRoomPrivateKey(ctx, *targetID, *validRoomID) if err != nil { return nil, err } diff --git a/syncapi/streams/stream_pdu.go b/syncapi/streams/stream_pdu.go index 545cbd9637..699f78e960 100644 --- a/syncapi/streams/stream_pdu.go +++ b/syncapi/streams/stream_pdu.go @@ -356,28 +356,32 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse( if ev.Type() != spec.MRoomPowerLevels || !ev.StateKeyEquals("") { continue } - pls, err := gomatrixserverlib.NewPowerLevelContentFromEvent(ev) + var pls gomatrixserverlib.PowerLevelContent + pls, err = gomatrixserverlib.NewPowerLevelContentFromEvent(ev) if err != nil { return r.From, err } newPls := make(map[string]int64) + var userID *spec.UserID for user, level := range pls.Users { validRoomID, _ := spec.NewRoomID(ev.RoomID()) - userID, err := p.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(user)) + userID, err = p.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(user)) if err != nil { return r.From, err } newPls[userID.String()] = level } - newPlBytes, err := json.Marshal(newPls) + var newPlBytes, newEv []byte + newPlBytes, err = json.Marshal(newPls) if err != nil { return r.From, err } - newEv, err := sjson.SetRawBytes(ev.JSON(), "content.users", newPlBytes) + newEv, err = sjson.SetRawBytes(ev.JSON(), "content.users", newPlBytes) if err != nil { return r.From, err } - evNew, err := gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionPseudoIDs).NewEventFromTrustedJSON(newEv, false) + var evNew gomatrixserverlib.PDU + evNew, err = gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionPseudoIDs).NewEventFromTrustedJSON(newEv, false) if err != nil { return r.From, err } @@ -508,6 +512,7 @@ func applyHistoryVisibilityFilter( return events, nil } +// nolint: gocyclo func (p *PDUStreamProvider) getJoinResponseForCompleteSync( ctx context.Context, snapshot storage.DatabaseTransaction, @@ -613,9 +618,10 @@ func (p *PDUStreamProvider) getJoinResponseForCompleteSync( return nil, err } newPls := make(map[string]int64) + var userID *spec.UserID for user, level := range pls.Users { validRoomID, _ := spec.NewRoomID(ev.RoomID()) - userID, err := p.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(user)) + userID, err = p.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(user)) if err != nil { return nil, err } From 45003cc564fd64c6be333e374822729c1793c011 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Fri, 16 Jun 2023 09:29:51 +0200 Subject: [PATCH 16/21] Also set the prev_content, if present --- syncapi/streams/stream_pdu.go | 126 ++++++++++++++++++++-------------- 1 file changed, 75 insertions(+), 51 deletions(-) diff --git a/syncapi/streams/stream_pdu.go b/syncapi/streams/stream_pdu.go index 699f78e960..8dbf2c6afd 100644 --- a/syncapi/streams/stream_pdu.go +++ b/syncapi/streams/stream_pdu.go @@ -16,6 +16,7 @@ import ( "github.com/matrix-org/dendrite/syncapi/types" userapi "github.com/matrix-org/dendrite/userapi/api" "github.com/matrix-org/gomatrixserverlib/spec" + "github.com/tidwall/gjson" "github.com/tidwall/sjson" "github.com/matrix-org/dendrite/syncapi/notifier" @@ -356,36 +357,12 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse( if ev.Type() != spec.MRoomPowerLevels || !ev.StateKeyEquals("") { continue } - var pls gomatrixserverlib.PowerLevelContent - pls, err = gomatrixserverlib.NewPowerLevelContentFromEvent(ev) + var newEvent gomatrixserverlib.PDU + newEvent, err = p.updatePowerLevelEvent(ctx, ev) if err != nil { return r.From, err } - newPls := make(map[string]int64) - var userID *spec.UserID - for user, level := range pls.Users { - validRoomID, _ := spec.NewRoomID(ev.RoomID()) - userID, err = p.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(user)) - if err != nil { - return r.From, err - } - newPls[userID.String()] = level - } - var newPlBytes, newEv []byte - newPlBytes, err = json.Marshal(newPls) - if err != nil { - return r.From, err - } - newEv, err = sjson.SetRawBytes(ev.JSON(), "content.users", newPlBytes) - if err != nil { - return r.From, err - } - var evNew gomatrixserverlib.PDU - evNew, err = gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionPseudoIDs).NewEventFromTrustedJSON(newEv, false) - if err != nil { - return r.From, err - } - events[i] = &rstypes.HeaderedEvent{PDU: evNew} + events[i] = &rstypes.HeaderedEvent{PDU: newEvent} } sEvents := gomatrixserverlib.HeaderedReverseTopologicalOrdering( @@ -463,6 +440,75 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse( return latestPosition, nil } +func (p *PDUStreamProvider) updatePowerLevelEvent(ctx context.Context, ev *rstypes.HeaderedEvent) (gomatrixserverlib.PDU, error) { + pls, err := gomatrixserverlib.NewPowerLevelContentFromEvent(ev) + if err != nil { + return nil, err + } + newPls := make(map[string]int64) + var userID *spec.UserID + for user, level := range pls.Users { + validRoomID, _ := spec.NewRoomID(ev.RoomID()) + userID, err = p.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(user)) + if err != nil { + return nil, err + } + newPls[userID.String()] = level + } + var newPlBytes, newEv []byte + newPlBytes, err = json.Marshal(newPls) + if err != nil { + return nil, err + } + newEv, err = sjson.SetRawBytes(ev.JSON(), "content.users", newPlBytes) + if err != nil { + return nil, err + } + + // do the same for prev content + prevContent := gjson.GetBytes(ev.JSON(), "unsigned.prev_content") + if !prevContent.Exists() { + var evNew gomatrixserverlib.PDU + evNew, err = gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionPseudoIDs).NewEventFromTrustedJSON(newEv, false) + if err != nil { + return nil, err + } + + return evNew, err + } + pls = gomatrixserverlib.PowerLevelContent{} + err = json.Unmarshal([]byte(prevContent.Raw), &pls) + if err != nil { + return nil, err + } + + newPls = make(map[string]int64) + for user, level := range pls.Users { + validRoomID, _ := spec.NewRoomID(ev.RoomID()) + userID, err = p.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(user)) + if err != nil { + return nil, err + } + newPls[userID.String()] = level + } + newPlBytes, err = json.Marshal(newPls) + if err != nil { + return nil, err + } + newEv, err = sjson.SetRawBytes(newEv, "unsigned.prev_content.users", newPlBytes) + if err != nil { + return nil, err + } + + var evNew gomatrixserverlib.PDU + evNew, err = gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionPseudoIDs).NewEventFromTrustedJSON(newEv, false) + if err != nil { + return nil, err + } + + return evNew, err +} + // applyHistoryVisibilityFilter gets the current room state and supplies it to ApplyHistoryVisibilityFilter, to make // sure we always return the required events in the timeline. func applyHistoryVisibilityFilter( @@ -613,33 +659,11 @@ func (p *PDUStreamProvider) getJoinResponseForCompleteSync( if ev.Type() != spec.MRoomPowerLevels || !ev.StateKeyEquals("") { continue } - pls, err := gomatrixserverlib.NewPowerLevelContentFromEvent(ev) - if err != nil { - return nil, err - } - newPls := make(map[string]int64) - var userID *spec.UserID - for user, level := range pls.Users { - validRoomID, _ := spec.NewRoomID(ev.RoomID()) - userID, err = p.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(user)) - if err != nil { - return nil, err - } - newPls[userID.String()] = level - } - newPlBytes, err := json.Marshal(newPls) - if err != nil { - return nil, err - } - newEv, err := sjson.SetRawBytes(ev.JSON(), "content.users", newPlBytes) - if err != nil { - return nil, err - } - evNew, err := gomatrixserverlib.MustGetRoomVersion(gomatrixserverlib.RoomVersionPseudoIDs).NewEventFromTrustedJSON(newEv, false) + newEvent, err := p.updatePowerLevelEvent(ctx, ev) if err != nil { return nil, err } - events[i] = &rstypes.HeaderedEvent{PDU: evNew} + events[i] = &rstypes.HeaderedEvent{PDU: newEvent} } jr.Timeline.PrevBatch = prevBatch From f2e98152487ff04ca7a6efcab3cc17c528163f2c Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Fri, 16 Jun 2023 12:33:57 +0200 Subject: [PATCH 17/21] Change the powerlevels from userID -> senderID --- clientapi/routing/sendevent.go | 46 +++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/clientapi/routing/sendevent.go b/clientapi/routing/sendevent.go index 1593814998..41a3793ae2 100644 --- a/clientapi/routing/sendevent.go +++ b/clientapi/routing/sendevent.go @@ -23,12 +23,6 @@ import ( "sync" "time" - "github.com/matrix-org/gomatrixserverlib" - "github.com/matrix-org/gomatrixserverlib/spec" - "github.com/matrix-org/util" - "github.com/prometheus/client_golang/prometheus" - "github.com/sirupsen/logrus" - "github.com/matrix-org/dendrite/clientapi/httputil" "github.com/matrix-org/dendrite/internal/eventutil" "github.com/matrix-org/dendrite/internal/transactions" @@ -36,6 +30,11 @@ import ( "github.com/matrix-org/dendrite/roomserver/types" "github.com/matrix-org/dendrite/setup/config" userapi "github.com/matrix-org/dendrite/userapi/api" + "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/gomatrixserverlib/spec" + "github.com/matrix-org/util" + "github.com/prometheus/client_golang/prometheus" + "github.com/sirupsen/logrus" ) // http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid @@ -68,6 +67,8 @@ var sendEventDuration = prometheus.NewHistogramVec( // /rooms/{roomID}/send/{eventType} // /rooms/{roomID}/send/{eventType}/{txnID} // /rooms/{roomID}/state/{eventType}/{stateKey} +// +// nolint: gocyclo func SendEvent( req *http.Request, device *userapi.Device, @@ -121,6 +122,17 @@ func SendEvent( delete(r, "join_authorised_via_users_server") } + // for power level events we need to replace the userID with the pseudoID + if roomVersion == gomatrixserverlib.RoomVersionPseudoIDs && eventType == spec.MRoomPowerLevels { + err = updatePowerLevels(req, r, roomID, rsAPI) + if err != nil { + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{Err: err.Error()}, + } + } + } + evTime, err := httputil.ParseTSParam(req) if err != nil { return util.JSONResponse{ @@ -225,6 +237,28 @@ func SendEvent( return res } +func updatePowerLevels(req *http.Request, r map[string]interface{}, roomID string, rsAPI api.ClientRoomserverAPI) error { + userMap := r["users"].(map[string]interface{}) + validRoomID, err := spec.NewRoomID(roomID) + if err != nil { + return err + } + for user, level := range userMap { + uID, err := spec.NewUserID(user, true) + if err != nil { + continue // we're modifying the map in place, so we're going to have invalid userIDs after the first iteration + } + senderID, err := rsAPI.QuerySenderIDForUser(req.Context(), *validRoomID, *uID) + if err != nil { + return err + } + userMap[string(senderID)] = level + delete(userMap, user) + } + r["users"] = userMap + return nil +} + // stateEqual compares the new and the existing state event content. If they are equal, returns a *util.JSONResponse // with the existing event_id, making this an idempotent request. func stateEqual(ctx context.Context, rsAPI api.ClientRoomserverAPI, eventType, stateKey, roomID string, newContent map[string]interface{}) *util.JSONResponse { From 52c888c507118815cb2b3e1b59a0f0f3503bc971 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Fri, 16 Jun 2023 12:54:00 +0200 Subject: [PATCH 18/21] Update GMSL --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index faa7c47db3..145e479a95 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-20230615155745-0c9f18717a12 + github.com/matrix-org/gomatrixserverlib v0.0.0-20230616092350-99b78e30a272 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 db58a3b55b..b5dc6dfddd 100644 --- a/go.sum +++ b/go.sum @@ -323,8 +323,8 @@ github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 h1:s7fexw github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230615155745-0c9f18717a12 h1:KqEEv5zDBgsLV/dkQPBpuMg65U8Us7AK2T8uQMKyu4k= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230615155745-0c9f18717a12/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230616092350-99b78e30a272 h1:YDpKHyojqwQU/L6I0bjp/BYPfn1aq/D2iBxC0jCSc/0= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230616092350-99b78e30a272/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= 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= From 88b0f6a053afcdcf3df9b5fb3f842bdfec4395e7 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Wed, 28 Jun 2023 12:11:42 +0200 Subject: [PATCH 19/21] We don't need to sign these events (correctly)? --- federationapi/routing/join.go | 10 ++-------- federationapi/routing/leave.go | 10 ++-------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/federationapi/routing/join.go b/federationapi/routing/join.go index b886382f73..7aa50f65a2 100644 --- a/federationapi/routing/join.go +++ b/federationapi/routing/join.go @@ -64,13 +64,7 @@ func MakeJoin( } createJoinTemplate := func(proto *gomatrixserverlib.ProtoEvent) (gomatrixserverlib.PDU, []gomatrixserverlib.PDU, error) { - // TODO: remove this once the join dance understands pseudo IDs - var dummyUserID *spec.UserID - dummyUserID, err = spec.NewUserID(fmt.Sprintf("@dummy:%s", request.Destination()), true) - if err != nil { - return nil, nil, err - } - identity, signErr := rsAPI.SigningIdentityFor(httpReq.Context(), roomID, *dummyUserID) + identity, signErr := cfg.Matrix.SigningIdentityFor(request.Destination()) if signErr != nil { util.GetLogger(httpReq.Context()).WithError(signErr).Errorf("obtaining signing identity for %s failed", request.Destination()) return nil, nil, spec.NotFound(fmt.Sprintf("Server name %q does not exist", request.Destination())) @@ -79,7 +73,7 @@ func MakeJoin( queryRes := api.QueryLatestEventsAndStateResponse{ RoomVersion: roomVersion, } - event, signErr := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, &identity, time.Now(), rsAPI, &queryRes) + event, signErr := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, identity, time.Now(), rsAPI, &queryRes) switch e := signErr.(type) { case nil: case eventutil.ErrRoomNoExists: diff --git a/federationapi/routing/leave.go b/federationapi/routing/leave.go index 3806341b3f..5c8dd00f3e 100644 --- a/federationapi/routing/leave.go +++ b/federationapi/routing/leave.go @@ -59,20 +59,14 @@ func MakeLeave( } createLeaveTemplate := func(proto *gomatrixserverlib.ProtoEvent) (gomatrixserverlib.PDU, []gomatrixserverlib.PDU, error) { - // TODO: remove this once the leave dance understands pseudo IDs - var dummyUserID *spec.UserID - dummyUserID, err = spec.NewUserID(fmt.Sprintf("@dummy:%s", request.Destination()), true) - if err != nil { - return nil, nil, err - } - identity, signErr := rsAPI.SigningIdentityFor(httpReq.Context(), roomID, *dummyUserID) + identity, signErr := cfg.Matrix.SigningIdentityFor(request.Destination()) if signErr != nil { util.GetLogger(httpReq.Context()).WithError(signErr).Errorf("obtaining signing identity for %s failed", request.Destination()) return nil, nil, spec.NotFound(fmt.Sprintf("Server name %q does not exist", request.Destination())) } queryRes := api.QueryLatestEventsAndStateResponse{} - event, buildErr := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, &identity, time.Now(), rsAPI, &queryRes) + event, buildErr := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, identity, time.Now(), rsAPI, &queryRes) switch e := buildErr.(type) { case nil: case eventutil.ErrRoomNoExists: From 6697f4377d749ac266ab8b381aee37244a4b9f79 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Wed, 28 Jun 2023 12:13:37 +0200 Subject: [PATCH 20/21] Move creation of pseudo ID keys to the roomserver --- clientapi/routing/membership.go | 19 ------------------- roomserver/internal/perform/perform_invite.go | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/clientapi/routing/membership.go b/clientapi/routing/membership.go index c6744ed855..60b120b9ce 100644 --- a/clientapi/routing/membership.go +++ b/clientapi/routing/membership.go @@ -454,25 +454,6 @@ func buildMembershipEvent( return nil, err } - // If we're inviting a local user, we can generate the needed key here. - if targetSenderID == "" && cfg.Matrix.IsLocalServerName(targetID.Domain()) { // todo: remove - var roomVersion gomatrixserverlib.RoomVersion - roomVersion, err = rsAPI.QueryRoomVersionForRoom(ctx, roomID) - if err != nil { - return nil, err - } - switch roomVersion { - case gomatrixserverlib.RoomVersionPseudoIDs: - var key ed25519.PrivateKey - key, err = rsAPI.GetOrCreateUserRoomPrivateKey(ctx, *targetID, *validRoomID) - if err != nil { - return nil, err - } - targetSenderID = spec.SenderIDFromPseudoIDKey(key) - } - - } - identity, err := rsAPI.SigningIdentityFor(ctx, *validRoomID, *userID) if err != nil { return nil, err diff --git a/roomserver/internal/perform/perform_invite.go b/roomserver/internal/perform/perform_invite.go index babd5f8123..f19a508a3a 100644 --- a/roomserver/internal/perform/perform_invite.go +++ b/roomserver/internal/perform/perform_invite.go @@ -153,6 +153,23 @@ func (r *Inviter) PerformInvite( } isTargetLocal := r.Cfg.Matrix.IsLocalServerName(invitedUser.Domain()) + // If we're inviting a local user, we can generate the needed pseudoID key here. (if needed) + if isTargetLocal { + var roomVersion gomatrixserverlib.RoomVersion + roomVersion, err = r.DB.GetRoomVersion(ctx, event.RoomID()) + if err != nil { + return err + } + + switch roomVersion { + case gomatrixserverlib.RoomVersionPseudoIDs: + _, err = r.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, *invitedUser, *validRoomID) + if err != nil { + return err + } + } + } + invitedSenderID, err := r.RSAPI.QuerySenderIDForUser(ctx, *validRoomID, *invitedUser) if err != nil { return fmt.Errorf("failed looking up senderID for invited user") From 86f217f692b155bb22cf21cd521a0285625020e1 Mon Sep 17 00:00:00 2001 From: Till <2353100+S7evinK@users.noreply.github.com> Date: Wed, 28 Jun 2023 19:22:39 +0200 Subject: [PATCH 21/21] Make it possible to join pseudo ID rooms (#3119) This should allow us to join pseudo ID rooms over federation. Also needs https://github.com/matrix-org/gomatrixserverlib/pull/397 --- federationapi/internal/perform.go | 20 +++- federationapi/routing/join.go | 12 +++ go.mod | 4 +- go.sum | 4 +- roomserver/api/api.go | 3 +- roomserver/internal/api.go | 15 ++- roomserver/internal/input/input_events.go | 2 +- .../internal/perform/perform_backfill.go | 2 +- .../internal/perform/perform_create_room.go | 2 +- roomserver/internal/perform/perform_join.go | 2 +- roomserver/roomserver_test.go | 10 +- roomserver/storage/interface.go | 5 +- roomserver/storage/shared/storage.go | 101 +++++++++--------- .../storage/sqlite3/user_room_keys_table.go | 5 +- syncapi/streams/stream_pdu.go | 28 ++++- 15 files changed, 145 insertions(+), 70 deletions(-) diff --git a/federationapi/internal/perform.go b/federationapi/internal/perform.go index 5a98cd2180..515b3377de 100644 --- a/federationapi/internal/perform.go +++ b/federationapi/internal/perform.go @@ -2,6 +2,7 @@ package internal import ( "context" + "crypto/ed25519" "encoding/json" "errors" "fmt" @@ -170,13 +171,24 @@ func (r *FederationInternalAPI) performJoinUsingServer( UserIDQuerier: func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) { return r.rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }, - SenderIDCreator: func(ctx context.Context, userID spec.UserID, roomID spec.RoomID) (spec.SenderID, error) { + GetOrCreateSenderID: func(ctx context.Context, userID spec.UserID, roomID spec.RoomID, roomVersion string) (spec.SenderID, ed25519.PrivateKey, error) { + // assign a roomNID, otherwise we can't create a private key for the user + _, nidErr := r.rsAPI.AssignRoomNID(ctx, roomID, gomatrixserverlib.RoomVersion(roomVersion)) + if nidErr != nil { + return "", nil, nidErr + } key, keyErr := r.rsAPI.GetOrCreateUserRoomPrivateKey(ctx, userID, roomID) if keyErr != nil { - return "", keyErr + return "", nil, keyErr } - - return spec.SenderIDFromPseudoIDKey(key), nil + return spec.SenderIDFromPseudoIDKey(key), key, nil + }, + StoreSenderIDFromPublicID: func(ctx context.Context, senderID spec.SenderID, userIDRaw string, roomID spec.RoomID) error { + storeUserID, userErr := spec.NewUserID(userIDRaw, true) + if userErr != nil { + return userErr + } + return r.rsAPI.StoreUserRoomPublicKey(ctx, senderID, *storeUserID, roomID) }, } response, joinErr := gomatrixserverlib.PerformJoin(ctx, r, joinInput) diff --git a/federationapi/routing/join.go b/federationapi/routing/join.go index 7aa50f65a2..bfa1ba8b8d 100644 --- a/federationapi/routing/join.go +++ b/federationapi/routing/join.go @@ -15,6 +15,7 @@ package routing import ( + "context" "fmt" "net/http" "sort" @@ -107,6 +108,10 @@ func MakeJoin( } } + if senderID == "" { + senderID = spec.SenderID(userID.String()) + } + input := gomatrixserverlib.HandleMakeJoinInput{ Context: httpReq.Context(), UserID: userID, @@ -218,6 +223,13 @@ func SendJoin( UserIDQuerier: func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(httpReq.Context(), roomID, senderID) }, + StoreSenderIDFromPublicID: func(ctx context.Context, senderID spec.SenderID, userIDRaw string, roomID spec.RoomID) error { + userID, userErr := spec.NewUserID(userIDRaw, true) + if userErr != nil { + return userErr + } + return rsAPI.StoreUserRoomPublicKey(ctx, senderID, *userID, roomID) + }, } response, joinErr := gomatrixserverlib.HandleSendJoin(input) switch e := joinErr.(type) { diff --git a/go.mod b/go.mod index 145e479a95..f43760e31d 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-20230616092350-99b78e30a272 + github.com/matrix-org/gomatrixserverlib v0.0.0-20230628151943-f6e3c7f7b093 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 @@ -43,6 +43,7 @@ require ( github.com/yggdrasil-network/yggdrasil-go v0.4.6 go.uber.org/atomic v1.10.0 golang.org/x/crypto v0.10.0 + golang.org/x/exp v0.0.0-20221205204356-47842c84f3db golang.org/x/image v0.5.0 golang.org/x/mobile v0.0.0-20221020085226-b36e6246172e golang.org/x/sync v0.1.0 @@ -124,7 +125,6 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect go.etcd.io/bbolt v1.3.6 // indirect - golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect golang.org/x/mod v0.8.0 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/sys v0.9.0 // indirect diff --git a/go.sum b/go.sum index b5dc6dfddd..e261f551fe 100644 --- a/go.sum +++ b/go.sum @@ -323,8 +323,8 @@ github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 h1:s7fexw github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230616092350-99b78e30a272 h1:YDpKHyojqwQU/L6I0bjp/BYPfn1aq/D2iBxC0jCSc/0= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230616092350-99b78e30a272/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230628151943-f6e3c7f7b093 h1:FHd3SYhU2ZxZhkssZ/7ms5+M2j+g94lYp8ztvA1E6tA= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230628151943-f6e3c7f7b093/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= 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/roomserver/api/api.go b/roomserver/api/api.go index 5d7728bd47..ab56529c5d 100644 --- a/roomserver/api/api.go +++ b/roomserver/api/api.go @@ -74,6 +74,7 @@ type RoomserverInternalAPI interface { type UserRoomPrivateKeyCreator interface { // GetOrCreateUserRoomPrivateKey gets the user room key for the specified user. If no key exists yet, a new one is created. GetOrCreateUserRoomPrivateKey(ctx context.Context, userID spec.UserID, roomID spec.RoomID) (ed25519.PrivateKey, error) + StoreUserRoomPublicKey(ctx context.Context, senderID spec.SenderID, userID spec.UserID, roomID spec.RoomID) error } type InputRoomEventsAPI interface { @@ -235,7 +236,7 @@ type FederationRoomserverAPI interface { QueryBulkStateContentAPI QuerySenderIDAPI UserRoomPrivateKeyCreator - + AssignRoomNID(ctx context.Context, roomID spec.RoomID, roomVersion gomatrixserverlib.RoomVersion) (roomNID types.RoomNID, err error) SigningIdentityFor(ctx context.Context, roomID spec.RoomID, senderID spec.UserID) (fclient.SigningIdentity, error) // QueryServerBannedFromRoom returns whether a server is banned from a room by server ACLs. QueryServerBannedFromRoom(ctx context.Context, req *QueryServerBannedFromRoomRequest, res *QueryServerBannedFromRoomResponse) error diff --git a/roomserver/internal/api.go b/roomserver/internal/api.go index 22ae23c80d..2e12671ffa 100644 --- a/roomserver/internal/api.go +++ b/roomserver/internal/api.go @@ -289,6 +289,15 @@ func (r *RoomserverInternalAPI) GetOrCreateUserRoomPrivateKey(ctx context.Contex return key, nil } +func (r *RoomserverInternalAPI) StoreUserRoomPublicKey(ctx context.Context, senderID spec.SenderID, userID spec.UserID, roomID spec.RoomID) error { + pubKeyBytes, err := senderID.RawBytes() + if err != nil { + return err + } + _, err = r.DB.InsertUserRoomPublicKey(ctx, userID, roomID, ed25519.PublicKey(pubKeyBytes)) + return err +} + func (r *RoomserverInternalAPI) SigningIdentityFor(ctx context.Context, roomID spec.RoomID, senderID spec.UserID) (fclient.SigningIdentity, error) { roomVersion, ok := r.Cache.GetRoomVersion(roomID.String()) if !ok { @@ -307,7 +316,7 @@ func (r *RoomserverInternalAPI) SigningIdentityFor(ctx context.Context, roomID s } return fclient.SigningIdentity{ PrivateKey: privKey, - KeyID: "ed25519", + KeyID: "ed25519:1", ServerName: "self", }, nil } @@ -317,3 +326,7 @@ func (r *RoomserverInternalAPI) SigningIdentityFor(ctx context.Context, roomID s } return *identity, err } + +func (r *RoomserverInternalAPI) AssignRoomNID(ctx context.Context, roomID spec.RoomID, roomVersion gomatrixserverlib.RoomVersion) (roomNID types.RoomNID, err error) { + return r.DB.AssignRoomNID(ctx, roomID, roomVersion) +} diff --git a/roomserver/internal/input/input_events.go b/roomserver/internal/input/input_events.go index d939abb3f6..db3c955025 100644 --- a/roomserver/internal/input/input_events.go +++ b/roomserver/internal/input/input_events.go @@ -406,7 +406,7 @@ func (r *Inputer) processRoomEvent( ) if !isRejected && !isCreateEvent { resolver := state.NewStateResolution(r.DB, roomInfo, r.Queryer) - redactionEvent, redactedEvent, err = r.DB.MaybeRedactEvent(ctx, roomInfo, eventNID, event, &resolver) + redactionEvent, redactedEvent, err = r.DB.MaybeRedactEvent(ctx, roomInfo, eventNID, event, &resolver, r.Queryer) if err != nil { return err } diff --git a/roomserver/internal/perform/perform_backfill.go b/roomserver/internal/perform/perform_backfill.go index 3fdc8e4d01..33200e819c 100644 --- a/roomserver/internal/perform/perform_backfill.go +++ b/roomserver/internal/perform/perform_backfill.go @@ -647,7 +647,7 @@ func persistEvents(ctx context.Context, db storage.Database, querier api.QuerySe resolver := state.NewStateResolution(db, roomInfo, querier) - _, redactedEvent, err := db.MaybeRedactEvent(ctx, roomInfo, eventNID, ev, &resolver) + _, redactedEvent, err := db.MaybeRedactEvent(ctx, roomInfo, eventNID, ev, &resolver, querier) if err != nil { logrus.WithError(err).WithField("event_id", ev.EventID()).Error("Failed to redact event") continue diff --git a/roomserver/internal/perform/perform_create_room.go b/roomserver/internal/perform/perform_create_room.go index 9316c1290d..8c96564533 100644 --- a/roomserver/internal/perform/perform_create_room.go +++ b/roomserver/internal/perform/perform_create_room.go @@ -196,7 +196,7 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo // sign all events with the pseudo ID key identity = &fclient.SigningIdentity{ ServerName: "self", - KeyID: "ed25519", + KeyID: "ed25519:1", PrivateKey: pseudoIDKey, } } diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go index 3883a5b964..c14554640a 100644 --- a/roomserver/internal/perform/perform_join.go +++ b/roomserver/internal/perform/perform_join.go @@ -314,7 +314,7 @@ func (r *Joiner) performJoinRoomByID( // sign the event with the pseudo ID key identity = fclient.SigningIdentity{ ServerName: "self", - KeyID: "ed25519", + KeyID: "ed25519:1", PrivateKey: pseudoIDKey, } } diff --git a/roomserver/roomserver_test.go b/roomserver/roomserver_test.go index 077957fa11..76b21ad23f 100644 --- a/roomserver/roomserver_test.go +++ b/roomserver/roomserver_test.go @@ -35,6 +35,14 @@ import ( "github.com/matrix-org/dendrite/test/testrig" ) +type FakeQuerier struct { + api.QuerySenderIDAPI +} + +func (f *FakeQuerier) QueryUserIDForSender(ctx context.Context, roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) { + return spec.NewUserID(string(senderID), true) +} + func TestUsers(t *testing.T) { test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) { cfg, processCtx, close := testrig.CreateConfig(t, dbType) @@ -566,7 +574,7 @@ func TestRedaction(t *testing.T) { err = updater.Commit() assert.NoError(t, err) - _, redactedEvent, err := db.MaybeRedactEvent(ctx, roomInfo, eventNID, ev.PDU, &plResolver) + _, redactedEvent, err := db.MaybeRedactEvent(ctx, roomInfo, eventNID, ev.PDU, &plResolver, &FakeQuerier{}) assert.NoError(t, err) if redactedEvent != nil { assert.Equal(t, ev.Redacts(), redactedEvent.EventID()) diff --git a/roomserver/storage/interface.go b/roomserver/storage/interface.go index 7156c11cc9..e9b4609ecc 100644 --- a/roomserver/storage/interface.go +++ b/roomserver/storage/interface.go @@ -18,6 +18,7 @@ import ( "context" "crypto/ed25519" + "github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib/spec" @@ -190,7 +191,7 @@ type Database interface { GetOrCreateEventTypeNID(ctx context.Context, eventType string) (eventTypeNID types.EventTypeNID, err error) GetOrCreateEventStateKeyNID(ctx context.Context, eventStateKey *string) (types.EventStateKeyNID, error) MaybeRedactEvent( - ctx context.Context, roomInfo *types.RoomInfo, eventNID types.EventNID, event gomatrixserverlib.PDU, plResolver state.PowerLevelResolver, + ctx context.Context, roomInfo *types.RoomInfo, eventNID types.EventNID, event gomatrixserverlib.PDU, plResolver state.PowerLevelResolver, querier api.QuerySenderIDAPI, ) (gomatrixserverlib.PDU, gomatrixserverlib.PDU, error) } @@ -251,7 +252,7 @@ type EventDatabase interface { // MaybeRedactEvent returns the redaction event and the redacted event if this call resulted in a redaction, else an error // (nil if there was nothing to do) MaybeRedactEvent( - ctx context.Context, roomInfo *types.RoomInfo, eventNID types.EventNID, event gomatrixserverlib.PDU, plResolver state.PowerLevelResolver, + ctx context.Context, roomInfo *types.RoomInfo, eventNID types.EventNID, event gomatrixserverlib.PDU, plResolver state.PowerLevelResolver, querier api.QuerySenderIDAPI, ) (gomatrixserverlib.PDU, gomatrixserverlib.PDU, error) StoreEvent(ctx context.Context, event gomatrixserverlib.PDU, roomInfo *types.RoomInfo, eventTypeNID types.EventTypeNID, eventStateKeyNID types.EventStateKeyNID, authEventNIDs []types.EventNID, isRejected bool) (types.EventNID, types.StateAtEvent, error) } diff --git a/roomserver/storage/shared/storage.go b/roomserver/storage/shared/storage.go index 0f2ac74cb2..fc3ace6a6f 100644 --- a/roomserver/storage/shared/storage.go +++ b/roomserver/storage/shared/storage.go @@ -10,6 +10,7 @@ import ( "sort" "github.com/matrix-org/dendrite/internal/eventutil" + "github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/util" @@ -991,6 +992,7 @@ func extractRoomVersionFromCreateEvent(event gomatrixserverlib.PDU) ( // Returns the redaction event and the redacted event if this call resulted in a redaction. func (d *EventDatabase) MaybeRedactEvent( ctx context.Context, roomInfo *types.RoomInfo, eventNID types.EventNID, event gomatrixserverlib.PDU, plResolver state.PowerLevelResolver, + querier api.QuerySenderIDAPI, ) (gomatrixserverlib.PDU, gomatrixserverlib.PDU, error) { var ( redactionEvent, redactedEvent *types.Event @@ -1030,15 +1032,18 @@ func (d *EventDatabase) MaybeRedactEvent( return nil } - // TODO: Don't hack senderID into userID here (pseudoIDs) + var validRoomID *spec.RoomID + validRoomID, err = spec.NewRoomID(redactedEvent.RoomID()) + if err != nil { + return err + } sender1Domain := "" - sender1, err1 := spec.NewUserID(string(redactedEvent.SenderID()), true) + sender1, err1 := querier.QueryUserIDForSender(ctx, *validRoomID, redactedEvent.SenderID()) if err1 == nil { sender1Domain = string(sender1.Domain()) } - // TODO: Don't hack senderID into userID here (pseudoIDs) sender2Domain := "" - sender2, err2 := spec.NewUserID(string(redactionEvent.SenderID()), true) + sender2, err2 := querier.QueryUserIDForSender(ctx, *validRoomID, redactionEvent.SenderID()) if err2 == nil { sender2Domain = string(sender2.Domain()) } @@ -1757,58 +1762,54 @@ func (d *Database) SelectUserRoomPublicKey(ctx context.Context, userID spec.User // SelectUserIDsForPublicKeys returns a map from roomID -> map from senderKey -> userID func (d *Database) SelectUserIDsForPublicKeys(ctx context.Context, publicKeys map[spec.RoomID][]ed25519.PublicKey) (result map[spec.RoomID]map[string]string, err error) { result = make(map[spec.RoomID]map[string]string, len(publicKeys)) - err = d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error { - // map all roomIDs to roomNIDs - query := make(map[types.RoomNID][]ed25519.PublicKey) - rooms := make(map[types.RoomNID]spec.RoomID) - for roomID, keys := range publicKeys { - roomNID, ok := d.Cache.GetRoomServerRoomNID(roomID.String()) - if !ok { - roomInfo, rErr := d.roomInfo(ctx, txn, roomID.String()) - if rErr != nil { - return rErr - } - if roomInfo == nil { - logrus.Warnf("missing room info for %s, there will be missing users in the response", roomID.String()) - continue - } - roomNID = roomInfo.RoomNID + // map all roomIDs to roomNIDs + query := make(map[types.RoomNID][]ed25519.PublicKey) + rooms := make(map[types.RoomNID]spec.RoomID) + for roomID, keys := range publicKeys { + roomNID, ok := d.Cache.GetRoomServerRoomNID(roomID.String()) + if !ok { + roomInfo, rErr := d.roomInfo(ctx, nil, roomID.String()) + if rErr != nil { + return nil, rErr } - - query[roomNID] = keys - rooms[roomNID] = roomID + if roomInfo == nil { + logrus.Warnf("missing room info for %s, there will be missing users in the response", roomID.String()) + continue + } + roomNID = roomInfo.RoomNID } - // get the user room key pars - userRoomKeyPairMap, sErr := d.UserRoomKeyTable.BulkSelectUserNIDs(ctx, txn, query) - if sErr != nil { - return sErr - } - nids := make([]types.EventStateKeyNID, 0, len(userRoomKeyPairMap)) - for _, nid := range userRoomKeyPairMap { - nids = append(nids, nid.EventStateKeyNID) - } - // get the userIDs - nidMap, seErr := d.EventStateKeys(ctx, nids) - if seErr != nil { - return seErr - } + query[roomNID] = keys + rooms[roomNID] = roomID + } - // build the result map (roomID -> map publicKey -> userID) - for publicKey, userRoomKeyPair := range userRoomKeyPairMap { - userID := nidMap[userRoomKeyPair.EventStateKeyNID] - roomID := rooms[userRoomKeyPair.RoomNID] - resMap, exists := result[roomID] - if !exists { - resMap = map[string]string{} - } - resMap[publicKey] = userID - result[roomID] = resMap - } + // get the user room key pars + userRoomKeyPairMap, sErr := d.UserRoomKeyTable.BulkSelectUserNIDs(ctx, nil, query) + if sErr != nil { + return nil, sErr + } + nids := make([]types.EventStateKeyNID, 0, len(userRoomKeyPairMap)) + for _, nid := range userRoomKeyPairMap { + nids = append(nids, nid.EventStateKeyNID) + } + // get the userIDs + nidMap, seErr := d.EventStateKeys(ctx, nids) + if seErr != nil { + return nil, seErr + } - return nil - }) + // build the result map (roomID -> map publicKey -> userID) + for publicKey, userRoomKeyPair := range userRoomKeyPairMap { + userID := nidMap[userRoomKeyPair.EventStateKeyNID] + roomID := rooms[userRoomKeyPair.RoomNID] + resMap, exists := result[roomID] + if !exists { + resMap = map[string]string{} + } + resMap[publicKey] = userID + result[roomID] = resMap + } return result, err } diff --git a/roomserver/storage/sqlite3/user_room_keys_table.go b/roomserver/storage/sqlite3/user_room_keys_table.go index d58b8ac3fe..5d6ddc9a8e 100644 --- a/roomserver/storage/sqlite3/user_room_keys_table.go +++ b/roomserver/storage/sqlite3/user_room_keys_table.go @@ -57,6 +57,7 @@ const selectUserRoomPublicKeySQL = `SELECT pseudo_id_pub_key FROM roomserver_use const selectUserNIDsSQL = `SELECT user_nid, room_nid, pseudo_id_pub_key FROM roomserver_user_room_keys WHERE room_nid IN ($1) AND pseudo_id_pub_key IN ($2)` type userRoomKeysStatements struct { + db *sql.DB insertUserRoomPrivateKeyStmt *sql.Stmt insertUserRoomPublicKeyStmt *sql.Stmt selectUserRoomKeyStmt *sql.Stmt @@ -70,7 +71,7 @@ func CreateUserRoomKeysTable(db *sql.DB) error { } func PrepareUserRoomKeysTable(db *sql.DB) (tables.UserRoomKeys, error) { - s := &userRoomKeysStatements{} + s := &userRoomKeysStatements{db: db} return s, sqlutil.StatementList{ {&s.insertUserRoomPrivateKeyStmt, insertUserRoomKeySQL}, {&s.insertUserRoomPublicKeyStmt, insertUserRoomPublicKeySQL}, @@ -137,7 +138,7 @@ func (s *userRoomKeysStatements) BulkSelectUserNIDs(ctx context.Context, txn *sq selectSQL := strings.Replace(selectUserNIDsSQL, "($2)", sqlutil.QueryVariadicOffset(len(senders), len(senderKeys)), 1) selectSQL = strings.Replace(selectSQL, "($1)", sqlutil.QueryVariadic(len(senderKeys)), 1) // replace $1 with the roomNIDs - selectStmt, err := txn.Prepare(selectSQL) + selectStmt, err := s.db.Prepare(selectSQL) if err != nil { return nil, err } diff --git a/syncapi/streams/stream_pdu.go b/syncapi/streams/stream_pdu.go index 8dbf2c6afd..1a4e5351d9 100644 --- a/syncapi/streams/stream_pdu.go +++ b/syncapi/streams/stream_pdu.go @@ -350,6 +350,7 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse( // left. Anything that appears in the filtered timeline will be removed from the // "state" section and kept in "timeline". + // update the powerlevel event for timeline events for i, ev := range events { if ev.Version() != gomatrixserverlib.RoomVersionPseudoIDs { continue @@ -371,7 +372,17 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse( ) delta.StateEvents = make([]*rstypes.HeaderedEvent, len(sEvents)) for i := range sEvents { - delta.StateEvents[i] = sEvents[i].(*rstypes.HeaderedEvent) + ev := sEvents[i] + delta.StateEvents[i] = ev.(*rstypes.HeaderedEvent) + // update the powerlevel event for state events + if ev.Version() == gomatrixserverlib.RoomVersionPseudoIDs && ev.Type() == spec.MRoomPowerLevels && ev.StateKeyEquals("") { + var newEvent gomatrixserverlib.PDU + newEvent, err = p.updatePowerLevelEvent(ctx, ev.(*rstypes.HeaderedEvent)) + if err != nil { + return r.From, err + } + delta.StateEvents[i] = &rstypes.HeaderedEvent{PDU: newEvent} + } } if len(delta.StateEvents) > 0 { @@ -652,6 +663,7 @@ func (p *PDUStreamProvider) getJoinResponseForCompleteSync( prevBatch.Decrement() } + // Update powerlevel events for timeline events for i, ev := range events { if ev.Version() != gomatrixserverlib.RoomVersionPseudoIDs { continue @@ -665,6 +677,20 @@ func (p *PDUStreamProvider) getJoinResponseForCompleteSync( } events[i] = &rstypes.HeaderedEvent{PDU: newEvent} } + // Update powerlevel events for state events + for i, ev := range stateEvents { + if ev.Version() != gomatrixserverlib.RoomVersionPseudoIDs { + continue + } + if ev.Type() != spec.MRoomPowerLevels || !ev.StateKeyEquals("") { + continue + } + newEvent, err := p.updatePowerLevelEvent(ctx, ev) + if err != nil { + return nil, err + } + stateEvents[i] = &rstypes.HeaderedEvent{PDU: newEvent} + } jr.Timeline.PrevBatch = prevBatch jr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), synctypes.FormatSync, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {