Implement GET /rooms/{roomID}/state/{type}/{stateKey} (#276)

* Implement GET /rooms/{roomID}/state/{type}/{stateKey}

* Add comments
This commit is contained in:
Erik Johnston 2017-10-06 11:23:58 +01:00 committed by GitHub
parent 1e6fc74d4f
commit f36269d9b1
4 changed files with 55 additions and 5 deletions

View File

@ -39,4 +39,14 @@ func Setup(apiMux *mux.Router, srp *sync.RequestPool, deviceDB *devices.Database
vars := mux.Vars(req) vars := mux.Vars(req)
return srp.OnIncomingStateRequest(req, vars["roomID"]) return srp.OnIncomingStateRequest(req, vars["roomID"])
})).Methods("GET") })).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")
} }

View File

@ -70,7 +70,7 @@ const selectJoinedUsersSQL = "" +
"SELECT room_id, state_key FROM syncapi_current_room_state WHERE type = 'm.room.member' AND membership = 'join'" "SELECT room_id, state_key FROM syncapi_current_room_state WHERE type = 'm.room.member' AND membership = 'join'"
const selectStateEventSQL = "" + 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 = "" + const selectEventsWithEventIDsSQL = "" +
"SELECT added_at, event_json FROM syncapi_current_room_state WHERE event_id = ANY($1)" "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( func (s *currentRoomStateStatements) selectStateEvent(
ctx context.Context, evType string, roomID string, stateKey string, ctx context.Context, roomID, evType, stateKey string,
) (*gomatrixserverlib.Event, error) { ) (*gomatrixserverlib.Event, error) {
stmt := s.selectStateEventStmt stmt := s.selectStateEventStmt
var res []byte 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 { if err == sql.ErrNoRows {
return nil, nil return nil, nil
} }

View File

@ -157,9 +157,9 @@ func (d *SyncServerDatabase) updateRoomState(
// If no event could be found, returns nil // If no event could be found, returns nil
// If there was an issue during the retrieval, returns an error // If there was an issue during the retrieval, returns an error
func (d *SyncServerDatabase) GetStateEvent( func (d *SyncServerDatabase) GetStateEvent(
ctx context.Context, evType, roomID, stateKey string, ctx context.Context, roomID, evType, stateKey string,
) (*gomatrixserverlib.Event, error) { ) (*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. // GetStateEventsForRoom fetches the state events for a given room.

View File

@ -120,6 +120,9 @@ type stateEventInStateResp struct {
// is publicly visible. Current behaviour is returning an empty array if the // is publicly visible. Current behaviour is returning an empty array if the
// user cannot see the room's history. // user cannot see the room's history.
func (rp *RequestPool) OnIncomingStateRequest(req *http.Request, roomID string) util.JSONResponse { 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) stateEvents, err := rp.db.GetStateEventsForRoom(req.Context(), roomID)
if err != nil { if err != nil {
return httputil.LogThenError(req, err) 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) { func (rp *RequestPool) currentSyncForUser(req syncRequest, currentPos types.StreamPosition) (*types.Response, error) {
// TODO: handle ignored users // TODO: handle ignored users
if req.since == types.StreamPosition(0) { if req.since == types.StreamPosition(0) {