diff --git a/federationapi/routing/state.go b/federationapi/routing/state.go index 37cbb9d1e..a202c92c2 100644 --- a/federationapi/routing/state.go +++ b/federationapi/routing/state.go @@ -129,6 +129,13 @@ func getState( return nil, nil, &resErr } + if response.IsRejected { + return nil, nil, &util.JSONResponse{ + Code: http.StatusNotFound, + JSON: jsonerror.NotFound("Event not found"), + } + } + if !response.RoomExists { return nil, nil, &util.JSONResponse{Code: http.StatusNotFound, JSON: nil} } diff --git a/roomserver/api/query.go b/roomserver/api/query.go index 8f84edcb5..ef2e6bb57 100644 --- a/roomserver/api/query.go +++ b/roomserver/api/query.go @@ -230,6 +230,8 @@ type QueryStateAndAuthChainResponse struct { // The lists will be in an arbitrary order. StateEvents []*gomatrixserverlib.HeaderedEvent `json:"state_events"` AuthChainEvents []*gomatrixserverlib.HeaderedEvent `json:"auth_chain_events"` + // True if the queried event was rejected earlier. + IsRejected bool `json:"is_rejected"` } // QueryRoomVersionCapabilitiesRequest asks for the default room version diff --git a/roomserver/internal/query/query.go b/roomserver/internal/query/query.go index 7e4d56684..5b33ec3c3 100644 --- a/roomserver/internal/query/query.go +++ b/roomserver/internal/query/query.go @@ -441,11 +441,11 @@ func (r *Queryer) QueryStateAndAuthChain( } var stateEvents []*gomatrixserverlib.Event - stateEvents, err = r.loadStateAtEventIDs(ctx, info, request.PrevEventIDs) + stateEvents, rejected, err := r.loadStateAtEventIDs(ctx, info, request.PrevEventIDs) if err != nil { return err } - + response.IsRejected = rejected response.PrevEventsExist = true // add the auth event IDs for the current state events too @@ -480,15 +480,23 @@ func (r *Queryer) QueryStateAndAuthChain( return err } -func (r *Queryer) loadStateAtEventIDs(ctx context.Context, roomInfo *types.RoomInfo, eventIDs []string) ([]*gomatrixserverlib.Event, error) { +func (r *Queryer) loadStateAtEventIDs(ctx context.Context, roomInfo *types.RoomInfo, eventIDs []string) ([]*gomatrixserverlib.Event, bool, error) { roomState := state.NewStateResolution(r.DB, roomInfo) prevStates, err := r.DB.StateAtEventIDs(ctx, eventIDs) if err != nil { switch err.(type) { case types.MissingEventError: - return nil, nil + return nil, false, nil default: - return nil, err + return nil, false, err + } + } + // Currently only used on /state and /state_ids + rejected := false + for i := range prevStates { + if prevStates[i].IsRejected { + rejected = true + break } } @@ -497,10 +505,12 @@ func (r *Queryer) loadStateAtEventIDs(ctx context.Context, roomInfo *types.RoomI ctx, prevStates, ) if err != nil { - return nil, err + return nil, rejected, err } - return helpers.LoadStateEvents(ctx, r.DB, stateEntries) + events, err := helpers.LoadStateEvents(ctx, r.DB, stateEntries) + + return events, rejected, err } type eventsFromIDs func(context.Context, []string) ([]types.Event, error) diff --git a/sytest-whitelist b/sytest-whitelist index 2052185fe..5d67aee6c 100644 --- a/sytest-whitelist +++ b/sytest-whitelist @@ -709,4 +709,8 @@ Gapped incremental syncs include all state changes Old leaves are present in gapped incremental syncs Leaves are present in non-gapped incremental syncs Members from the gap are included in gappy incr LL sync -Presence can be set from sync \ No newline at end of file +Presence can be set from sync +/state returns M_NOT_FOUND for a rejected message event +/state_ids returns M_NOT_FOUND for a rejected message event +/state returns M_NOT_FOUND for a rejected state event +/state_ids returns M_NOT_FOUND for a rejected state event \ No newline at end of file