From 8ea1a11105ea7e66aa459537bcbef0de606147cd Mon Sep 17 00:00:00 2001 From: devonh Date: Wed, 7 Jun 2023 17:14:35 +0000 Subject: [PATCH] Use SenderID Type (#3105) --- appservice/consumers/roomserver.go | 2 +- clientapi/routing/directory.go | 16 +++- clientapi/routing/membership.go | 36 ++++++++- clientapi/routing/profile.go | 15 +++- clientapi/routing/redaction.go | 27 +++++-- clientapi/routing/sendevent.go | 21 +++++- clientapi/threepid/invites.go | 12 ++- cmd/resolve-state/main.go | 2 +- federationapi/federationapi_test.go | 13 +++- federationapi/internal/perform.go | 28 ++++--- federationapi/routing/invite.go | 4 +- federationapi/routing/join.go | 32 +++++--- federationapi/routing/leave.go | 32 +++++--- federationapi/routing/threepid.go | 14 ++-- go.mod | 2 +- go.sum | 4 +- internal/pushrules/evaluate.go | 2 +- internal/pushrules/evaluate_test.go | 8 +- internal/transactionrequest.go | 2 +- internal/transactionrequest_test.go | 8 +- roomserver/api/alias.go | 8 +- roomserver/api/api.go | 4 +- roomserver/internal/alias.go | 17 +++-- roomserver/internal/helpers/auth.go | 6 +- roomserver/internal/input/input_events.go | 12 +-- .../internal/input/input_events_test.go | 4 +- roomserver/internal/input/input_missing.go | 10 +-- roomserver/internal/perform/perform_admin.go | 26 ++++--- .../internal/perform/perform_backfill.go | 4 +- .../internal/perform/perform_create_room.go | 33 +++++++- roomserver/internal/perform/perform_invite.go | 10 ++- roomserver/internal/perform/perform_join.go | 17 +++-- roomserver/internal/perform/perform_leave.go | 19 +++-- .../internal/perform/perform_upgrade.go | 68 +++++++++++++---- roomserver/internal/query/query.go | 8 +- roomserver/roomserver_test.go | 12 +-- roomserver/state/state.go | 6 +- roomserver/storage/interface.go | 6 +- .../storage/shared/membership_updater.go | 2 +- roomserver/storage/shared/room_updater.go | 2 +- roomserver/storage/shared/storage.go | 12 +-- setup/mscs/msc2836/msc2836.go | 2 +- setup/mscs/msc2836/msc2836_test.go | 6 +- setup/mscs/msc2946/msc2946.go | 2 +- syncapi/consumers/roomserver.go | 2 +- syncapi/routing/context.go | 8 +- syncapi/routing/memberships.go | 19 ++++- syncapi/routing/messages.go | 6 +- syncapi/routing/search.go | 8 +- syncapi/routing/search_test.go | 4 +- syncapi/storage/interface.go | 6 +- syncapi/storage/shared/storage_consumer.go | 75 +++++++++---------- syncapi/storage/shared/storage_sync.go | 19 ++--- syncapi/storage/storage_test.go | 2 +- syncapi/streams/stream_pdu.go | 30 ++++---- syncapi/syncapi_test.go | 4 +- syncapi/types/types.go | 2 +- test/room.go | 6 +- userapi/consumers/roomserver.go | 6 +- userapi/consumers/roomserver_test.go | 4 +- 60 files changed, 502 insertions(+), 275 deletions(-) diff --git a/appservice/consumers/roomserver.go b/appservice/consumers/roomserver.go index 06625ad7..ff124514 100644 --- a/appservice/consumers/roomserver.go +++ b/appservice/consumers/roomserver.go @@ -181,7 +181,7 @@ func (s *OutputRoomEventConsumer) sendEvents( // Create the transaction body. transaction, err := json.Marshal( ApplicationServiceTransaction{ - Events: synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), synctypes.FormatAll, func(roomID, senderID string) (*spec.UserID, error) { + Events: synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), synctypes.FormatAll, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return s.rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }), }, diff --git a/clientapi/routing/directory.go b/clientapi/routing/directory.go index 0c842e6a..034296f4 100644 --- a/clientapi/routing/directory.go +++ b/clientapi/routing/directory.go @@ -338,7 +338,21 @@ func SetVisibility( // NOTSPEC: Check if the user's power is greater than power required to change m.room.canonical_alias event power, _ := gomatrixserverlib.NewPowerLevelContentFromEvent(queryEventsRes.StateEvents[0].PDU) - if power.UserLevel(dev.UserID) < power.EventLevel(spec.MRoomCanonicalAlias, true) { + fullUserID, err := spec.NewUserID(dev.UserID, true) + if err != nil { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: spec.Forbidden("userID doesn't have power level to change visibility"), + } + } + senderID, err := rsAPI.QuerySenderIDForUser(req.Context(), roomID, *fullUserID) + if err != nil { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: spec.Forbidden("userID doesn't have power level to change visibility"), + } + } + if power.UserLevel(senderID) < power.EventLevel(spec.MRoomCanonicalAlias, true) { return util.JSONResponse{ Code: http.StatusForbidden, JSON: spec.Forbidden("userID doesn't have power level to change visibility"), diff --git a/clientapi/routing/membership.go b/clientapi/routing/membership.go index 0fe0a4ad..78829bec 100644 --- a/clientapi/routing/membership.go +++ b/clientapi/routing/membership.go @@ -66,7 +66,21 @@ func SendBan( if errRes != nil { return *errRes } - allowedToBan := pl.UserLevel(device.UserID) >= pl.Ban + fullUserID, err := spec.NewUserID(device.UserID, true) + if err != nil { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: spec.Forbidden("You don't have permission to ban this user, bad userID"), + } + } + senderID, err := rsAPI.QuerySenderIDForUser(req.Context(), roomID, *fullUserID) + if err != nil { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: spec.Forbidden("You don't have permission to ban this user, unknown senderID"), + } + } + allowedToBan := pl.UserLevel(senderID) >= pl.Ban if !allowedToBan { return util.JSONResponse{ Code: http.StatusForbidden, @@ -142,7 +156,21 @@ func SendKick( if errRes != nil { return *errRes } - allowedToKick := pl.UserLevel(device.UserID) >= pl.Kick + fullUserID, err := spec.NewUserID(device.UserID, true) + if err != nil { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: spec.Forbidden("You don't have permission to kick this user, bad userID"), + } + } + senderID, err := rsAPI.QuerySenderIDForUser(req.Context(), roomID, *fullUserID) + if err != nil { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: spec.Forbidden("You don't have permission to kick this user, unknown senderID"), + } + } + allowedToKick := pl.UserLevel(senderID) >= pl.Kick if !allowedToKick { return util.JSONResponse{ Code: http.StatusForbidden, @@ -151,7 +179,7 @@ func SendKick( } var queryRes roomserverAPI.QueryMembershipForUserResponse - err := rsAPI.QueryMembershipForUser(req.Context(), &roomserverAPI.QueryMembershipForUserRequest{ + err = rsAPI.QueryMembershipForUser(req.Context(), &roomserverAPI.QueryMembershipForUserRequest{ RoomID: roomID, UserID: body.UserID, }, &queryRes) @@ -319,7 +347,7 @@ func buildMembershipEventDirect( rsAPI roomserverAPI.ClientRoomserverAPI, ) (*types.HeaderedEvent, error) { proto := gomatrixserverlib.ProtoEvent{ - Sender: sender, + SenderID: sender, RoomID: roomID, Type: "m.room.member", StateKey: &targetUserID, diff --git a/clientapi/routing/profile.go b/clientapi/routing/profile.go index 2c9d0cbb..e734e2e4 100644 --- a/clientapi/routing/profile.go +++ b/clientapi/routing/profile.go @@ -363,12 +363,21 @@ func buildMembershipEvents( ) ([]*types.HeaderedEvent, error) { evs := []*types.HeaderedEvent{} + fullUserID, err := spec.NewUserID(userID, true) + if err != nil { + return nil, err + } for _, roomID := range roomIDs { + senderID, err := rsAPI.QuerySenderIDForUser(ctx, roomID, *fullUserID) + if err != nil { + return nil, err + } + senderIDString := string(senderID) proto := gomatrixserverlib.ProtoEvent{ - Sender: userID, + SenderID: senderIDString, RoomID: roomID, Type: "m.room.member", - StateKey: &userID, + StateKey: &senderIDString, } content := gomatrixserverlib.MemberContent{ @@ -378,7 +387,7 @@ func buildMembershipEvents( content.DisplayName = newProfile.DisplayName content.AvatarURL = newProfile.AvatarURL - if err := proto.SetContent(content); err != nil { + if err = proto.SetContent(content); err != nil { return nil, err } diff --git a/clientapi/routing/redaction.go b/clientapi/routing/redaction.go index e94c7748..22474fc0 100644 --- a/clientapi/routing/redaction.go +++ b/clientapi/routing/redaction.go @@ -73,10 +73,25 @@ func SendRedaction( } } + fullUserID, userIDErr := spec.NewUserID(device.UserID, true) + if userIDErr != nil { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: spec.Forbidden("userID doesn't have power level to redact"), + } + } + senderID, queryErr := rsAPI.QuerySenderIDForUser(req.Context(), roomID, *fullUserID) + if queryErr != nil { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: spec.Forbidden("userID doesn't have power level to redact"), + } + } + // "Users may redact their own events, and any user with a power level greater than or equal // to the redact power level of the room may redact events there" // https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-rooms-roomid-redact-eventid-txnid - allowedToRedact := ev.SenderID() == device.UserID // TODO: Should replace device.UserID with device...PerRoomKey + allowedToRedact := ev.SenderID() == senderID // TODO: Should replace device.UserID with device...PerRoomKey if !allowedToRedact { plEvent := roomserverAPI.GetStateEvent(req.Context(), rsAPI, roomID, gomatrixserverlib.StateKeyTuple{ EventType: spec.MRoomPowerLevels, @@ -97,7 +112,7 @@ func SendRedaction( ), } } - allowedToRedact = pl.UserLevel(device.UserID) >= pl.Redact + allowedToRedact = pl.UserLevel(senderID) >= pl.Redact } if !allowedToRedact { return util.JSONResponse{ @@ -114,10 +129,10 @@ func SendRedaction( // create the new event and set all the fields we can proto := gomatrixserverlib.ProtoEvent{ - Sender: device.UserID, - RoomID: roomID, - Type: spec.MRoomRedaction, - Redacts: eventID, + SenderID: string(senderID), + RoomID: roomID, + Type: spec.MRoomRedaction, + Redacts: eventID, } err := proto.SetContent(r) if err != nil { diff --git a/clientapi/routing/sendevent.go b/clientapi/routing/sendevent.go index 8b09f399..4d0a9f24 100644 --- a/clientapi/routing/sendevent.go +++ b/clientapi/routing/sendevent.go @@ -266,16 +266,29 @@ func generateSendEvent( evTime time.Time, ) (gomatrixserverlib.PDU, *util.JSONResponse) { // parse the incoming http request - userID := device.UserID + fullUserID, err := spec.NewUserID(device.UserID, true) + if err != nil { + return nil, &util.JSONResponse{ + Code: http.StatusBadRequest, + JSON: spec.BadJSON("Bad userID"), + } + } + senderID, err := rsAPI.QuerySenderIDForUser(ctx, roomID, *fullUserID) + if err != nil { + return nil, &util.JSONResponse{ + Code: http.StatusNotFound, + JSON: spec.NotFound("Unable to find senderID for user"), + } + } // create the new event and set all the fields we can proto := gomatrixserverlib.ProtoEvent{ - Sender: userID, + SenderID: string(senderID), RoomID: roomID, Type: eventType, StateKey: stateKey, } - err := proto.SetContent(r) + err = proto.SetContent(r) if err != nil { util.GetLogger(ctx).WithError(err).Error("proto.SetContent failed") return nil, &util.JSONResponse{ @@ -331,7 +344,7 @@ func generateSendEvent( stateEvents[i] = queryRes.StateEvents[i].PDU } provider := gomatrixserverlib.NewAuthEvents(gomatrixserverlib.ToPDUs(stateEvents)) - if err = gomatrixserverlib.Allowed(e.PDU, &provider, func(roomID, senderID string) (*spec.UserID, error) { + if err = gomatrixserverlib.Allowed(e.PDU, &provider, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }); err != nil { return nil, &util.JSONResponse{ diff --git a/clientapi/threepid/invites.go b/clientapi/threepid/invites.go index 9f4f62e4..e7ffbac2 100644 --- a/clientapi/threepid/invites.go +++ b/clientapi/threepid/invites.go @@ -355,8 +355,16 @@ func emit3PIDInviteEvent( rsAPI api.ClientRoomserverAPI, evTime time.Time, ) error { + userID, err := spec.NewUserID(device.UserID, true) + if err != nil { + return err + } + sender, err := rsAPI.QuerySenderIDForUser(ctx, roomID, *userID) + if err != nil { + return err + } proto := &gomatrixserverlib.ProtoEvent{ - Sender: device.UserID, + SenderID: string(sender), RoomID: roomID, Type: "m.room.third_party_invite", StateKey: &res.Token, @@ -370,7 +378,7 @@ func emit3PIDInviteEvent( PublicKeys: res.PublicKeys, } - if err := proto.SetContent(content); err != nil { + if err = proto.SetContent(content); err != nil { return err } diff --git a/cmd/resolve-state/main.go b/cmd/resolve-state/main.go index 36040309..15c87f1a 100644 --- a/cmd/resolve-state/main.go +++ b/cmd/resolve-state/main.go @@ -183,7 +183,7 @@ func main() { fmt.Println("Resolving state") var resolved Events resolved, err = gomatrixserverlib.ResolveConflicts( - gomatrixserverlib.RoomVersion(*roomVersion), events, authEvents, func(roomID, senderID string) (*spec.UserID, error) { + gomatrixserverlib.RoomVersion(*roomVersion), events, authEvents, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return roomserverDB.GetUserIDForSender(ctx, roomID, senderID) }, ) diff --git a/federationapi/federationapi_test.go b/federationapi/federationapi_test.go index a97bcdea..17390843 100644 --- a/federationapi/federationapi_test.go +++ b/federationapi/federationapi_test.go @@ -36,8 +36,12 @@ type fedRoomserverAPI struct { queryRoomsForUser func(ctx context.Context, req *rsapi.QueryRoomsForUserRequest, res *rsapi.QueryRoomsForUserResponse) error } -func (f *fedRoomserverAPI) QueryUserIDForSender(ctx context.Context, roomID string, senderID string) (*spec.UserID, error) { - return spec.NewUserID(senderID, true) +func (f *fedRoomserverAPI) QueryUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error) { + return spec.NewUserID(string(senderID), true) +} + +func (f *fedRoomserverAPI) QuerySenderIDForUser(ctx context.Context, roomID string, userID spec.UserID) (spec.SenderID, error) { + return spec.SenderID(userID.String()), nil } // PerformJoin will call this function @@ -115,12 +119,13 @@ func (f *fedClient) MakeJoin(ctx context.Context, origin, s spec.ServerName, roo defer f.fedClientMutex.Unlock() for _, r := range f.allowJoins { if r.ID == roomID { + senderIDString := userID res.RoomVersion = r.Version res.JoinEvent = gomatrixserverlib.ProtoEvent{ - Sender: userID, + SenderID: senderIDString, RoomID: roomID, Type: "m.room.member", - StateKey: &userID, + StateKey: &senderIDString, Content: spec.RawJSON([]byte(`{"membership":"join"}`)), PrevEvents: r.ForwardExtremities(), } diff --git a/federationapi/internal/perform.go b/federationapi/internal/perform.go index 2d59d0f9..485b79a0 100644 --- a/federationapi/internal/perform.go +++ b/federationapi/internal/perform.go @@ -154,9 +154,14 @@ func (r *FederationInternalAPI) performJoinUsingServer( if err != nil { return err } + senderID, err := r.rsAPI.QuerySenderIDForUser(ctx, roomID, *user) + if err != nil { + return err + } joinInput := gomatrixserverlib.PerformJoinInput{ UserID: user, + SenderID: senderID, RoomID: room, ServerName: serverName, Content: content, @@ -164,10 +169,10 @@ func (r *FederationInternalAPI) performJoinUsingServer( PrivateKey: r.cfg.Matrix.PrivateKey, KeyID: r.cfg.Matrix.KeyID, KeyRing: r.keyRing, - EventProvider: federatedEventProvider(ctx, r.federation, r.keyRing, user.Domain(), serverName, func(roomID, senderID string) (*spec.UserID, error) { + EventProvider: federatedEventProvider(ctx, r.federation, r.keyRing, user.Domain(), serverName, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }), - UserIDQuerier: func(roomID, senderID string) (*spec.UserID, error) { + UserIDQuerier: func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }, } @@ -363,7 +368,7 @@ func (r *FederationInternalAPI) performOutboundPeekUsingServer( // authenticate the state returned (check its auth events etc) // the equivalent of CheckSendJoinResponse() - userIDProvider := func(roomID, senderID string) (*spec.UserID, error) { + userIDProvider := func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.rsAPI.QueryUserIDForSender(ctx, roomID, senderID) } authEvents, stateEvents, err := gomatrixserverlib.CheckStateResponse( @@ -414,7 +419,7 @@ func (r *FederationInternalAPI) PerformLeave( request *api.PerformLeaveRequest, response *api.PerformLeaveResponse, ) (err error) { - _, origin, err := r.cfg.Matrix.SplitLocalID('@', request.UserID) + userID, err := spec.NewUserID(request.UserID, true) if err != nil { return err } @@ -433,7 +438,7 @@ func (r *FederationInternalAPI) PerformLeave( // request. respMakeLeave, err := r.federation.MakeLeave( ctx, - origin, + userID.Domain(), serverName, request.RoomID, request.UserID, @@ -454,9 +459,14 @@ func (r *FederationInternalAPI) PerformLeave( // Set all the fields to be what they should be, this should be a no-op // but it's possible that the remote server returned us something "odd" + senderID, err := r.rsAPI.QuerySenderIDForUser(ctx, request.RoomID, *userID) + if err != nil { + return err + } + senderIDString := string(senderID) respMakeLeave.LeaveEvent.Type = spec.MRoomMember - respMakeLeave.LeaveEvent.Sender = request.UserID - respMakeLeave.LeaveEvent.StateKey = &request.UserID + respMakeLeave.LeaveEvent.SenderID = senderIDString + respMakeLeave.LeaveEvent.StateKey = &senderIDString respMakeLeave.LeaveEvent.RoomID = request.RoomID respMakeLeave.LeaveEvent.Redacts = "" leaveEB := verImpl.NewEventBuilderFromProtoEvent(&respMakeLeave.LeaveEvent) @@ -478,7 +488,7 @@ func (r *FederationInternalAPI) PerformLeave( // Build the leave event. event, err := leaveEB.Build( time.Now(), - origin, + userID.Domain(), r.cfg.Matrix.KeyID, r.cfg.Matrix.PrivateKey, ) @@ -490,7 +500,7 @@ func (r *FederationInternalAPI) PerformLeave( // Try to perform a send_leave using the newly built event. err = r.federation.SendLeave( ctx, - origin, + userID.Domain(), serverName, event, ) diff --git a/federationapi/routing/invite.go b/federationapi/routing/invite.go index d792335b..5b15f810 100644 --- a/federationapi/routing/invite.go +++ b/federationapi/routing/invite.go @@ -95,7 +95,7 @@ func InviteV2( StateQuerier: rsAPI.StateQuerier(), InviteEvent: inviteReq.Event(), StrippedState: inviteReq.InviteRoomState(), - UserIDQuerier: func(roomID, senderID string) (*spec.UserID, error) { + UserIDQuerier: func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(httpReq.Context(), roomID, senderID) }, } @@ -188,7 +188,7 @@ func InviteV1( StateQuerier: rsAPI.StateQuerier(), InviteEvent: event, StrippedState: strippedState, - UserIDQuerier: func(roomID, senderID string) (*spec.UserID, error) { + UserIDQuerier: func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(httpReq.Context(), roomID, senderID) }, } diff --git a/federationapi/routing/join.go b/federationapi/routing/join.go index 9da05918..d1480192 100644 --- a/federationapi/routing/join.go +++ b/federationapi/routing/join.go @@ -55,7 +55,7 @@ func MakeJoin( RoomID: roomID.String(), } res := api.QueryServerJoinedToRoomResponse{} - if err := rsAPI.QueryServerJoinedToRoom(httpReq.Context(), &req, &res); err != nil { + if err = rsAPI.QueryServerJoinedToRoom(httpReq.Context(), &req, &res); err != nil { util.GetLogger(httpReq.Context()).WithError(err).Error("rsAPI.QueryServerJoinedToRoom failed") return util.JSONResponse{ Code: http.StatusInternalServerError, @@ -64,26 +64,26 @@ func MakeJoin( } createJoinTemplate := func(proto *gomatrixserverlib.ProtoEvent) (gomatrixserverlib.PDU, []gomatrixserverlib.PDU, error) { - identity, err := cfg.Matrix.SigningIdentityFor(request.Destination()) - if err != nil { - util.GetLogger(httpReq.Context()).WithError(err).Errorf("obtaining signing identity for %s failed", request.Destination()) + 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{ RoomVersion: roomVersion, } - event, err := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, identity, time.Now(), rsAPI, &queryRes) - switch e := err.(type) { + event, signErr := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, identity, time.Now(), rsAPI, &queryRes) + switch e := signErr.(type) { case nil: case eventutil.ErrRoomNoExists: - util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed") + util.GetLogger(httpReq.Context()).WithError(signErr).Error("eventutil.BuildEvent failed") return nil, nil, spec.NotFound("Room does not exist") case gomatrixserverlib.BadJSONError: - util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed") + util.GetLogger(httpReq.Context()).WithError(signErr).Error("eventutil.BuildEvent failed") return nil, nil, spec.BadJSON(e.Error()) default: - util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed") + util.GetLogger(httpReq.Context()).WithError(signErr).Error("eventutil.BuildEvent failed") return nil, nil, spec.InternalServerError{} } @@ -98,9 +98,19 @@ func MakeJoin( Roomserver: rsAPI, } + senderID, err := rsAPI.QuerySenderIDForUser(httpReq.Context(), roomID.String(), userID) + if err != nil { + util.GetLogger(httpReq.Context()).WithError(err).Error("rsAPI.QuerySenderIDForUser failed") + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{}, + } + } + input := gomatrixserverlib.HandleMakeJoinInput{ Context: httpReq.Context(), UserID: userID, + SenderID: senderID, RoomID: roomID, RoomVersion: roomVersion, RemoteVersions: remoteVersions, @@ -108,7 +118,7 @@ func MakeJoin( LocalServerName: cfg.Matrix.ServerName, LocalServerInRoom: res.RoomExists && res.IsInRoom, RoomQuerier: &roomQuerier, - UserIDQuerier: func(roomID, senderID string) (*spec.UserID, error) { + UserIDQuerier: func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(httpReq.Context(), roomID, senderID) }, BuildEventTemplate: createJoinTemplate, @@ -205,7 +215,7 @@ func SendJoin( PrivateKey: cfg.Matrix.PrivateKey, Verifier: keys, MembershipQuerier: &api.MembershipQuerier{Roomserver: rsAPI}, - UserIDQuerier: func(roomID, senderID string) (*spec.UserID, error) { + UserIDQuerier: func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(httpReq.Context(), roomID, senderID) }, } diff --git a/federationapi/routing/leave.go b/federationapi/routing/leave.go index 30e99c4f..716276be 100644 --- a/federationapi/routing/leave.go +++ b/federationapi/routing/leave.go @@ -50,7 +50,7 @@ func MakeLeave( RoomID: roomID.String(), } res := api.QueryServerJoinedToRoomResponse{} - if err := rsAPI.QueryServerJoinedToRoom(httpReq.Context(), &req, &res); err != nil { + if err = rsAPI.QueryServerJoinedToRoom(httpReq.Context(), &req, &res); err != nil { util.GetLogger(httpReq.Context()).WithError(err).Error("rsAPI.QueryServerJoinedToRoom failed") return util.JSONResponse{ Code: http.StatusInternalServerError, @@ -59,24 +59,24 @@ func MakeLeave( } createLeaveTemplate := func(proto *gomatrixserverlib.ProtoEvent) (gomatrixserverlib.PDU, []gomatrixserverlib.PDU, error) { - identity, err := cfg.Matrix.SigningIdentityFor(request.Destination()) - if err != nil { - util.GetLogger(httpReq.Context()).WithError(err).Errorf("obtaining signing identity for %s failed", request.Destination()) + 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, err := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, identity, time.Now(), rsAPI, &queryRes) - switch e := err.(type) { + event, buildErr := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, identity, time.Now(), rsAPI, &queryRes) + switch e := buildErr.(type) { case nil: case eventutil.ErrRoomNoExists: - util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed") + util.GetLogger(httpReq.Context()).WithError(buildErr).Error("eventutil.BuildEvent failed") return nil, nil, spec.NotFound("Room does not exist") case gomatrixserverlib.BadJSONError: - util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed") + util.GetLogger(httpReq.Context()).WithError(buildErr).Error("eventutil.BuildEvent failed") return nil, nil, spec.BadJSON(e.Error()) default: - util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed") + util.GetLogger(httpReq.Context()).WithError(buildErr).Error("eventutil.BuildEvent failed") return nil, nil, spec.InternalServerError{} } @@ -87,15 +87,25 @@ func MakeLeave( return event, stateEvents, nil } + senderID, err := rsAPI.QuerySenderIDForUser(httpReq.Context(), roomID.String(), userID) + if err != nil { + util.GetLogger(httpReq.Context()).WithError(err).Error("rsAPI.QuerySenderIDForUser failed") + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{}, + } + } + input := gomatrixserverlib.HandleMakeLeaveInput{ UserID: userID, + SenderID: senderID, RoomID: roomID, RoomVersion: roomVersion, RequestOrigin: request.Origin(), LocalServerName: cfg.Matrix.ServerName, LocalServerInRoom: res.RoomExists && res.IsInRoom, BuildEventTemplate: createLeaveTemplate, - UserIDQuerier: func(roomID, senderID string) (*spec.UserID, error) { + UserIDQuerier: func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(httpReq.Context(), roomID, senderID) }, } @@ -216,7 +226,7 @@ func SendLeave( JSON: spec.BadJSON("No state key was provided in the leave event."), } } - if !event.StateKeyEquals(event.SenderID()) { + if !event.StateKeyEquals(string(event.SenderID())) { return util.JSONResponse{ Code: http.StatusBadRequest, JSON: spec.BadJSON("Event state key must match the event sender."), diff --git a/federationapi/routing/threepid.go b/federationapi/routing/threepid.go index 76a2f3d5..360802de 100644 --- a/federationapi/routing/threepid.go +++ b/federationapi/routing/threepid.go @@ -140,22 +140,24 @@ func ExchangeThirdPartyInvite( } } - _, senderDomain, err := cfg.Matrix.SplitLocalID('@', proto.Sender) - if err != nil { + userID, err := rsAPI.QueryUserIDForSender(httpReq.Context(), roomID, spec.SenderID(proto.SenderID)) + if err != nil || userID == nil { return util.JSONResponse{ Code: http.StatusBadRequest, - JSON: spec.BadJSON("Invalid sender ID: " + err.Error()), + JSON: spec.BadJSON("Invalid sender ID"), } } + senderDomain := userID.Domain() // Check that the state key is correct. - _, targetDomain, err := gomatrixserverlib.SplitID('@', *proto.StateKey) - if err != nil { + targetUserID, err := rsAPI.QueryUserIDForSender(httpReq.Context(), roomID, spec.SenderID(*proto.StateKey)) + if err != nil || targetUserID == nil { return util.JSONResponse{ Code: http.StatusBadRequest, JSON: spec.BadJSON("The event's state key isn't a Matrix user ID"), } } + targetDomain := targetUserID.Domain() // Check that the target user is from the requesting homeserver. if targetDomain != request.Origin() { @@ -271,7 +273,7 @@ func createInviteFrom3PIDInvite( // Build the event proto := &gomatrixserverlib.ProtoEvent{ Type: "m.room.member", - Sender: inv.Sender, + SenderID: inv.Sender, RoomID: inv.RoomID, StateKey: &inv.MXID, } diff --git a/go.mod b/go.mod index 10551f70..3621428c 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-20230606202811-a644d5d8fb66 + github.com/matrix-org/gomatrixserverlib v0.0.0-20230607161930-ea5ef168992d 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 3ec1c115..1ee0261f 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-20230606202811-a644d5d8fb66 h1:6SixhMmB5Ir10xUJ6zh3A4NBxSaZCSz2s5U63Wg0eEU= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230606202811-a644d5d8fb66/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230607161930-ea5ef168992d h1:MjL8SXRzhO61aXDFL+gA3Bx1SicqLGL9gCWXDv8jkD8= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230607161930-ea5ef168992d/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/internal/pushrules/evaluate.go b/internal/pushrules/evaluate.go index da33d386..ac760895 100644 --- a/internal/pushrules/evaluate.go +++ b/internal/pushrules/evaluate.go @@ -28,7 +28,7 @@ type EvaluationContext interface { // HasPowerLevel returns whether the user has at least the given // power in the room of the current event. - HasPowerLevel(userID, levelKey string) (bool, error) + HasPowerLevel(senderID spec.SenderID, levelKey string) (bool, error) } // A kindAndRules is just here to simplify iteration of the (ordered) diff --git a/internal/pushrules/evaluate_test.go b/internal/pushrules/evaluate_test.go index 34c1436f..859d1f8a 100644 --- a/internal/pushrules/evaluate_test.go +++ b/internal/pushrules/evaluate_test.go @@ -8,8 +8,8 @@ import ( "github.com/matrix-org/gomatrixserverlib/spec" ) -func UserIDForSender(roomID string, senderID string) (*spec.UserID, error) { - return spec.NewUserID(senderID, true) +func UserIDForSender(roomID string, senderID spec.SenderID) (*spec.UserID, error) { + return spec.NewUserID(string(senderID), true) } func TestRuleSetEvaluatorMatchEvent(t *testing.T) { @@ -158,8 +158,8 @@ type fakeEvaluationContext struct{ memberCount int } func (fakeEvaluationContext) UserDisplayName() string { return "Dear User" } func (f fakeEvaluationContext) RoomMemberCount() (int, error) { return f.memberCount, nil } -func (fakeEvaluationContext) HasPowerLevel(userID, levelKey string) (bool, error) { - return userID == "@poweruser:example.com" && levelKey == "powerlevel", nil +func (fakeEvaluationContext) HasPowerLevel(senderID spec.SenderID, levelKey string) (bool, error) { + return senderID == "@poweruser:example.com" && levelKey == "powerlevel", nil } func TestPatternMatches(t *testing.T) { diff --git a/internal/transactionrequest.go b/internal/transactionrequest.go index 0bbe0720..b2929bb5 100644 --- a/internal/transactionrequest.go +++ b/internal/transactionrequest.go @@ -167,7 +167,7 @@ func (t *TxnReq) ProcessTransaction(ctx context.Context) (*fclient.RespSend, *ut } continue } - if err = gomatrixserverlib.VerifyEventSignatures(ctx, event, t.keys, func(roomID, senderID string) (*spec.UserID, error) { + if err = gomatrixserverlib.VerifyEventSignatures(ctx, event, t.keys, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return t.rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }); err != nil { util.GetLogger(ctx).WithError(err).Debugf("Transaction: Couldn't validate signature of event %q", event.EventID()) diff --git a/internal/transactionrequest_test.go b/internal/transactionrequest_test.go index 6f3ce0b3..1d32c806 100644 --- a/internal/transactionrequest_test.go +++ b/internal/transactionrequest_test.go @@ -70,8 +70,8 @@ type FakeRsAPI struct { bannedFromRoom bool } -func (r *FakeRsAPI) QueryUserIDForSender(ctx context.Context, roomID string, senderID string) (*spec.UserID, error) { - return spec.NewUserID(senderID, true) +func (r *FakeRsAPI) QueryUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error) { + return spec.NewUserID(string(senderID), true) } func (r *FakeRsAPI) QueryRoomVersionForRoom( @@ -642,8 +642,8 @@ type testRoomserverAPI struct { queryLatestEventsAndState func(*rsAPI.QueryLatestEventsAndStateRequest) rsAPI.QueryLatestEventsAndStateResponse } -func (t *testRoomserverAPI) QueryUserIDForSender(ctx context.Context, roomID string, senderID string) (*spec.UserID, error) { - return spec.NewUserID(senderID, true) +func (t *testRoomserverAPI) QueryUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error) { + return spec.NewUserID(string(senderID), true) } func (t *testRoomserverAPI) InputRoomEvents( diff --git a/roomserver/api/alias.go b/roomserver/api/alias.go index 1b947540..c091cf6a 100644 --- a/roomserver/api/alias.go +++ b/roomserver/api/alias.go @@ -14,7 +14,11 @@ package api -import "regexp" +import ( + "regexp" + + "github.com/matrix-org/gomatrixserverlib/spec" +) // SetRoomAliasRequest is a request to SetRoomAlias type SetRoomAliasRequest struct { @@ -62,7 +66,7 @@ type GetAliasesForRoomIDResponse struct { // RemoveRoomAliasRequest is a request to RemoveRoomAlias type RemoveRoomAliasRequest struct { // ID of the user removing the alias - SenderID string `json:"user_id"` + SenderID spec.SenderID `json:"user_id"` // The room alias to remove Alias string `json:"alias"` } diff --git a/roomserver/api/api.go b/roomserver/api/api.go index d61a0553..8c2cbd6b 100644 --- a/roomserver/api/api.go +++ b/roomserver/api/api.go @@ -77,8 +77,8 @@ type InputRoomEventsAPI interface { } type QuerySenderIDAPI interface { - QuerySenderIDForUser(ctx context.Context, roomID string, userID spec.UserID) (string, error) - QueryUserIDForSender(ctx context.Context, roomID string, senderID string) (*spec.UserID, error) + QuerySenderIDForUser(ctx context.Context, roomID string, userID spec.UserID) (spec.SenderID, error) + QueryUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error) } // Query the latest events and state for a room from the room server. diff --git a/roomserver/internal/alias.go b/roomserver/internal/alias.go index dcfb26b8..c950024a 100644 --- a/roomserver/internal/alias.go +++ b/roomserver/internal/alias.go @@ -130,7 +130,7 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias( } sender, err := r.QueryUserIDForSender(ctx, roomID, request.SenderID) - if err != nil { + if err != nil || sender == nil { return fmt.Errorf("r.QueryUserIDForSender: %w", err) } virtualHost := sender.Domain() @@ -141,7 +141,7 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias( return fmt.Errorf("r.DB.GetCreatorIDForAlias: %w", err) } - if creatorID != request.SenderID { + if spec.SenderID(creatorID) != request.SenderID { var plEvent *types.HeaderedEvent var pls *gomatrixserverlib.PowerLevelContent @@ -173,23 +173,24 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias( return err } - sender := request.SenderID + senderID := request.SenderID if request.SenderID != ev.SenderID() { - sender = ev.SenderID() + senderID = ev.SenderID() } - - _, senderDomain, err := r.Cfg.Global.SplitLocalID('@', sender) - if err != nil { + sender, err := r.QueryUserIDForSender(ctx, roomID, senderID) + if err != nil || sender == nil { return err } + senderDomain := sender.Domain() + identity, err := r.Cfg.Global.SigningIdentityFor(senderDomain) if err != nil { return err } proto := &gomatrixserverlib.ProtoEvent{ - Sender: sender, + SenderID: string(senderID), RoomID: ev.RoomID(), Type: ev.Type(), StateKey: ev.StateKey(), diff --git a/roomserver/internal/helpers/auth.go b/roomserver/internal/helpers/auth.go index 932ce615..7782d07d 100644 --- a/roomserver/internal/helpers/auth.go +++ b/roomserver/internal/helpers/auth.go @@ -76,7 +76,7 @@ func CheckForSoftFail( } // Check if the event is allowed. - if err = gomatrixserverlib.Allowed(event.PDU, &authEvents, func(roomID, senderID string) (*spec.UserID, error) { + if err = gomatrixserverlib.Allowed(event.PDU, &authEvents, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return db.GetUserIDForSender(ctx, roomID, senderID) }); err != nil { // return true, nil @@ -139,8 +139,8 @@ func (ae *authEvents) JoinRules() (gomatrixserverlib.PDU, error) { } // Memmber implements gomatrixserverlib.AuthEventProvider -func (ae *authEvents) Member(stateKey string) (gomatrixserverlib.PDU, error) { - return ae.lookupEvent(types.MRoomMemberNID, stateKey), nil +func (ae *authEvents) Member(stateKey spec.SenderID) (gomatrixserverlib.PDU, error) { + return ae.lookupEvent(types.MRoomMemberNID, string(stateKey)), nil } // ThirdPartyInvite implements gomatrixserverlib.AuthEventProvider diff --git a/roomserver/internal/input/input_events.go b/roomserver/internal/input/input_events.go index 764bdfe2..1f273da0 100644 --- a/roomserver/internal/input/input_events.go +++ b/roomserver/internal/input/input_events.go @@ -282,7 +282,7 @@ func (r *Inputer) processRoomEvent( // Check if the event is allowed by its auth events. If it isn't then // we consider the event to be "rejected" — it will still be persisted. - if err = gomatrixserverlib.Allowed(event, &authEvents, func(roomID, senderID string) (*spec.UserID, error) { + if err = gomatrixserverlib.Allowed(event, &authEvents, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.DB.GetUserIDForSender(ctx, roomID, senderID) }); err != nil { isRejected = true @@ -501,7 +501,7 @@ func (r *Inputer) processRoomEvent( func (r *Inputer) handleRemoteRoomUpgrade(ctx context.Context, event gomatrixserverlib.PDU) error { oldRoomID := event.RoomID() newRoomID := gjson.GetBytes(event.Content(), "replacement_room").Str - return r.DB.UpgradeRoom(ctx, oldRoomID, newRoomID, event.SenderID()) + return r.DB.UpgradeRoom(ctx, oldRoomID, newRoomID, string(event.SenderID())) } // processStateBefore works out what the state is before the event and @@ -587,7 +587,7 @@ func (r *Inputer) processStateBefore( stateBeforeAuth := gomatrixserverlib.NewAuthEvents( gomatrixserverlib.ToPDUs(stateBeforeEvent), ) - if rejectionErr = gomatrixserverlib.Allowed(event, &stateBeforeAuth, func(roomID, senderID string) (*spec.UserID, error) { + if rejectionErr = gomatrixserverlib.Allowed(event, &stateBeforeAuth, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.DB.GetUserIDForSender(ctx, roomID, senderID) }); rejectionErr != nil { rejectionErr = fmt.Errorf("Allowed() failed for stateBeforeEvent: %w", rejectionErr) @@ -700,7 +700,7 @@ nextAuthEvent: // Check the signatures of the event. If this fails then we'll simply // skip it, because gomatrixserverlib.Allowed() will notice a problem // if a critical event is missing anyway. - if err := gomatrixserverlib.VerifyEventSignatures(ctx, authEvent, r.FSAPI.KeyRing(), func(roomID, senderID string) (*spec.UserID, error) { + if err := gomatrixserverlib.VerifyEventSignatures(ctx, authEvent, r.FSAPI.KeyRing(), func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.DB.GetUserIDForSender(ctx, roomID, senderID) }); err != nil { continue nextAuthEvent @@ -718,7 +718,7 @@ nextAuthEvent: } // Check if the auth event should be rejected. - err := gomatrixserverlib.Allowed(authEvent, auth, func(roomID, senderID string) (*spec.UserID, error) { + err := gomatrixserverlib.Allowed(authEvent, auth, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.DB.GetUserIDForSender(ctx, roomID, senderID) }) if isRejected = err != nil; isRejected { @@ -875,7 +875,7 @@ func (r *Inputer) kickGuests(ctx context.Context, event gomatrixserverlib.PDU, r RoomID: event.RoomID(), Type: spec.MRoomMember, StateKey: &stateKey, - Sender: stateKey, + SenderID: stateKey, PrevEvents: prevEvents, } diff --git a/roomserver/internal/input/input_events_test.go b/roomserver/internal/input/input_events_test.go index 0ba7d19f..5f2cd956 100644 --- a/roomserver/internal/input/input_events_test.go +++ b/roomserver/internal/input/input_events_test.go @@ -58,7 +58,9 @@ func Test_EventAuth(t *testing.T) { } // Finally check that the event is NOT allowed - if err := gomatrixserverlib.Allowed(ev.PDU, &allower, func(roomID, senderID string) (*spec.UserID, error) { return spec.NewUserID(senderID, true) }); err == nil { + if err := gomatrixserverlib.Allowed(ev.PDU, &allower, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { + return spec.NewUserID(string(senderID), true) + }); err == nil { t.Fatalf("event should not be allowed, but it was") } } diff --git a/roomserver/internal/input/input_missing.go b/roomserver/internal/input/input_missing.go index ac0670fc..f0f974d2 100644 --- a/roomserver/internal/input/input_missing.go +++ b/roomserver/internal/input/input_missing.go @@ -473,7 +473,7 @@ func (t *missingStateReq) resolveStatesAndCheck(ctx context.Context, roomVersion stateEventList = append(stateEventList, state.StateEvents...) } resolvedStateEvents, err := gomatrixserverlib.ResolveConflicts( - roomVersion, gomatrixserverlib.ToPDUs(stateEventList), gomatrixserverlib.ToPDUs(authEventList), func(roomID, senderID string) (*spec.UserID, error) { + roomVersion, gomatrixserverlib.ToPDUs(stateEventList), gomatrixserverlib.ToPDUs(authEventList), func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return t.db.GetUserIDForSender(ctx, roomID, senderID) }, ) @@ -482,7 +482,7 @@ func (t *missingStateReq) resolveStatesAndCheck(ctx context.Context, roomVersion } // apply the current event retryAllowedState: - if err = checkAllowedByState(backwardsExtremity, resolvedStateEvents, func(roomID, senderID string) (*spec.UserID, error) { + if err = checkAllowedByState(backwardsExtremity, resolvedStateEvents, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return t.db.GetUserIDForSender(ctx, roomID, senderID) }); err != nil { switch missing := err.(type) { @@ -569,7 +569,7 @@ func (t *missingStateReq) getMissingEvents(ctx context.Context, e gomatrixserver // will be added and duplicates will be removed. missingEvents := make([]gomatrixserverlib.PDU, 0, len(missingResp.Events)) for _, ev := range missingResp.Events.UntrustedEvents(roomVersion) { - if err = gomatrixserverlib.VerifyEventSignatures(ctx, ev, t.keys, func(roomID, senderID string) (*spec.UserID, error) { + if err = gomatrixserverlib.VerifyEventSignatures(ctx, ev, t.keys, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return t.db.GetUserIDForSender(ctx, roomID, senderID) }); err != nil { continue @@ -660,7 +660,7 @@ func (t *missingStateReq) lookupMissingStateViaState( authEvents, stateEvents, err := gomatrixserverlib.CheckStateResponse(ctx, &fclient.RespState{ StateEvents: state.GetStateEvents(), AuthEvents: state.GetAuthEvents(), - }, roomVersion, t.keys, nil, func(roomID, senderID string) (*spec.UserID, error) { + }, roomVersion, t.keys, nil, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return t.db.GetUserIDForSender(ctx, roomID, senderID) }) if err != nil { @@ -897,7 +897,7 @@ func (t *missingStateReq) lookupEvent(ctx context.Context, roomVersion gomatrixs t.log.WithField("missing_event_id", missingEventID).Warnf("Failed to get missing /event for event ID from %d server(s)", len(t.servers)) return nil, fmt.Errorf("wasn't able to find event via %d server(s)", len(t.servers)) } - if err := gomatrixserverlib.VerifyEventSignatures(ctx, event, t.keys, func(roomID, senderID string) (*spec.UserID, error) { + if err := gomatrixserverlib.VerifyEventSignatures(ctx, event, t.keys, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return t.db.GetUserIDForSender(ctx, roomID, senderID) }); err != nil { t.log.WithError(err).Warnf("Couldn't validate signature of event %q from /event", event.EventID()) diff --git a/roomserver/internal/perform/perform_admin.go b/roomserver/internal/perform/perform_admin.go index ca736cb6..eeb1ac40 100644 --- a/roomserver/internal/perform/perform_admin.go +++ b/roomserver/internal/perform/perform_admin.go @@ -96,14 +96,15 @@ func (r *Admin) PerformAdminEvacuateRoom( RoomID: roomID, Type: spec.MRoomMember, StateKey: &stateKey, - Sender: stateKey, + SenderID: stateKey, PrevEvents: prevEvents, } - _, senderDomain, err = gomatrixserverlib.SplitID('@', fledglingEvent.Sender) - if err != nil { + userID, err := r.Queryer.QueryUserIDForSender(ctx, roomID, spec.SenderID(fledglingEvent.SenderID)) + if err != nil || userID == nil { continue } + senderDomain = userID.Domain() if fledglingEvent.Content, err = json.Marshal(memberContent); err != nil { return nil, err @@ -233,10 +234,11 @@ func (r *Admin) PerformAdminDownloadState( ctx context.Context, roomID, userID string, serverName spec.ServerName, ) error { - _, senderDomain, err := r.Cfg.Matrix.SplitLocalID('@', userID) + fullUserID, err := spec.NewUserID(userID, true) if err != nil { return err } + senderDomain := fullUserID.Domain() roomInfo, err := r.DB.RoomInfo(ctx, roomID) if err != nil { @@ -262,7 +264,7 @@ func (r *Admin) PerformAdminDownloadState( return fmt.Errorf("r.Inputer.FSAPI.LookupState (%q): %s", fwdExtremity, err) } for _, authEvent := range state.GetAuthEvents().UntrustedEvents(roomInfo.RoomVersion) { - if err = gomatrixserverlib.VerifyEventSignatures(ctx, authEvent, r.Inputer.KeyRing, func(roomID, senderID string) (*spec.UserID, error) { + if err = gomatrixserverlib.VerifyEventSignatures(ctx, authEvent, r.Inputer.KeyRing, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.DB.GetUserIDForSender(ctx, roomID, senderID) }); err != nil { continue @@ -270,7 +272,7 @@ func (r *Admin) PerformAdminDownloadState( authEventMap[authEvent.EventID()] = authEvent } for _, stateEvent := range state.GetStateEvents().UntrustedEvents(roomInfo.RoomVersion) { - if err = gomatrixserverlib.VerifyEventSignatures(ctx, stateEvent, r.Inputer.KeyRing, func(roomID, senderID string) (*spec.UserID, error) { + if err = gomatrixserverlib.VerifyEventSignatures(ctx, stateEvent, r.Inputer.KeyRing, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.DB.GetUserIDForSender(ctx, roomID, senderID) }); err != nil { continue @@ -291,11 +293,15 @@ func (r *Admin) PerformAdminDownloadState( stateIDs = append(stateIDs, stateEvent.EventID()) } + senderID, err := r.Queryer.QuerySenderIDForUser(ctx, roomID, *fullUserID) + if err != nil { + return err + } proto := &gomatrixserverlib.ProtoEvent{ - Type: "org.matrix.dendrite.state_download", - Sender: userID, - RoomID: roomID, - Content: spec.RawJSON("{}"), + Type: "org.matrix.dendrite.state_download", + SenderID: string(senderID), + RoomID: roomID, + Content: spec.RawJSON("{}"), } eventsNeeded, err := gomatrixserverlib.StateNeededForProtoEvent(proto) diff --git a/roomserver/internal/perform/perform_backfill.go b/roomserver/internal/perform/perform_backfill.go index 0f743f4e..38815093 100644 --- a/roomserver/internal/perform/perform_backfill.go +++ b/roomserver/internal/perform/perform_backfill.go @@ -121,7 +121,7 @@ func (r *Backfiller) backfillViaFederation(ctx context.Context, req *api.Perform // Specifically the test "Outbound federation can backfill events" events, err := gomatrixserverlib.RequestBackfill( ctx, req.VirtualHost, requester, - r.KeyRing, req.RoomID, info.RoomVersion, req.PrevEventIDs(), 100, func(roomID, senderID string) (*spec.UserID, error) { + r.KeyRing, req.RoomID, info.RoomVersion, req.PrevEventIDs(), 100, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.DB.GetUserIDForSender(ctx, roomID, senderID) }, ) @@ -212,7 +212,7 @@ func (r *Backfiller) fetchAndStoreMissingEvents(ctx context.Context, roomVer gom continue } loader := gomatrixserverlib.NewEventsLoader(roomVer, r.KeyRing, backfillRequester, backfillRequester.ProvideEvents, false) - result, err := loader.LoadAndVerify(ctx, res.PDUs, gomatrixserverlib.TopologicalOrderByPrevEvents, func(roomID, senderID string) (*spec.UserID, error) { + result, err := loader.LoadAndVerify(ctx, res.PDUs, gomatrixserverlib.TopologicalOrderByPrevEvents, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.DB.GetUserIDForSender(ctx, roomID, senderID) }) if err != nil { diff --git a/roomserver/internal/perform/perform_create_room.go b/roomserver/internal/perform/perform_create_room.go index 897bd3a0..a3ba20f7 100644 --- a/roomserver/internal/perform/perform_create_room.go +++ b/roomserver/internal/perform/perform_create_room.go @@ -270,11 +270,19 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo var builtEvents []*types.HeaderedEvent authEvents := gomatrixserverlib.NewAuthEvents(nil) + senderID, err := c.RSAPI.QuerySenderIDForUser(ctx, roomID.String(), userID) + if err != nil { + util.GetLogger(ctx).WithError(err).Error("rsapi.QuerySenderIDForUser failed") + return "", &util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{}, + } + } for i, e := range eventsToMake { depth := i + 1 // depth starts at 1 builder := verImpl.NewEventBuilderFromProtoEvent(&gomatrixserverlib.ProtoEvent{ - Sender: userID.String(), + SenderID: string(senderID), RoomID: roomID.String(), Type: e.Type, StateKey: &e.StateKey, @@ -308,7 +316,7 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo } } - if err = gomatrixserverlib.Allowed(ev, &authEvents, func(roomID, senderID string) (*spec.UserID, error) { + if err = gomatrixserverlib.Allowed(ev, &authEvents, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return c.DB.GetUserIDForSender(ctx, roomID, senderID) }); err != nil { util.GetLogger(ctx).WithError(err).Error("gomatrixserverlib.Allowed failed") @@ -409,11 +417,28 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo // Process the invites. var inviteEvent *types.HeaderedEvent for _, invitee := range createRequest.InvitedUsers { + inviteeUserID, userIDErr := spec.NewUserID(invitee, true) + if userIDErr != nil { + util.GetLogger(ctx).WithError(userIDErr).Error("invalid UserID") + return "", &util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{}, + } + } + inviteeSenderID, queryErr := c.RSAPI.QuerySenderIDForUser(ctx, roomID.String(), *inviteeUserID) + if queryErr != nil { + util.GetLogger(ctx).WithError(queryErr).Error("rsapi.QuerySenderIDForUser failed") + return "", &util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{}, + } + } + inviteeString := string(inviteeSenderID) proto := gomatrixserverlib.ProtoEvent{ - Sender: userID.String(), + SenderID: string(senderID), RoomID: roomID.String(), Type: "m.room.member", - StateKey: &invitee, + StateKey: &inviteeString, } content := gomatrixserverlib.MemberContent{ diff --git a/roomserver/internal/perform/perform_invite.go b/roomserver/internal/perform/perform_invite.go index e8e20ede..56ee1606 100644 --- a/roomserver/internal/perform/perform_invite.go +++ b/roomserver/internal/perform/perform_invite.go @@ -98,7 +98,7 @@ func (r *Inviter) ProcessInviteMembership( var outputUpdates []api.OutputEvent var updater *shared.MembershipUpdater - userID, err := r.RSAPI.QueryUserIDForSender(ctx, inviteEvent.RoomID(), *inviteEvent.StateKey()) + userID, err := r.RSAPI.QueryUserIDForSender(ctx, inviteEvent.RoomID(), spec.SenderID(*inviteEvent.StateKey())) if err != nil { return nil, api.ErrInvalidID{Err: fmt.Errorf("the user ID %s is invalid", *inviteEvent.StateKey())} } @@ -148,15 +148,21 @@ func (r *Inviter) PerformInvite( return err } + invitedSenderID, err := r.RSAPI.QuerySenderIDForUser(ctx, event.RoomID(), *invitedUser) + if err != nil { + return fmt.Errorf("failed looking up senderID for invited user") + } + input := gomatrixserverlib.PerformInviteInput{ RoomID: *validRoomID, InviteEvent: event.PDU, InvitedUser: *invitedUser, + InvitedSenderID: invitedSenderID, IsTargetLocal: isTargetLocal, StrippedState: req.InviteRoomState, MembershipQuerier: &api.MembershipQuerier{Roomserver: r.RSAPI}, StateQuerier: &QueryState{r.DB}, - UserIDQuerier: func(roomID, senderID string) (*spec.UserID, error) { + UserIDQuerier: func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.DB.GetUserIDForSender(ctx, roomID, senderID) }, } diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go index 181a9349..d41cc214 100644 --- a/roomserver/internal/perform/perform_join.go +++ b/roomserver/internal/perform/perform_join.go @@ -175,15 +175,20 @@ func (r *Joiner) performJoinRoomByID( } // Prepare the template for the join event. - userID := req.UserID - _, userDomain, err := r.Cfg.Matrix.SplitLocalID('@', userID) + userID, err := spec.NewUserID(req.UserID, true) if err != nil { - return "", "", rsAPI.ErrInvalidID{Err: fmt.Errorf("user ID %q is invalid: %w", userID, err)} + return "", "", rsAPI.ErrInvalidID{Err: fmt.Errorf("user ID %q is invalid: %w", req.UserID, err)} } + senderID, err := r.RSAPI.QuerySenderIDForUser(ctx, req.RoomIDOrAlias, *userID) + if err != nil { + return "", "", rsAPI.ErrInvalidID{Err: fmt.Errorf("user ID %q is invalid: %w", req.UserID, err)} + } + senderIDString := string(senderID) + userDomain := userID.Domain() proto := gomatrixserverlib.ProtoEvent{ Type: spec.MRoomMember, - Sender: userID, - StateKey: &userID, + SenderID: senderIDString, + StateKey: &senderIDString, RoomID: req.RoomIDOrAlias, Redacts: "", } @@ -295,7 +300,7 @@ func (r *Joiner) performJoinRoomByID( // is really no harm in just sending another membership event. membershipReq := &api.QueryMembershipForUserRequest{ RoomID: req.RoomIDOrAlias, - UserID: userID, + UserID: userID.String(), } membershipRes := &api.QueryMembershipForUserResponse{} _ = r.Queryer.QueryMembershipForUser(ctx, membershipReq, membershipRes) diff --git a/roomserver/internal/perform/perform_leave.go b/roomserver/internal/perform/perform_leave.go index 90102aee..094537f8 100644 --- a/roomserver/internal/perform/perform_leave.go +++ b/roomserver/internal/perform/perform_leave.go @@ -152,11 +152,19 @@ func (r *Leaver) performLeaveRoomByID( } // Prepare the template for the leave event. - userID := req.UserID + fullUserID, err := spec.NewUserID(req.UserID, true) + if err != nil { + return nil, err + } + senderID, err := r.RSAPI.QuerySenderIDForUser(ctx, req.RoomID, *fullUserID) + if err != nil { + return nil, err + } + senderIDString := string(senderID) proto := gomatrixserverlib.ProtoEvent{ Type: spec.MRoomMember, - Sender: userID, - StateKey: &userID, + SenderID: senderIDString, + StateKey: &senderIDString, RoomID: req.RoomID, Redacts: "", } @@ -168,10 +176,7 @@ func (r *Leaver) performLeaveRoomByID( } // Get the sender domain. - _, senderDomain, serr := r.Cfg.Matrix.SplitLocalID('@', proto.Sender) - if serr != nil { - return nil, fmt.Errorf("sender %q is invalid", proto.Sender) - } + senderDomain := fullUserID.Domain() // We know that the user is in the room at this point so let's build // a leave event. diff --git a/roomserver/internal/perform/perform_upgrade.go b/roomserver/internal/perform/perform_upgrade.go index 8c0df1c4..5710352b 100644 --- a/roomserver/internal/perform/perform_upgrade.go +++ b/roomserver/internal/perform/perform_upgrade.go @@ -175,8 +175,16 @@ func moveLocalAliases(ctx context.Context, return fmt.Errorf("Failed to get old room aliases: %w", err) } + fullUserID, err := spec.NewUserID(userID, true) + if err != nil { + return fmt.Errorf("Failed to get userID: %w", err) + } + senderID, err := URSAPI.QuerySenderIDForUser(ctx, roomID, *fullUserID) + if err != nil { + return fmt.Errorf("Failed to get senderID: %w", err) + } for _, alias := range aliasRes.Aliases { - removeAliasReq := api.RemoveRoomAliasRequest{SenderID: userID, Alias: alias} + removeAliasReq := api.RemoveRoomAliasRequest{SenderID: senderID, Alias: alias} removeAliasRes := api.RemoveRoomAliasResponse{} if err = URSAPI.RemoveRoomAlias(ctx, &removeAliasReq, &removeAliasRes); err != nil { return fmt.Errorf("Failed to remove old room alias: %w", err) @@ -287,7 +295,15 @@ func (r *Upgrader) userIsAuthorized(ctx context.Context, userID, roomID string, } // Check for power level required to send tombstone event (marks the current room as obsolete), // if not found, use the StateDefault power level - return pl.UserLevel(userID) >= pl.EventLevel("m.room.tombstone", true) + fullUserID, err := spec.NewUserID(userID, true) + if err != nil { + return false + } + senderID, err := r.URSAPI.QuerySenderIDForUser(ctx, roomID, *fullUserID) + if err != nil { + return false + } + return pl.UserLevel(senderID) >= pl.EventLevel("m.room.tombstone", true) } // nolint:gocyclo @@ -383,7 +399,16 @@ func (r *Upgrader) generateInitialEvents(ctx context.Context, oldRoom *api.Query util.GetLogger(ctx).WithError(err).Error() return nil, fmt.Errorf("Power level event content was invalid") } - tempPowerLevelsEvent, powerLevelsOverridden := createTemporaryPowerLevels(powerLevelContent, userID) + + fullUserID, err := spec.NewUserID(userID, true) + if err != nil { + return nil, err + } + senderID, err := r.URSAPI.QuerySenderIDForUser(ctx, roomID, *fullUserID) + if err != nil { + return nil, err + } + tempPowerLevelsEvent, powerLevelsOverridden := createTemporaryPowerLevels(powerLevelContent, senderID) // Now do the join rules event, same as the create and membership // events. We'll set a sane default of "invite" so that if the @@ -452,8 +477,16 @@ func (r *Upgrader) sendInitialEvents(ctx context.Context, evTime time.Time, user for i, e := range eventsToMake { depth := i + 1 // depth starts at 1 + fullUserID, userIDErr := spec.NewUserID(userID, true) + if userIDErr != nil { + return userIDErr + } + senderID, queryErr := r.URSAPI.QuerySenderIDForUser(ctx, newRoomID, *fullUserID) + if queryErr != nil { + return queryErr + } proto := gomatrixserverlib.ProtoEvent{ - Sender: userID, + SenderID: string(senderID), RoomID: newRoomID, Type: e.Type, StateKey: &e.StateKey, @@ -484,7 +517,7 @@ func (r *Upgrader) sendInitialEvents(ctx context.Context, evTime time.Time, user } - if err = gomatrixserverlib.Allowed(event, &authEvents, func(roomID, senderID string) (*spec.UserID, error) { + if err = gomatrixserverlib.Allowed(event, &authEvents, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.URSAPI.QueryUserIDForSender(ctx, roomID, senderID) }); err != nil { return fmt.Errorf("Failed to auth new %q event: %w", builder.Type, err) @@ -530,21 +563,26 @@ func (r *Upgrader) makeTombstoneEvent( } func (r *Upgrader) makeHeaderedEvent(ctx context.Context, evTime time.Time, userID, roomID string, event gomatrixserverlib.FledglingEvent) (*types.HeaderedEvent, error) { + fullUserID, err := spec.NewUserID(userID, true) + if err != nil { + return nil, err + } + senderID, err := r.URSAPI.QuerySenderIDForUser(ctx, roomID, *fullUserID) + if err != nil { + return nil, err + } proto := gomatrixserverlib.ProtoEvent{ - Sender: userID, + SenderID: string(senderID), RoomID: roomID, Type: event.Type, StateKey: &event.StateKey, } - err := proto.SetContent(event.Content) + err = proto.SetContent(event.Content) if err != nil { return nil, fmt.Errorf("failed to set new %q event content: %w", proto.Type, err) } // Get the sender domain. - _, senderDomain, serr := r.Cfg.Matrix.SplitLocalID('@', proto.Sender) - if serr != nil { - return nil, fmt.Errorf("Failed to split user ID %q: %w", proto.Sender, err) - } + senderDomain := fullUserID.Domain() identity, err := r.Cfg.Matrix.SigningIdentityFor(senderDomain) if err != nil { return nil, fmt.Errorf("failed to get signing identity for %q: %w", senderDomain, err) @@ -569,7 +607,7 @@ func (r *Upgrader) makeHeaderedEvent(ctx context.Context, evTime time.Time, user stateEvents[i] = queryRes.StateEvents[i].PDU } provider := gomatrixserverlib.NewAuthEvents(stateEvents) - if err = gomatrixserverlib.Allowed(headeredEvent.PDU, &provider, func(roomID, senderID string) (*spec.UserID, error) { + if err = gomatrixserverlib.Allowed(headeredEvent.PDU, &provider, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.URSAPI.QueryUserIDForSender(ctx, roomID, senderID) }); err != nil { return nil, api.ErrNotAllowed{Err: fmt.Errorf("failed to auth new %q event: %w", proto.Type, err)} // TODO: Is this error string comprehensible to the client? @@ -578,7 +616,7 @@ func (r *Upgrader) makeHeaderedEvent(ctx context.Context, evTime time.Time, user return headeredEvent, nil } -func createTemporaryPowerLevels(powerLevelContent *gomatrixserverlib.PowerLevelContent, userID string) (gomatrixserverlib.FledglingEvent, bool) { +func createTemporaryPowerLevels(powerLevelContent *gomatrixserverlib.PowerLevelContent, senderID spec.SenderID) (gomatrixserverlib.FledglingEvent, bool) { // Work out what power level we need in order to be able to send events // of all types into the room. neededPowerLevel := powerLevelContent.StateDefault @@ -603,8 +641,8 @@ func createTemporaryPowerLevels(powerLevelContent *gomatrixserverlib.PowerLevelC // If the user who is upgrading the room doesn't already have sufficient // power, then elevate their power levels. - if tempPowerLevelContent.UserLevel(userID) < neededPowerLevel { - tempPowerLevelContent.Users[userID] = neededPowerLevel + if tempPowerLevelContent.UserLevel(senderID) < neededPowerLevel { + tempPowerLevelContent.Users[string(senderID)] = neededPowerLevel powerLevelsOverridden = true } diff --git a/roomserver/internal/query/query.go b/roomserver/internal/query/query.go index 707e95b2..ae2b7cf5 100644 --- a/roomserver/internal/query/query.go +++ b/roomserver/internal/query/query.go @@ -159,7 +159,7 @@ func (r *Queryer) QueryStateAfterEvents( } stateEvents, err = gomatrixserverlib.ResolveConflicts( - info.RoomVersion, gomatrixserverlib.ToPDUs(stateEvents), gomatrixserverlib.ToPDUs(authEvents), func(roomID, senderID string) (*spec.UserID, error) { + info.RoomVersion, gomatrixserverlib.ToPDUs(stateEvents), gomatrixserverlib.ToPDUs(authEvents), func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.DB.GetUserIDForSender(ctx, roomID, senderID) }, ) @@ -637,7 +637,7 @@ func (r *Queryer) QueryStateAndAuthChain( if request.ResolveState { stateEvents, err = gomatrixserverlib.ResolveConflicts( - info.RoomVersion, gomatrixserverlib.ToPDUs(stateEvents), gomatrixserverlib.ToPDUs(authEvents), func(roomID, senderID string) (*spec.UserID, error) { + info.RoomVersion, gomatrixserverlib.ToPDUs(stateEvents), gomatrixserverlib.ToPDUs(authEvents), func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.DB.GetUserIDForSender(ctx, roomID, senderID) }, ) @@ -975,10 +975,10 @@ func (r *Queryer) QueryRestrictedJoinAllowed(ctx context.Context, roomID spec.Ro return verImpl.CheckRestrictedJoin(ctx, r.Cfg.Global.ServerName, &api.JoinRoomQuerier{Roomserver: r}, roomID, userID) } -func (r *Queryer) QuerySenderIDForUser(ctx context.Context, roomID string, userID spec.UserID) (string, error) { +func (r *Queryer) QuerySenderIDForUser(ctx context.Context, roomID string, userID spec.UserID) (spec.SenderID, error) { return r.DB.GetSenderIDForUser(ctx, roomID, userID) } -func (r *Queryer) QueryUserIDForSender(ctx context.Context, roomID string, senderID string) (*spec.UserID, error) { +func (r *Queryer) QueryUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error) { return r.DB.GetUserIDForSender(ctx, roomID, senderID) } diff --git a/roomserver/roomserver_test.go b/roomserver/roomserver_test.go index 11a0f581..5e6ba7d4 100644 --- a/roomserver/roomserver_test.go +++ b/roomserver/roomserver_test.go @@ -392,7 +392,7 @@ func TestPurgeRoom(t *testing.T) { type fledglingEvent struct { Type string StateKey *string - Sender string + SenderID string RoomID string Redacts string Depth int64 @@ -405,7 +405,7 @@ func mustCreateEvent(t *testing.T, ev fledglingEvent) (result *types.HeaderedEve seed := make([]byte, ed25519.SeedSize) // zero seed key := ed25519.NewKeyFromSeed(seed) eb := gomatrixserverlib.MustGetRoomVersion(roomVer).NewEventBuilderFromProtoEvent(&gomatrixserverlib.ProtoEvent{ - Sender: ev.Sender, + SenderID: ev.SenderID, Type: ev.Type, StateKey: ev.StateKey, RoomID: ev.RoomID, @@ -444,7 +444,7 @@ func TestRedaction(t *testing.T) { builderEv := mustCreateEvent(t, fledglingEvent{ Type: spec.MRoomRedaction, - Sender: alice.ID, + SenderID: alice.ID, RoomID: room.ID, Redacts: redactedEvent.EventID(), Depth: redactedEvent.Depth() + 1, @@ -461,7 +461,7 @@ func TestRedaction(t *testing.T) { builderEv := mustCreateEvent(t, fledglingEvent{ Type: spec.MRoomRedaction, - Sender: alice.ID, + SenderID: alice.ID, RoomID: room.ID, Redacts: redactedEvent.EventID(), Depth: redactedEvent.Depth() + 1, @@ -478,7 +478,7 @@ func TestRedaction(t *testing.T) { builderEv := mustCreateEvent(t, fledglingEvent{ Type: spec.MRoomRedaction, - Sender: bob.ID, + SenderID: bob.ID, RoomID: room.ID, Redacts: redactedEvent.EventID(), Depth: redactedEvent.Depth() + 1, @@ -494,7 +494,7 @@ func TestRedaction(t *testing.T) { builderEv := mustCreateEvent(t, fledglingEvent{ Type: spec.MRoomRedaction, - Sender: charlie.ID, + SenderID: charlie.ID, RoomID: room.ID, Redacts: redactedEvent.EventID(), Depth: redactedEvent.Depth() + 1, diff --git a/roomserver/state/state.go b/roomserver/state/state.go index 3131cbff..b9c5bbc4 100644 --- a/roomserver/state/state.go +++ b/roomserver/state/state.go @@ -44,7 +44,7 @@ type StateResolutionStorage interface { AddState(ctx context.Context, roomNID types.RoomNID, stateBlockNIDs []types.StateBlockNID, state []types.StateEntry) (types.StateSnapshotNID, error) Events(ctx context.Context, roomVersion gomatrixserverlib.RoomVersion, eventNIDs []types.EventNID) ([]types.Event, error) EventsFromIDs(ctx context.Context, roomInfo *types.RoomInfo, eventIDs []string) ([]types.Event, error) - GetUserIDForSender(ctx context.Context, roomID string, senderID string) (*spec.UserID, error) + GetUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error) } type StateResolution struct { @@ -947,7 +947,7 @@ func (v *StateResolution) resolveConflictsV1( } // Resolve the conflicts. - resolvedEvents := gomatrixserverlib.ResolveStateConflicts(conflictedEvents, authEvents, func(roomID, senderID string) (*spec.UserID, error) { + resolvedEvents := gomatrixserverlib.ResolveStateConflicts(conflictedEvents, authEvents, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return v.db.GetUserIDForSender(ctx, roomID, senderID) }) @@ -1061,7 +1061,7 @@ func (v *StateResolution) resolveConflictsV2( conflictedEvents, nonConflictedEvents, authEvents, - func(roomID, senderID string) (*spec.UserID, error) { + func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return v.db.GetUserIDForSender(ctx, roomID, senderID) }, ) diff --git a/roomserver/storage/interface.go b/roomserver/storage/interface.go index 2d007bed..523cc361 100644 --- a/roomserver/storage/interface.go +++ b/roomserver/storage/interface.go @@ -167,9 +167,9 @@ type Database interface { // GetKnownUsers searches all users that userID knows about. GetKnownUsers(ctx context.Context, userID, searchString string, limit int) ([]string, error) // GetKnownUsers tries to obtain the current mxid for a given user. - GetUserIDForSender(ctx context.Context, roomID string, senderID string) (*spec.UserID, error) + GetUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error) // GetKnownUsers tries to obtain the current senderID for a given user. - GetSenderIDForUser(ctx context.Context, roomID string, userID spec.UserID) (string, error) + GetSenderIDForUser(ctx context.Context, roomID string, userID spec.UserID) (spec.SenderID, error) // GetKnownRooms returns a list of all rooms we know about. GetKnownRooms(ctx context.Context) ([]string, error) // ForgetRoom sets a flag in the membership table, that the user wishes to forget a specific room @@ -215,7 +215,7 @@ type RoomDatabase interface { GetOrCreateEventTypeNID(ctx context.Context, eventType string) (eventTypeNID types.EventTypeNID, err error) GetOrCreateEventStateKeyNID(ctx context.Context, eventStateKey *string) (types.EventStateKeyNID, error) GetStateEvent(ctx context.Context, roomID, evType, stateKey string) (*types.HeaderedEvent, error) - GetUserIDForSender(ctx context.Context, roomID string, senderID string) (*spec.UserID, error) + GetUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error) } type EventDatabase interface { diff --git a/roomserver/storage/shared/membership_updater.go b/roomserver/storage/shared/membership_updater.go index 105e61df..a96e8707 100644 --- a/roomserver/storage/shared/membership_updater.go +++ b/roomserver/storage/shared/membership_updater.go @@ -101,7 +101,7 @@ func (u *MembershipUpdater) Update(newMembership tables.MembershipState, event * var inserted bool // Did the query result in a membership change? var retired []string // Did we retire any updates in the process? return inserted, retired, u.d.Writer.Do(u.d.DB, u.txn, func(txn *sql.Tx) error { - senderUserNID, err := u.d.assignStateKeyNID(u.ctx, u.txn, event.SenderID()) + senderUserNID, err := u.d.assignStateKeyNID(u.ctx, u.txn, string(event.SenderID())) if err != nil { return fmt.Errorf("u.d.AssignStateKeyNID: %w", err) } diff --git a/roomserver/storage/shared/room_updater.go b/roomserver/storage/shared/room_updater.go index 73500138..6fb57332 100644 --- a/roomserver/storage/shared/room_updater.go +++ b/roomserver/storage/shared/room_updater.go @@ -252,6 +252,6 @@ func (u *RoomUpdater) MembershipUpdater(targetUserNID types.EventStateKeyNID, ta return u.d.membershipUpdaterTxn(u.ctx, u.txn, u.roomInfo.RoomNID, targetUserNID, targetLocal) } -func (u *RoomUpdater) GetUserIDForSender(ctx context.Context, roomID string, senderID string) (*spec.UserID, error) { +func (u *RoomUpdater) GetUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error) { return u.d.GetUserIDForSender(ctx, roomID, senderID) } diff --git a/roomserver/storage/shared/storage.go b/roomserver/storage/shared/storage.go index 406d7cf1..f2f84235 100644 --- a/roomserver/storage/shared/storage.go +++ b/roomserver/storage/shared/storage.go @@ -990,13 +990,13 @@ func (d *EventDatabase) MaybeRedactEvent( // TODO: Don't hack senderID into userID here (pseudoIDs) sender1Domain := "" - sender1, err1 := spec.NewUserID(redactedEvent.SenderID(), true) + sender1, err1 := spec.NewUserID(string(redactedEvent.SenderID()), true) if err1 == nil { sender1Domain = string(sender1.Domain()) } // TODO: Don't hack senderID into userID here (pseudoIDs) sender2Domain := "" - sender2, err2 := spec.NewUserID(redactionEvent.SenderID(), true) + sender2, err2 := spec.NewUserID(string(redactionEvent.SenderID()), true) if err2 == nil { sender2Domain = string(sender2.Domain()) } @@ -1524,14 +1524,14 @@ func (d *Database) GetKnownUsers(ctx context.Context, userID, searchString strin return d.MembershipTable.SelectKnownUsers(ctx, nil, stateKeyNID, searchString, limit) } -func (d *Database) GetUserIDForSender(ctx context.Context, roomID string, senderID string) (*spec.UserID, error) { +func (d *Database) GetUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error) { // TODO: Use real logic once DB for pseudoIDs is in place - return spec.NewUserID(senderID, true) + return spec.NewUserID(string(senderID), true) } -func (d *Database) GetSenderIDForUser(ctx context.Context, roomID string, userID spec.UserID) (string, error) { +func (d *Database) GetSenderIDForUser(ctx context.Context, roomID string, userID spec.UserID) (spec.SenderID, error) { // TODO: Use real logic once DB for pseudoIDs is in place - return userID.String(), nil + return spec.SenderID(userID.String()), nil } // GetKnownRooms returns a list of all rooms we know about. diff --git a/setup/mscs/msc2836/msc2836.go b/setup/mscs/msc2836/msc2836.go index 5ce3b430..47eb544e 100644 --- a/setup/mscs/msc2836/msc2836.go +++ b/setup/mscs/msc2836/msc2836.go @@ -94,7 +94,7 @@ type MSC2836EventRelationshipsResponse struct { func toClientResponse(ctx context.Context, res *MSC2836EventRelationshipsResponse, rsAPI roomserver.RoomserverInternalAPI) *EventRelationshipResponse { out := &EventRelationshipResponse{ - Events: synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(res.ParsedEvents), synctypes.FormatAll, func(roomID, senderID string) (*spec.UserID, error) { + Events: synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(res.ParsedEvents), synctypes.FormatAll, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }), Limited: res.Limited, diff --git a/setup/mscs/msc2836/msc2836_test.go b/setup/mscs/msc2836/msc2836_test.go index c463fd72..551d7ad4 100644 --- a/setup/mscs/msc2836/msc2836_test.go +++ b/setup/mscs/msc2836/msc2836_test.go @@ -525,8 +525,8 @@ type testRoomserverAPI struct { events map[string]*types.HeaderedEvent } -func (r *testRoomserverAPI) QueryUserIDForSender(ctx context.Context, roomID string, senderID string) (*spec.UserID, error) { - return spec.NewUserID(senderID, true) +func (r *testRoomserverAPI) QueryUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error) { + return spec.NewUserID(string(senderID), true) } func (r *testRoomserverAPI) QueryEventsByID(ctx context.Context, req *roomserver.QueryEventsByIDRequest, res *roomserver.QueryEventsByIDResponse) error { @@ -590,7 +590,7 @@ func mustCreateEvent(t *testing.T, ev fledglingEvent) (result *types.HeaderedEve seed := make([]byte, ed25519.SeedSize) // zero seed key := ed25519.NewKeyFromSeed(seed) eb := gomatrixserverlib.MustGetRoomVersion(roomVer).NewEventBuilderFromProtoEvent(&gomatrixserverlib.ProtoEvent{ - Sender: ev.Sender, + SenderID: ev.Sender, Depth: 999, Type: ev.Type, StateKey: ev.StateKey, diff --git a/setup/mscs/msc2946/msc2946.go b/setup/mscs/msc2946/msc2946.go index f380d3d4..3e5ffda9 100644 --- a/setup/mscs/msc2946/msc2946.go +++ b/setup/mscs/msc2946/msc2946.go @@ -730,7 +730,7 @@ func stripped(ev gomatrixserverlib.PDU) *fclient.MSC2946StrippedEvent { Type: ev.Type(), StateKey: *ev.StateKey(), Content: ev.Content(), - Sender: ev.SenderID(), + Sender: string(ev.SenderID()), OriginServerTS: ev.OriginServerTS(), } } diff --git a/syncapi/consumers/roomserver.go b/syncapi/consumers/roomserver.go index c0836465..8a2a0b1f 100644 --- a/syncapi/consumers/roomserver.go +++ b/syncapi/consumers/roomserver.go @@ -523,7 +523,7 @@ func (s *OutputRoomEventConsumer) updateStateEvent(event *rstypes.HeaderedEvent) prev := types.PrevEventRef{ PrevContent: prevEvent.Content(), ReplacesState: prevEvent.EventID(), - PrevSender: prevEvent.SenderID(), + PrevSenderID: string(prevEvent.SenderID()), } event.PDU, err = event.SetUnsigned(prev) diff --git a/syncapi/routing/context.go b/syncapi/routing/context.go index 27e99a35..7fb88faa 100644 --- a/syncapi/routing/context.go +++ b/syncapi/routing/context.go @@ -193,10 +193,10 @@ func Context( } } - eventsBeforeClient := synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(eventsBeforeFiltered), synctypes.FormatAll, func(roomID, senderID string) (*spec.UserID, error) { + eventsBeforeClient := synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(eventsBeforeFiltered), synctypes.FormatAll, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }) - eventsAfterClient := synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(eventsAfterFiltered), synctypes.FormatAll, func(roomID, senderID string) (*spec.UserID, error) { + eventsAfterClient := synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(eventsAfterFiltered), synctypes.FormatAll, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }) @@ -204,7 +204,7 @@ func Context( if filter.LazyLoadMembers { allEvents := append(eventsBeforeFiltered, eventsAfterFiltered...) allEvents = append(allEvents, &requestedEvent) - evs := synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(allEvents), synctypes.FormatAll, func(roomID, senderID string) (*spec.UserID, error) { + evs := synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(allEvents), synctypes.FormatAll, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }) newState, err = applyLazyLoadMembers(ctx, device, snapshot, roomID, evs, lazyLoadCache) @@ -227,7 +227,7 @@ func Context( Event: &ev, EventsAfter: eventsAfterClient, EventsBefore: eventsBeforeClient, - State: synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(newState), synctypes.FormatAll, func(roomID, senderID string) (*spec.UserID, error) { + State: synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(newState), synctypes.FormatAll, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }), } diff --git a/syncapi/routing/memberships.go b/syncapi/routing/memberships.go index 9c2319dd..813167a5 100644 --- a/syncapi/routing/memberships.go +++ b/syncapi/routing/memberships.go @@ -144,7 +144,22 @@ func GetMemberships( JSON: spec.InternalServerError{}, } } - res.Joined[ev.SenderID()] = joinedMember(content) + + userID, err := rsAPI.QueryUserIDForSender(req.Context(), ev.RoomID(), ev.SenderID()) + if err != nil || userID == nil { + util.GetLogger(req.Context()).WithError(err).Error("rsAPI.QueryUserIDForSender failed") + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{}, + } + } + if err != nil { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: spec.Forbidden("You don't have permission to kick this user, unknown senderID"), + } + } + res.Joined[userID.String()] = joinedMember(content) } return util.JSONResponse{ Code: http.StatusOK, @@ -153,7 +168,7 @@ func GetMemberships( } return util.JSONResponse{ Code: http.StatusOK, - JSON: getMembershipResponse{synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(result), synctypes.FormatAll, func(roomID, senderID string) (*spec.UserID, error) { + JSON: getMembershipResponse{synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(result), synctypes.FormatAll, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(req.Context(), roomID, senderID) })}, } diff --git a/syncapi/routing/messages.go b/syncapi/routing/messages.go index 879739d0..781fd53e 100644 --- a/syncapi/routing/messages.go +++ b/syncapi/routing/messages.go @@ -273,7 +273,7 @@ func OnIncomingMessagesRequest( JSON: spec.InternalServerError{}, } } - res.State = append(res.State, synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(membershipEvents), synctypes.FormatAll, func(roomID, senderID string) (*spec.UserID, error) { + res.State = append(res.State, synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(membershipEvents), synctypes.FormatAll, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(req.Context(), roomID, senderID) })...) } @@ -385,7 +385,7 @@ func (r *messagesReq) retrieveEvents(ctx context.Context, rsAPI api.SyncRoomserv "events_before": len(events), "events_after": len(filteredEvents), }).Debug("applied history visibility (messages)") - return synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(filteredEvents), synctypes.FormatAll, func(roomID, senderID string) (*spec.UserID, error) { + return synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(filteredEvents), synctypes.FormatAll, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }), start, end, err } @@ -495,7 +495,7 @@ func (r *messagesReq) handleNonEmptyEventsSlice(streamEvents []types.StreamEvent } // Append the events ve previously retrieved locally. - events = append(events, r.snapshot.StreamEventsToEvents(nil, streamEvents)...) + events = append(events, r.snapshot.StreamEventsToEvents(r.ctx, nil, streamEvents, r.rsAPI)...) sort.Sort(eventsByDepth(events)) return diff --git a/syncapi/routing/search.go b/syncapi/routing/search.go index 9cf3eabe..add50b18 100644 --- a/syncapi/routing/search.go +++ b/syncapi/routing/search.go @@ -213,7 +213,7 @@ func Search(req *http.Request, device *api.Device, syncDB storage.Database, fts profile, ok := knownUsersProfiles[userID.String()] if !ok { - stateEvent, stateErr := snapshot.GetStateEvent(ctx, ev.RoomID(), spec.MRoomMember, ev.SenderID()) + stateEvent, stateErr := snapshot.GetStateEvent(ctx, ev.RoomID(), spec.MRoomMember, string(ev.SenderID())) if stateErr != nil { logrus.WithError(stateErr).WithField("sender_id", event.SenderID()).Warn("failed to query userprofile") continue @@ -239,10 +239,10 @@ func Search(req *http.Request, device *api.Device, syncDB storage.Database, fts Context: SearchContextResponse{ Start: startToken.String(), End: endToken.String(), - EventsAfter: synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(eventsAfter), synctypes.FormatSync, func(roomID, senderID string) (*spec.UserID, error) { + EventsAfter: synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(eventsAfter), synctypes.FormatSync, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(req.Context(), roomID, senderID) }), - EventsBefore: synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(eventsBefore), synctypes.FormatSync, func(roomID, senderID string) (*spec.UserID, error) { + EventsBefore: synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(eventsBefore), synctypes.FormatSync, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(req.Context(), roomID, senderID) }), ProfileInfo: profileInfos, @@ -263,7 +263,7 @@ func Search(req *http.Request, device *api.Device, syncDB storage.Database, fts JSON: spec.InternalServerError{}, } } - stateForRooms[event.RoomID()] = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(state), synctypes.FormatSync, func(roomID, senderID string) (*spec.UserID, error) { + stateForRooms[event.RoomID()] = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(state), synctypes.FormatSync, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return rsAPI.QueryUserIDForSender(req.Context(), roomID, senderID) }) } diff --git a/syncapi/routing/search_test.go b/syncapi/routing/search_test.go index b36be823..5eb094ca 100644 --- a/syncapi/routing/search_test.go +++ b/syncapi/routing/search_test.go @@ -25,8 +25,8 @@ import ( type FakeSyncRoomserverAPI struct{ rsapi.SyncRoomserverAPI } -func (f *FakeSyncRoomserverAPI) QueryUserIDForSender(ctx context.Context, roomID string, senderID string) (*spec.UserID, error) { - return spec.NewUserID(senderID, true) +func (f *FakeSyncRoomserverAPI) QueryUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error) { + return spec.NewUserID(string(senderID), true) } func TestSearch(t *testing.T) { diff --git a/syncapi/storage/interface.go b/syncapi/storage/interface.go index 302b9bad..8798b62e 100644 --- a/syncapi/storage/interface.go +++ b/syncapi/storage/interface.go @@ -44,8 +44,8 @@ type DatabaseTransaction interface { MaxStreamPositionForRelations(ctx context.Context) (types.StreamPosition, error) CurrentState(ctx context.Context, roomID string, stateFilterPart *synctypes.StateFilter, excludeEventIDs []string) ([]*rstypes.HeaderedEvent, error) - GetStateDeltasForFullStateSync(ctx context.Context, device *userapi.Device, r types.Range, userID string, stateFilter *synctypes.StateFilter) ([]types.StateDelta, []string, error) - GetStateDeltas(ctx context.Context, device *userapi.Device, r types.Range, userID string, stateFilter *synctypes.StateFilter) ([]types.StateDelta, []string, error) + GetStateDeltasForFullStateSync(ctx context.Context, device *userapi.Device, r types.Range, userID string, stateFilter *synctypes.StateFilter, rsAPI api.SyncRoomserverAPI) ([]types.StateDelta, []string, error) + GetStateDeltas(ctx context.Context, device *userapi.Device, r types.Range, userID string, stateFilter *synctypes.StateFilter, rsAPI api.SyncRoomserverAPI) ([]types.StateDelta, []string, error) RoomIDsWithMembership(ctx context.Context, userID string, membership string) ([]string, error) MembershipCount(ctx context.Context, roomID, membership string, pos types.StreamPosition) (int, error) GetRoomSummary(ctx context.Context, roomID, userID string) (summary *types.Summary, err error) @@ -90,7 +90,7 @@ type DatabaseTransaction interface { // StreamEventsToEvents converts streamEvent to Event. If device is non-nil and // matches the streamevent.transactionID device then the transaction ID gets // added to the unsigned section of the output event. - StreamEventsToEvents(device *userapi.Device, in []types.StreamEvent) []*rstypes.HeaderedEvent + StreamEventsToEvents(ctx context.Context, device *userapi.Device, in []types.StreamEvent, rsAPI api.SyncRoomserverAPI) []*rstypes.HeaderedEvent // SendToDeviceUpdatesForSync returns a list of send-to-device updates. It returns the // relevant events within the given ranges for the supplied user ID and device ID. SendToDeviceUpdatesForSync(ctx context.Context, userID, deviceID string, from, to types.StreamPosition) (pos types.StreamPosition, events []types.SendToDeviceEvent, err error) diff --git a/syncapi/storage/shared/storage_consumer.go b/syncapi/storage/shared/storage_consumer.go index 17a6a69c..5bd3b1f0 100644 --- a/syncapi/storage/shared/storage_consumer.go +++ b/syncapi/storage/shared/storage_consumer.go @@ -99,7 +99,41 @@ func (d *Database) Events(ctx context.Context, eventIDs []string) ([]*rstypes.He // We don't include a device here as we only include transaction IDs in // incremental syncs. - return d.StreamEventsToEvents(nil, streamEvents), nil + return d.StreamEventsToEvents(ctx, nil, streamEvents, nil), nil +} + +func (d *Database) StreamEventsToEvents(ctx context.Context, device *userapi.Device, in []types.StreamEvent, rsAPI api.SyncRoomserverAPI) []*rstypes.HeaderedEvent { + out := make([]*rstypes.HeaderedEvent, len(in)) + for i := 0; i < len(in); i++ { + out[i] = in[i].HeaderedEvent + if device != nil && in[i].TransactionID != nil { + userID, err := spec.NewUserID(device.UserID, true) + if err != nil { + logrus.WithFields(logrus.Fields{ + "event_id": out[i].EventID(), + }).WithError(err).Warnf("Failed to add transaction ID to event") + continue + } + deviceSenderID, err := rsAPI.QuerySenderIDForUser(ctx, in[i].RoomID(), *userID) + if err != nil { + logrus.WithFields(logrus.Fields{ + "event_id": out[i].EventID(), + }).WithError(err).Warnf("Failed to add transaction ID to event") + continue + } + if deviceSenderID == in[i].SenderID() && device.SessionID == in[i].TransactionID.SessionID { + err := out[i].SetUnsignedField( + "transaction_id", in[i].TransactionID.TransactionID, + ) + if err != nil { + logrus.WithFields(logrus.Fields{ + "event_id": out[i].EventID(), + }).WithError(err).Warnf("Failed to add transaction ID to event") + } + } + } + } + return out } // AddInviteEvent stores a new invite event for a user. @@ -190,45 +224,6 @@ func (d *Database) UpsertAccountData( return } -func (d *Database) StreamEventsToEvents(device *userapi.Device, in []types.StreamEvent) []*rstypes.HeaderedEvent { - out := make([]*rstypes.HeaderedEvent, len(in)) - for i := 0; i < len(in); i++ { - out[i] = in[i].HeaderedEvent - if device != nil && in[i].TransactionID != nil { - userID, err := spec.NewUserID(device.UserID, true) - if err != nil { - logrus.WithFields(logrus.Fields{ - "event_id": out[i].EventID(), - }).WithError(err).Warnf("Failed to add transaction ID to event") - continue - } - deviceSenderID, err := d.getSenderIDForUser(in[i].RoomID(), *userID) - if err != nil { - logrus.WithFields(logrus.Fields{ - "event_id": out[i].EventID(), - }).WithError(err).Warnf("Failed to add transaction ID to event") - continue - } - if deviceSenderID == in[i].SenderID() && device.SessionID == in[i].TransactionID.SessionID { - err := out[i].SetUnsignedField( - "transaction_id", in[i].TransactionID.TransactionID, - ) - if err != nil { - logrus.WithFields(logrus.Fields{ - "event_id": out[i].EventID(), - }).WithError(err).Warnf("Failed to add transaction ID to event") - } - } - } - } - return out -} - -func (d *Database) getSenderIDForUser(roomID string, userID spec.UserID) (string, error) { // nolint - // TODO: Repalce with actual logic for pseudoIDs - return userID.String(), nil -} - // handleBackwardExtremities adds this event as a backwards extremity if and only if we do not have all of // the events listed in the event's 'prev_events'. This function also updates the backwards extremities table // to account for the fact that the given event is no longer a backwards extremity, but may be marked as such. diff --git a/syncapi/storage/shared/storage_sync.go b/syncapi/storage/shared/storage_sync.go index f2b1c58d..df961385 100644 --- a/syncapi/storage/shared/storage_sync.go +++ b/syncapi/storage/shared/storage_sync.go @@ -10,6 +10,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/dendrite/internal/eventutil" + "github.com/matrix-org/dendrite/roomserver/api" rstypes "github.com/matrix-org/dendrite/roomserver/types" "github.com/matrix-org/dendrite/syncapi/synctypes" "github.com/matrix-org/dendrite/syncapi/types" @@ -186,7 +187,7 @@ func (d *DatabaseTransaction) Events(ctx context.Context, eventIDs []string) ([] // We don't include a device here as we only include transaction IDs in // incremental syncs. - return d.StreamEventsToEvents(nil, streamEvents), nil + return d.StreamEventsToEvents(ctx, nil, streamEvents, nil), nil } func (d *DatabaseTransaction) AllJoinedUsersInRooms(ctx context.Context) (map[string][]string, error) { @@ -325,7 +326,7 @@ func (d *DatabaseTransaction) GetBackwardTopologyPos( func (d *DatabaseTransaction) GetStateDeltas( ctx context.Context, device *userapi.Device, r types.Range, userID string, - stateFilter *synctypes.StateFilter, + stateFilter *synctypes.StateFilter, rsAPI api.SyncRoomserverAPI, ) (deltas []types.StateDelta, joinedRoomsIDs []string, err error) { // Implement membership change algorithm: https://github.com/matrix-org/synapse/blob/v0.19.3/synapse/handlers/sync.py#L821 // - Get membership list changes for this user in this sync response @@ -417,7 +418,7 @@ func (d *DatabaseTransaction) GetStateDeltas( if !peek.Deleted { deltas = append(deltas, types.StateDelta{ Membership: spec.Peek, - StateEvents: d.StreamEventsToEvents(device, state[peek.RoomID]), + StateEvents: d.StreamEventsToEvents(ctx, device, state[peek.RoomID], rsAPI), RoomID: peek.RoomID, }) } @@ -462,7 +463,7 @@ func (d *DatabaseTransaction) GetStateDeltas( deltas = append(deltas, types.StateDelta{ Membership: membership, MembershipPos: ev.StreamPosition, - StateEvents: d.StreamEventsToEvents(device, stateFiltered[roomID]), + StateEvents: d.StreamEventsToEvents(ctx, device, stateFiltered[roomID], rsAPI), RoomID: roomID, }) break @@ -474,7 +475,7 @@ func (d *DatabaseTransaction) GetStateDeltas( for _, joinedRoomID := range joinedRoomIDs { deltas = append(deltas, types.StateDelta{ Membership: spec.Join, - StateEvents: d.StreamEventsToEvents(device, stateFiltered[joinedRoomID]), + StateEvents: d.StreamEventsToEvents(ctx, device, stateFiltered[joinedRoomID], rsAPI), RoomID: joinedRoomID, NewlyJoined: newlyJoinedRooms[joinedRoomID], }) @@ -490,7 +491,7 @@ func (d *DatabaseTransaction) GetStateDeltas( func (d *DatabaseTransaction) GetStateDeltasForFullStateSync( ctx context.Context, device *userapi.Device, r types.Range, userID string, - stateFilter *synctypes.StateFilter, + stateFilter *synctypes.StateFilter, rsAPI api.SyncRoomserverAPI, ) ([]types.StateDelta, []string, error) { // Look up all memberships for the user. We only care about rooms that a // user has ever interacted with — joined to, kicked/banned from, left. @@ -531,7 +532,7 @@ func (d *DatabaseTransaction) GetStateDeltasForFullStateSync( } deltas[peek.RoomID] = types.StateDelta{ Membership: spec.Peek, - StateEvents: d.StreamEventsToEvents(device, s), + StateEvents: d.StreamEventsToEvents(ctx, device, s, rsAPI), RoomID: peek.RoomID, } } @@ -560,7 +561,7 @@ func (d *DatabaseTransaction) GetStateDeltasForFullStateSync( deltas[roomID] = types.StateDelta{ Membership: membership, MembershipPos: ev.StreamPosition, - StateEvents: d.StreamEventsToEvents(device, stateStreamEvents), + StateEvents: d.StreamEventsToEvents(ctx, device, stateStreamEvents, rsAPI), RoomID: roomID, } } @@ -581,7 +582,7 @@ func (d *DatabaseTransaction) GetStateDeltasForFullStateSync( } deltas[joinedRoomID] = types.StateDelta{ Membership: spec.Join, - StateEvents: d.StreamEventsToEvents(device, s), + StateEvents: d.StreamEventsToEvents(ctx, device, s, rsAPI), RoomID: joinedRoomID, } } diff --git a/syncapi/storage/storage_test.go b/syncapi/storage/storage_test.go index 08ca99a7..bc64aa50 100644 --- a/syncapi/storage/storage_test.go +++ b/syncapi/storage/storage_test.go @@ -214,7 +214,7 @@ func TestGetEventsInRangeWithTopologyToken(t *testing.T) { if err != nil { t.Fatalf("GetEventsInTopologicalRange returned an error: %s", err) } - gots := snapshot.StreamEventsToEvents(nil, paginatedEvents) + gots := snapshot.StreamEventsToEvents(context.Background(), nil, paginatedEvents, nil) test.AssertEventsEqual(t, gots, test.Reversed(events[len(events)-5:])) }) }) diff --git a/syncapi/streams/stream_pdu.go b/syncapi/streams/stream_pdu.go index 8f83a089..d214980b 100644 --- a/syncapi/streams/stream_pdu.go +++ b/syncapi/streams/stream_pdu.go @@ -175,12 +175,12 @@ func (p *PDUStreamProvider) IncrementalSync( eventFilter := req.Filter.Room.Timeline if req.WantFullState { - if stateDeltas, syncJoinedRooms, err = snapshot.GetStateDeltasForFullStateSync(ctx, req.Device, r, req.Device.UserID, &stateFilter); err != nil { + if stateDeltas, syncJoinedRooms, err = snapshot.GetStateDeltasForFullStateSync(ctx, req.Device, r, req.Device.UserID, &stateFilter, p.rsAPI); err != nil { req.Log.WithError(err).Error("p.DB.GetStateDeltasForFullStateSync failed") return from } } else { - if stateDeltas, syncJoinedRooms, err = snapshot.GetStateDeltas(ctx, req.Device, r, req.Device.UserID, &stateFilter); err != nil { + if stateDeltas, syncJoinedRooms, err = snapshot.GetStateDeltas(ctx, req.Device, r, req.Device.UserID, &stateFilter, p.rsAPI); err != nil { req.Log.WithError(err).Error("p.DB.GetStateDeltas failed") return from } @@ -275,7 +275,7 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse( limited := dbEvents[delta.RoomID].Limited recEvents := gomatrixserverlib.ReverseTopologicalOrdering( - gomatrixserverlib.ToPDUs(snapshot.StreamEventsToEvents(device, recentStreamEvents)), + gomatrixserverlib.ToPDUs(snapshot.StreamEventsToEvents(ctx, device, recentStreamEvents, p.rsAPI)), gomatrixserverlib.TopologicalOrderByPrevEvents, ) recentEvents := make([]*rstypes.HeaderedEvent, len(recEvents)) @@ -376,13 +376,13 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse( } } jr.Timeline.PrevBatch = &prevBatch - jr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), synctypes.FormatSync, func(roomID, senderID string) (*spec.UserID, error) { + jr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), synctypes.FormatSync, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }) // If we are limited by the filter AND the history visibility filter // didn't "remove" events, return that the response is limited. jr.Timeline.Limited = (limited && len(events) == len(recentEvents)) || delta.NewlyJoined - jr.State.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(delta.StateEvents), synctypes.FormatSync, func(roomID, senderID string) (*spec.UserID, error) { + jr.State.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(delta.StateEvents), synctypes.FormatSync, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }) req.Response.Rooms.Join[delta.RoomID] = jr @@ -391,11 +391,11 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse( jr := types.NewJoinResponse() jr.Timeline.PrevBatch = &prevBatch // TODO: Apply history visibility on peeked rooms - jr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(recentEvents), synctypes.FormatSync, func(roomID, senderID string) (*spec.UserID, error) { + jr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(recentEvents), synctypes.FormatSync, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }) jr.Timeline.Limited = limited - jr.State.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(delta.StateEvents), synctypes.FormatSync, func(roomID, senderID string) (*spec.UserID, error) { + jr.State.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(delta.StateEvents), synctypes.FormatSync, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }) req.Response.Rooms.Peek[delta.RoomID] = jr @@ -406,13 +406,13 @@ func (p *PDUStreamProvider) addRoomDeltaToResponse( case spec.Ban: lr := types.NewLeaveResponse() lr.Timeline.PrevBatch = &prevBatch - lr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), synctypes.FormatSync, func(roomID, senderID string) (*spec.UserID, error) { + lr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), synctypes.FormatSync, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }) // If we are limited by the filter AND the history visibility filter // didn't "remove" events, return that the response is limited. lr.Timeline.Limited = limited && len(events) == len(recentEvents) - lr.State.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(delta.StateEvents), synctypes.FormatSync, func(roomID, senderID string) (*spec.UserID, error) { + lr.State.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(delta.StateEvents), synctypes.FormatSync, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }) req.Response.Rooms.Leave[delta.RoomID] = lr @@ -437,7 +437,7 @@ func applyHistoryVisibilityFilter( for _, ev := range recentEvents { if ev.StateKey() != nil { stateTypes = append(stateTypes, ev.Type()) - senders = append(senders, ev.SenderID()) + senders = append(senders, string(ev.SenderID())) } } @@ -512,7 +512,7 @@ func (p *PDUStreamProvider) getJoinResponseForCompleteSync( // We don't include a device here as we don't need to send down // transaction IDs for complete syncs, but we do it anyway because Sytest demands it for: // "Can sync a room with a message with a transaction id" - which does a complete sync to check. - recentEvents := snapshot.StreamEventsToEvents(device, recentStreamEvents) + recentEvents := snapshot.StreamEventsToEvents(ctx, device, recentStreamEvents, p.rsAPI) events := recentEvents // Only apply history visibility checks if the response is for joined rooms @@ -564,13 +564,13 @@ func (p *PDUStreamProvider) getJoinResponseForCompleteSync( } jr.Timeline.PrevBatch = prevBatch - jr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), synctypes.FormatSync, func(roomID, senderID string) (*spec.UserID, error) { + jr.Timeline.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), synctypes.FormatSync, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }) // If we are limited by the filter AND the history visibility filter // didn't "remove" events, return that the response is limited. jr.Timeline.Limited = limited && len(events) == len(recentEvents) - jr.State.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(stateEvents), synctypes.FormatSync, func(roomID, senderID string) (*spec.UserID, error) { + jr.State.Events = synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(stateEvents), synctypes.FormatSync, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return p.rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }) return jr, nil @@ -593,8 +593,8 @@ func (p *PDUStreamProvider) lazyLoadMembers( // Add all users the client doesn't know about yet to a list for _, event := range timelineEvents { // Membership is not yet cached, add it to the list - if _, ok := p.lazyLoadCache.IsLazyLoadedUserCached(device, roomID, event.SenderID()); !ok { - timelineUsers[event.SenderID()] = struct{}{} + if _, ok := p.lazyLoadCache.IsLazyLoadedUserCached(device, roomID, string(event.SenderID())); !ok { + timelineUsers[string(event.SenderID())] = struct{}{} } } // Preallocate with the same amount, even if it will end up with fewer values diff --git a/syncapi/syncapi_test.go b/syncapi/syncapi_test.go index 78c857ab..b9f13c51 100644 --- a/syncapi/syncapi_test.go +++ b/syncapi/syncapi_test.go @@ -40,8 +40,8 @@ type syncRoomserverAPI struct { rooms []*test.Room } -func (s *syncRoomserverAPI) QueryUserIDForSender(ctx context.Context, roomID string, senderID string) (*spec.UserID, error) { - return spec.NewUserID(senderID, true) +func (s *syncRoomserverAPI) QueryUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error) { + return spec.NewUserID(string(senderID), true) } func (s *syncRoomserverAPI) QueryLatestEventsAndState(ctx context.Context, req *rsapi.QueryLatestEventsAndStateRequest, res *rsapi.QueryLatestEventsAndStateResponse) error { diff --git a/syncapi/types/types.go b/syncapi/types/types.go index 526a120d..a3dc7f54 100644 --- a/syncapi/types/types.go +++ b/syncapi/types/types.go @@ -343,7 +343,7 @@ func NewStreamTokenFromString(tok string) (token StreamingToken, err error) { type PrevEventRef struct { PrevContent json.RawMessage `json:"prev_content"` ReplacesState string `json:"replaces_state"` - PrevSender string `json:"prev_sender"` + PrevSenderID string `json:"prev_sender"` } type DeviceLists struct { diff --git a/test/room.go b/test/room.go index 4cdb73aa..b19c57dd 100644 --- a/test/room.go +++ b/test/room.go @@ -39,8 +39,8 @@ var ( roomIDCounter = int64(0) ) -func UserIDForSender(roomID string, senderID string) (*spec.UserID, error) { - return spec.NewUserID(senderID, true) +func UserIDForSender(roomID string, senderID spec.SenderID) (*spec.UserID, error) { + return spec.NewUserID(string(senderID), true) } type Room struct { @@ -168,7 +168,7 @@ func (r *Room) CreateEvent(t *testing.T, creator *User, eventType string, conten } builder := gomatrixserverlib.MustGetRoomVersion(r.Version).NewEventBuilderFromProtoEvent(&gomatrixserverlib.ProtoEvent{ - Sender: creator.ID, + SenderID: creator.ID, RoomID: r.ID, Type: eventType, StateKey: mod.stateKey, diff --git a/userapi/consumers/roomserver.go b/userapi/consumers/roomserver.go index c025deee..df507eb2 100644 --- a/userapi/consumers/roomserver.go +++ b/userapi/consumers/roomserver.go @@ -108,7 +108,7 @@ func (s *OutputRoomEventConsumer) onMessage(ctx context.Context, msgs []*nats.Ms } if s.cfg.Matrix.ReportStats.Enabled { - go s.storeMessageStats(ctx, event.Type(), event.SenderID(), event.RoomID()) + go s.storeMessageStats(ctx, event.Type(), string(event.SenderID()), event.RoomID()) } log.WithFields(log.Fields{ @@ -664,7 +664,7 @@ func (s *OutputRoomEventConsumer) evaluatePushRules(ctx context.Context, event * roomSize: roomSize, } eval := pushrules.NewRuleSetEvaluator(ec, &ruleSets.Global) - rule, err := eval.MatchEvent(event.PDU, func(roomID, senderID string) (*spec.UserID, error) { + rule, err := eval.MatchEvent(event.PDU, func(roomID string, senderID spec.SenderID) (*spec.UserID, error) { return s.rsAPI.QueryUserIDForSender(ctx, roomID, senderID) }) if err != nil { @@ -698,7 +698,7 @@ func (rse *ruleSetEvalContext) UserDisplayName() string { return rse.mem.Display func (rse *ruleSetEvalContext) RoomMemberCount() (int, error) { return rse.roomSize, nil } -func (rse *ruleSetEvalContext) HasPowerLevel(senderID, levelKey string) (bool, error) { +func (rse *ruleSetEvalContext) HasPowerLevel(senderID spec.SenderID, levelKey string) (bool, error) { req := &rsapi.QueryLatestEventsAndStateRequest{ RoomID: rse.roomID, StateToFetch: []gomatrixserverlib.StateKeyTuple{ diff --git a/userapi/consumers/roomserver_test.go b/userapi/consumers/roomserver_test.go index 899a5aaf..95424715 100644 --- a/userapi/consumers/roomserver_test.go +++ b/userapi/consumers/roomserver_test.go @@ -47,8 +47,8 @@ func mustCreateEvent(t *testing.T, content string) *types.HeaderedEvent { type FakeUserRoomserverAPI struct{ rsapi.UserRoomserverAPI } -func (f *FakeUserRoomserverAPI) QueryUserIDForSender(ctx context.Context, roomID string, senderID string) (*spec.UserID, error) { - return spec.NewUserID(senderID, true) +func (f *FakeUserRoomserverAPI) QueryUserIDForSender(ctx context.Context, roomID string, senderID spec.SenderID) (*spec.UserID, error) { + return spec.NewUserID(string(senderID), true) } func Test_evaluatePushRules(t *testing.T) {