WIP: Make room members filterable

This commit is contained in:
Alex Chan 2021-06-22 14:26:31 -04:00
parent 3a77bca28b
commit e50dbe61be
8 changed files with 76 additions and 16 deletions

View file

@ -51,16 +51,47 @@ type databaseJoinedMember struct {
AvatarURL string `json:"avatar_url"` AvatarURL string `json:"avatar_url"`
} }
// // MembershipFilter is an enum representing kinds of membership to a room
// type MembershipFilter string
// const (
// MembershipDefault MembershipFilter = "none"
// MembershipJoin MembershipFilter = "join"
// MembershipInvite MembershipFilter = "invite"
// MembershipLeave MembershipFilter = "leave"
// MembershipBan MembershipFilter = "ban"
// )
// GetMemberships implements GET /rooms/{roomId}/members // GetMemberships implements GET /rooms/{roomId}/members
func GetMemberships( func GetMemberships(
req *http.Request, device *userapi.Device, roomID string, joinedOnly bool, req *http.Request, device *userapi.Device, roomID string, joinedOnly bool,
_ *config.ClientAPI, _ *config.ClientAPI,
rsAPI api.RoomserverInternalAPI, rsAPI api.RoomserverInternalAPI,
) util.JSONResponse { ) util.JSONResponse {
// how would i unpack this nicely into
// type queryParams struct {
// membership string
// notMembership string
// }
membership := req.URL.Query().Get("membership")
notMembership := req.URL.Query().Get("not_membership")
membershipStatusFilter := []string{"join", "invite", "leave", "ban"}
if len(notMembership) > 0 {
for i, v := range membershipStatusFilter {
if v == notMembership {
membershipStatusFilter = append(membershipStatusFilter[:i], membershipStatusFilter[i+1:]...)
}
}
} else if len(membership) > 0 {
membershipStatusFilter = []string{membership}
} else {
membershipStatusFilter = []string{}
}
queryReq := api.QueryMembershipsForRoomRequest{ queryReq := api.QueryMembershipsForRoomRequest{
JoinedOnly: joinedOnly, JoinedOnly: joinedOnly,
RoomID: roomID, MembershipStatusFilter: membershipStatusFilter,
Sender: device.UserID, RoomID: roomID,
Sender: device.UserID,
} }
var queryRes api.QueryMembershipsForRoomResponse var queryRes api.QueryMembershipsForRoomResponse
if err := rsAPI.QueryMembershipsForRoom(req.Context(), &queryReq, &queryRes); err != nil { if err := rsAPI.QueryMembershipsForRoom(req.Context(), &queryReq, &queryRes); err != nil {

View file

@ -148,7 +148,8 @@ type QueryMembershipForUserResponse struct {
// QueryMembershipsForRoomRequest is a request to QueryMembershipsForRoom // QueryMembershipsForRoomRequest is a request to QueryMembershipsForRoom
type QueryMembershipsForRoomRequest struct { type QueryMembershipsForRoomRequest struct {
// If true, only returns the membership events of "join" membership // If true, only returns the membership events of "join" membership
JoinedOnly bool `json:"joined_only"` JoinedOnly bool `json:"joined_only"`
MembershipStatusFilter []string `json:"membership_status_filter"`
// ID of the room to fetch memberships from // ID of the room to fetch memberships from
RoomID string `json:"room_id"` RoomID string `json:"room_id"`
// Optional - ID of the user sending the request, for checking if the // Optional - ID of the user sending the request, for checking if the

View file

@ -59,7 +59,7 @@ func IsServerCurrentlyInRoom(ctx context.Context, db storage.Database, serverNam
return false, fmt.Errorf("unknown room %s", roomID) return false, fmt.Errorf("unknown room %s", roomID)
} }
eventNIDs, err := db.GetMembershipEventNIDsForRoom(ctx, info.RoomNID, true, false) eventNIDs, err := db.GetMembershipEventNIDsForRoom(ctx, info.RoomNID, []string{"join"}, false)
if err != nil { if err != nil {
return false, err return false, err
} }

View file

@ -256,7 +256,7 @@ func (r *Inputer) calculateAndSetState(
stateAtEvent.Overwrite = true stateAtEvent.Overwrite = true
var joinEventNIDs []types.EventNID var joinEventNIDs []types.EventNID
// Request join memberships only for local users only. // Request join memberships only for local users only.
if joinEventNIDs, err = r.DB.GetMembershipEventNIDsForRoom(ctx, roomInfo.RoomNID, true, true); err == nil { if joinEventNIDs, err = r.DB.GetMembershipEventNIDsForRoom(ctx, roomInfo.RoomNID, []string{"join"}, true); err == nil {
// If we have no local users that are joined to the room then any state about // If we have no local users that are joined to the room then any state about
// the room that we have is quite possibly out of date. Therefore in that case // the room that we have is quite possibly out of date. Therefore in that case
// we should overwrite it rather than merge it. // we should overwrite it rather than merge it.

View file

@ -537,7 +537,7 @@ func joinEventsFromHistoryVisibility(
if err != nil { if err != nil {
return nil, err return nil, err
} }
joinEventNIDs, err := db.GetMembershipEventNIDsForRoom(ctx, info.RoomNID, true, false) joinEventNIDs, err := db.GetMembershipEventNIDsForRoom(ctx, info.RoomNID, []string{"join"}, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -251,7 +251,7 @@ func (r *Queryer) QueryMembershipsForRoom(
if request.Sender == "" { if request.Sender == "" {
var events []types.Event var events []types.Event
var eventNIDs []types.EventNID var eventNIDs []types.EventNID
eventNIDs, err = r.DB.GetMembershipEventNIDsForRoom(ctx, info.RoomNID, request.JoinedOnly, false) eventNIDs, err = r.DB.GetMembershipEventNIDsForRoom(ctx, info.RoomNID, request.MembershipStatusFilter, false)
if err != nil { if err != nil {
return fmt.Errorf("r.DB.GetMembershipEventNIDsForRoom: %w", err) return fmt.Errorf("r.DB.GetMembershipEventNIDsForRoom: %w", err)
} }
@ -286,7 +286,7 @@ func (r *Queryer) QueryMembershipsForRoom(
var stateEntries []types.StateEntry var stateEntries []types.StateEntry
if stillInRoom { if stillInRoom {
var eventNIDs []types.EventNID var eventNIDs []types.EventNID
eventNIDs, err = r.DB.GetMembershipEventNIDsForRoom(ctx, info.RoomNID, request.JoinedOnly, false) eventNIDs, err = r.DB.GetMembershipEventNIDsForRoom(ctx, info.RoomNID, request.MembershipStatusFilter, false)
if err != nil { if err != nil {
return err return err
} }
@ -328,7 +328,7 @@ func (r *Queryer) QueryServerJoinedToRoom(
} }
response.RoomExists = true response.RoomExists = true
eventNIDs, err := r.DB.GetMembershipEventNIDsForRoom(ctx, info.RoomNID, true, false) eventNIDs, err := r.DB.GetMembershipEventNIDsForRoom(ctx, info.RoomNID, []string{"join"}, false)
if err != nil { if err != nil {
return fmt.Errorf("r.DB.GetMembershipEventNIDsForRoom: %w", err) return fmt.Errorf("r.DB.GetMembershipEventNIDsForRoom: %w", err)
} }

View file

@ -131,7 +131,7 @@ type Database interface {
// been members of a given room. Only lookup events of "join" membership if // been members of a given room. Only lookup events of "join" membership if
// joinOnly is set to true. // joinOnly is set to true.
// Returns an error if there was a problem talking to the database. // Returns an error if there was a problem talking to the database.
GetMembershipEventNIDsForRoom(ctx context.Context, roomNID types.RoomNID, joinOnly bool, localOnly bool) ([]types.EventNID, error) GetMembershipEventNIDsForRoom(ctx context.Context, roomNID types.RoomNID, membershipStatusFilter []string, localOnly bool) ([]types.EventNID, error)
// EventsFromIDs looks up the Events for a list of event IDs. Does not error if event was // EventsFromIDs looks up the Events for a list of event IDs. Does not error if event was
// not found. // not found.
// Returns an error if the retrieval went wrong. // Returns an error if the retrieval went wrong.

View file

@ -343,12 +343,40 @@ func (d *Database) GetMembership(ctx context.Context, roomNID types.RoomNID, req
} }
func (d *Database) GetMembershipEventNIDsForRoom( func (d *Database) GetMembershipEventNIDsForRoom(
ctx context.Context, roomNID types.RoomNID, joinOnly bool, localOnly bool, ctx context.Context, roomNID types.RoomNID, membershipStatusFilter []string, localOnly bool,
) ([]types.EventNID, error) { ) ([]types.EventNID, error) {
if joinOnly { var eventNIDs []types.EventNID
return d.MembershipTable.SelectMembershipsFromRoomAndMembership( var filteredEventNIDs []types.EventNID
ctx, roomNID, tables.MembershipStateJoin, localOnly, var err error
) if len(membershipStatusFilter) > 0 {
for _, filter := range membershipStatusFilter {
if filter == "join" {
filteredEventNIDs, err = d.MembershipTable.SelectMembershipsFromRoomAndMembership(
ctx, roomNID, tables.MembershipStateJoin, localOnly,
)
if err != nil {
return eventNIDs, err
}
eventNIDs = append(eventNIDs, filteredEventNIDs...)
} else if filter == "invite" {
filteredEventNIDs, err = d.MembershipTable.SelectMembershipsFromRoomAndMembership(
ctx, roomNID, tables.MembershipStateInvite, localOnly,
)
if err != nil {
return eventNIDs, err
}
eventNIDs = append(eventNIDs, filteredEventNIDs...)
} else {
filteredEventNIDs, err = d.MembershipTable.SelectMembershipsFromRoomAndMembership(
ctx, roomNID, tables.MembershipStateLeaveOrBan, localOnly,
)
if err != nil {
return eventNIDs, err
}
eventNIDs = append(eventNIDs, filteredEventNIDs...)
}
}
return eventNIDs, err
} }
return d.MembershipTable.SelectMembershipsFromRoom(ctx, roomNID, localOnly) return d.MembershipTable.SelectMembershipsFromRoom(ctx, roomNID, localOnly)