From f36269d9b1d31771165b4bda9646a57895073864 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 6 Oct 2017 11:23:58 +0100 Subject: [PATCH] Implement GET /rooms/{roomID}/state/{type}/{stateKey} (#276) * Implement GET /rooms/{roomID}/state/{type}/{stateKey} * Add comments --- .../dendrite/syncapi/routing/routing.go | 10 +++++ .../storage/current_room_state_table.go | 6 +-- .../dendrite/syncapi/storage/syncserver.go | 4 +- .../dendrite/syncapi/sync/requestpool.go | 40 +++++++++++++++++++ 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/github.com/matrix-org/dendrite/syncapi/routing/routing.go b/src/github.com/matrix-org/dendrite/syncapi/routing/routing.go index 5bad22b5..15ca267a 100644 --- a/src/github.com/matrix-org/dendrite/syncapi/routing/routing.go +++ b/src/github.com/matrix-org/dendrite/syncapi/routing/routing.go @@ -39,4 +39,14 @@ func Setup(apiMux *mux.Router, srp *sync.RequestPool, deviceDB *devices.Database vars := mux.Vars(req) return srp.OnIncomingStateRequest(req, vars["roomID"]) })).Methods("GET") + + r0mux.Handle("/rooms/{roomID}/state/{type}", common.MakeAuthAPI("room_state", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse { + vars := mux.Vars(req) + return srp.OnIncomingStateTypeRequest(req, vars["roomID"], vars["type"], "") + })).Methods("GET") + + r0mux.Handle("/rooms/{roomID}/state/{type}/{stateKey}", common.MakeAuthAPI("room_state", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse { + vars := mux.Vars(req) + return srp.OnIncomingStateTypeRequest(req, vars["roomID"], vars["type"], vars["stateKey"]) + })).Methods("GET") } diff --git a/src/github.com/matrix-org/dendrite/syncapi/storage/current_room_state_table.go b/src/github.com/matrix-org/dendrite/syncapi/storage/current_room_state_table.go index c5879d53..852bfd76 100644 --- a/src/github.com/matrix-org/dendrite/syncapi/storage/current_room_state_table.go +++ b/src/github.com/matrix-org/dendrite/syncapi/storage/current_room_state_table.go @@ -70,7 +70,7 @@ const selectJoinedUsersSQL = "" + "SELECT room_id, state_key FROM syncapi_current_room_state WHERE type = 'm.room.member' AND membership = 'join'" const selectStateEventSQL = "" + - "SELECT event_json FROM syncapi_current_room_state WHERE type = $1 AND room_id = $2 AND state_key = $3" + "SELECT event_json FROM syncapi_current_room_state WHERE room_id = $1 AND type = $2 AND state_key = $3" const selectEventsWithEventIDsSQL = "" + "SELECT added_at, event_json FROM syncapi_current_room_state WHERE event_id = ANY($1)" @@ -233,11 +233,11 @@ func rowsToEvents(rows *sql.Rows) ([]gomatrixserverlib.Event, error) { } func (s *currentRoomStateStatements) selectStateEvent( - ctx context.Context, evType string, roomID string, stateKey string, + ctx context.Context, roomID, evType, stateKey string, ) (*gomatrixserverlib.Event, error) { stmt := s.selectStateEventStmt var res []byte - err := stmt.QueryRowContext(ctx, evType, roomID, stateKey).Scan(&res) + err := stmt.QueryRowContext(ctx, roomID, evType, stateKey).Scan(&res) if err == sql.ErrNoRows { return nil, nil } diff --git a/src/github.com/matrix-org/dendrite/syncapi/storage/syncserver.go b/src/github.com/matrix-org/dendrite/syncapi/storage/syncserver.go index 383e86da..8a059739 100644 --- a/src/github.com/matrix-org/dendrite/syncapi/storage/syncserver.go +++ b/src/github.com/matrix-org/dendrite/syncapi/storage/syncserver.go @@ -157,9 +157,9 @@ func (d *SyncServerDatabase) updateRoomState( // If no event could be found, returns nil // If there was an issue during the retrieval, returns an error func (d *SyncServerDatabase) GetStateEvent( - ctx context.Context, evType, roomID, stateKey string, + ctx context.Context, roomID, evType, stateKey string, ) (*gomatrixserverlib.Event, error) { - return d.roomstate.selectStateEvent(ctx, evType, roomID, stateKey) + return d.roomstate.selectStateEvent(ctx, roomID, evType, stateKey) } // GetStateEventsForRoom fetches the state events for a given room. diff --git a/src/github.com/matrix-org/dendrite/syncapi/sync/requestpool.go b/src/github.com/matrix-org/dendrite/syncapi/sync/requestpool.go index 56ba3d13..1067c98b 100644 --- a/src/github.com/matrix-org/dendrite/syncapi/sync/requestpool.go +++ b/src/github.com/matrix-org/dendrite/syncapi/sync/requestpool.go @@ -120,6 +120,9 @@ type stateEventInStateResp struct { // is publicly visible. Current behaviour is returning an empty array if the // user cannot see the room's history. func (rp *RequestPool) OnIncomingStateRequest(req *http.Request, roomID string) util.JSONResponse { + // TODO(#287): Auth request and handle the case where the user has left (where + // we should return the state at the poin they left) + stateEvents, err := rp.db.GetStateEventsForRoom(req.Context(), roomID) if err != nil { return httputil.LogThenError(req, err) @@ -156,6 +159,43 @@ func (rp *RequestPool) OnIncomingStateRequest(req *http.Request, roomID string) } } +// OnIncomingStateTypeRequest is called when a client makes a +// /rooms/{roomID}/state/{type}/{statekey} request. It will look in current +// state to see if there is an event with that type and state key, if there +// is then (by default) we return the content, otherwise a 404. +func (rp *RequestPool) OnIncomingStateTypeRequest(req *http.Request, roomID string, evType, stateKey string) util.JSONResponse { + // TODO(#287): Auth request and handle the case where the user has left (where + // we should return the state at the poin they left) + + logger := util.GetLogger(req.Context()) + logger.WithFields(log.Fields{ + "roomID": roomID, + "evType": evType, + "stateKey": stateKey, + }).Info("Fetching state") + + event, err := rp.db.GetStateEvent(req.Context(), roomID, evType, stateKey) + if err != nil { + return httputil.LogThenError(req, err) + } + + if event == nil { + return util.JSONResponse{ + Code: 404, + JSON: jsonerror.NotFound("cannot find state"), + } + } + + stateEvent := stateEventInStateResp{ + ClientEvent: gomatrixserverlib.ToClientEvent(*event, gomatrixserverlib.FormatAll), + } + + return util.JSONResponse{ + Code: 200, + JSON: stateEvent.Content, + } +} + func (rp *RequestPool) currentSyncForUser(req syncRequest, currentPos types.StreamPosition) (*types.Response, error) { // TODO: handle ignored users if req.since == types.StreamPosition(0) {