From 853e82506bbbd0a6e169846d8b029295db749ddf Mon Sep 17 00:00:00 2001 From: Anant Prakash Date: Fri, 22 Jun 2018 16:16:19 +0530 Subject: [PATCH] [federation] Implement state APIs (#486) * Refactor GetEvents * [federationapi] Add state APIs --- .../dendrite/federationapi/routing/events.go | 29 +++- .../dendrite/federationapi/routing/routing.go | 22 +++ .../dendrite/federationapi/routing/state.go | 127 ++++++++++++++++++ 3 files changed, 173 insertions(+), 5 deletions(-) create mode 100644 src/github.com/matrix-org/dendrite/federationapi/routing/state.go diff --git a/src/github.com/matrix-org/dendrite/federationapi/routing/events.go b/src/github.com/matrix-org/dendrite/federationapi/routing/events.go index 02262891..ed56ec7a 100644 --- a/src/github.com/matrix-org/dendrite/federationapi/routing/events.go +++ b/src/github.com/matrix-org/dendrite/federationapi/routing/events.go @@ -35,6 +35,22 @@ func GetEvent( _ gomatrixserverlib.KeyRing, eventID string, ) util.JSONResponse { + event, err := getEvent(ctx, request, query, eventID) + if err != nil { + return *err + } + + return util.JSONResponse{Code: http.StatusOK, JSON: event} +} + +// getEvent returns the requested event, +// otherwise it returns an error response which can be sent to the client. +func getEvent( + ctx context.Context, + request *gomatrixserverlib.FederationRequest, + query api.RoomserverQueryAPI, + eventID string, +) (*gomatrixserverlib.Event, *util.JSONResponse) { var authResponse api.QueryServerAllowedToSeeEventResponse err := query.QueryServerAllowedToSeeEvent( ctx, @@ -45,11 +61,13 @@ func GetEvent( &authResponse, ) if err != nil { - return util.ErrorResponse(err) + resErr := util.ErrorResponse(err) + return nil, &resErr } if !authResponse.AllowedToSeeEvent { - return util.MessageResponse(http.StatusForbidden, "server not allowed to see event") + resErr := util.MessageResponse(http.StatusForbidden, "server not allowed to see event") + return nil, &resErr } var eventsResponse api.QueryEventsByIDResponse @@ -59,12 +77,13 @@ func GetEvent( &eventsResponse, ) if err != nil { - return util.ErrorResponse(err) + resErr := util.ErrorResponse(err) + return nil, &resErr } if len(eventsResponse.Events) == 0 { - return util.JSONResponse{Code: http.StatusNotFound, JSON: nil} + return nil, &util.JSONResponse{Code: http.StatusNotFound, JSON: nil} } - return util.JSONResponse{Code: http.StatusOK, JSON: &eventsResponse.Events[0]} + return &eventsResponse.Events[0], nil } diff --git a/src/github.com/matrix-org/dendrite/federationapi/routing/routing.go b/src/github.com/matrix-org/dendrite/federationapi/routing/routing.go index f43866ea..52e00f2b 100644 --- a/src/github.com/matrix-org/dendrite/federationapi/routing/routing.go +++ b/src/github.com/matrix-org/dendrite/federationapi/routing/routing.go @@ -106,6 +106,28 @@ func Setup( }, )).Methods(http.MethodGet) + v1fedmux.Handle("/state/{roomID}/{eventID}", common.MakeFedAPI( + "federation_get_event_auth", cfg.Matrix.ServerName, keys, + func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse { + vars := mux.Vars(httpReq) + return GetState( + httpReq.Context(), request, cfg, query, time.Now(), + keys, vars["roomID"], vars["eventID"], + ) + }, + )).Methods(http.MethodGet) + + v1fedmux.Handle("/state_ids/{roomID}/{eventID}", common.MakeFedAPI( + "federation_get_event_auth", cfg.Matrix.ServerName, keys, + func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse { + vars := mux.Vars(httpReq) + return GetStateIDs( + httpReq.Context(), request, cfg, query, time.Now(), + keys, vars["roomID"], vars["eventID"], + ) + }, + )).Methods(http.MethodGet) + v1fedmux.Handle("/query/directory/", common.MakeFedAPI( "federation_query_room_alias", cfg.Matrix.ServerName, keys, func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse { diff --git a/src/github.com/matrix-org/dendrite/federationapi/routing/state.go b/src/github.com/matrix-org/dendrite/federationapi/routing/state.go new file mode 100644 index 00000000..03046ece --- /dev/null +++ b/src/github.com/matrix-org/dendrite/federationapi/routing/state.go @@ -0,0 +1,127 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package routing + +import ( + "context" + "net/http" + "time" + + "github.com/matrix-org/dendrite/common/config" + "github.com/matrix-org/dendrite/roomserver/api" + "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/util" +) + +// GetState returns state events & auth events for the roomID, eventID +func GetState( + ctx context.Context, + request *gomatrixserverlib.FederationRequest, + _ config.Dendrite, + query api.RoomserverQueryAPI, + _ time.Time, + _ gomatrixserverlib.KeyRing, + roomID string, + eventID string, +) util.JSONResponse { + state, err := getState(ctx, request, query, roomID, eventID) + if err != nil { + return *err + } + + return util.JSONResponse{Code: http.StatusOK, JSON: state} +} + +// GetStateIDs returns state event IDs & auth event IDs for the roomID, eventID +func GetStateIDs( + ctx context.Context, + request *gomatrixserverlib.FederationRequest, + _ config.Dendrite, + query api.RoomserverQueryAPI, + _ time.Time, + _ gomatrixserverlib.KeyRing, + roomID string, + eventID string, +) util.JSONResponse { + state, err := getState(ctx, request, query, roomID, eventID) + if err != nil { + return *err + } + + stateEventIDs := getIDsFromEvent(state.StateEvents) + authEventIDs := getIDsFromEvent(state.AuthEvents) + + return util.JSONResponse{Code: http.StatusOK, JSON: gomatrixserverlib.RespStateIDs{ + StateEventIDs: stateEventIDs, + AuthEventIDs: authEventIDs, + }, + } +} + +func getState( + ctx context.Context, + request *gomatrixserverlib.FederationRequest, + query api.RoomserverQueryAPI, + roomID string, + eventID string, +) (*gomatrixserverlib.RespState, *util.JSONResponse) { + event, resErr := getEvent(ctx, request, query, eventID) + if resErr != nil { + return nil, resErr + } + + prevEventIDs := getIDsFromEventRef(event.PrevEvents()) + authEventIDs := getIDsFromEventRef(event.AuthEvents()) + + var response api.QueryStateAndAuthChainResponse + err := query.QueryStateAndAuthChain( + ctx, + &api.QueryStateAndAuthChainRequest{ + RoomID: roomID, + PrevEventIDs: prevEventIDs, + AuthEventIDs: authEventIDs, + }, + &response, + ) + if err != nil { + resErr := util.ErrorResponse(err) + return nil, &resErr + } + + if !response.RoomExists { + return nil, &util.JSONResponse{Code: http.StatusNotFound, JSON: nil} + } + + return &gomatrixserverlib.RespState{ + StateEvents: response.StateEvents, + AuthEvents: response.AuthChainEvents, + }, nil +} + +func getIDsFromEventRef(events []gomatrixserverlib.EventReference) []string { + IDs := make([]string, len(events)) + for i := range events { + IDs[i] = events[i].EventID + } + + return IDs +} + +func getIDsFromEvent(events []gomatrixserverlib.Event) []string { + IDs := make([]string, len(events)) + for i := range events { + IDs[i] = events[i].EventID() + } + + return IDs +}