From 67f2fecb265950a5f2e635fe17e0168044ae5938 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Thu, 21 Sep 2017 19:12:25 +0200 Subject: [PATCH] Implement /state endpoint --- .../dendrite/syncapi/routing/routing.go | 5 +++ .../dendrite/syncapi/storage/syncserver.go | 10 +++++ .../dendrite/syncapi/sync/requestpool.go | 44 +++++++++++++++++++ 3 files changed, 59 insertions(+) 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 e95a7a250..e90b18909 100644 --- a/src/github.com/matrix-org/dendrite/syncapi/routing/routing.go +++ b/src/github.com/matrix-org/dendrite/syncapi/routing/routing.go @@ -33,4 +33,9 @@ func Setup(apiMux *mux.Router, srp *sync.RequestPool, deviceDB *devices.Database r0mux.Handle("/sync", common.MakeAuthAPI("sync", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse { return srp.OnIncomingSyncRequest(req, device) })).Methods("GET") + + r0mux.Handle("/rooms/{roomID}/state", common.MakeAuthAPI("room_state", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse { + vars := mux.Vars(req) + return srp.OnIncomingStateRequest(req, vars["roomID"]) + })) } 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 3ab7e1c7c..d65ea8ecf 100644 --- a/src/github.com/matrix-org/dendrite/syncapi/storage/syncserver.go +++ b/src/github.com/matrix-org/dendrite/syncapi/storage/syncserver.go @@ -162,6 +162,16 @@ func (d *SyncServerDatabase) GetStateEvent( return d.roomstate.selectStateEvent(ctx, evType, roomID, stateKey) } +func (d *SyncServerDatabase) GetStateEventsForRoom( + ctx context.Context, roomID string, +) (stateEvents []gomatrixserverlib.Event, err error) { + err = common.WithTransaction(d.db, func(txn *sql.Tx) error { + stateEvents, err = d.roomstate.selectCurrentState(ctx, txn, roomID) + return err + }) + return +} + // SyncStreamPosition returns the latest position in the sync stream. Returns 0 if there are no events yet. func (d *SyncServerDatabase) SyncStreamPosition(ctx context.Context) (types.StreamPosition, error) { return d.syncStreamPositionTx(ctx, nil) 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 c9b86a6f1..c0524ee05 100644 --- a/src/github.com/matrix-org/dendrite/syncapi/sync/requestpool.go +++ b/src/github.com/matrix-org/dendrite/syncapi/sync/requestpool.go @@ -15,6 +15,8 @@ package sync import ( + "encoding/json" + "fmt" "net/http" "time" @@ -105,6 +107,48 @@ func (rp *RequestPool) OnIncomingSyncRequest(req *http.Request, device *authtype } } +type stateEventInResp struct { + gomatrixserverlib.ClientEvent + PrevContent json.RawMessage `json:"prev_content,omitempty"` + ReplacesState string `json:"replaces_state,omitempty"` +} + +func (rp *RequestPool) OnIncomingStateRequest(req *http.Request, roomID string) util.JSONResponse { + stateEvents, err := rp.db.GetStateEventsForRoom(req.Context(), roomID) + if err != nil { + return httputil.LogThenError(req, err) + } + + resp := []stateEventInResp{} + // Fill the prev_content and replaces_state keys if necessary + for _, event := range stateEvents { + stateEvent := stateEventInResp{ClientEvent: gomatrixserverlib.ToClientEvent(event, gomatrixserverlib.FormatAll)} + var prevEventRef types.PrevEventRef + fmt.Println(len(event.Unsigned())) + if len(event.Unsigned()) > 0 { + if err := json.Unmarshal(event.Unsigned(), &prevEventRef); err != nil { + return httputil.LogThenError(req, err) + } + // Fills the previous state event ID if the state event replaces another + // state event + if len(prevEventRef.ReplacesState) > 0 { + stateEvent.ReplacesState = prevEventRef.ReplacesState + } + // Fill the previous event if the state event references a previous event + if prevEventRef.PrevContent != nil { + stateEvent.PrevContent = prevEventRef.PrevContent + } + } + + resp = append(resp, stateEvent) + } + + return util.JSONResponse{ + Code: 200, + JSON: resp, + } +} + func (rp *RequestPool) currentSyncForUser(req syncRequest, currentPos types.StreamPosition) (*types.Response, error) { // TODO: handle ignored users if req.since == types.StreamPosition(0) {