mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-13 01:43:09 -06:00
Add the /joined_rooms API
This commit is contained in:
parent
d2ae425752
commit
0b169f9a2f
|
|
@ -30,6 +30,10 @@ type response struct {
|
|||
Chunk []gomatrixserverlib.ClientEvent `json:"chunk"`
|
||||
}
|
||||
|
||||
type joinedResponse struct {
|
||||
JoinedRooms []string `json:"joined_rooms,flow"`
|
||||
}
|
||||
|
||||
// GetMemberships implements GET /rooms/{roomId}/members
|
||||
func GetMemberships(
|
||||
req *http.Request, device *authtypes.Device, roomID string, joinedOnly bool,
|
||||
|
|
@ -58,3 +62,24 @@ func GetMemberships(
|
|||
JSON: response{queryRes.JoinEvents},
|
||||
}
|
||||
}
|
||||
|
||||
// GetJoinedRooms implements GET /joined_rooms
|
||||
func GetJoinedRooms(
|
||||
req *http.Request, device *authtypes.Device,
|
||||
_ config.Dendrite,
|
||||
queryAPI api.RoomserverQueryAPI,
|
||||
) util.JSONResponse {
|
||||
queryReq := api.QueryRoomsForUserRequest{
|
||||
UserID: device.UserID,
|
||||
Membership:"join",
|
||||
}
|
||||
var queryRes api.QueryRoomsForUserResponse
|
||||
if err := queryAPI.QueryRoomsForUser(req.Context(), &queryReq, &queryRes); err != nil {
|
||||
return httputil.LogThenError(req, err)
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: joinedResponse{queryRes.RoomIDs},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -344,6 +344,12 @@ func Setup(
|
|||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
||||
r0mux.Handle("/joined_rooms",
|
||||
common.MakeAuthAPI("joined_rooms", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||
return GetJoinedRooms(req, device, cfg, queryAPI)
|
||||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
||||
r0mux.Handle("/rooms/{roomID}/read_markers",
|
||||
common.MakeExternalAPI("rooms_read_markers", func(req *http.Request) util.JSONResponse {
|
||||
// TODO: return the read_markers.
|
||||
|
|
|
|||
|
|
@ -138,6 +138,20 @@ type QueryMembershipsForRoomResponse struct {
|
|||
HasBeenInRoom bool `json:"has_been_in_room"`
|
||||
}
|
||||
|
||||
// QueryRoomsForUserRequest is a request to QueryRoomsForUser
|
||||
type QueryRoomsForUserRequest struct {
|
||||
// The ID of the user sending the request
|
||||
UserID string `json:"user_id"`
|
||||
// The membership state to be queried for
|
||||
Membership string `json:"membership"`
|
||||
}
|
||||
|
||||
// QueryRoomsForUserResponse is a response to QueryRoomsForUser
|
||||
type QueryRoomsForUserResponse struct {
|
||||
// The room IDs that match the user ID and membership requested
|
||||
RoomIDs []string `json:"room_ids,flow"`
|
||||
}
|
||||
|
||||
// QueryInvitesForUserRequest is a request to QueryInvitesForUser
|
||||
type QueryInvitesForUserRequest struct {
|
||||
// The room ID to look up invites in.
|
||||
|
|
@ -251,6 +265,13 @@ type RoomserverQueryAPI interface {
|
|||
response *QueryMembershipsForRoomResponse,
|
||||
) error
|
||||
|
||||
// Query a list of rooms the user has membership in
|
||||
QueryRoomsForUser(
|
||||
ctx context.Context,
|
||||
request *QueryRoomsForUserRequest,
|
||||
response *QueryRoomsForUserResponse,
|
||||
) error
|
||||
|
||||
// Query a list of invite event senders for a user in a room.
|
||||
QueryInvitesForUser(
|
||||
ctx context.Context,
|
||||
|
|
@ -297,6 +318,9 @@ const RoomserverQueryMembershipForUserPath = "/api/roomserver/queryMembershipFor
|
|||
// RoomserverQueryMembershipsForRoomPath is the HTTP path for the QueryMembershipsForRoom API
|
||||
const RoomserverQueryMembershipsForRoomPath = "/api/roomserver/queryMembershipsForRoom"
|
||||
|
||||
// RoomserverQueryRoomsForUserPath is the HTTP path for the QueryRoomsForUser API
|
||||
const RoomserverQueryRoomsForUserPath = "/api/roomserver/queryRoomsForUser"
|
||||
|
||||
// RoomserverQueryInvitesForUserPath is the HTTP path for the QueryInvitesForUser API
|
||||
const RoomserverQueryInvitesForUserPath = "/api/roomserver/queryInvitesForUser"
|
||||
|
||||
|
|
@ -388,6 +412,18 @@ func (h *httpRoomserverQueryAPI) QueryMembershipsForRoom(
|
|||
return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
|
||||
}
|
||||
|
||||
func (h *httpRoomserverQueryAPI) QueryRoomsForUser(
|
||||
ctx context.Context,
|
||||
request *QueryRoomsForUserRequest,
|
||||
response *QueryRoomsForUserResponse,
|
||||
) error {
|
||||
span, ctx := opentracing.StartSpanFromContext(ctx, "QueryRoomsForUser")
|
||||
defer span.Finish()
|
||||
|
||||
apiURL := h.roomserverURL + RoomserverQueryRoomsForUserPath
|
||||
return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
|
||||
}
|
||||
|
||||
// QueryInvitesForUser implements RoomserverQueryAPI
|
||||
func (h *httpRoomserverQueryAPI) QueryInvitesForUser(
|
||||
ctx context.Context,
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ type RoomserverQueryAPIDatabase interface {
|
|||
// Returns 0 if the room doesn't exists.
|
||||
// Returns an error if there was a problem talking to the database.
|
||||
RoomNID(ctx context.Context, roomID string) (types.RoomNID, error)
|
||||
// Look up the room IDs corresponding to the room numeric IDs
|
||||
// Returns an error if there was a problem talking to the database.
|
||||
GetRoomIDs(ctx context.Context, roomNIDs []types.RoomNID) ([]string, error)
|
||||
// Look up event references for the latest events in the room and the current state snapshot.
|
||||
// Returns the latest events, the current state and the maximum depth of the latest events plus 1.
|
||||
// Returns an error if there was a problem talking to the database.
|
||||
|
|
@ -72,6 +75,11 @@ type RoomserverQueryAPIDatabase interface {
|
|||
GetMembershipEventNIDsForRoom(
|
||||
ctx context.Context, roomNID types.RoomNID, joinOnly bool,
|
||||
) ([]types.EventNID, error)
|
||||
// Lookup the rooms for which a user has a particular membership state.
|
||||
// Returns an error if there was a problem talkign to the database.
|
||||
GetRoomsForUserMembership(
|
||||
ctx context.Context, userNID types.EventStateKeyNID, membership string,
|
||||
) ([]types.RoomNID, error)
|
||||
// Look up 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.
|
||||
|
|
@ -367,6 +375,32 @@ func (r *RoomserverQueryAPI) getMembershipsBeforeEventNID(
|
|||
return events, nil
|
||||
}
|
||||
|
||||
// QueryRoomsForUser implements api.RoomserverQueryAPI
|
||||
func (r *RoomserverQueryAPI) QueryRoomsForUser(
|
||||
ctx context.Context,
|
||||
request *api.QueryRoomsForUserRequest,
|
||||
response *api.QueryRoomsForUserResponse,
|
||||
) error {
|
||||
targetUserNIDs, err := r.DB.EventStateKeyNIDs(ctx, []string{request.UserID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
targetUserNID := targetUserNIDs[request.UserID]
|
||||
|
||||
roomNIDs, err := r.DB.GetRoomsForUserMembership(ctx, targetUserNID, request.Membership)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
roomIDs, err := r.DB.GetRoomIDs(ctx, roomNIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
response.RoomIDs = roomIDs
|
||||
return nil
|
||||
}
|
||||
|
||||
// QueryInvitesForUser implements api.RoomserverQueryAPI
|
||||
func (r *RoomserverQueryAPI) QueryInvitesForUser(
|
||||
ctx context.Context,
|
||||
|
|
@ -652,6 +686,20 @@ func (r *RoomserverQueryAPI) SetupHTTP(servMux *http.ServeMux) {
|
|||
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
|
||||
}),
|
||||
)
|
||||
servMux.Handle(
|
||||
api.RoomserverQueryRoomsForUserPath,
|
||||
common.MakeInternalAPI("queryRoomsForUser", func(req *http.Request) util.JSONResponse {
|
||||
var request api.QueryRoomsForUserRequest
|
||||
var response api.QueryRoomsForUserResponse
|
||||
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
if err := r.QueryRoomsForUser(req.Context(), &request, &response); err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
|
||||
}),
|
||||
)
|
||||
servMux.Handle(
|
||||
api.RoomserverQueryInvitesForUserPath,
|
||||
common.MakeInternalAPI("queryInvitesForUser", func(req *http.Request) util.JSONResponse {
|
||||
|
|
|
|||
|
|
@ -89,12 +89,17 @@ const updateMembershipSQL = "" +
|
|||
"UPDATE roomserver_membership SET sender_nid = $3, membership_nid = $4, event_nid = $5" +
|
||||
" WHERE room_nid = $1 AND target_nid = $2"
|
||||
|
||||
const selectRoomsForUserMembershipSQL = "" +
|
||||
"SELECT room_nid FROM roomserver_membership" +
|
||||
" WHERE target_nid = $1 AND membership_nid = $2"
|
||||
|
||||
type membershipStatements struct {
|
||||
insertMembershipStmt *sql.Stmt
|
||||
selectMembershipForUpdateStmt *sql.Stmt
|
||||
selectMembershipFromRoomAndTargetStmt *sql.Stmt
|
||||
selectMembershipsFromRoomAndMembershipStmt *sql.Stmt
|
||||
selectMembershipsFromRoomStmt *sql.Stmt
|
||||
selectRoomsForUserMembershipStmt *sql.Stmt
|
||||
updateMembershipStmt *sql.Stmt
|
||||
}
|
||||
|
||||
|
|
@ -110,6 +115,7 @@ func (s *membershipStatements) prepare(db *sql.DB) (err error) {
|
|||
{&s.selectMembershipFromRoomAndTargetStmt, selectMembershipFromRoomAndTargetSQL},
|
||||
{&s.selectMembershipsFromRoomAndMembershipStmt, selectMembershipsFromRoomAndMembershipSQL},
|
||||
{&s.selectMembershipsFromRoomStmt, selectMembershipsFromRoomSQL},
|
||||
{&s.selectRoomsForUserMembershipStmt, selectRoomsForUserMembershipSQL},
|
||||
{&s.updateMembershipStmt, updateMembershipSQL},
|
||||
}.prepare(db)
|
||||
}
|
||||
|
|
@ -180,6 +186,26 @@ func (s *membershipStatements) selectMembershipsFromRoomAndMembership(
|
|||
return
|
||||
}
|
||||
|
||||
func (s *membershipStatements) selectRoomsForUserMembership(
|
||||
ctx context.Context,
|
||||
targetUserNID types.EventStateKeyNID, membership membershipState,
|
||||
) (roomNIDs []types.RoomNID, err error) {
|
||||
stmt := s.selectRoomsForUserMembershipStmt
|
||||
rows, err := stmt.QueryContext(ctx, targetUserNID, membership)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
var rNID types.RoomNID
|
||||
if err = rows.Scan(&rNID); err != nil {
|
||||
return
|
||||
}
|
||||
roomNIDs = append(roomNIDs, rNID)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *membershipStatements) updateMembership(
|
||||
ctx context.Context,
|
||||
txn *sql.Tx, roomNID types.RoomNID, targetUserNID types.EventStateKeyNID,
|
||||
|
|
|
|||
|
|
@ -51,6 +51,9 @@ const insertRoomNIDSQL = "" +
|
|||
const selectRoomNIDSQL = "" +
|
||||
"SELECT room_nid FROM roomserver_rooms WHERE room_id = $1"
|
||||
|
||||
const selectRoomIDSQL = "" +
|
||||
"SELECT room_id FROM roomserver_rooms WHERE room_nid = $1"
|
||||
|
||||
const selectLatestEventNIDsSQL = "" +
|
||||
"SELECT latest_event_nids, state_snapshot_nid FROM roomserver_rooms WHERE room_nid = $1"
|
||||
|
||||
|
|
@ -63,6 +66,7 @@ const updateLatestEventNIDsSQL = "" +
|
|||
type roomStatements struct {
|
||||
insertRoomNIDStmt *sql.Stmt
|
||||
selectRoomNIDStmt *sql.Stmt
|
||||
selectRoomIDStmt *sql.Stmt
|
||||
selectLatestEventNIDsStmt *sql.Stmt
|
||||
selectLatestEventNIDsForUpdateStmt *sql.Stmt
|
||||
updateLatestEventNIDsStmt *sql.Stmt
|
||||
|
|
@ -76,6 +80,7 @@ func (s *roomStatements) prepare(db *sql.DB) (err error) {
|
|||
return statementList{
|
||||
{&s.insertRoomNIDStmt, insertRoomNIDSQL},
|
||||
{&s.selectRoomNIDStmt, selectRoomNIDSQL},
|
||||
{&s.selectRoomIDStmt, selectRoomIDSQL},
|
||||
{&s.selectLatestEventNIDsStmt, selectLatestEventNIDsSQL},
|
||||
{&s.selectLatestEventNIDsForUpdateStmt, selectLatestEventNIDsForUpdateSQL},
|
||||
{&s.updateLatestEventNIDsStmt, updateLatestEventNIDsSQL},
|
||||
|
|
@ -100,6 +105,15 @@ func (s *roomStatements) selectRoomNID(
|
|||
return types.RoomNID(roomNID), err
|
||||
}
|
||||
|
||||
func (s *roomStatements) selectRoomID(
|
||||
ctx context.Context, txn *sql.Tx, roomNID types.RoomNID,
|
||||
) (string, error) {
|
||||
var roomID string
|
||||
stmt := common.TxStmt(txn, s.selectRoomIDStmt)
|
||||
err := stmt.QueryRowContext(ctx, roomNID).Scan(&roomID)
|
||||
return roomID, err
|
||||
}
|
||||
|
||||
func (s *roomStatements) selectLatestEventNIDs(
|
||||
ctx context.Context, roomNID types.RoomNID,
|
||||
) ([]types.EventNID, types.StateSnapshotNID, error) {
|
||||
|
|
|
|||
|
|
@ -412,6 +412,21 @@ func (d *Database) RoomNID(ctx context.Context, roomID string) (types.RoomNID, e
|
|||
return roomNID, err
|
||||
}
|
||||
|
||||
func (d *Database) GetRoomIDs(ctx context.Context, roomNIDs []types.RoomNID) ([]string, error) {
|
||||
roomIDs := make([]string, 0)
|
||||
|
||||
for _, nid := range roomNIDs {
|
||||
roomID, err := d.statements.selectRoomID(ctx, nil, nid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
roomIDs = append(roomIDs, roomID)
|
||||
}
|
||||
|
||||
return roomIDs, nil
|
||||
}
|
||||
|
||||
// LatestEventIDs implements query.RoomserverQueryAPIDatabase
|
||||
func (d *Database) LatestEventIDs(
|
||||
ctx context.Context, roomNID types.RoomNID,
|
||||
|
|
@ -431,6 +446,20 @@ func (d *Database) LatestEventIDs(
|
|||
return references, currentStateSnapshotNID, depth, nil
|
||||
}
|
||||
|
||||
func (d *Database) GetRoomsForUserMembership(
|
||||
ctx context.Context,
|
||||
userNID types.EventStateKeyNID,
|
||||
membership string,
|
||||
) (roomNIDs []types.RoomNID, err error) {
|
||||
membershipNID := membershipStateLeaveOrBan
|
||||
if membership == "join" {
|
||||
membershipNID = membershipStateJoin
|
||||
} else if membership == "invite" {
|
||||
membershipNID = membershipStateInvite
|
||||
}
|
||||
return d.statements.selectRoomsForUserMembership(ctx, userNID, membershipNID)
|
||||
}
|
||||
|
||||
// GetInvitesForUser implements query.RoomserverQueryAPIDatabase
|
||||
func (d *Database) GetInvitesForUser(
|
||||
ctx context.Context,
|
||||
|
|
|
|||
Loading…
Reference in a new issue