diff --git a/src/github.com/matrix-org/dendrite/federationapi/routing/routing.go b/src/github.com/matrix-org/dendrite/federationapi/routing/routing.go index 025089073..2f7530559 100644 --- a/src/github.com/matrix-org/dendrite/federationapi/routing/routing.go +++ b/src/github.com/matrix-org/dendrite/federationapi/routing/routing.go @@ -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"], + ) + }, + )) } diff --git a/src/github.com/matrix-org/dendrite/roomserver/api/query.go b/src/github.com/matrix-org/dendrite/roomserver/api/query.go index c26955ab1..41c7821d7 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/api/query.go +++ b/src/github.com/matrix-org/dendrite/roomserver/api/query.go @@ -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 { diff --git a/src/github.com/matrix-org/dendrite/roomserver/query/query.go b/src/github.com/matrix-org/dendrite/roomserver/query/query.go index cbbfa63a3..6d3be2037 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/query/query.go +++ b/src/github.com/matrix-org/dendrite/roomserver/query/query.go @@ -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} + }), + ) } diff --git a/src/github.com/matrix-org/dendrite/roomserver/state/state.go b/src/github.com/matrix-org/dendrite/roomserver/state/state.go index 3c2780aeb..0323be37d 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/state/state.go +++ b/src/github.com/matrix-org/dendrite/roomserver/state/state.go @@ -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) { diff --git a/src/github.com/matrix-org/dendrite/roomserver/storage/storage.go b/src/github.com/matrix-org/dendrite/roomserver/storage/storage.go index 8a0523e56..85c5160a8 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/storage/storage.go +++ b/src/github.com/matrix-org/dendrite/roomserver/storage/storage.go @@ -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)