mirror of
https://github.com/hoernschen/dendrite.git
synced 2024-12-27 07:28:27 +00:00
* Move /room/{roomID}/state endpoints into client API (#606) * Update sytest-whitelist * Blacklist tests which rely on endpoints we don't implement
This commit is contained in:
parent
73d2f59e30
commit
895a72b6ee
9 changed files with 93 additions and 49 deletions
|
@ -149,6 +149,31 @@ func Setup(
|
||||||
return GetEvent(req, device, vars["roomID"], vars["eventID"], cfg, queryAPI, federation, keyRing)
|
return GetEvent(req, device, vars["roomID"], vars["eventID"], cfg, queryAPI, federation, keyRing)
|
||||||
}),
|
}),
|
||||||
).Methods(http.MethodGet, http.MethodOptions)
|
).Methods(http.MethodGet, http.MethodOptions)
|
||||||
|
|
||||||
|
r0mux.Handle("/rooms/{roomID}/state", common.MakeAuthAPI("room_state", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||||
|
vars, err := common.URLDecodeMapValues(mux.Vars(req))
|
||||||
|
if err != nil {
|
||||||
|
return util.ErrorResponse(err)
|
||||||
|
}
|
||||||
|
return OnIncomingStateRequest(req.Context(), queryAPI, vars["roomID"])
|
||||||
|
})).Methods(http.MethodGet, http.MethodOptions)
|
||||||
|
|
||||||
|
r0mux.Handle("/rooms/{roomID}/state/{type}", common.MakeAuthAPI("room_state", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||||
|
vars, err := common.URLDecodeMapValues(mux.Vars(req))
|
||||||
|
if err != nil {
|
||||||
|
return util.ErrorResponse(err)
|
||||||
|
}
|
||||||
|
return OnIncomingStateTypeRequest(req.Context(), queryAPI, vars["roomID"], vars["type"], "")
|
||||||
|
})).Methods(http.MethodGet, http.MethodOptions)
|
||||||
|
|
||||||
|
r0mux.Handle("/rooms/{roomID}/state/{type}/{stateKey}", common.MakeAuthAPI("room_state", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||||
|
vars, err := common.URLDecodeMapValues(mux.Vars(req))
|
||||||
|
if err != nil {
|
||||||
|
return util.ErrorResponse(err)
|
||||||
|
}
|
||||||
|
return OnIncomingStateTypeRequest(req.Context(), queryAPI, vars["roomID"], vars["type"], vars["stateKey"])
|
||||||
|
})).Methods(http.MethodGet, http.MethodOptions)
|
||||||
|
|
||||||
r0mux.Handle("/rooms/{roomID}/state/{eventType:[^/]+/?}",
|
r0mux.Handle("/rooms/{roomID}/state/{eventType:[^/]+/?}",
|
||||||
common.MakeAuthAPI("send_message", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
common.MakeAuthAPI("send_message", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||||
vars, err := common.URLDecodeMapValues(mux.Vars(req))
|
vars, err := common.URLDecodeMapValues(mux.Vars(req))
|
||||||
|
@ -164,6 +189,7 @@ func Setup(
|
||||||
return SendEvent(req, device, vars["roomID"], eventType, nil, &emptyString, cfg, queryAPI, producer, nil)
|
return SendEvent(req, device, vars["roomID"], eventType, nil, &emptyString, cfg, queryAPI, producer, nil)
|
||||||
}),
|
}),
|
||||||
).Methods(http.MethodPut, http.MethodOptions)
|
).Methods(http.MethodPut, http.MethodOptions)
|
||||||
|
|
||||||
r0mux.Handle("/rooms/{roomID}/state/{eventType}/{stateKey}",
|
r0mux.Handle("/rooms/{roomID}/state/{eventType}/{stateKey}",
|
||||||
common.MakeAuthAPI("send_message", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
common.MakeAuthAPI("send_message", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||||
vars, err := common.URLDecodeMapValues(mux.Vars(req))
|
vars, err := common.URLDecodeMapValues(mux.Vars(req))
|
||||||
|
|
|
@ -15,11 +15,12 @@
|
||||||
package routing
|
package routing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||||
"github.com/matrix-org/dendrite/syncapi/storage"
|
"github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/syncapi/types"
|
"github.com/matrix-org/dendrite/syncapi/types"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
|
@ -39,22 +40,29 @@ type stateEventInStateResp struct {
|
||||||
// TODO: Check if the user is in the room. If not, check if the room's history
|
// TODO: Check if the user is in the room. If not, check if the room's history
|
||||||
// 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 OnIncomingStateRequest(req *http.Request, db storage.Database, roomID string) util.JSONResponse {
|
func OnIncomingStateRequest(ctx context.Context, queryAPI api.RoomserverQueryAPI, roomID string) util.JSONResponse {
|
||||||
// TODO(#287): Auth request and handle the case where the user has left (where
|
// TODO(#287): Auth request and handle the case where the user has left (where
|
||||||
// we should return the state at the poin they left)
|
// we should return the state at the poin they left)
|
||||||
|
stateReq := api.QueryLatestEventsAndStateRequest{
|
||||||
|
RoomID: roomID,
|
||||||
|
}
|
||||||
|
stateRes := api.QueryLatestEventsAndStateResponse{}
|
||||||
|
|
||||||
stateFilter := gomatrixserverlib.DefaultStateFilter()
|
if err := queryAPI.QueryLatestEventsAndState(ctx, &stateReq, &stateRes); err != nil {
|
||||||
// TODO: stateFilter should not limit the number of state events (or only limits abusive number of events)
|
util.GetLogger(ctx).WithError(err).Error("queryAPI.QueryLatestEventsAndState failed")
|
||||||
|
|
||||||
stateEvents, err := db.GetStateEventsForRoom(req.Context(), roomID, &stateFilter)
|
|
||||||
if err != nil {
|
|
||||||
util.GetLogger(req.Context()).WithError(err).Error("db.GetStateEventsForRoom failed")
|
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(stateRes.StateEvents) == 0 {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusNotFound,
|
||||||
|
JSON: jsonerror.NotFound("cannot find state"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resp := []stateEventInStateResp{}
|
resp := []stateEventInStateResp{}
|
||||||
// Fill the prev_content and replaces_state keys if necessary
|
// Fill the prev_content and replaces_state keys if necessary
|
||||||
for _, event := range stateEvents {
|
for _, event := range stateRes.StateEvents {
|
||||||
stateEvent := stateEventInStateResp{
|
stateEvent := stateEventInStateResp{
|
||||||
ClientEvent: gomatrixserverlib.HeaderedToClientEvents(
|
ClientEvent: gomatrixserverlib.HeaderedToClientEvents(
|
||||||
[]gomatrixserverlib.HeaderedEvent{event}, gomatrixserverlib.FormatAll,
|
[]gomatrixserverlib.HeaderedEvent{event}, gomatrixserverlib.FormatAll,
|
||||||
|
@ -63,7 +71,7 @@ func OnIncomingStateRequest(req *http.Request, db storage.Database, roomID strin
|
||||||
var prevEventRef types.PrevEventRef
|
var prevEventRef types.PrevEventRef
|
||||||
if len(event.Unsigned()) > 0 {
|
if len(event.Unsigned()) > 0 {
|
||||||
if err := json.Unmarshal(event.Unsigned(), &prevEventRef); err != nil {
|
if err := json.Unmarshal(event.Unsigned(), &prevEventRef); err != nil {
|
||||||
util.GetLogger(req.Context()).WithError(err).Error("json.Unmarshal failed")
|
util.GetLogger(ctx).WithError(err).Error("json.Unmarshal failed")
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
// Fills the previous state event ID if the state event replaces another
|
// Fills the previous state event ID if the state event replaces another
|
||||||
|
@ -90,24 +98,32 @@ func OnIncomingStateRequest(req *http.Request, db storage.Database, roomID strin
|
||||||
// /rooms/{roomID}/state/{type}/{statekey} request. It will look in current
|
// /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
|
// 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.
|
// is then (by default) we return the content, otherwise a 404.
|
||||||
func OnIncomingStateTypeRequest(req *http.Request, db storage.Database, roomID string, evType, stateKey string) util.JSONResponse {
|
func OnIncomingStateTypeRequest(ctx context.Context, queryAPI api.RoomserverQueryAPI, roomID string, evType, stateKey string) util.JSONResponse {
|
||||||
// TODO(#287): Auth request and handle the case where the user has left (where
|
// TODO(#287): Auth request and handle the case where the user has left (where
|
||||||
// we should return the state at the poin they left)
|
// we should return the state at the poin they left)
|
||||||
|
util.GetLogger(ctx).WithFields(log.Fields{
|
||||||
logger := util.GetLogger(req.Context())
|
|
||||||
logger.WithFields(log.Fields{
|
|
||||||
"roomID": roomID,
|
"roomID": roomID,
|
||||||
"evType": evType,
|
"evType": evType,
|
||||||
"stateKey": stateKey,
|
"stateKey": stateKey,
|
||||||
}).Info("Fetching state")
|
}).Info("Fetching state")
|
||||||
|
|
||||||
event, err := db.GetStateEvent(req.Context(), roomID, evType, stateKey)
|
stateReq := api.QueryLatestEventsAndStateRequest{
|
||||||
if err != nil {
|
RoomID: roomID,
|
||||||
util.GetLogger(req.Context()).WithError(err).Error("db.GetStateEvent failed")
|
StateToFetch: []gomatrixserverlib.StateKeyTuple{
|
||||||
|
gomatrixserverlib.StateKeyTuple{
|
||||||
|
EventType: evType,
|
||||||
|
StateKey: stateKey,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
stateRes := api.QueryLatestEventsAndStateResponse{}
|
||||||
|
|
||||||
|
if err := queryAPI.QueryLatestEventsAndState(ctx, &stateReq, &stateRes); err != nil {
|
||||||
|
util.GetLogger(ctx).WithError(err).Error("queryAPI.QueryLatestEventsAndState failed")
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
|
|
||||||
if event == nil {
|
if len(stateRes.StateEvents) == 0 {
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusNotFound,
|
Code: http.StatusNotFound,
|
||||||
JSON: jsonerror.NotFound("cannot find state"),
|
JSON: jsonerror.NotFound("cannot find state"),
|
||||||
|
@ -115,7 +131,7 @@ func OnIncomingStateTypeRequest(req *http.Request, db storage.Database, roomID s
|
||||||
}
|
}
|
||||||
|
|
||||||
stateEvent := stateEventInStateResp{
|
stateEvent := stateEventInStateResp{
|
||||||
ClientEvent: gomatrixserverlib.HeaderedToClientEvent(*event, gomatrixserverlib.FormatAll),
|
ClientEvent: gomatrixserverlib.HeaderedToClientEvent(stateRes.StateEvents[0], gomatrixserverlib.FormatAll),
|
||||||
}
|
}
|
||||||
|
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
|
@ -73,6 +73,10 @@ func AddPrevEventsToEvent(
|
||||||
return fmt.Errorf("gomatrixserverlib.StateNeededForEventBuilder: %w", err)
|
return fmt.Errorf("gomatrixserverlib.StateNeededForEventBuilder: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(eventsNeeded.Tuples()) == 0 {
|
||||||
|
return errors.New("expecting state tuples for event builder, got none")
|
||||||
|
}
|
||||||
|
|
||||||
// Ask the roomserver for information about this room
|
// Ask the roomserver for information about this room
|
||||||
queryReq := api.QueryLatestEventsAndStateRequest{
|
queryReq := api.QueryLatestEventsAndStateRequest{
|
||||||
RoomID: builder.RoomID,
|
RoomID: builder.RoomID,
|
||||||
|
|
|
@ -271,6 +271,10 @@ func buildMembershipEvent(
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(eventsNeeded.Tuples()) == 0 {
|
||||||
|
return nil, errors.New("expecting state tuples for event builder, got none")
|
||||||
|
}
|
||||||
|
|
||||||
// Ask the roomserver for information about this room
|
// Ask the roomserver for information about this room
|
||||||
queryReq := roomserverAPI.QueryLatestEventsAndStateRequest{
|
queryReq := roomserverAPI.QueryLatestEventsAndStateRequest{
|
||||||
RoomID: builder.RoomID,
|
RoomID: builder.RoomID,
|
||||||
|
|
|
@ -17,6 +17,7 @@ package alias
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -218,6 +219,9 @@ func (r *RoomserverAliasAPI) sendUpdatedAliasesEvent(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if len(eventsNeeded.Tuples()) == 0 {
|
||||||
|
return errors.New("expecting state tuples for event builder, got none")
|
||||||
|
}
|
||||||
req := roomserverAPI.QueryLatestEventsAndStateRequest{
|
req := roomserverAPI.QueryLatestEventsAndStateRequest{
|
||||||
RoomID: roomID,
|
RoomID: roomID,
|
||||||
StateToFetch: eventsNeeded.Tuples(),
|
StateToFetch: eventsNeeded.Tuples(),
|
||||||
|
|
|
@ -132,10 +132,18 @@ func (r *RoomserverQueryAPI) QueryLatestEventsAndState(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var stateEntries []types.StateEntry
|
||||||
|
if len(request.StateToFetch) == 0 {
|
||||||
|
// Look up all room state.
|
||||||
|
stateEntries, err = roomState.LoadStateAtSnapshot(
|
||||||
|
ctx, currentStateSnapshotNID,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
// Look up the current state for the requested tuples.
|
// Look up the current state for the requested tuples.
|
||||||
stateEntries, err := roomState.LoadStateAtSnapshotForStringTuples(
|
stateEntries, err = roomState.LoadStateAtSnapshotForStringTuples(
|
||||||
ctx, currentStateSnapshotNID, request.StateToFetch,
|
ctx, currentStateSnapshotNID, request.StateToFetch,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,30 +56,6 @@ func Setup(
|
||||||
return srp.OnIncomingSyncRequest(req, device)
|
return srp.OnIncomingSyncRequest(req, device)
|
||||||
})).Methods(http.MethodGet, http.MethodOptions)
|
})).Methods(http.MethodGet, http.MethodOptions)
|
||||||
|
|
||||||
r0mux.Handle("/rooms/{roomID}/state", common.MakeAuthAPI("room_state", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
|
||||||
vars, err := common.URLDecodeMapValues(mux.Vars(req))
|
|
||||||
if err != nil {
|
|
||||||
return util.ErrorResponse(err)
|
|
||||||
}
|
|
||||||
return OnIncomingStateRequest(req, syncDB, vars["roomID"])
|
|
||||||
})).Methods(http.MethodGet, http.MethodOptions)
|
|
||||||
|
|
||||||
r0mux.Handle("/rooms/{roomID}/state/{type}", common.MakeAuthAPI("room_state", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
|
||||||
vars, err := common.URLDecodeMapValues(mux.Vars(req))
|
|
||||||
if err != nil {
|
|
||||||
return util.ErrorResponse(err)
|
|
||||||
}
|
|
||||||
return OnIncomingStateTypeRequest(req, syncDB, vars["roomID"], vars["type"], "")
|
|
||||||
})).Methods(http.MethodGet, http.MethodOptions)
|
|
||||||
|
|
||||||
r0mux.Handle("/rooms/{roomID}/state/{type}/{stateKey}", common.MakeAuthAPI("room_state", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
|
||||||
vars, err := common.URLDecodeMapValues(mux.Vars(req))
|
|
||||||
if err != nil {
|
|
||||||
return util.ErrorResponse(err)
|
|
||||||
}
|
|
||||||
return OnIncomingStateTypeRequest(req, syncDB, vars["roomID"], vars["type"], vars["stateKey"])
|
|
||||||
})).Methods(http.MethodGet, http.MethodOptions)
|
|
||||||
|
|
||||||
r0mux.Handle("/rooms/{roomID}/messages", common.MakeAuthAPI("room_messages", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
r0mux.Handle("/rooms/{roomID}/messages", common.MakeAuthAPI("room_messages", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||||
vars, err := common.URLDecodeMapValues(mux.Vars(req))
|
vars, err := common.URLDecodeMapValues(mux.Vars(req))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -35,3 +35,7 @@ Inbound federation rejects invites which are not signed by the sender
|
||||||
|
|
||||||
# Blacklisted because we don't support ignores yet
|
# Blacklisted because we don't support ignores yet
|
||||||
Ignore invite in incremental sync
|
Ignore invite in incremental sync
|
||||||
|
|
||||||
|
# Blacklisted because this test calls /r0/events which we don't implement
|
||||||
|
New room members see their own join event
|
||||||
|
Existing members see new members' join events
|
||||||
|
|
|
@ -55,8 +55,9 @@ Request to logout with invalid an access token is rejected
|
||||||
Request to logout without an access token is rejected
|
Request to logout without an access token is rejected
|
||||||
Room creation reports m.room.create to myself
|
Room creation reports m.room.create to myself
|
||||||
Room creation reports m.room.member to myself
|
Room creation reports m.room.member to myself
|
||||||
New room members see their own join event
|
# Blacklisted because these tests call /r0/events which we don't implement
|
||||||
Existing members see new members' join events
|
# New room members see their own join event
|
||||||
|
# Existing members see new members' join events
|
||||||
setting 'm.room.power_levels' respects room powerlevel
|
setting 'm.room.power_levels' respects room powerlevel
|
||||||
Unprivileged users can set m.room.topic if it only needs level 0
|
Unprivileged users can set m.room.topic if it only needs level 0
|
||||||
Users cannot set ban powerlevel higher than their own
|
Users cannot set ban powerlevel higher than their own
|
||||||
|
@ -245,3 +246,4 @@ Remote user can backfill in a room with version 4
|
||||||
Outbound federation can send invites via v2 API
|
Outbound federation can send invites via v2 API
|
||||||
User can invite local user to room with version 3
|
User can invite local user to room with version 3
|
||||||
User can invite local user to room with version 4
|
User can invite local user to room with version 4
|
||||||
|
A pair of servers can establish a join in a v2 room
|
||||||
|
|
Loading…
Reference in a new issue