diff --git a/clientapi/routing/createroom.go b/clientapi/routing/createroom.go index 71f733747..35ab2d5d7 100644 --- a/clientapi/routing/createroom.go +++ b/clientapi/routing/createroom.go @@ -371,10 +371,7 @@ func createRoom( } // If this is a direct message then we should invite the participants. - fmt.Println("INVITEES:") for _, invitee := range r.Invite { - fmt.Println("*", invitee) - // Build the invite event. inviteEvent, err := buildMembershipEvent( req.Context(), invitee, "", accountDB, device, gomatrixserverlib.Invite, @@ -389,6 +386,10 @@ func createRoom( var strippedState []gomatrixserverlib.InviteV2StrippedState for _, event := range candidates { switch event.Type() { + case gomatrixserverlib.MRoomName: + fallthrough + case gomatrixserverlib.MRoomCanonicalAlias: + fallthrough case "m.room.encryption": // TODO: move this to gmsl fallthrough case gomatrixserverlib.MRoomMember: diff --git a/clientapi/routing/membership.go b/clientapi/routing/membership.go index 7d9a4efad..fd11d2fc6 100644 --- a/clientapi/routing/membership.go +++ b/clientapi/routing/membership.go @@ -26,7 +26,6 @@ import ( "github.com/matrix-org/dendrite/clientapi/jsonerror" "github.com/matrix-org/dendrite/clientapi/threepid" currentstateAPI "github.com/matrix-org/dendrite/currentstateserver/api" - federationSenderAPI "github.com/matrix-org/dendrite/federationsender/api" "github.com/matrix-org/dendrite/internal/config" "github.com/matrix-org/dendrite/internal/eventutil" "github.com/matrix-org/dendrite/roomserver/api" @@ -173,7 +172,6 @@ func SendInvite( req *http.Request, accountDB accounts.Database, device *userapi.Device, roomID string, cfg *config.ClientAPI, rsAPI roomserverAPI.RoomserverInternalAPI, asAPI appserviceAPI.AppServiceQueryAPI, - fsAPI federationSenderAPI.FederationSenderInternalAPI, ) util.JSONResponse { body, evTime, _, reqErr := extractRequestData(req, roomID, rsAPI) if reqErr != nil { diff --git a/clientapi/routing/routing.go b/clientapi/routing/routing.go index fcbff2800..d40621ec3 100644 --- a/clientapi/routing/routing.go +++ b/clientapi/routing/routing.go @@ -142,7 +142,7 @@ func Setup( if err != nil { return util.ErrorResponse(err) } - return SendInvite(req, accountDB, device, vars["roomID"], cfg, rsAPI, asAPI, federationSender) + return SendInvite(req, accountDB, device, vars["roomID"], cfg, rsAPI, asAPI) }), ).Methods(http.MethodPost, http.MethodOptions) r0mux.Handle("/rooms/{roomID}/kick", diff --git a/federationapi/routing/invite.go b/federationapi/routing/invite.go index 88cf6e480..eb65de641 100644 --- a/federationapi/routing/invite.go +++ b/federationapi/routing/invite.go @@ -144,7 +144,7 @@ func processInvite( // Add the invite event to the roomserver. if err := api.SendInvite( - ctx, rsAPI, signedEvent.Headered(roomVer), strippedState, event.Origin(), nil, + ctx, rsAPI, signedEvent.Headered(roomVer), strippedState, api.DoNotSendToOtherServers, nil, ); err != nil { util.GetLogger(ctx).WithError(err).Error("producer.SendInvite failed") return jsonerror.InternalServerError() diff --git a/roomserver/api/wrapper.go b/roomserver/api/wrapper.go index 742ebe66d..3a76d7783 100644 --- a/roomserver/api/wrapper.go +++ b/roomserver/api/wrapper.go @@ -16,6 +16,7 @@ package api import ( "context" + "fmt" "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/util" @@ -100,6 +101,8 @@ func SendInvite( inviteRoomState []gomatrixserverlib.InviteV2StrippedState, sendAsServer gomatrixserverlib.ServerName, txnID *TransactionID, ) error { + // Start by sending the invite request into the roomserver. This will + // trigger the federation request amongst other things if needed. request := &PerformInviteRequest{ Event: inviteEvent, InviteRoomState: inviteRoomState, @@ -108,7 +111,28 @@ func SendInvite( TransactionID: txnID, } response := &PerformInviteResponse{} - return rsAPI.PerformInvite(ctx, request, response) + if err := rsAPI.PerformInvite(ctx, request, response); err != nil { + return fmt.Errorf("rsAPI.PerformInvite: %w", err) + } + + // Now send the invite event into the roomserver. If the room is known + // locally then this will succeed, notifying existing users in the room + // about the new invite. If the room isn't known locally then this will + // fail - and that's also OK. + inputReq := &InputRoomEventsRequest{ + InputRoomEvents: []InputRoomEvent{ + { + Kind: KindNew, + Event: inviteEvent, + AuthEventIDs: inviteEvent.AuthEventIDs(), + SendAsServer: DoNotSendToOtherServers, + }, + }, + } + inputRes := &InputRoomEventsResponse{} + _ = rsAPI.InputRoomEvents(ctx, inputReq, inputRes) + + return nil } // GetEvent returns the event or nil, even on errors. diff --git a/roomserver/internal/perform_invite.go b/roomserver/internal/perform_invite.go index c6e13a539..8fa9db1f0 100644 --- a/roomserver/internal/perform_invite.go +++ b/roomserver/internal/perform_invite.go @@ -36,26 +36,26 @@ func (r *RoomserverInternalAPI) PerformInvite( }).Info("processing invite event") _, domain, _ := gomatrixserverlib.SplitID('@', targetUserID) - isTargetLocalUser := domain == r.Cfg.Matrix.ServerName - isOriginLocalUser := event.Origin() == r.Cfg.Matrix.ServerName + isTargetLocal := domain == r.Cfg.Matrix.ServerName + isOriginLocal := event.Origin() == r.Cfg.Matrix.ServerName - // If the invite originated from us and the target isn't local then we - // should try and send the invite over federation first. It might be - // that the remote user doesn't exist, in which case we can give up - // processing here. - if isOriginLocalUser && !isTargetLocalUser { - fsReq := &federationSenderAPI.PerformInviteRequest{ - RoomVersion: req.RoomVersion, - Event: req.Event, + inviteState := req.InviteRoomState + if len(inviteState) == 0 { + if is, err := buildInviteStrippedState(ctx, r.DB, req); err == nil { + inviteState = is } - fsRes := &federationSenderAPI.PerformInviteResponse{} - if err := r.fsAPI.PerformInvite(ctx, fsReq, fsRes); err != nil { - return fmt.Errorf("r.fsAPI.PerformInvite: %w", err) + } + if len(inviteState) == 0 { + if err := event.SetUnsignedField("invite_room_state", struct{}{}); err != nil { + return err + } + } else { + if err := event.SetUnsignedField("invite_room_state", inviteState); err != nil { + return err } - event = fsRes.SignedEvent } - updater, err := r.DB.MembershipUpdater(ctx, roomID, targetUserID, isTargetLocalUser, req.RoomVersion) + updater, err := r.DB.MembershipUpdater(ctx, roomID, targetUserID, isTargetLocal, req.RoomVersion) if err != nil { return err } @@ -101,9 +101,9 @@ func (r *RoomserverInternalAPI) PerformInvite( } } - // check that the user is allowed to do this. We can only do this check if it is - // a local invite as we have the auth events, else we have to take it on trust. - if isOriginLocalUser { + if isOriginLocal { + // check that the user is allowed to do this. We can only do this check if it is + // a local invite as we have the auth events, else we have to take it on trust. _, err = checkAuthEvents(ctx, r.DB, req.Event, req.Event.AuthEventIDs()) if err != nil { log.WithError(err).WithField("event_id", event.EventID()).WithField("auth_event_ids", event.AuthEventIDs()).Error( @@ -117,50 +117,22 @@ func (r *RoomserverInternalAPI) PerformInvite( } return err } - } - if len(req.InviteRoomState) > 0 { - // If we were supplied with some invite room state already (which is - // most likely to be if the event came in over federation) then use - // that. - if err = event.SetUnsignedField("invite_room_state", req.InviteRoomState); err != nil { - return err - } - } else { - // There's no invite room state, so let's have a go at building it - // up from local data (which is most likely to be if the event came - // from the CS API). If we know about the room then we can insert - // the invite room state, if we don't then we just fail quietly. - if irs, ierr := buildInviteStrippedState(ctx, r.DB, req); ierr == nil { - if err = event.SetUnsignedField("invite_room_state", irs); err != nil { - return err + // If the invite originated from us and the target isn't local then we + // should try and send the invite over federation first. It might be + // that the remote user doesn't exist, in which case we can give up + // processing here. + if req.SendAsServer != api.DoNotSendToOtherServers && !isTargetLocal { + fsReq := &federationSenderAPI.PerformInviteRequest{ + RoomVersion: req.RoomVersion, + Event: req.Event, + InviteRoomState: inviteState, } - } else { - log.WithError(ierr).Warn("failed to build invite stripped state") - // still set the field else synapse deployments don't process the invite - if err = event.SetUnsignedField("invite_room_state", struct{}{}); err != nil { - return err + fsRes := &federationSenderAPI.PerformInviteResponse{} + if err = r.fsAPI.PerformInvite(ctx, fsReq, fsRes); err != nil { + return fmt.Errorf("r.fsAPI.PerformInvite: %w", err) } - } - } - - // If we're the sender of the event then we should send the invite - // event into the room so that the room state is updated and other - // room participants will see the invite. - if isOriginLocalUser { - inputReq := &api.InputRoomEventsRequest{ - InputRoomEvents: []api.InputRoomEvent{ - { - Kind: api.KindNew, - Event: event, - AuthEventIDs: event.AuthEventIDs(), - SendAsServer: api.DoNotSendToOtherServers, - }, - }, - } - inputRes := &api.InputRoomEventsResponse{} - if err = r.InputRoomEvents(ctx, inputReq, inputRes); err != nil { - return fmt.Errorf("r.InputRoomEvents: %w", err) + event = fsRes.SignedEvent } } @@ -193,7 +165,7 @@ func buildInviteStrippedState( for _, t := range []string{ gomatrixserverlib.MRoomName, gomatrixserverlib.MRoomCanonicalAlias, gomatrixserverlib.MRoomAliases, gomatrixserverlib.MRoomJoinRules, - "m.room.avatar", + "m.room.avatar", "m.room.encryption", } { stateWanted = append(stateWanted, gomatrixserverlib.StateKeyTuple{ EventType: t,