diff --git a/src/github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/membership_table.go b/src/github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/membership_table.go index 70affdc33..f11193d82 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/membership_table.go +++ b/src/github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/membership_table.go @@ -50,6 +50,9 @@ const selectMembershipSQL = "" + const selectMembershipsByLocalpartSQL = "" + "SELECT room_id, event_id FROM memberships WHERE localpart = $1" +const selectMembershipsByRoomIDSQL = "" + + "SELECT localpart, event_id FROM memberships WHERE room_id = $1" + const deleteMembershipsByEventIDsSQL = "" + "DELETE FROM memberships WHERE event_id = ANY($1)" @@ -61,6 +64,7 @@ type membershipStatements struct { insertMembershipStmt *sql.Stmt selectMembershipByEventIDStmt *sql.Stmt selectMembershipsByLocalpartStmt *sql.Stmt + selectMembershipsByRoomIDStmt *sql.Stmt updateMembershipByEventIDStmt *sql.Stmt } @@ -78,6 +82,9 @@ func (s *membershipStatements) prepare(db *sql.DB) (err error) { if s.selectMembershipsByLocalpartStmt, err = db.Prepare(selectMembershipsByLocalpartSQL); err != nil { return } + if s.selectMembershipsByRoomIDStmt, err = db.Prepare(selectMembershipsByRoomIDSQL); err != nil { + return + } if s.updateMembershipByEventIDStmt, err = db.Prepare(updateMembershipByEventIDSQL); err != nil { return } @@ -115,6 +122,27 @@ func (s *membershipStatements) selectMembershipsByLocalpart(localpart string) (m return } +func (s *membershipStatements) selectMembershipsByRoomID(roomID string) (memberships []authtypes.Membership, err error) { + rows, err := s.selectMembershipsByRoomIDStmt.Query(roomID) + if err != nil { + return + } + + memberships = []authtypes.Membership{} + + defer rows.Close() + for rows.Next() { + var m authtypes.Membership + m.RoomID = roomID + if err := rows.Scan(&m.Localpart, &m.EventID); err != nil { + return nil, err + } + memberships = append(memberships, m) + } + + return +} + func (s *membershipStatements) updateMembershipByEventID(oldEventID string, newEventID string) (err error) { _, err = s.updateMembershipByEventIDStmt.Exec(oldEventID, newEventID) return diff --git a/src/github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/storage.go b/src/github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/storage.go index ca9deac09..eec3011e8 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/storage.go +++ b/src/github.com/matrix-org/dendrite/clientapi/auth/storage/accounts/storage.go @@ -156,14 +156,22 @@ func (d *Database) UpdateMemberships(eventsToAdd []gomatrixserverlib.Event, idsT }) } -// GetMembershipsByLocalpart returns an array containing the IDs of all the rooms -// a user matching a given localpart is a member of +// GetMembershipsByLocalpart returns an array containing the memberships for all +// the rooms a user matching a given localpart is a member of // If no membership match the given localpart, returns an empty array // If there was an issue during the retrieval, returns the SQL error func (d *Database) GetMembershipsByLocalpart(localpart string) (memberships []authtypes.Membership, err error) { return d.memberships.selectMembershipsByLocalpart(localpart) } +// GetMembershipsByRoomID returns an array containing the memberships for all +// the users that are member of a given room +// If no membership match the given localpart, returns an empty array +// If there was an issue during the retrieval, returns the SQL error +func (d *Database) GetMembershipsByRoomID(roomID string) (memberships []authtypes.Membership, err error) { + return d.memberships.selectMembershipsByRoomID(roomID) +} + // UpdateMembership update the "join" membership event ID of a membership. // This is useful in case of membership upgrade (e.g. profile update) // If there was an issue during the update, returns the SQL error diff --git a/src/github.com/matrix-org/dendrite/clientapi/readers/memberships.go b/src/github.com/matrix-org/dendrite/clientapi/readers/memberships.go new file mode 100644 index 000000000..f4f209447 --- /dev/null +++ b/src/github.com/matrix-org/dendrite/clientapi/readers/memberships.go @@ -0,0 +1,64 @@ +// Copyright 2017 Vector Creations Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package readers + +import ( + "net/http" + + "github.com/matrix-org/dendrite/clientapi/auth/storage/accounts" + "github.com/matrix-org/dendrite/clientapi/httputil" + "github.com/matrix-org/dendrite/roomserver/api" + "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/util" +) + +// GetMemberships implements GET /rooms/{roomId}/members +func GetMemberships( + req *http.Request, roomID string, accountDB *accounts.Database, + queryAPI api.RoomserverQueryAPI, +) util.JSONResponse { + // TODO: Check if the user is or has been in the room, and respond with + // M_FORBIDDEN if not. If the user has been in the room before but isn't + // anymore, send the members list as it was before they left. + + memberships, err := accountDB.GetMembershipsByRoomID(roomID) + if err != nil { + return httputil.LogThenError(req, err) + } + + eventIDs := []string{} + for _, membership := range memberships { + eventIDs = append(eventIDs, membership.EventID) + } + + queryReq := api.QueryEventsByIDRequest{ + EventIDs: eventIDs, + } + var queryRes api.QueryEventsByIDResponse + if err := queryAPI.QueryEventsByID(&queryReq, &queryRes); err != nil { + return httputil.LogThenError(req, err) + } + + events := []gomatrixserverlib.ClientEvent{} + for _, event := range queryRes.Events { + ev := gomatrixserverlib.ToClientEvent(event, gomatrixserverlib.FormatAll) + events = append(events, ev) + } + + return util.JSONResponse{ + Code: 200, + JSON: events, + } +} 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 aeb231645..0302a6400 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/routing/routing.go +++ b/src/github.com/matrix-org/dendrite/clientapi/routing/routing.go @@ -303,6 +303,13 @@ 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, vars["roomID"], accountDB, queryAPI) + }), + ) + r0mux.Handle("/rooms/{roomID}/read_markers", common.MakeAPI("rooms_read_markers", func(req *http.Request) util.JSONResponse { // TODO: return the read_markers.