diff --git a/src/github.com/matrix-org/dendrite/clientapi/readers/memberships.go b/src/github.com/matrix-org/dendrite/clientapi/readers/memberships.go index 9d7519ee7..530dbe73a 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/readers/memberships.go +++ b/src/github.com/matrix-org/dendrite/clientapi/readers/memberships.go @@ -33,13 +33,14 @@ type response struct { // GetMemberships implements GET /rooms/{roomId}/members func GetMemberships( - req *http.Request, device *authtypes.Device, roomID string, + req *http.Request, device *authtypes.Device, roomID string, joinedOnly bool, accountDB *accounts.Database, cfg config.Dendrite, queryAPI api.RoomserverQueryAPI, ) util.JSONResponse { queryReq := api.QueryMembershipsForRoomRequest{ - RoomID: roomID, - Sender: device.UserID, + JoinedOnly: joinedOnly, + RoomID: roomID, + Sender: device.UserID, } var queryRes api.QueryMembershipsForRoomResponse if err := queryAPI.QueryMembershipsForRoom(&queryReq, &queryRes); err != nil { diff --git a/src/github.com/matrix-org/dendrite/clientapi/routing/routing.go b/src/github.com/matrix-org/dendrite/clientapi/routing/routing.go index 32301c784..7a1078f18 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/routing/routing.go +++ b/src/github.com/matrix-org/dendrite/clientapi/routing/routing.go @@ -302,7 +302,14 @@ func Setup( r0mux.Handle("/rooms/{roomID}/members", common.MakeAuthAPI("rooms_members", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse { vars := mux.Vars(req) - return readers.GetMemberships(req, device, vars["roomID"], accountDB, cfg, queryAPI) + return readers.GetMemberships(req, device, vars["roomID"], false, accountDB, cfg, queryAPI) + }), + ) + + r0mux.Handle("/rooms/{roomID}/joined_members", + common.MakeAuthAPI("rooms_members", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse { + vars := mux.Vars(req) + return readers.GetMemberships(req, device, vars["roomID"], true, accountDB, cfg, queryAPI) }), ) 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 e9573d1b4..c26955ab1 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/api/query.go +++ b/src/github.com/matrix-org/dendrite/roomserver/api/query.go @@ -102,6 +102,8 @@ type QueryEventsByIDResponse struct { // QueryMembershipsForRoomRequest is a request to QueryMembershipsForRoom type QueryMembershipsForRoomRequest struct { + // If true, only returns the membership events of "join" membership + JoinedOnly bool `json:"joined_only"` // ID of the room to fetch memberships from RoomID string `json:"room_id"` // ID of the user sending the request 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 56e605604..cbbfa63a3 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/query/query.go +++ b/src/github.com/matrix-org/dendrite/roomserver/query/query.go @@ -49,10 +49,11 @@ type RoomserverQueryAPIDatabase interface { // false if not. // Returns an error if there was a problem talking to the database. GetMembership(roomNID types.RoomNID, requestSenderUserID string) (membershipEventNID types.EventNID, stillInRoom bool, err error) - // Lookup the "join" membership event numeric IDs for all user that are - // currently members of a given room. + // Lookup the membership event numeric IDs for all user that are or have + // been members of a given room. Only lookup events of "join" membership if + // joinOnly is set to true. // Returns an error if there was a problem talking to the database. - GetJoinMembershipEventNIDsForRoom(roomNID types.RoomNID) ([]types.EventNID, error) + GetMembershipEventNIDsForRoom(roomNID types.RoomNID, joinOnly bool) ([]types.EventNID, 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. @@ -217,14 +218,14 @@ func (r *RoomserverQueryAPI) QueryMembershipsForRoom( var events []types.Event if stillInRoom { var eventNIDs []types.EventNID - eventNIDs, err = r.DB.GetJoinMembershipEventNIDsForRoom(roomNID) + eventNIDs, err = r.DB.GetMembershipEventNIDsForRoom(roomNID, request.JoinedOnly) if err != nil { return err } events, err = r.DB.Events(eventNIDs) } else { - events, err = r.getMembershipsBeforeEventNID(membershipEventNID) + events, err = r.getMembershipsBeforeEventNID(membershipEventNID, request.JoinedOnly) } if err != nil { @@ -243,7 +244,7 @@ func (r *RoomserverQueryAPI) QueryMembershipsForRoom( // of the event's room as it was when this event was fired, then filters the state events to // only keep the "m.room.member" events with a "join" membership. These events are returned. // Returns an error if there was an issue fetching the events. -func (r *RoomserverQueryAPI) getMembershipsBeforeEventNID(eventNID types.EventNID) ([]types.Event, error) { +func (r *RoomserverQueryAPI) getMembershipsBeforeEventNID(eventNID types.EventNID, joinedOnly bool) ([]types.Event, error) { events := []types.Event{} // Lookup the event NID eIDs, err := r.DB.EventIDs([]types.EventNID{eventNID}) @@ -277,6 +278,10 @@ func (r *RoomserverQueryAPI) getMembershipsBeforeEventNID(eventNID types.EventNI return nil, err } + if !joinedOnly { + return stateEvents, nil + } + // Filter the events to only keep the "join" membership events for _, event := range stateEvents { membership, err := event.Membership() diff --git a/src/github.com/matrix-org/dendrite/roomserver/storage/membership_table.go b/src/github.com/matrix-org/dendrite/roomserver/storage/membership_table.go index 6edc7a528..5db772aad 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/storage/membership_table.go +++ b/src/github.com/matrix-org/dendrite/roomserver/storage/membership_table.go @@ -77,7 +77,7 @@ const selectMembershipsFromRoomAndMembershipSQL = "" + " WHERE room_nid = $1 AND membership_nid = $2" const selectMembershipsFromRoomSQL = "" + - "SELECT membership_nid, event_nid FROM roomserver_membership" + + "SELECT event_nid FROM roomserver_membership" + " WHERE room_nid = $1" const selectMembershipForUpdateSQL = "" + @@ -140,20 +140,18 @@ func (s *membershipStatements) selectMembershipFromRoomAndTarget( func (s *membershipStatements) selectMembershipsFromRoom( roomNID types.RoomNID, -) (eventNIDs map[types.EventNID]membershipState, err error) { +) (eventNIDs []types.EventNID, err error) { rows, err := s.selectMembershipsFromRoomStmt.Query(roomNID) if err != nil { return } - eventNIDs = make(map[types.EventNID]membershipState) for rows.Next() { var eNID types.EventNID - var membership membershipState - if err = rows.Scan(&membership, &eNID); err != nil { + if err = rows.Scan(&eNID); err != nil { return } - eventNIDs[eNID] = membership + eventNIDs = append(eventNIDs, eNID) } return } 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 a3076e0b5..8a0523e56 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/storage/storage.go +++ b/src/github.com/matrix-org/dendrite/roomserver/storage/storage.go @@ -576,9 +576,13 @@ func (d *Database) GetMembership(roomNID types.RoomNID, requestSenderUserID stri return senderMembershipEventNID, senderMembership == membershipStateJoin, nil } -// GetJoinMembershipEventNIDsForRoom implements query.RoomserverQueryAPIDB -func (d *Database) GetJoinMembershipEventNIDsForRoom(roomNID types.RoomNID) ([]types.EventNID, error) { - return d.statements.selectMembershipsFromRoomAndMembership(roomNID, membershipStateJoin) +// GetMembershipEventNIDsForRoom implements query.RoomserverQueryAPIDB +func (d *Database) GetMembershipEventNIDsForRoom(roomNID types.RoomNID, joinOnly bool) ([]types.EventNID, error) { + if joinOnly { + return d.statements.selectMembershipsFromRoomAndMembership(roomNID, membershipStateJoin) + } + + return d.statements.selectMembershipsFromRoom(roomNID) } type transaction struct {