diff --git a/federationsender/consumers/roomserver.go b/federationsender/consumers/roomserver.go index 9e7472814..efeb53fa6 100644 --- a/federationsender/consumers/roomserver.go +++ b/federationsender/consumers/roomserver.go @@ -139,7 +139,7 @@ func (s *OutputRoomEventConsumer) processMessage(ore api.OutputNewRoomEvent) err return nil } - if ore.SendAsServer == api.DoNotSendToOtherServers || ore.Type == api.OutputRoomState { + if ore.SendAsServer == api.DoNotSendToOtherServers { // Ignore event that we don't need to send anywhere. return nil } diff --git a/roomserver/api/wrapper.go b/roomserver/api/wrapper.go index d5e4b567c..6be2cce9d 100644 --- a/roomserver/api/wrapper.go +++ b/roomserver/api/wrapper.go @@ -47,7 +47,12 @@ func SendEventWithState( ctx context.Context, rsAPI RoomserverInternalAPI, state *gomatrixserverlib.RespState, event gomatrixserverlib.HeaderedEvent, haveEventIDs map[string]bool, ) error { - stateEvents, err := state.Events() + isCurrentState := map[string]struct{}{} + for _, se := range state.StateEvents { + isCurrentState[se.EventID()] = struct{}{} + } + + authAndStateEvents, err := state.Events() if err != nil { return err } @@ -55,36 +60,38 @@ func SendEventWithState( var ires []InputRoomEvent var stateIDs []string - for _, stateEvent := range stateEvents { - if stateEvent.StateKey() == nil { + for _, authOrStateEvent := range authAndStateEvents { + if authOrStateEvent.StateKey() == nil { continue } - if haveEventIDs[stateEvent.EventID()] { + if haveEventIDs[authOrStateEvent.EventID()] { continue } - if stateEvent.Type() == event.Type() && *stateEvent.StateKey() == *event.StateKey() { - // If this event is an old state event that will be replaced by the - // given event, then store it as an outlier instead. We don't want - // to include it in the current room state as we will end up violating - // unique constraints in the state block, but we need the event to - // be stored as it may be referred to as an auth_event or prev_event. + if _, ok := isCurrentState[authOrStateEvent.EventID()]; !ok { + // If this is an auth event rather than a current state event + // then store it as an outlier. We won't include it in the + // current state set for the input event. ires = append(ires, InputRoomEvent{ Kind: KindOutlier, - Event: stateEvent.Headered(event.RoomVersion), - AuthEventIDs: stateEvent.AuthEventIDs(), + Event: authOrStateEvent.Headered(event.RoomVersion), + AuthEventIDs: authOrStateEvent.AuthEventIDs(), }) continue } + // The event is a current state event. Send it as a rewrite + // event so that we generate a state output event for it. ires = append(ires, InputRoomEvent{ Kind: KindRewrite, - Event: stateEvent.Headered(event.RoomVersion), - AuthEventIDs: stateEvent.AuthEventIDs(), + Event: authOrStateEvent.Headered(event.RoomVersion), + AuthEventIDs: authOrStateEvent.AuthEventIDs(), HasState: true, StateEventIDs: stateIDs, }) - stateIDs = append(stateIDs, stateEvent.EventID()) + stateIDs = append(stateIDs, authOrStateEvent.EventID()) } + // Send the final event as a new event, which will generate + // a timeline output event for it. ires = append(ires, InputRoomEvent{ Kind: KindNew, Event: event, diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go index 3d1942272..011b592b6 100644 --- a/roomserver/internal/perform/perform_join.go +++ b/roomserver/internal/perform/perform_join.go @@ -25,6 +25,7 @@ import ( "github.com/matrix-org/dendrite/internal/config" "github.com/matrix-org/dendrite/internal/eventutil" "github.com/matrix-org/dendrite/roomserver/api" + "github.com/matrix-org/dendrite/roomserver/auth" "github.com/matrix-org/dendrite/roomserver/internal/helpers" "github.com/matrix-org/dendrite/roomserver/internal/input" "github.com/matrix-org/dendrite/roomserver/storage" @@ -334,6 +335,10 @@ func buildEvent( return nil, nil, fmt.Errorf("QueryLatestEventsAndState: %w", err) } + if !auth.IsAnyUserOnServerWithMembership(cfg.ServerName, gomatrixserverlib.UnwrapEventHeaders(queryRes.StateEvents), "join") { + return nil, nil, eventutil.ErrRoomNoExists + } + ev, err := eventutil.BuildEvent(ctx, builder, cfg, time.Now(), &eventsNeeded, &queryRes) if err != nil { return nil, nil, err diff --git a/syncapi/consumers/roomserver.go b/syncapi/consumers/roomserver.go index 52672245f..5ca1be118 100644 --- a/syncapi/consumers/roomserver.go +++ b/syncapi/consumers/roomserver.go @@ -143,11 +143,6 @@ func (s *OutputRoomEventConsumer) onNewRoomEvent( } } - if msg.Type == api.OutputRoomState { - s.notifyKeyChanges(&ev) - return nil - } - pduPos, err := s.db.WriteEvent( ctx, &ev, @@ -155,7 +150,7 @@ func (s *OutputRoomEventConsumer) onNewRoomEvent( msg.AddsStateEventIDs, msg.RemovesStateEventIDs, msg.TransactionID, - false, + msg.Type == api.OutputRoomState, ) if err != nil { // panic rather than continue with an inconsistent database