processStateBefore works out what the state is before the event and then checks the event auths against the state at the time. It also tries to determine what the history visibility was of the event at the time, so that it can be sent in the output event to downstream components. nolint:nakedret
( ctx context.Context, input *api.InputRoomEvent, missingPrev bool, )
| 426 | // components. |
| 427 | // nolint:nakedret |
| 428 | func (r *Inputer) processStateBefore( |
| 429 | ctx context.Context, |
| 430 | input *api.InputRoomEvent, |
| 431 | missingPrev bool, |
| 432 | ) (historyVisibility gomatrixserverlib.HistoryVisibility, rejectionErr error, err error) { |
| 433 | historyVisibility = gomatrixserverlib.HistoryVisibilityJoined // Default to restrictive. |
| 434 | event := input.Event.Unwrap() |
| 435 | isCreateEvent := event.Type() == gomatrixserverlib.MRoomCreate && event.StateKeyEquals("") |
| 436 | var stateBeforeEvent []*gomatrixserverlib.Event |
| 437 | switch { |
| 438 | case isCreateEvent: |
| 439 | // There's no state before a create event so there is nothing |
| 440 | // else to do. |
| 441 | return |
| 442 | case input.HasState: |
| 443 | // If we're overriding the state then we need to go and retrieve |
| 444 | // them from the database. It's a hard error if they are missing. |
| 445 | stateEvents, err := r.DB.EventsFromIDs(ctx, input.StateEventIDs) |
| 446 | if err != nil { |
| 447 | return "", nil, fmt.Errorf("r.DB.EventsFromIDs: %w", err) |
| 448 | } |
| 449 | stateBeforeEvent = make([]*gomatrixserverlib.Event, 0, len(stateEvents)) |
| 450 | for _, entry := range stateEvents { |
| 451 | stateBeforeEvent = append(stateBeforeEvent, entry.Event) |
| 452 | } |
| 453 | case missingPrev: |
| 454 | // We don't know all of the prev events, so we can't work out |
| 455 | // the state before the event. Reject it in that case. |
| 456 | rejectionErr = fmt.Errorf("event %q has missing prev events", event.EventID()) |
| 457 | return |
| 458 | case len(event.PrevEventIDs()) == 0: |
| 459 | // There should be prev events since it's not a create event. |
| 460 | // A non-create event that claims to have no prev events is |
| 461 | // invalid, so reject it. |
| 462 | rejectionErr = fmt.Errorf("event %q must have prev events", event.EventID()) |
| 463 | return |
| 464 | default: |
| 465 | // For all non-create events, there must be prev events, so we'll |
| 466 | // ask the query API for the relevant tuples needed for auth. We |
| 467 | // will include the history visibility here even though we don't |
| 468 | // actually need it for auth, because we want to send it in the |
| 469 | // output events. |
| 470 | tuplesNeeded := gomatrixserverlib.StateNeededForAuth([]*gomatrixserverlib.Event{event}).Tuples() |
| 471 | tuplesNeeded = append(tuplesNeeded, gomatrixserverlib.StateKeyTuple{ |
| 472 | EventType: gomatrixserverlib.MRoomHistoryVisibility, |
| 473 | StateKey: "", |
| 474 | }) |
| 475 | stateBeforeReq := &api.QueryStateAfterEventsRequest{ |
| 476 | RoomID: event.RoomID(), |
| 477 | PrevEventIDs: event.PrevEventIDs(), |
| 478 | StateToFetch: tuplesNeeded, |
| 479 | } |
| 480 | stateBeforeRes := &api.QueryStateAfterEventsResponse{} |
| 481 | if err := r.Queryer.QueryStateAfterEvents(ctx, stateBeforeReq, stateBeforeRes); err != nil { |
| 482 | return "", nil, fmt.Errorf("r.Queryer.QueryStateAfterEvents: %w", err) |
| 483 | } |
| 484 | switch { |
| 485 | case !stateBeforeRes.RoomExists: |
no test coverage detected