From 803647be5675e1a7e4bf56daa12755681af026f8 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sat, 12 Sep 2020 01:24:28 +0100 Subject: [PATCH] handle SS /peek --- federationapi/routing/peek.go | 112 +++++++++++++++++++++++++++++++ federationapi/routing/routing.go | 36 +++++++++- 2 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 federationapi/routing/peek.go diff --git a/federationapi/routing/peek.go b/federationapi/routing/peek.go new file mode 100644 index 000000000..12df15448 --- /dev/null +++ b/federationapi/routing/peek.go @@ -0,0 +1,112 @@ +// Copyright 2020 New Vector Ltd +// +// 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" + + "github.com/matrix-org/dendrite/clientapi/jsonerror" + "github.com/matrix-org/dendrite/internal/config" + "github.com/matrix-org/dendrite/roomserver/api" + "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/util" +) + +// Peek implements the /peek API +func Peek( + httpReq *http.Request, + request *gomatrixserverlib.FederationRequest, + cfg *config.FederationAPI, + rsAPI api.RoomserverInternalAPI, + roomID, peekID string, + remoteVersions []gomatrixserverlib.RoomVersion, +) util.JSONResponse { + verReq := api.QueryRoomVersionForRoomRequest{RoomID: roomID} + verRes := api.QueryRoomVersionForRoomResponse{} + if err := rsAPI.QueryRoomVersionForRoom(httpReq.Context(), &verReq, &verRes); err != nil { + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: jsonerror.InternalServerError(), + } + } + + // Check that the room that the remote side is trying to join is actually + // one of the room versions that they listed in their supported ?ver= in + // the peek URL. + remoteSupportsVersion := false + for _, v := range remoteVersions { + if v == verRes.RoomVersion { + remoteSupportsVersion = true + break + } + } + // If it isn't, stop trying to join the room. + if !remoteSupportsVersion { + return util.JSONResponse{ + Code: http.StatusBadRequest, + JSON: jsonerror.IncompatibleRoomVersion(verRes.RoomVersion), + } + } + + // TODO: Check history visibility + + state, err := getCurrentState(httpReq.Context(), request, rsAPI, roomID) + if err != nil { + return *err + } + + return util.JSONResponse{ + Code: http.StatusOK, + JSON: map[string]interface{}{ + "state": state, + "room_version": verRes.RoomVersion, + }, + } +} + + +func getCurrentState( + ctx context.Context, + request *gomatrixserverlib.FederationRequest, + rsAPI api.RoomserverInternalAPI, + roomID string, +) (*gomatrixserverlib.RespPeek, *util.JSONResponse) { + var response api.QueryStateAndAuthChainResponse + err := rsAPI.QueryStateAndAuthChain( + ctx, + &api.QueryStateAndAuthChainRequest{ + RoomID: roomID, + PrevEventIDs: []string{}, + AuthEventIDs: []string{}, + }, + &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.RespPeek{ + StateEvents: gomatrixserverlib.UnwrapEventHeaders(response.StateEvents), + AuthEvents: gomatrixserverlib.UnwrapEventHeaders(response.AuthChainEvents), + RoomVersion: response.RoomVersion, + RenewalInterval: 60 * 60 * 1000 * 1000, // one hour + }, nil +} diff --git a/federationapi/routing/routing.go b/federationapi/routing/routing.go index b41ecadbb..805ef4ab8 100644 --- a/federationapi/routing/routing.go +++ b/federationapi/routing/routing.go @@ -207,7 +207,37 @@ func Setup( }, )).Methods(http.MethodGet) - v1fedmux.Handle("/make_join/{roomID}/{eventID}", httputil.MakeFedAPI( + v1fedmux.Handle("/peek/{roomID}/{peekID}", httputil.MakeFedAPI( + "federation_peek", cfg.Matrix.ServerName, keys, wakeup, + func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { + if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: jsonerror.Forbidden("Forbidden by server ACLs"), + } + } + roomID := vars["roomID"] + peekID := vars["peekID"] + queryVars := httpReq.URL.Query() + remoteVersions := []gomatrixserverlib.RoomVersion{} + if vers, ok := queryVars["ver"]; ok { + // The remote side supplied a ?ver= so use that to build up the list + // of supported room versions + for _, v := range vers { + remoteVersions = append(remoteVersions, gomatrixserverlib.RoomVersion(v)) + } + } else { + // The remote side didn't supply a ?ver= so just assume that they only + // support room version 1 + remoteVersions = append(remoteVersions, gomatrixserverlib.RoomVersionV1) + } + return Peek( + httpReq, request, cfg, rsAPI, roomID, peekID, remoteVersions, + ) + }, + )).Methods(http.MethodPut, http.MethodDelete) + + v1fedmux.Handle("/make_join/{roomID}/{userID}", httputil.MakeFedAPI( "federation_make_join", cfg.Matrix.ServerName, keys, wakeup, func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { @@ -217,7 +247,7 @@ func Setup( } } roomID := vars["roomID"] - eventID := vars["eventID"] + userID := vars["userID"] queryVars := httpReq.URL.Query() remoteVersions := []gomatrixserverlib.RoomVersion{} if vers, ok := queryVars["ver"]; ok { @@ -233,7 +263,7 @@ func Setup( remoteVersions = append(remoteVersions, gomatrixserverlib.RoomVersionV1) } return MakeJoin( - httpReq, request, cfg, rsAPI, roomID, eventID, remoteVersions, + httpReq, request, cfg, rsAPI, roomID, userID, remoteVersions, ) }, )).Methods(http.MethodGet)