package auth import ( "github.com/dariuszjaniak/warp/server/internal/matrix/event" ) // StateKey identifies one piece of room state: an event type and a state // key together. Room state is a map from this to an event. type StateKey struct { Type string StateKey string } // State is the room state an event is authorised against. // // It is only ever the handful of events the rules actually read — the // create event, the power levels, the join rules, the members involved and // any third-party invite — not the whole state of the room. Two callers // build it differently: event intake builds it from the event's own // auth_events, and state resolution builds it from the state it has // resolved so far. type State map[StateKey]*event.Event // NewState indexes a set of state events. // // A non-state event in the input is ignored rather than refused: the usual // source is an event's auth_events, and a server that cited something odd // there should fail the auth_events checks, not crash the indexer. func NewState(events []*event.Event) State { st := make(State, len(events)) for _, e := range events { if sk, ok := e.StateKey(); ok { st[StateKey{Type: e.Type(), StateKey: sk}] = e } } return st } // Get returns one state event, or nil. func (s State) Get(eventType, stateKey string) *event.Event { return s[StateKey{Type: eventType, StateKey: stateKey}] } // Create returns the m.room.create event, or nil if the state does not // contain one — which for any event but the create event itself means the // event cannot be authorised at all. func (s State) Create() *event.Event { return s.Get(event.TypeCreate, "") } // PowerLevels returns the m.room.power_levels event, or nil. A room // without one is not broken: until the creator sends one, the defaults // apply and the creator alone has power. func (s State) PowerLevels() *event.Event { return s.Get(event.TypePowerLevels, "") } // JoinRules returns the m.room.join_rules event, or nil. func (s State) JoinRules() *event.Event { return s.Get(event.TypeJoinRules, "") } // Member returns a user's m.room.member event, or nil. func (s State) Member(userID string) *event.Event { return s.Get(event.TypeMember, userID) } // ThirdPartyInvite returns the m.room.third_party_invite event for a token, // or nil. func (s State) ThirdPartyInvite(token string) *event.Event { return s.Get(event.TypeThirdPartyInvite, token) } // Membership returns a user's membership in the room. // // A user with no m.room.member event has never been in the room, which the // rules treat exactly like having left: every rule that cares asks whether // the membership *is* something, never whether it is absent. func (s State) Membership(userID string) string { e := s.Member(userID) if e == nil { return event.MembershipLeave } membership, err := e.Membership() if err != nil || membership == "" { return event.MembershipLeave } return membership } // JoinRule returns the room's join rule, defaulting to "invite" as the // spec does for a room with no m.room.join_rules event. func (s State) JoinRule() string { e := s.JoinRules() if e == nil { return JoinRuleInvite } rule, err := joinRuleOf(e) if err != nil || rule == "" { return JoinRuleInvite } return rule }