Add get event federation API

This commit is contained in:
Erik Johnston 2017-09-05 10:58:34 +01:00
parent 643d05b157
commit 2d20c67f66
5 changed files with 135 additions and 2 deletions

View file

@ -16,6 +16,7 @@ package routing
import (
"net/http"
"time"
"github.com/gorilla/mux"
"github.com/matrix-org/dendrite/clientapi/producers"
@ -77,4 +78,14 @@ func Setup(
)
},
))
v1fedmux.Handle("/event/{eventID}", common.MakeFedAPI(
"federation_get_event", cfg.Matrix.ServerName, keys,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse {
vars := mux.Vars(httpReq)
return readers.GetEvent(
httpReq, request, cfg, query, time.Now(), keys, vars["eventID"],
)
},
))
}

View file

@ -136,6 +136,20 @@ type QueryInvitesForUserResponse struct {
InviteSenderUserIDs []string `json:"invite_sender_user_ids"`
}
// QueryServerAllowedToSeeEventRequest is a request to QueryServerAllowedToSeeEvent
type QueryServerAllowedToSeeEventRequest struct {
// The event ID to look up invites in.
EventID string `json:"event_id"`
// The server interested in the event
ServerName gomatrixserverlib.ServerName `json:"server_name"`
}
// QueryServerAllowedToSeeEventResponse is a response to QueryServerAllowedToSeeEvent
type QueryServerAllowedToSeeEventResponse struct {
// Wether the server in question is allowed to see the event
AllowedToSeeEvent bool `json:"can_see_event"`
}
// 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.
@ -167,6 +181,12 @@ type RoomserverQueryAPI interface {
request *QueryInvitesForUserRequest,
response *QueryInvitesForUserResponse,
) error
// Query whether a server is allowed to see an event
QueryServerAllowedToSeeEvent(
request *QueryServerAllowedToSeeEventRequest,
response *QueryServerAllowedToSeeEventResponse,
) error
}
// RoomserverQueryLatestEventsAndStatePath is the HTTP path for the QueryLatestEventsAndState API.
@ -184,6 +204,9 @@ const RoomserverQueryMembershipsForRoomPath = "/api/roomserver/queryMembershipsF
// RoomserverQueryInvitesForUserPath is the HTTP path for the QueryInvitesForUser API
const RoomserverQueryInvitesForUserPath = "/api/roomserver/queryInvitesForUser"
// RoomserverQueryServerAllowedToSeeEventPath is the HTTP path for the QueryServerAllowedToSeeEvent API
const RoomserverQueryServerAllowedToSeeEventPath = "/api/roomserver/queryServerAllowedToSeeEvent"
// 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 {
@ -243,6 +266,15 @@ func (h *httpRoomserverQueryAPI) QueryInvitesForUser(
return postJSON(h.httpClient, apiURL, request, response)
}
// QueryServerAllowedToSeeEvent implements RoomserverQueryAPI
func (h *httpRoomserverQueryAPI) QueryServerAllowedToSeeEvent(
request *QueryServerAllowedToSeeEventRequest,
response *QueryServerAllowedToSeeEventResponse,
) error {
apiURL := h.roomserverURL + RoomserverQueryServerAllowedToSeeEventPath
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 {

View file

@ -330,6 +330,58 @@ func (r *RoomserverQueryAPI) QueryInvitesForUser(
return nil
}
// QueryServerAllowedToSeeEvent implements api.RoomserverQueryAPI
func (r *RoomserverQueryAPI) QueryServerAllowedToSeeEvent(
request *api.QueryServerAllowedToSeeEventRequest,
response *api.QueryServerAllowedToSeeEventResponse,
) error {
stateEntries, err := state.LoadStateAtEvent(r.DB, request.EventID)
if err != nil {
return err
}
stateAtEvent, err := r.loadStateEvents(stateEntries)
if err != nil {
return err
}
// TODO: Should this be lifted out of here to a more general set of
// auth functions?
isInRoom := false
for _, ev := range stateAtEvent {
membership, err := ev.Membership()
if err != nil {
continue
}
if membership != "join" {
continue
}
stateKey := ev.StateKey()
if stateKey == nil {
continue
}
_, domain, err := gomatrixserverlib.SplitID('@', *stateKey)
if domain == request.ServerName {
isInRoom = true
break
}
}
if isInRoom {
response.AllowedToSeeEvent = true
return nil
}
// TODO: Check if history visibility is shared and if the server is currently in the room
response.AllowedToSeeEvent = false
return nil
}
// SetupHTTP adds the RoomserverQueryAPI handlers to the http.ServeMux.
func (r *RoomserverQueryAPI) SetupHTTP(servMux *http.ServeMux) {
servMux.Handle(
@ -402,4 +454,18 @@ func (r *RoomserverQueryAPI) SetupHTTP(servMux *http.ServeMux) {
return util.JSONResponse{Code: 200, JSON: &response}
}),
)
servMux.Handle(
api.RoomserverQueryServerAllowedToSeeEventPath,
common.MakeAPI("queryServerAllowedToSeeEvent", func(req *http.Request) util.JSONResponse {
var request api.QueryServerAllowedToSeeEventRequest
var response api.QueryServerAllowedToSeeEventResponse
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
return util.ErrorResponse(err)
}
if err := r.QueryServerAllowedToSeeEvent(&request, &response); err != nil {
return util.ErrorResponse(err)
}
return util.JSONResponse{Code: 200, JSON: &response}
}),
)
}

