Make user directory only show remote users you know about from your joined rooms

This commit is contained in:
Neil Alexander 2020-07-27 16:19:49 +01:00
parent 1fdb7f1a45
commit b7176c12e0
No known key found for this signature in database
GPG key ID: A02A2019A2BB0944
9 changed files with 21 additions and 13 deletions

View file

@ -585,6 +585,7 @@ func Setup(
} }
return *SearchUserDirectory( return *SearchUserDirectory(
req.Context(), req.Context(),
device,
userAPI, userAPI,
stateAPI, stateAPI,
cfg.Matrix.ServerName, cfg.Matrix.ServerName,

View file

@ -32,6 +32,7 @@ type UserDirectoryResponse struct {
func SearchUserDirectory( func SearchUserDirectory(
ctx context.Context, ctx context.Context,
device *userapi.Device,
userAPI userapi.UserInternalAPI, userAPI userapi.UserInternalAPI,
stateAPI currentstateAPI.CurrentStateInternalAPI, stateAPI currentstateAPI.CurrentStateInternalAPI,
serverName gomatrixserverlib.ServerName, serverName gomatrixserverlib.ServerName,
@ -81,6 +82,7 @@ func SearchUserDirectory(
if len(results) <= limit { if len(results) <= limit {
stateReq := &currentstateAPI.QueryKnownUsersRequest{ stateReq := &currentstateAPI.QueryKnownUsersRequest{
UserID: device.UserID,
SearchString: searchString, SearchString: searchString,
Limit: limit - len(results), Limit: limit - len(results),
} }

View file

@ -92,6 +92,7 @@ type QueryCurrentStateResponse struct {
} }
type QueryKnownUsersRequest struct { type QueryKnownUsersRequest struct {
UserID string `json:"user_id"`
SearchString string `json:"search_string"` SearchString string `json:"search_string"`
Limit int `json:"limit"` Limit int `json:"limit"`
} }

View file

@ -51,7 +51,7 @@ func (a *CurrentStateInternalAPI) QueryRoomsForUser(ctx context.Context, req *ap
} }
func (a *CurrentStateInternalAPI) QueryKnownUsers(ctx context.Context, req *api.QueryKnownUsersRequest, res *api.QueryKnownUsersResponse) error { func (a *CurrentStateInternalAPI) QueryKnownUsers(ctx context.Context, req *api.QueryKnownUsersRequest, res *api.QueryKnownUsersResponse) error {
users, err := a.DB.GetKnownUsers(ctx, req.SearchString, req.Limit) users, err := a.DB.GetKnownUsers(ctx, req.UserID, req.SearchString, req.Limit)
if err != nil { if err != nil {
return err return err
} }

View file

@ -39,6 +39,6 @@ type Database interface {
RedactEvent(ctx context.Context, redactedEventID string, redactedBecause gomatrixserverlib.HeaderedEvent) error RedactEvent(ctx context.Context, redactedEventID string, redactedBecause gomatrixserverlib.HeaderedEvent) error
// JoinedUsersSetInRooms returns all joined users in the rooms given, along with the count of how many times they appear. // JoinedUsersSetInRooms returns all joined users in the rooms given, along with the count of how many times they appear.
JoinedUsersSetInRooms(ctx context.Context, roomIDs []string) (map[string]int, error) JoinedUsersSetInRooms(ctx context.Context, roomIDs []string) (map[string]int, error)
// GetKnownUsers searches all users that we know about. // GetKnownUsers searches all users that userID knows about.
GetKnownUsers(ctx context.Context, searchString string, limit int) ([]string, error) GetKnownUsers(ctx context.Context, userID, searchString string, limit int) ([]string, error)
} }

View file

@ -83,7 +83,9 @@ const selectJoinedUsersSetForRoomsSQL = "" +
" type = 'm.room.member' and content_value = 'join' GROUP BY state_key" " type = 'm.room.member' and content_value = 'join' GROUP BY state_key"
const selectKnownUsersSQL = "" + const selectKnownUsersSQL = "" +
"SELECT DISTINCT state_key FROM currentstate_current_room_state WHERE type = 'm.room.member' AND state_key LIKE $1 LIMIT $2" "SELECT DISTINCT state_key FROM currentstate_current_room_state WHERE room_id = ANY(" +
" SELECT DISTINCT room_id FROM currentstate_current_room_state WHERE state_key=$1 AND TYPE='m.room.member' AND content_value='join'" +
") AND TYPE='m.room.member' AND content_value='join' AND state_key LIKE $2 LIMIT $3"
type currentRoomStateStatements struct { type currentRoomStateStatements struct {
upsertRoomStateStmt *sql.Stmt upsertRoomStateStmt *sql.Stmt
@ -304,8 +306,8 @@ func (s *currentRoomStateStatements) SelectBulkStateContent(
return strippedEvents, rows.Err() return strippedEvents, rows.Err()
} }
func (s *currentRoomStateStatements) SelectKnownUsers(ctx context.Context, searchString string, limit int) ([]string, error) { func (s *currentRoomStateStatements) SelectKnownUsers(ctx context.Context, userID, searchString string, limit int) ([]string, error) {
rows, err := s.selectKnownUsersStmt.QueryContext(ctx, fmt.Sprintf("%%%s%%", searchString), limit) rows, err := s.selectKnownUsersStmt.QueryContext(ctx, userID, fmt.Sprintf("%%%s%%", searchString), limit)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return nil, nil return nil, nil
} }

View file

@ -90,6 +90,6 @@ func (d *Database) JoinedUsersSetInRooms(ctx context.Context, roomIDs []string)
return d.CurrentRoomState.SelectJoinedUsersSetForRooms(ctx, roomIDs) return d.CurrentRoomState.SelectJoinedUsersSetForRooms(ctx, roomIDs)
} }
func (d *Database) GetKnownUsers(ctx context.Context, searchString string, limit int) ([]string, error) { func (d *Database) GetKnownUsers(ctx context.Context, userID, searchString string, limit int) ([]string, error) {
return d.CurrentRoomState.SelectKnownUsers(ctx, searchString, limit) return d.CurrentRoomState.SelectKnownUsers(ctx, userID, searchString, limit)
} }

View file

@ -71,7 +71,9 @@ const selectJoinedUsersSetForRoomsSQL = "" +
"SELECT state_key, COUNT(room_id) FROM currentstate_current_room_state WHERE room_id IN ($1) AND type = 'm.room.member' and content_value = 'join' GROUP BY state_key" "SELECT state_key, COUNT(room_id) FROM currentstate_current_room_state WHERE room_id IN ($1) AND type = 'm.room.member' and content_value = 'join' GROUP BY state_key"
const selectKnownUsersSQL = "" + const selectKnownUsersSQL = "" +
"SELECT DISTINCT state_key FROM currentstate_current_room_state WHERE type = 'm.room.member' AND state_key LIKE $1 LIMIT $2" "SELECT DISTINCT state_key FROM currentstate_current_room_state WHERE room_id IN (" +
" SELECT DISTINCT room_id FROM currentstate_current_room_state WHERE state_key=$1 AND TYPE='m.room.member' AND content_value='join'" +
") AND TYPE='m.room.member' AND content_value='join' AND state_key LIKE $2 LIMIT $3"
type currentRoomStateStatements struct { type currentRoomStateStatements struct {
db *sql.DB db *sql.DB
@ -324,8 +326,8 @@ func (s *currentRoomStateStatements) SelectBulkStateContent(
return strippedEvents, rows.Err() return strippedEvents, rows.Err()
} }
func (s *currentRoomStateStatements) SelectKnownUsers(ctx context.Context, searchString string, limit int) ([]string, error) { func (s *currentRoomStateStatements) SelectKnownUsers(ctx context.Context, userID, searchString string, limit int) ([]string, error) {
rows, err := s.selectKnownUsersStmt.QueryContext(ctx, fmt.Sprintf("%%%s%%", searchString), limit) rows, err := s.selectKnownUsersStmt.QueryContext(ctx, userID, fmt.Sprintf("%%%s%%", searchString), limit)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return nil, nil return nil, nil
} }

View file

@ -39,8 +39,8 @@ type CurrentRoomState interface {
// SelectJoinedUsersSetForRooms returns the set of all users in the rooms who are joined to any of these rooms, along with the // SelectJoinedUsersSetForRooms returns the set of all users in the rooms who are joined to any of these rooms, along with the
// counts of how many rooms they are joined. // counts of how many rooms they are joined.
SelectJoinedUsersSetForRooms(ctx context.Context, roomIDs []string) (map[string]int, error) SelectJoinedUsersSetForRooms(ctx context.Context, roomIDs []string) (map[string]int, error)
// SelectKnownUsers searches all users that we know about. // SelectKnownUsers searches all users that userID knows about.
SelectKnownUsers(ctx context.Context, searchString string, limit int) ([]string, error) SelectKnownUsers(ctx context.Context, userID, searchString string, limit int) ([]string, error)
} }
// StrippedEvent represents a stripped event for returning extracted content values. // StrippedEvent represents a stripped event for returning extracted content values.