mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-10 16:33:11 -06:00
Implement the API on the roomserver and client API server
This commit is contained in:
parent
86c2174faf
commit
9b3ecd5cdd
|
|
@ -23,7 +23,6 @@ import (
|
|||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/common/config"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -33,59 +32,24 @@ func GetMemberships(
|
|||
accountDB *accounts.Database, cfg config.Dendrite,
|
||||
queryAPI api.RoomserverQueryAPI,
|
||||
) util.JSONResponse {
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
queryReq := api.QueryMembershipsForRoomRequest{
|
||||
RoomID: roomID,
|
||||
Sender: device.UserID,
|
||||
}
|
||||
_, server, err := gomatrixserverlib.SplitID('!', roomID)
|
||||
if err != nil {
|
||||
var queryRes api.QueryMembershipsForRoomResponse
|
||||
if err := queryAPI.QueryMembershipsForRoom(&queryReq, &queryRes); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
}
|
||||
|
||||
events := []gomatrixserverlib.ClientEvent{}
|
||||
if server == cfg.Matrix.ServerName {
|
||||
// TODO: If the user has been in the room before but isn't
|
||||
// anymore, only send the members list as it was before they left.
|
||||
membership, err := accountDB.GetMembership(localpart, roomID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
if !queryRes.HasBeenInRoom {
|
||||
return util.JSONResponse{
|
||||
Code: 403,
|
||||
JSON: jsonerror.Forbidden("You aren't a member of the room and weren't previously a member of the room."),
|
||||
}
|
||||
|
||||
if membership == nil {
|
||||
return util.JSONResponse{
|
||||
Code: 403,
|
||||
JSON: jsonerror.Forbidden("You aren't a member of the room and weren't previously a member of the room."),
|
||||
}
|
||||
}
|
||||
|
||||
memberships, err := accountDB.GetMembershipsByRoomID(roomID)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
}
|
||||
|
||||
eventIDs := []string{}
|
||||
for _, membership := range memberships {
|
||||
eventIDs = append(eventIDs, membership.EventID)
|
||||
}
|
||||
|
||||
queryReq := api.QueryEventsByIDRequest{
|
||||
EventIDs: eventIDs,
|
||||
}
|
||||
var queryRes api.QueryEventsByIDResponse
|
||||
if err := queryAPI.QueryEventsByID(&queryReq, &queryRes); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
}
|
||||
|
||||
for _, event := range queryRes.Events {
|
||||
ev := gomatrixserverlib.ToClientEvent(event, gomatrixserverlib.FormatAll)
|
||||
events = append(events, ev)
|
||||
}
|
||||
} else {
|
||||
// TODO: Get memberships from federation
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: 200,
|
||||
JSON: events,
|
||||
JSON: queryRes.JoinEvents,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,6 +100,23 @@ type QueryEventsByIDResponse struct {
|
|||
Events []gomatrixserverlib.Event `json:"events"`
|
||||
}
|
||||
|
||||
// QueryMembershipsForRoomRequest is a request to QueryMembershipsForRoom
|
||||
type QueryMembershipsForRoomRequest struct {
|
||||
// ID of the room to fetch memberships from
|
||||
RoomID string `json:"room_id"`
|
||||
// ID of the user sending the request
|
||||
Sender string `json:"sender"`
|
||||
}
|
||||
|
||||
// QueryMembershipsForRoomResponse is a response to QueryMembershipsForRoom
|
||||
type QueryMembershipsForRoomResponse struct {
|
||||
// The "m.room.member" events (of "join" membership) in the client format
|
||||
JoinEvents []gomatrixserverlib.ClientEvent `json:"join_events"`
|
||||
// True if the user has been in room before and has either stayed in it or
|
||||
// left it.
|
||||
HasBeenInRoom bool `json:"has_been_in_room"`
|
||||
}
|
||||
|
||||
// RoomserverQueryAPI is used to query information from the room server.
|
||||
type RoomserverQueryAPI interface {
|
||||
// Query the latest events and state for a room from the room server.
|
||||
|
|
@ -119,6 +136,12 @@ type RoomserverQueryAPI interface {
|
|||
request *QueryEventsByIDRequest,
|
||||
response *QueryEventsByIDResponse,
|
||||
) error
|
||||
|
||||
// Query a list of membership events for a room
|
||||
QueryMembershipsForRoom(
|
||||
request *QueryMembershipsForRoomRequest,
|
||||
response *QueryMembershipsForRoomResponse,
|
||||
) error
|
||||
}
|
||||
|
||||
// RoomserverQueryLatestEventsAndStatePath is the HTTP path for the QueryLatestEventsAndState API.
|
||||
|
|
@ -130,6 +153,9 @@ const RoomserverQueryStateAfterEventsPath = "/api/roomserver/queryStateAfterEven
|
|||
// RoomserverQueryEventsByIDPath is the HTTP path for the QueryEventsByID API.
|
||||
const RoomserverQueryEventsByIDPath = "/api/roomserver/queryEventsByID"
|
||||
|
||||
// RoomserverQueryMembershipsForRoomPath is the HTTP path for the QueryMembershipsForRoom API
|
||||
const RoomserverQueryMembershipsForRoomPath = "/api/roomserver/queryMembershipsForRoom"
|
||||
|
||||
// NewRoomserverQueryAPIHTTP creates a RoomserverQueryAPI implemented by talking to a HTTP POST API.
|
||||
// If httpClient is nil then it uses the http.DefaultClient
|
||||
func NewRoomserverQueryAPIHTTP(roomserverURL string, httpClient *http.Client) RoomserverQueryAPI {
|
||||
|
|
@ -171,6 +197,15 @@ func (h *httpRoomserverQueryAPI) QueryEventsByID(
|
|||
return postJSON(h.httpClient, apiURL, request, response)
|
||||
}
|
||||
|
||||
// QueryMembershipsForRoom implements RoomserverQueryAPI
|
||||
func (h *httpRoomserverQueryAPI) QueryMembershipsForRoom(
|
||||
request *QueryMembershipsForRoomRequest,
|
||||
response *QueryMembershipsForRoomResponse,
|
||||
) error {
|
||||
apiURL := h.roomserverURL + RoomserverQueryMembershipsForRoomPath
|
||||
return postJSON(h.httpClient, apiURL, request, response)
|
||||
}
|
||||
|
||||
func postJSON(httpClient *http.Client, apiURL string, request, response interface{}) error {
|
||||
jsonBytes, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -52,6 +52,13 @@ type RoomserverQueryAPIDatabase interface {
|
|||
// Remove a given room alias.
|
||||
// Returns an error if there was a problem talking to the database.
|
||||
RemoveRoomAlias(alias string) error
|
||||
// Lookup the join events for all members in a room as requested by a given
|
||||
// user. If the user is currently in the room, returns the room's current
|
||||
// members, if not returns an empty array (TODO: Fix it)
|
||||
// If the user requesting the list of members has never been in the room,
|
||||
// returns nil.
|
||||
// If there was an issue retrieving the events, returns an error.
|
||||
GetMembershipEvents(roomNID types.RoomNID, requestSenderUserID string) (events []types.Event, err error)
|
||||
}
|
||||
|
||||
// RoomserverQueryAPI is an implementation of api.RoomserverQueryAPI
|
||||
|
|
@ -182,6 +189,37 @@ func (r *RoomserverQueryAPI) loadEvents(eventNIDs []types.EventNID) ([]gomatrixs
|
|||
return result, nil
|
||||
}
|
||||
|
||||
// QueryMembershipsForRoom implements api.RoomserverQueryAPI
|
||||
func (r *RoomserverQueryAPI) QueryMembershipsForRoom(
|
||||
request *api.QueryMembershipsForRoomRequest,
|
||||
response *api.QueryMembershipsForRoomResponse,
|
||||
) error {
|
||||
roomNID, err := r.DB.RoomNID(request.RoomID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
events, err := r.DB.GetMembershipEvents(roomNID, request.Sender)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if events == nil {
|
||||
response.HasBeenInRoom = false
|
||||
response.JoinEvents = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
response.HasBeenInRoom = true
|
||||
response.JoinEvents = []gomatrixserverlib.ClientEvent{}
|
||||
for _, event := range events {
|
||||
clientEvent := gomatrixserverlib.ToClientEvent(event.Event, gomatrixserverlib.FormatAll)
|
||||
response.JoinEvents = append(response.JoinEvents, clientEvent)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetupHTTP adds the RoomserverQueryAPI handlers to the http.ServeMux.
|
||||
func (r *RoomserverQueryAPI) SetupHTTP(servMux *http.ServeMux) {
|
||||
servMux.Handle(
|
||||
|
|
@ -226,4 +264,18 @@ func (r *RoomserverQueryAPI) SetupHTTP(servMux *http.ServeMux) {
|
|||
return util.JSONResponse{Code: 200, JSON: &response}
|
||||
}),
|
||||
)
|
||||
servMux.Handle(
|
||||
api.RoomserverQueryMembershipsForRoomPath,
|
||||
common.MakeAPI("queryMembershipsForRoom", func(req *http.Request) util.JSONResponse {
|
||||
var request api.QueryMembershipsForRoomRequest
|
||||
var response api.QueryMembershipsForRoomResponse
|
||||
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
if err := r.QueryMembershipsForRoom(&request, &response); err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
return util.JSONResponse{Code: 200, JSON: &response}
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -508,18 +508,13 @@ func (u *membershipUpdater) SetToLeave(senderUserID string, eventID string) ([]s
|
|||
return inviteEventIDs, nil
|
||||
}
|
||||
|
||||
// GetMembershipEvents returns an array containing the join events for all
|
||||
// members in a room as requested by a given user. If the user is currently in
|
||||
// the room, returns the room's current members, if not returns an empty array
|
||||
// TODO: in this case, send the list of members as it was when the user left
|
||||
// If the user requesting the list of members has never been in the room, returns
|
||||
// nil.
|
||||
// If there was an issue retrieving the events, returns an error.
|
||||
// GetMembershipEvents implements query.RoomserverQueryAPIDB
|
||||
func (d *Database) GetMembershipEvents(roomNID types.RoomNID, requestSenderUserID string) (events []types.Event, err error) {
|
||||
txn, err := d.db.Begin()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer txn.Commit()
|
||||
|
||||
requestSenderUserNID, err := d.assignStateKeyNID(txn, requestSenderUserID)
|
||||
if err != nil {
|
||||
|
|
@ -550,6 +545,9 @@ func (d *Database) GetMembershipEvents(roomNID types.RoomNID, requestSenderUserI
|
|||
// only stores the latest join event NID for a given target user.
|
||||
// The solution would be to build the state of a room after before
|
||||
// the leave event and extract a members list from it.
|
||||
// For now, we return an empty slice so we know the user has been
|
||||
// in the room before.
|
||||
events = []types.Event{}
|
||||
}
|
||||
|
||||
return
|
||||
|
|
|
|||
Loading…
Reference in a new issue