View file

@ -18,12 +18,13 @@ package state
import (
"fmt"
"sort"
"time"
"github.com/matrix-org/dendrite/roomserver/types"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
"github.com/prometheus/client_golang/prometheus"
"sort"
"time"
)
// A RoomStateDatabase has the storage APIs needed to load state from the database
@ -56,6 +57,8 @@ type RoomStateDatabase interface {
// Look up the Events for a list of numeric event IDs.
// Returns a sorted list of events.
Events(eventNIDs []types.EventNID) ([]types.Event, error)
// Look up snapshot NID for an event ID string
SnapshotNIDFromEventID(eventID string) (types.StateSnapshotNID, error)
}
// LoadStateAtSnapshot loads the full state of a room at a particular snapshot.
@ -96,6 +99,21 @@ func LoadStateAtSnapshot(db RoomStateDatabase, stateNID types.StateSnapshotNID)
return fullState, nil
}
// LoadStateAtEvent loads the full state of a room at a particular event.
func LoadStateAtEvent(db RoomStateDatabase, eventID string) ([]types.StateEntry, error) {
snapshotNID, err := db.SnapshotNIDFromEventID(eventID)
if err != nil {
return nil, err
}
stateEntries, err := LoadStateAtSnapshot(db, snapshotNID)
if err != nil {
return nil, err
}
return stateEntries, nil
}
// LoadCombinedStateAfterEvents loads a snapshot of the state after each of the events
// and combines those snapshots together into a single list.
func LoadCombinedStateAfterEvents(db RoomStateDatabase, prevStates []types.StateAtEvent) ([]types.StateEntry, error) {

View file

@ -226,6 +226,12 @@ func (d *Database) StateEntries(stateBlockNIDs []types.StateBlockNID) ([]types.S
return d.statements.bulkSelectStateBlockEntries(stateBlockNIDs)
}
// SnapshotNIDFromEventID implements state.RoomStateDatabase
func (d *Database) SnapshotNIDFromEventID(eventID string) (types.StateSnapshotNID, error) {
_, stateNID, err := d.statements.selectEvent(eventID)
return stateNID, err
}
// EventIDs implements input.RoomEventDatabase
func (d *Database) EventIDs(eventNIDs []types.EventNID) (map[types.EventNID]string, error) {
return d.statements.bulkSelectEventID(eventNIDs)