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 f07da59e5..7ec6184e1 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/api/query.go +++ b/src/github.com/matrix-org/dendrite/roomserver/api/query.go @@ -117,6 +117,23 @@ type QueryMembershipsForRoomResponse struct { HasBeenInRoom bool `json:"has_been_in_room"` } +// QueryInvitesForUserRequest is a request to QueryInvitesForUser +type QueryInvitesForUserRequest struct { + // The room ID to look up invites in. + RoomID string `json:"room_id"` + // The User ID to look up invites for. + TargetUserID string `json:"target_user_id"` +} + +// QueryInvitesForUserResponse is a response to QueryInvitesForUser +// This is used when accepting an invite or rejecting a invite to tell which +// remote matrix servers to contact. +type QueryInvitesForUserResponse struct { + // A list of matrix user IDs for each sender of an active invite targeting + // the requested user ID. + InviteSenderUserIDs []string `json:"invite_sender_user_ids"` +} + // 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. @@ -142,6 +159,12 @@ type RoomserverQueryAPI interface { request *QueryMembershipsForRoomRequest, response *QueryMembershipsForRoomResponse, ) error + + // Query a list of invite event senders for a user in a room. + QueryInvitesForUser( + request *QueryInvitesForUserRequest, + response *QueryInvitesForUserResponse, + ) error } // RoomserverQueryLatestEventsAndStatePath is the HTTP path for the QueryLatestEventsAndState API. @@ -156,6 +179,9 @@ const RoomserverQueryEventsByIDPath = "/api/roomserver/queryEventsByID" // RoomserverQueryMembershipsForRoomPath is the HTTP path for the QueryMembershipsForRoom API const RoomserverQueryMembershipsForRoomPath = "/api/roomserver/queryMembershipsForRoom" +// RoomserverQueryInvitesForUserPath is the HTTP path for the QueryInvitesForUser API +const RoomserverQueryInvitesForUserPath = "/api/roomserver/queryInvitesForUser" + // 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 { @@ -206,6 +232,14 @@ func (h *httpRoomserverQueryAPI) QueryMembershipsForRoom( return postJSON(h.httpClient, apiURL, request, response) } +func (h *httpRoomserverQueryAPI) QueryInvitesForUser( + request *QueryInvitesForUserRequest, + response *QueryInvitesForUserResponse, +) error { + apiURL := h.roomserverURL + RoomserverQueryInvitesForUserPath + 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 84f5d44c3..768264938 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/query/query.go +++ b/src/github.com/matrix-org/dendrite/roomserver/query/query.go @@ -40,18 +40,6 @@ type RoomserverQueryAPIDatabase interface { // Lookup the numeric IDs for a list of events. // Returns an error if there was a problem talking to the database. EventNIDs(eventIDs []string) (map[string]types.EventNID, error) - // Save a given room alias with the room ID it refers to. - // Returns an error if there was a problem talking to the database. - SetRoomAlias(alias string, roomID string) error - // Lookup the room ID a given alias refers to. - // Returns an error if there was a problem talking to the database. - GetRoomIDFromAlias(alias string) (string, error) - // Lookup all aliases referring to a given room ID. - // Returns an error if there was a problem talking to the database. - GetAliasesFromRoomID(roomID string) ([]string, error) - // 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) @@ -59,6 +47,13 @@ type RoomserverQueryAPIDatabase interface { // returns nil. // If there was an issue retrieving the events, returns an error. GetMembershipEvents(roomNID types.RoomNID, requestSenderUserID string) (events []types.Event, err error) + // Lookup the active invites targeting a user in a room and return the + // numeric state key IDs for the user IDs who sent them. + // Returns an error if there was a problem talking to the database. + GetInvitesForUser(roomNID types.RoomNID, targetUserNID types.EventStateKeyNID) (senderUserNIDs []types.EventStateKeyNID, err error) + // Lookup the string event state keys for a list of numeric event state keys + // Returns an error if there was a problem talking to the database. + EventStateKeys([]types.EventStateKeyNID) (map[types.EventStateKeyNID]string, error) } // RoomserverQueryAPI is an implementation of api.RoomserverQueryAPI @@ -220,6 +215,39 @@ func (r *RoomserverQueryAPI) QueryMembershipsForRoom( return nil } +// QueryInvitesForUser implements api.RoomserverQueryAPI +func (r *RoomserverQueryAPI) QueryInvitesForUser( + request *api.QueryInvitesForUserRequest, + response *api.QueryInvitesForUserResponse, +) error { + roomNID, err := r.DB.RoomNID(request.RoomID) + if err != nil { + return err + } + + targetUserNIDs, err := r.DB.EventStateKeyNIDs([]string{request.TargetUserID}) + if err != nil { + return err + } + targetUserNID := targetUserNIDs[request.TargetUserID] + + senderUserNIDs, err := r.DB.GetInvitesForUser(roomNID, targetUserNID) + if err != nil { + return err + } + + senderUserIDs, err := r.DB.EventStateKeys(senderUserNIDs) + if err != nil { + return err + } + + for _, senderUserID := range senderUserIDs { + response.InviteSenderUserIDs = append(response.InviteSenderUserIDs, senderUserID) + } + + return nil +} + // SetupHTTP adds the RoomserverQueryAPI handlers to the http.ServeMux. func (r *RoomserverQueryAPI) SetupHTTP(servMux *http.ServeMux) { servMux.Handle( @@ -278,4 +306,18 @@ func (r *RoomserverQueryAPI) SetupHTTP(servMux *http.ServeMux) { return util.JSONResponse{Code: 200, JSON: &response} }), ) + servMux.Handle( + api.RoomserverQueryInvitesForUserPath, + common.MakeAPI("queryInvitesForUser", func(req *http.Request) util.JSONResponse { + var request api.QueryInvitesForUserRequest + var response api.QueryInvitesForUserResponse + if err := json.NewDecoder(req.Body).Decode(&request); err != nil { + return util.ErrorResponse(err) + } + if err := r.QueryInvitesForUser(&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/storage/storage.go b/src/github.com/matrix-org/dendrite/roomserver/storage/storage.go index fbbc723ee..c10d1f6fd 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/storage/storage.go +++ b/src/github.com/matrix-org/dendrite/roomserver/storage/storage.go @@ -161,7 +161,12 @@ func (d *Database) EventStateKeyNIDs(eventStateKeys []string) (map[string]types. return d.statements.bulkSelectEventStateKeyNID(eventStateKeys) } -// EventNIDs implements query.RoomQueryDatabase +// EventStateKeys implements query.RoomserverQueryAPIDatabase +func (d *Database) EventStateKeys(eventStateKeyNIDs []types.EventStateKeyNID) (map[types.EventStateKeyNID]string, error) { + return d.statements.bulkSelectEventStateKey(eventStateKeyNIDs) +} + +// EventNIDs implements query.RoomserverQueryAPIDatabase func (d *Database) EventNIDs(eventIDs []string) (map[string]types.EventNID, error) { return d.statements.bulkSelectEventNID(eventIDs) } @@ -353,6 +358,13 @@ func (d *Database) LatestEventIDs(roomNID types.RoomNID) ([]gomatrixserverlib.Ev return references, currentStateSnapshotNID, depth, nil } +// GetInvitesForUser implements query.RoomserverQueryAPIDB +func (d *Database) GetInvitesForUser( + roomNID types.RoomNID, targetUserNID types.EventStateKeyNID, +) (senderUserIDs []types.EventStateKeyNID, err error) { + return d.statements.selectInviteActiveForUserInRoom(targetUserNID, roomNID) +} + // SetRoomAlias implements alias.RoomserverAliasAPIDB func (d *Database) SetRoomAlias(alias string, roomID string) error { return d.statements.insertRoomAlias(alias, roomID)