MM-12234: configurable limit to user autocomplete and search matches (#9499)
* unit test cleanup * allow limiting user search results * clean up test users before starting * model UserSearchOptions to simplify parameters
Этот коммит содержится в:
коммит произвёл
Harrison Healey
родитель
e8c9ccaa7e
Коммит
715097cc76
@@ -970,12 +970,11 @@ func (us SqlUserStore) GetAnyUnreadPostCountForChannel(userId string, channelId
|
||||
})
|
||||
}
|
||||
|
||||
func (us SqlUserStore) Search(teamId string, term string, options map[string]bool) store.StoreChannel {
|
||||
func (us SqlUserStore) Search(teamId string, term string, options *model.UserSearchOptions) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
searchQuery := ""
|
||||
|
||||
if teamId == "" {
|
||||
|
||||
// Id != '' is added because both SEARCH_CLAUSE and INACTIVE_CLAUSE start with an AND
|
||||
searchQuery = `
|
||||
SELECT
|
||||
@@ -986,8 +985,8 @@ func (us SqlUserStore) Search(teamId string, term string, options map[string]boo
|
||||
Id != ''
|
||||
SEARCH_CLAUSE
|
||||
INACTIVE_CLAUSE
|
||||
ORDER BY Username ASC
|
||||
LIMIT 100`
|
||||
ORDER BY Username ASC
|
||||
LIMIT :Limit`
|
||||
} else {
|
||||
searchQuery = `
|
||||
SELECT
|
||||
@@ -1000,16 +999,19 @@ func (us SqlUserStore) Search(teamId string, term string, options map[string]boo
|
||||
AND TeamMembers.DeleteAt = 0
|
||||
SEARCH_CLAUSE
|
||||
INACTIVE_CLAUSE
|
||||
ORDER BY Users.Username ASC
|
||||
LIMIT 100`
|
||||
ORDER BY Users.Username ASC
|
||||
LIMIT :Limit`
|
||||
}
|
||||
|
||||
*result = us.performSearch(searchQuery, term, options, map[string]interface{}{"TeamId": teamId})
|
||||
*result = us.performSearch(searchQuery, term, options, map[string]interface{}{
|
||||
"TeamId": teamId,
|
||||
"Limit": options.Limit,
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func (us SqlUserStore) SearchWithoutTeam(term string, options map[string]bool) store.StoreChannel {
|
||||
func (us SqlUserStore) SearchWithoutTeam(term string, options *model.UserSearchOptions) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
searchQuery := `
|
||||
SELECT
|
||||
@@ -1027,14 +1029,16 @@ func (us SqlUserStore) SearchWithoutTeam(term string, options map[string]bool) s
|
||||
SEARCH_CLAUSE
|
||||
INACTIVE_CLAUSE
|
||||
ORDER BY Username ASC
|
||||
LIMIT 100`
|
||||
LIMIT :Limit`
|
||||
|
||||
*result = us.performSearch(searchQuery, term, options, map[string]interface{}{})
|
||||
*result = us.performSearch(searchQuery, term, options, map[string]interface{}{
|
||||
"Limit": options.Limit,
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func (us SqlUserStore) SearchNotInTeam(notInTeamId string, term string, options map[string]bool) store.StoreChannel {
|
||||
func (us SqlUserStore) SearchNotInTeam(notInTeamId string, term string, options *model.UserSearchOptions) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
searchQuery := `
|
||||
SELECT
|
||||
@@ -1048,14 +1052,17 @@ func (us SqlUserStore) SearchNotInTeam(notInTeamId string, term string, options
|
||||
SEARCH_CLAUSE
|
||||
INACTIVE_CLAUSE
|
||||
ORDER BY Users.Username ASC
|
||||
LIMIT 100`
|
||||
LIMIT :Limit`
|
||||
|
||||
*result = us.performSearch(searchQuery, term, options, map[string]interface{}{"NotInTeamId": notInTeamId})
|
||||
*result = us.performSearch(searchQuery, term, options, map[string]interface{}{
|
||||
"NotInTeamId": notInTeamId,
|
||||
"Limit": options.Limit,
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func (us SqlUserStore) SearchNotInChannel(teamId string, channelId string, term string, options map[string]bool) store.StoreChannel {
|
||||
func (us SqlUserStore) SearchNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
searchQuery := ""
|
||||
if teamId == "" {
|
||||
@@ -1071,7 +1078,7 @@ func (us SqlUserStore) SearchNotInChannel(teamId string, channelId string, term
|
||||
SEARCH_CLAUSE
|
||||
INACTIVE_CLAUSE
|
||||
ORDER BY Users.Username ASC
|
||||
LIMIT 100`
|
||||
LIMIT :Limit`
|
||||
} else {
|
||||
searchQuery = `
|
||||
SELECT
|
||||
@@ -1089,30 +1096,37 @@ func (us SqlUserStore) SearchNotInChannel(teamId string, channelId string, term
|
||||
SEARCH_CLAUSE
|
||||
INACTIVE_CLAUSE
|
||||
ORDER BY Users.Username ASC
|
||||
LIMIT 100`
|
||||
LIMIT :Limit`
|
||||
}
|
||||
|
||||
*result = us.performSearch(searchQuery, term, options, map[string]interface{}{"TeamId": teamId, "ChannelId": channelId})
|
||||
|
||||
*result = us.performSearch(searchQuery, term, options, map[string]interface{}{
|
||||
"TeamId": teamId,
|
||||
"ChannelId": channelId,
|
||||
"Limit": options.Limit,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func (us SqlUserStore) SearchInChannel(channelId string, term string, options map[string]bool) store.StoreChannel {
|
||||
func (us SqlUserStore) SearchInChannel(channelId string, term string, options *model.UserSearchOptions) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
searchQuery := `
|
||||
SELECT
|
||||
Users.*
|
||||
FROM
|
||||
Users, ChannelMembers
|
||||
WHERE
|
||||
ChannelMembers.ChannelId = :ChannelId
|
||||
AND ChannelMembers.UserId = Users.Id
|
||||
SEARCH_CLAUSE
|
||||
INACTIVE_CLAUSE
|
||||
ORDER BY Users.Username ASC
|
||||
LIMIT 100`
|
||||
SELECT
|
||||
Users.*
|
||||
FROM
|
||||
Users, ChannelMembers
|
||||
WHERE
|
||||
ChannelMembers.ChannelId = :ChannelId
|
||||
AND ChannelMembers.UserId = Users.Id
|
||||
SEARCH_CLAUSE
|
||||
INACTIVE_CLAUSE
|
||||
ORDER BY Users.Username ASC
|
||||
LIMIT :Limit
|
||||
`
|
||||
|
||||
*result = us.performSearch(searchQuery, term, options, map[string]interface{}{"ChannelId": channelId})
|
||||
*result = us.performSearch(searchQuery, term, options, map[string]interface{}{
|
||||
"ChannelId": channelId,
|
||||
"Limit": options.Limit,
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
@@ -1160,7 +1174,7 @@ func generateSearchQuery(searchQuery string, terms []string, fields []string, pa
|
||||
return strings.Replace(searchQuery, "SEARCH_CLAUSE", fmt.Sprintf(" AND %s ", searchClause), 1)
|
||||
}
|
||||
|
||||
func (us SqlUserStore) performSearch(searchQuery string, term string, options map[string]bool, parameters map[string]interface{}) store.StoreResult {
|
||||
func (us SqlUserStore) performSearch(searchQuery string, term string, options *model.UserSearchOptions, parameters map[string]interface{}) store.StoreResult {
|
||||
result := store.StoreResult{}
|
||||
|
||||
// These chars must be removed from the like query.
|
||||
@@ -1173,16 +1187,22 @@ func (us SqlUserStore) performSearch(searchQuery string, term string, options ma
|
||||
term = strings.Replace(term, c, "*"+c, -1)
|
||||
}
|
||||
|
||||
searchType := USER_SEARCH_TYPE_ALL
|
||||
if ok := options[store.USER_SEARCH_OPTION_NAMES_ONLY]; ok {
|
||||
searchType = USER_SEARCH_TYPE_NAMES
|
||||
} else if ok = options[store.USER_SEARCH_OPTION_NAMES_ONLY_NO_FULL_NAME]; ok {
|
||||
searchType = USER_SEARCH_TYPE_NAMES_NO_FULL_NAME
|
||||
} else if ok = options[store.USER_SEARCH_OPTION_ALL_NO_FULL_NAME]; ok {
|
||||
searchType = USER_SEARCH_TYPE_ALL_NO_FULL_NAME
|
||||
searchType := USER_SEARCH_TYPE_NAMES_NO_FULL_NAME
|
||||
if options.AllowEmails {
|
||||
if options.AllowFullNames {
|
||||
searchType = USER_SEARCH_TYPE_ALL
|
||||
} else {
|
||||
searchType = USER_SEARCH_TYPE_ALL_NO_FULL_NAME
|
||||
}
|
||||
} else {
|
||||
if options.AllowFullNames {
|
||||
searchType = USER_SEARCH_TYPE_NAMES
|
||||
} else {
|
||||
searchType = USER_SEARCH_TYPE_NAMES_NO_FULL_NAME
|
||||
}
|
||||
}
|
||||
|
||||
if ok := options[store.USER_SEARCH_OPTION_ALLOW_INACTIVE]; ok {
|
||||
if ok := options.AllowInactive; ok {
|
||||
searchQuery = strings.Replace(searchQuery, "INACTIVE_CLAUSE", "", 1)
|
||||
} else {
|
||||
searchQuery = strings.Replace(searchQuery, "INACTIVE_CLAUSE", "AND Users.DeleteAt = 0", 1)
|
||||
|
||||
@@ -272,11 +272,11 @@ type UserStore interface {
|
||||
GetAnyUnreadPostCountForChannel(userId string, channelId string) StoreChannel
|
||||
GetRecentlyActiveUsersForTeam(teamId string, offset, limit int) StoreChannel
|
||||
GetNewUsersForTeam(teamId string, offset, limit int) StoreChannel
|
||||
Search(teamId string, term string, options map[string]bool) StoreChannel
|
||||
SearchNotInTeam(notInTeamId string, term string, options map[string]bool) StoreChannel
|
||||
SearchInChannel(channelId string, term string, options map[string]bool) StoreChannel
|
||||
SearchNotInChannel(teamId string, channelId string, term string, options map[string]bool) StoreChannel
|
||||
SearchWithoutTeam(term string, options map[string]bool) StoreChannel
|
||||
Search(teamId string, term string, options *model.UserSearchOptions) StoreChannel
|
||||
SearchNotInTeam(notInTeamId string, term string, options *model.UserSearchOptions) StoreChannel
|
||||
SearchInChannel(channelId string, term string, options *model.UserSearchOptions) StoreChannel
|
||||
SearchNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) StoreChannel
|
||||
SearchWithoutTeam(term string, options *model.UserSearchOptions) StoreChannel
|
||||
AnalyticsGetInactiveUsersCount() StoreChannel
|
||||
AnalyticsGetSystemAdminCount() StoreChannel
|
||||
GetProfilesNotInTeam(teamId string, offset int, limit int) StoreChannel
|
||||
|
||||
@@ -314,6 +314,22 @@ func (_m *ChannelStore) GetChannelMembersForExport(userId string, teamId string)
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetChannelMembersTimezones provides a mock function with given fields: channelId
|
||||
func (_m *ChannelStore) GetChannelMembersTimezones(channelId string) store.StoreChannel {
|
||||
ret := _m.Called(channelId)
|
||||
|
||||
var r0 store.StoreChannel
|
||||
if rf, ok := ret.Get(0).(func(string) store.StoreChannel); ok {
|
||||
r0 = rf(channelId)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.StoreChannel)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetChannelUnread provides a mock function with given fields: channelId, userId
|
||||
func (_m *ChannelStore) GetChannelUnread(channelId string, userId string) store.StoreChannel {
|
||||
ret := _m.Called(channelId, userId)
|
||||
@@ -442,21 +458,6 @@ func (_m *ChannelStore) GetMember(channelId string, userId string) store.StoreCh
|
||||
return r0
|
||||
}
|
||||
|
||||
func (_m *ChannelStore) GetChannelMembersTimezones(channelId string) store.StoreChannel {
|
||||
ret := _m.Called(channelId)
|
||||
|
||||
var r0 store.StoreChannel
|
||||
if rf, ok := ret.Get(0).(func(string) store.StoreChannel); ok {
|
||||
r0 = rf(channelId)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.StoreChannel)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetMemberCount provides a mock function with given fields: channelId, allowFromCache
|
||||
func (_m *ChannelStore) GetMemberCount(channelId string, allowFromCache bool) store.StoreChannel {
|
||||
ret := _m.Called(channelId, allowFromCache)
|
||||
|
||||
@@ -626,11 +626,11 @@ func (_m *UserStore) Save(user *model.User) store.StoreChannel {
|
||||
}
|
||||
|
||||
// Search provides a mock function with given fields: teamId, term, options
|
||||
func (_m *UserStore) Search(teamId string, term string, options map[string]bool) store.StoreChannel {
|
||||
func (_m *UserStore) Search(teamId string, term string, options *model.UserSearchOptions) store.StoreChannel {
|
||||
ret := _m.Called(teamId, term, options)
|
||||
|
||||
var r0 store.StoreChannel
|
||||
if rf, ok := ret.Get(0).(func(string, string, map[string]bool) store.StoreChannel); ok {
|
||||
if rf, ok := ret.Get(0).(func(string, string, *model.UserSearchOptions) store.StoreChannel); ok {
|
||||
r0 = rf(teamId, term, options)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
@@ -642,11 +642,11 @@ func (_m *UserStore) Search(teamId string, term string, options map[string]bool)
|
||||
}
|
||||
|
||||
// SearchInChannel provides a mock function with given fields: channelId, term, options
|
||||
func (_m *UserStore) SearchInChannel(channelId string, term string, options map[string]bool) store.StoreChannel {
|
||||
func (_m *UserStore) SearchInChannel(channelId string, term string, options *model.UserSearchOptions) store.StoreChannel {
|
||||
ret := _m.Called(channelId, term, options)
|
||||
|
||||
var r0 store.StoreChannel
|
||||
if rf, ok := ret.Get(0).(func(string, string, map[string]bool) store.StoreChannel); ok {
|
||||
if rf, ok := ret.Get(0).(func(string, string, *model.UserSearchOptions) store.StoreChannel); ok {
|
||||
r0 = rf(channelId, term, options)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
@@ -658,11 +658,11 @@ func (_m *UserStore) SearchInChannel(channelId string, term string, options map[
|
||||
}
|
||||
|
||||
// SearchNotInChannel provides a mock function with given fields: teamId, channelId, term, options
|
||||
func (_m *UserStore) SearchNotInChannel(teamId string, channelId string, term string, options map[string]bool) store.StoreChannel {
|
||||
func (_m *UserStore) SearchNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) store.StoreChannel {
|
||||
ret := _m.Called(teamId, channelId, term, options)
|
||||
|
||||
var r0 store.StoreChannel
|
||||
if rf, ok := ret.Get(0).(func(string, string, string, map[string]bool) store.StoreChannel); ok {
|
||||
if rf, ok := ret.Get(0).(func(string, string, string, *model.UserSearchOptions) store.StoreChannel); ok {
|
||||
r0 = rf(teamId, channelId, term, options)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
@@ -674,11 +674,11 @@ func (_m *UserStore) SearchNotInChannel(teamId string, channelId string, term st
|
||||
}
|
||||
|
||||
// SearchNotInTeam provides a mock function with given fields: notInTeamId, term, options
|
||||
func (_m *UserStore) SearchNotInTeam(notInTeamId string, term string, options map[string]bool) store.StoreChannel {
|
||||
func (_m *UserStore) SearchNotInTeam(notInTeamId string, term string, options *model.UserSearchOptions) store.StoreChannel {
|
||||
ret := _m.Called(notInTeamId, term, options)
|
||||
|
||||
var r0 store.StoreChannel
|
||||
if rf, ok := ret.Get(0).(func(string, string, map[string]bool) store.StoreChannel); ok {
|
||||
if rf, ok := ret.Get(0).(func(string, string, *model.UserSearchOptions) store.StoreChannel); ok {
|
||||
r0 = rf(notInTeamId, term, options)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
@@ -690,11 +690,11 @@ func (_m *UserStore) SearchNotInTeam(notInTeamId string, term string, options ma
|
||||
}
|
||||
|
||||
// SearchWithoutTeam provides a mock function with given fields: term, options
|
||||
func (_m *UserStore) SearchWithoutTeam(term string, options map[string]bool) store.StoreChannel {
|
||||
func (_m *UserStore) SearchWithoutTeam(term string, options *model.UserSearchOptions) store.StoreChannel {
|
||||
ret := _m.Called(term, options)
|
||||
|
||||
var r0 store.StoreChannel
|
||||
if rf, ok := ret.Get(0).(func(string, map[string]bool) store.StoreChannel); ok {
|
||||
if rf, ok := ret.Get(0).(func(string, *model.UserSearchOptions) store.StoreChannel); ok {
|
||||
r0 = rf(term, options)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
|
||||
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Ссылка в новой задаче
Block a user