From 346f5d6334917616ca9b96bfaa8040c5938daf92 Mon Sep 17 00:00:00 2001 From: Kegsay Date: Fri, 17 Mar 2017 16:28:15 +0000 Subject: [PATCH] Use gomatrixserverlib.StateKeyTuple and helper functions for auth (#44) * Update gomatrixserverib dep * Use helper functions when creating rooms * Use gomatrixserverlib.StateKeyTuple --- .../dendrite/clientapi/writers/createroom.go | 52 ++---------- .../dendrite/clientapi/writers/sendevent.go | 28 +------ .../matrix-org/dendrite/common/types.go | 12 --- .../dendrite/roomserver/api/query.go | 3 +- .../roomserver-integration-tests/main.go | 3 +- .../dendrite/roomserver/state/state.go | 10 +-- vendor/manifest | 4 +- .../matrix-org/gomatrixserverlib/event.go | 12 +++ .../matrix-org/gomatrixserverlib/eventauth.go | 84 ++++++++++++++++--- 9 files changed, 101 insertions(+), 107 deletions(-) diff --git a/src/github.com/matrix-org/dendrite/clientapi/writers/createroom.go b/src/github.com/matrix-org/dendrite/clientapi/writers/createroom.go index 79bc285a7..1868ff9ff 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/writers/createroom.go +++ b/src/github.com/matrix-org/dendrite/clientapi/writers/createroom.go @@ -14,7 +14,6 @@ import ( "github.com/matrix-org/dendrite/clientapi/httputil" "github.com/matrix-org/dendrite/clientapi/jsonerror" "github.com/matrix-org/dendrite/clientapi/producers" - "github.com/matrix-org/dendrite/common" "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/util" ) @@ -112,8 +111,6 @@ func createRoom(req *http.Request, cfg config.ClientAPI, roomID string, producer "roomID": roomID, }).Info("Creating new room") - // Remember events we've built and key off the state tuple so we can look them up easily when filling in auth_events - builtEventMap := make(map[common.StateKeyTuple]*gomatrixserverlib.Event) var builtEvents []gomatrixserverlib.Event // send events into the room in order of: @@ -165,7 +162,7 @@ func createRoom(req *http.Request, cfg config.ClientAPI, roomID string, producer if i > 0 { builder.PrevEvents = []gomatrixserverlib.EventReference{builtEvents[i-1].EventReference()} } - ev, err := buildEvent(&builder, builtEventMap, cfg) + ev, err := buildEvent(&builder, &authEvents, cfg) if err != nil { return httputil.LogThenError(req, err) } @@ -175,7 +172,6 @@ func createRoom(req *http.Request, cfg config.ClientAPI, roomID string, producer } // Add the event to the list of auth events - builtEventMap[common.StateKeyTuple{e.Type, e.StateKey}] = ev builtEvents = append(builtEvents, *ev) authEvents.AddEvent(ev) } @@ -193,14 +189,18 @@ func createRoom(req *http.Request, cfg config.ClientAPI, roomID string, producer // buildEvent fills out auth_events for the builder then builds the event func buildEvent(builder *gomatrixserverlib.EventBuilder, - events map[common.StateKeyTuple]*gomatrixserverlib.Event, + provider gomatrixserverlib.AuthEventProvider, cfg config.ClientAPI) (*gomatrixserverlib.Event, error) { eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(builder) if err != nil { return nil, err } - builder.AuthEvents = authEventsFromStateNeeded(eventsNeeded, events) + refs, err := eventsNeeded.AuthEventReferences(provider) + if err != nil { + return nil, err + } + builder.AuthEvents = refs eventID := fmt.Sprintf("$%s:%s", util.RandomString(16), cfg.ServerName) now := time.Now() event, err := builder.Build(eventID, now, cfg.ServerName, cfg.KeyID, cfg.PrivateKey) @@ -209,41 +209,3 @@ func buildEvent(builder *gomatrixserverlib.EventBuilder, } return &event, nil } - -func authEventsFromStateNeeded(eventsNeeded gomatrixserverlib.StateNeeded, - events map[common.StateKeyTuple]*gomatrixserverlib.Event) (authEvents []gomatrixserverlib.EventReference) { - - // These events are only "needed" if they exist, so if they don't exist we can safely ignore them. - if eventsNeeded.Create { - ev := events[common.StateKeyTuple{"m.room.create", ""}] - if ev != nil { - authEvents = append(authEvents, ev.EventReference()) - } - } - if eventsNeeded.JoinRules { - ev := events[common.StateKeyTuple{"m.room.join_rules", ""}] - if ev != nil { - authEvents = append(authEvents, ev.EventReference()) - } - } - if eventsNeeded.PowerLevels { - ev := events[common.StateKeyTuple{"m.room.power_levels", ""}] - if ev != nil { - authEvents = append(authEvents, ev.EventReference()) - } - } - - for _, userID := range eventsNeeded.Member { - ev := events[common.StateKeyTuple{"m.room.member", userID}] - if ev != nil { - authEvents = append(authEvents, ev.EventReference()) - } - } - for _, token := range eventsNeeded.ThirdPartyInvite { - ev := events[common.StateKeyTuple{"m.room.member", token}] - if ev != nil { - authEvents = append(authEvents, ev.EventReference()) - } - } - return -} diff --git a/src/github.com/matrix-org/dendrite/clientapi/writers/sendevent.go b/src/github.com/matrix-org/dendrite/clientapi/writers/sendevent.go index 3e321447c..726e15d7e 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/writers/sendevent.go +++ b/src/github.com/matrix-org/dendrite/clientapi/writers/sendevent.go @@ -11,7 +11,6 @@ import ( "github.com/matrix-org/dendrite/clientapi/httputil" "github.com/matrix-org/dendrite/clientapi/jsonerror" "github.com/matrix-org/dendrite/clientapi/producers" - "github.com/matrix-org/dendrite/common" "github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/util" @@ -48,7 +47,7 @@ func SendEvent(req *http.Request, roomID, eventType, txnID string, stateKey *str builder.SetContent(r) // work out what will be required in order to send this event - requiredStateEvents, err := stateNeeded(&builder) + needed, err := gomatrixserverlib.StateNeededForEventBuilder(&builder) if err != nil { return httputil.LogThenError(req, err) } @@ -56,7 +55,7 @@ func SendEvent(req *http.Request, roomID, eventType, txnID string, stateKey *str // Ask the roomserver for information about this room queryReq := api.QueryLatestEventsAndStateRequest{ RoomID: roomID, - StateToFetch: requiredStateEvents, + StateToFetch: needed.Tuples(), } var queryRes api.QueryLatestEventsAndStateResponse if queryErr := queryAPI.QueryLatestEventsAndState(&queryReq, &queryRes); queryErr != nil { @@ -105,26 +104,3 @@ func SendEvent(req *http.Request, roomID, eventType, txnID string, stateKey *str JSON: sendEventResponse{e.EventID()}, } } - -func stateNeeded(builder *gomatrixserverlib.EventBuilder) (requiredStateEvents []common.StateKeyTuple, err error) { - authEvents, err := gomatrixserverlib.StateNeededForEventBuilder(builder) - if err != nil { - return - } - if authEvents.Create { - requiredStateEvents = append(requiredStateEvents, common.StateKeyTuple{"m.room.create", ""}) - } - if authEvents.JoinRules { - requiredStateEvents = append(requiredStateEvents, common.StateKeyTuple{"m.room.join_rules", ""}) - } - if authEvents.PowerLevels { - requiredStateEvents = append(requiredStateEvents, common.StateKeyTuple{"m.room.power_levels", ""}) - } - for _, userID := range authEvents.Member { - requiredStateEvents = append(requiredStateEvents, common.StateKeyTuple{"m.room.member", userID}) - } - for _, token := range authEvents.ThirdPartyInvite { - requiredStateEvents = append(requiredStateEvents, common.StateKeyTuple{"m.room.third_party_invite", token}) - } - return -} diff --git a/src/github.com/matrix-org/dendrite/common/types.go b/src/github.com/matrix-org/dendrite/common/types.go index 125838f21..805d0c79a 100644 --- a/src/github.com/matrix-org/dendrite/common/types.go +++ b/src/github.com/matrix-org/dendrite/common/types.go @@ -1,13 +1 @@ package common - -// StateKeyTuple is a pair of an event type and state_key. -// This is typically used as a key in a map. -type StateKeyTuple struct { - // The "type" key of a matrix event. - EventType string - // The "state_key" of a matrix event. - // The empty string is a legitimate value for the "state_key" in matrix - // so take care to initialise this field lest you accidentally request a - // "state_key" with the go default of the empty string. - EventStateKey string -} diff --git a/src/github.com/matrix-org/dendrite/roomserver/api/query.go b/src/github.com/matrix-org/dendrite/roomserver/api/query.go index 06e75a745..be859b1be 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/api/query.go +++ b/src/github.com/matrix-org/dendrite/roomserver/api/query.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/matrix-org/dendrite/common" "github.com/matrix-org/gomatrixserverlib" "net/http" ) @@ -15,7 +14,7 @@ type QueryLatestEventsAndStateRequest struct { RoomID string // The state key tuples to fetch from the room current state. // If this list is empty or nil then no state events are returned. - StateToFetch []common.StateKeyTuple + StateToFetch []gomatrixserverlib.StateKeyTuple } // QueryLatestEventsAndStateResponse is a response to QueryLatestEventsAndState diff --git a/src/github.com/matrix-org/dendrite/roomserver/roomserver-integration-tests/main.go b/src/github.com/matrix-org/dendrite/roomserver/roomserver-integration-tests/main.go index 6c051cb90..b2bd3760d 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/roomserver-integration-tests/main.go +++ b/src/github.com/matrix-org/dendrite/roomserver/roomserver-integration-tests/main.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "github.com/matrix-org/dendrite/common" "github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/gomatrixserverlib" "os" @@ -368,7 +367,7 @@ func main() { if err := q.QueryLatestEventsAndState( &api.QueryLatestEventsAndStateRequest{ RoomID: "!HCXfdvrfksxuYnIFiJ:matrix.org", - StateToFetch: []common.StateKeyTuple{ + StateToFetch: []gomatrixserverlib.StateKeyTuple{ {"m.room.member", "@richvdh:matrix.org"}, }, }, diff --git a/src/github.com/matrix-org/dendrite/roomserver/state/state.go b/src/github.com/matrix-org/dendrite/roomserver/state/state.go index b014c722b..780b061c5 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/state/state.go +++ b/src/github.com/matrix-org/dendrite/roomserver/state/state.go @@ -4,8 +4,8 @@ package state import ( "fmt" - "github.com/matrix-org/dendrite/common" "github.com/matrix-org/dendrite/roomserver/types" + "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/util" "sort" ) @@ -200,12 +200,12 @@ func DifferenceBetweeenStateSnapshots(db RoomStateDatabase, oldStateNID, newStat // stringTuplesToNumericTuples converts the string state key tuples into numeric IDs // If there isn't a numeric ID for either the event type or the event state key then the tuple is discarded. // Returns an error if there was a problem talking to the database. -func stringTuplesToNumericTuples(db RoomStateDatabase, stringTuples []common.StateKeyTuple) ([]types.StateKeyTuple, error) { +func stringTuplesToNumericTuples(db RoomStateDatabase, stringTuples []gomatrixserverlib.StateKeyTuple) ([]types.StateKeyTuple, error) { eventTypes := make([]string, len(stringTuples)) stateKeys := make([]string, len(stringTuples)) for i := range stringTuples { eventTypes[i] = stringTuples[i].EventType - stateKeys[i] = stringTuples[i].EventStateKey + stateKeys[i] = stringTuples[i].StateKey } eventTypes = util.UniqueStrings(eventTypes) eventTypeMap, err := db.EventTypeNIDs(eventTypes) @@ -223,7 +223,7 @@ func stringTuplesToNumericTuples(db RoomStateDatabase, stringTuples []common.Sta var numericTuple types.StateKeyTuple var ok1, ok2 bool numericTuple.EventTypeNID, ok1 = eventTypeMap[stringTuple.EventType] - numericTuple.EventStateKeyNID, ok2 = stateKeyMap[stringTuple.EventStateKey] + numericTuple.EventStateKeyNID, ok2 = stateKeyMap[stringTuple.StateKey] // Discard the tuple if there wasn't a numeric ID for either the event type or the state key. if ok1 && ok2 { result = append(result, numericTuple) @@ -239,7 +239,7 @@ func stringTuplesToNumericTuples(db RoomStateDatabase, stringTuples []common.Sta // This is typically the state before an event or the current state of a room. // Returns a sorted list of state entries or an error if there was a problem talking to the database. func LoadStateAtSnapshotForStringTuples( - db RoomStateDatabase, stateNID types.StateSnapshotNID, stateKeyTuples []common.StateKeyTuple, + db RoomStateDatabase, stateNID types.StateSnapshotNID, stateKeyTuples []gomatrixserverlib.StateKeyTuple, ) ([]types.StateEntry, error) { numericTuples, err := stringTuplesToNumericTuples(db, stateKeyTuples) if err != nil { diff --git a/vendor/manifest b/vendor/manifest index 61f8d20aa..bc0297d6c 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -92,7 +92,7 @@ { "importpath": "github.com/matrix-org/gomatrixserverlib", "repository": "https://github.com/matrix-org/gomatrixserverlib", - "revision": "775bc0b4341689c9fbb573008c3095495738f092", + "revision": "e757e4f7f675c7356d4b2953059718f1b4598a08", "branch": "master" }, { @@ -206,4 +206,4 @@ "branch": "master" } ] -} \ No newline at end of file +} diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/event.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/event.go index 439642a31..126830307 100644 --- a/vendor/src/github.com/matrix-org/gomatrixserverlib/event.go +++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/event.go @@ -22,6 +22,18 @@ import ( "time" ) +// A StateKeyTuple is the combination of an event type and an event state key. +// It is often used as a key in maps. +type StateKeyTuple struct { + // The "type" key of a matrix event. + EventType string + // The "state_key" of a matrix event. + // The empty string is a legitimate value for the "state_key" in matrix + // so take care to initialise this field lest you accidentally request a + // "state_key" with the go default of the empty string. + StateKey string +} + // An EventReference is a reference to a matrix event. type EventReference struct { // The event ID of the event. diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/eventauth.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/eventauth.go index 523c0c939..e7d5c5156 100644 --- a/vendor/src/github.com/matrix-org/gomatrixserverlib/eventauth.go +++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/eventauth.go @@ -44,6 +44,69 @@ type StateNeeded struct { ThirdPartyInvite []string } +// Tuples returns the needed state key tuples for performing auth on an event. +func (s StateNeeded) Tuples() (res []StateKeyTuple) { + if s.Create { + res = append(res, StateKeyTuple{"m.room.create", ""}) + } + if s.JoinRules { + res = append(res, StateKeyTuple{"m.room.join_rules", ""}) + } + if s.PowerLevels { + res = append(res, StateKeyTuple{"m.room.power_levels", ""}) + } + for _, userID := range s.Member { + res = append(res, StateKeyTuple{"m.room.member", userID}) + } + for _, token := range s.ThirdPartyInvite { + res = append(res, StateKeyTuple{"m.room.third_party_invite", token}) + } + return +} + +// AuthEventReferences returns the auth_events references for the StateNeeded. Returns an error if the +// provider returns an error. If an event is missing from the provider but is required in StateNeeded, it +// is skipped over: no error is returned. +func (s StateNeeded) AuthEventReferences(provider AuthEventProvider) (refs []EventReference, err error) { + var e *Event + if s.Create { + if e, err = provider.Create(); err != nil { + return + } else if e != nil { + refs = append(refs, e.EventReference()) + } + } + if s.JoinRules { + if e, err = provider.JoinRules(); err != nil { + return + } else if e != nil { + refs = append(refs, e.EventReference()) + } + } + if s.PowerLevels { + if e, err = provider.PowerLevels(); err != nil { + return + } else if e != nil { + refs = append(refs, e.EventReference()) + } + } + for _, userID := range s.Member { + if e, err = provider.Member(userID); err != nil { + return + } else if e != nil { + refs = append(refs, e.EventReference()) + } + } + for _, token := range s.ThirdPartyInvite { + if e, err = provider.ThirdPartyInvite(token); err != nil { + return + } else if e != nil { + refs = append(refs, e.EventReference()) + } + } + return +} + // StateNeededForEventBuilder returns the event types and state_keys needed to authenticate the // event being built. These events should be put under 'auth_events' for the event being built. // Returns an error if the state needed could not be calculated with the given builder, e.g @@ -175,14 +238,9 @@ type AuthEventProvider interface { ThirdPartyInvite(stateKey string) (*Event, error) } -type stateKeyTuple struct { - Type string - StateKey string -} - // AuthEvents is an implementation of AuthEventProvider backed by a map. type AuthEvents struct { - events map[stateKeyTuple]*Event + events map[StateKeyTuple]*Event } // AddEvent adds an event to the provider. If an event already existed for the (type, state_key) then @@ -191,39 +249,39 @@ func (a *AuthEvents) AddEvent(event *Event) error { if event.StateKey() == nil { return fmt.Errorf("AddEvent: event %s does not have a state key", event.Type()) } - a.events[stateKeyTuple{event.Type(), *event.StateKey()}] = event + a.events[StateKeyTuple{event.Type(), *event.StateKey()}] = event return nil } // Create implements AuthEventProvider func (a *AuthEvents) Create() (*Event, error) { - return a.events[stateKeyTuple{"m.room.create", ""}], nil + return a.events[StateKeyTuple{"m.room.create", ""}], nil } // JoinRules implements AuthEventProvider func (a *AuthEvents) JoinRules() (*Event, error) { - return a.events[stateKeyTuple{"m.room.join_rules", ""}], nil + return a.events[StateKeyTuple{"m.room.join_rules", ""}], nil } // PowerLevels implements AuthEventProvider func (a *AuthEvents) PowerLevels() (*Event, error) { - return a.events[stateKeyTuple{"m.room.power_levels", ""}], nil + return a.events[StateKeyTuple{"m.room.power_levels", ""}], nil } // Member implements AuthEventProvider func (a *AuthEvents) Member(stateKey string) (*Event, error) { - return a.events[stateKeyTuple{"m.room.member", stateKey}], nil + return a.events[StateKeyTuple{"m.room.member", stateKey}], nil } // ThirdPartyInvite implements AuthEventProvider func (a *AuthEvents) ThirdPartyInvite(stateKey string) (*Event, error) { - return a.events[stateKeyTuple{"m.room.third_party_invite", stateKey}], nil + return a.events[StateKeyTuple{"m.room.third_party_invite", stateKey}], nil } // NewAuthEvents returns an AuthEventProvider backed by the given events. New events can be added by // calling AddEvent(). func NewAuthEvents(events []*Event) AuthEvents { - a := AuthEvents{make(map[stateKeyTuple]*Event)} + a := AuthEvents{make(map[StateKeyTuple]*Event)} for _, e := range events { a.AddEvent(e) }