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
Этот коммит содержится в:
Jesse Hallam
2018-10-17 11:24:12 -04:00
коммит произвёл Harrison Healey
родитель e8c9ccaa7e
Коммит 715097cc76
12 изменённых файлов: 1148 добавлений и 674 удалений

Просмотреть файл

@@ -184,8 +184,11 @@ func (me *TestHelper) TearDown() {
go func() { go func() {
defer wg.Done() defer wg.Done()
options := map[string]bool{} options := &model.UserSearchOptions{
options[store.USER_SEARCH_OPTION_NAMES_ONLY_NO_FULL_NAME] = true AllowEmails: false,
AllowFullNames: false,
Limit: model.USER_SEARCH_MAX_LIMIT,
}
if result := <-me.App.Srv.Store.User().Search("", "fakeuser", options); result.Err != nil { if result := <-me.App.Srv.Store.User().Search("", "fakeuser", options); result.Err != nil {
mlog.Error("Error tearing down test users") mlog.Error("Error tearing down test users")
} else { } else {

Просмотреть файл

@@ -14,7 +14,6 @@ import (
"github.com/mattermost/mattermost-server/app" "github.com/mattermost/mattermost-server/app"
"github.com/mattermost/mattermost-server/mlog" "github.com/mattermost/mattermost-server/mlog"
"github.com/mattermost/mattermost-server/model" "github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/store"
) )
func (api *API) InitUser() { func (api *API) InitUser() {
@@ -547,23 +546,26 @@ func searchUsers(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
searchOptions := map[string]bool{} if props.Limit <= 0 || props.Limit > model.USER_SEARCH_MAX_LIMIT {
searchOptions[store.USER_SEARCH_OPTION_ALLOW_INACTIVE] = props.AllowInactive c.SetInvalidParam("limit")
return
if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
hideFullName := !c.App.Config().PrivacySettings.ShowFullName
hideEmail := !c.App.Config().PrivacySettings.ShowEmailAddress
if hideFullName && hideEmail {
searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY_NO_FULL_NAME] = true
} else if hideFullName {
searchOptions[store.USER_SEARCH_OPTION_ALL_NO_FULL_NAME] = true
} else if hideEmail {
searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true
}
} }
profiles, err := c.App.SearchUsers(props, searchOptions, c.IsSystemAdmin()) options := &model.UserSearchOptions{
IsAdmin: c.IsSystemAdmin(),
AllowInactive: props.AllowInactive,
Limit: props.Limit,
}
if c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
options.AllowEmails = true
options.AllowFullNames = true
} else {
options.AllowEmails = c.App.Config().PrivacySettings.ShowEmailAddress
options.AllowFullNames = c.App.Config().PrivacySettings.ShowFullName
}
profiles, err := c.App.SearchUsers(props, options)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return
@@ -576,17 +578,26 @@ func autocompleteUsers(c *Context, w http.ResponseWriter, r *http.Request) {
channelId := r.URL.Query().Get("in_channel") channelId := r.URL.Query().Get("in_channel")
teamId := r.URL.Query().Get("in_team") teamId := r.URL.Query().Get("in_team")
name := r.URL.Query().Get("name") name := r.URL.Query().Get("name")
limitStr := r.URL.Query().Get("limit")
limit, _ := strconv.Atoi(limitStr)
if limitStr == "" {
limit = model.USER_SEARCH_DEFAULT_LIMIT
}
autocomplete := new(model.UserAutocomplete) autocomplete := new(model.UserAutocomplete)
var err *model.AppError var err *model.AppError
searchOptions := map[string]bool{} options := &model.UserSearchOptions{
IsAdmin: c.IsSystemAdmin(),
// Never autocomplete on emails.
AllowEmails: false,
Limit: limit,
}
hideFullName := !c.App.Config().PrivacySettings.ShowFullName if c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
if hideFullName && !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { options.AllowFullNames = true
searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY_NO_FULL_NAME] = true
} else { } else {
searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true options.AllowFullNames = c.App.Config().PrivacySettings.ShowFullName
} }
if len(channelId) > 0 { if len(channelId) > 0 {
@@ -606,8 +617,8 @@ func autocompleteUsers(c *Context, w http.ResponseWriter, r *http.Request) {
if len(channelId) > 0 { if len(channelId) > 0 {
// Applying the provided teamId here is useful for DMs and GMs which don't belong // Applying the provided teamId here is useful for DMs and GMs which don't belong
// to a team. Applying it when the channel does belong to a team makes less sense, // to a team. Applying it when the channel does belong to a team makes less sense,
//t but the permissions are checked above regardless. // but the permissions are checked above regardless.
result, err := c.App.AutocompleteUsersInChannel(teamId, channelId, name, searchOptions, c.IsSystemAdmin()) result, err := c.App.AutocompleteUsersInChannel(teamId, channelId, name, options)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return
@@ -616,7 +627,7 @@ func autocompleteUsers(c *Context, w http.ResponseWriter, r *http.Request) {
autocomplete.Users = result.InChannel autocomplete.Users = result.InChannel
autocomplete.OutOfChannel = result.OutOfChannel autocomplete.OutOfChannel = result.OutOfChannel
} else if len(teamId) > 0 { } else if len(teamId) > 0 {
result, err := c.App.AutocompleteUsersInTeam(teamId, name, searchOptions, c.IsSystemAdmin()) result, err := c.App.AutocompleteUsersInTeam(teamId, name, options)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return
@@ -625,7 +636,7 @@ func autocompleteUsers(c *Context, w http.ResponseWriter, r *http.Request) {
autocomplete.Users = result.InTeam autocomplete.Users = result.InTeam
} else { } else {
// No permission check required // No permission check required
result, err := c.App.SearchUsersInTeam("", name, searchOptions, c.IsSystemAdmin()) result, err := c.App.SearchUsersInTeam("", name, options)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return

Просмотреть файл

@@ -759,92 +759,92 @@ func TestAutocompleteUsers(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) { cfg.PrivacySettings.ShowFullName = showFullName }) th.App.UpdateConfig(func(cfg *model.Config) { cfg.PrivacySettings.ShowFullName = showFullName })
}() }()
rusers, resp := Client.AutocompleteUsersInChannel(teamId, channelId, username, "") rusers, resp := Client.AutocompleteUsersInChannel(teamId, channelId, username, model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckNoError(t, resp) CheckNoError(t, resp)
if len(rusers.Users) != 1 { if len(rusers.Users) != 1 {
t.Fatal("should have returned 1 user") t.Fatal("should have returned 1 user")
} }
rusers, resp = Client.AutocompleteUsersInChannel(teamId, channelId, "amazonses", "") rusers, resp = Client.AutocompleteUsersInChannel(teamId, channelId, "amazonses", model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckNoError(t, resp) CheckNoError(t, resp)
if len(rusers.Users) != 0 { if len(rusers.Users) != 0 {
t.Fatal("should have returned 0 users") t.Fatal("should have returned 0 users")
} }
rusers, resp = Client.AutocompleteUsersInChannel(teamId, channelId, "", "") rusers, resp = Client.AutocompleteUsersInChannel(teamId, channelId, "", model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckNoError(t, resp) CheckNoError(t, resp)
if len(rusers.Users) < 2 { if len(rusers.Users) < 2 {
t.Fatal("should have many users") t.Fatal("should have many users")
} }
rusers, resp = Client.AutocompleteUsersInChannel("", channelId, "", "") rusers, resp = Client.AutocompleteUsersInChannel("", channelId, "", model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckNoError(t, resp) CheckNoError(t, resp)
if len(rusers.Users) < 2 { if len(rusers.Users) < 2 {
t.Fatal("should have many users") t.Fatal("should have many users")
} }
rusers, resp = Client.AutocompleteUsersInTeam(teamId, username, "") rusers, resp = Client.AutocompleteUsersInTeam(teamId, username, model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckNoError(t, resp) CheckNoError(t, resp)
if len(rusers.Users) != 1 { if len(rusers.Users) != 1 {
t.Fatal("should have returned 1 user") t.Fatal("should have returned 1 user")
} }
rusers, resp = Client.AutocompleteUsers(username, "") rusers, resp = Client.AutocompleteUsers(username, model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckNoError(t, resp) CheckNoError(t, resp)
if len(rusers.Users) != 1 { if len(rusers.Users) != 1 {
t.Fatal("should have returned 1 users") t.Fatal("should have returned 1 users")
} }
rusers, resp = Client.AutocompleteUsers("", "") rusers, resp = Client.AutocompleteUsers("", model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckNoError(t, resp) CheckNoError(t, resp)
if len(rusers.Users) < 2 { if len(rusers.Users) < 2 {
t.Fatal("should have returned many users") t.Fatal("should have returned many users")
} }
rusers, resp = Client.AutocompleteUsersInTeam(teamId, "amazonses", "") rusers, resp = Client.AutocompleteUsersInTeam(teamId, "amazonses", model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckNoError(t, resp) CheckNoError(t, resp)
if len(rusers.Users) != 0 { if len(rusers.Users) != 0 {
t.Fatal("should have returned 0 users") t.Fatal("should have returned 0 users")
} }
rusers, resp = Client.AutocompleteUsersInTeam(teamId, "", "") rusers, resp = Client.AutocompleteUsersInTeam(teamId, "", model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckNoError(t, resp) CheckNoError(t, resp)
if len(rusers.Users) < 2 { if len(rusers.Users) < 2 {
t.Fatal("should have many users") t.Fatal("should have many users")
} }
Client.Logout() Client.Logout()
_, resp = Client.AutocompleteUsersInChannel(teamId, channelId, username, "") _, resp = Client.AutocompleteUsersInChannel(teamId, channelId, username, model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckUnauthorizedStatus(t, resp) CheckUnauthorizedStatus(t, resp)
_, resp = Client.AutocompleteUsersInTeam(teamId, username, "") _, resp = Client.AutocompleteUsersInTeam(teamId, username, model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckUnauthorizedStatus(t, resp) CheckUnauthorizedStatus(t, resp)
_, resp = Client.AutocompleteUsers(username, "") _, resp = Client.AutocompleteUsers(username, model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckUnauthorizedStatus(t, resp) CheckUnauthorizedStatus(t, resp)
user := th.CreateUser() user := th.CreateUser()
Client.Login(user.Email, user.Password) Client.Login(user.Email, user.Password)
_, resp = Client.AutocompleteUsersInChannel(teamId, channelId, username, "") _, resp = Client.AutocompleteUsersInChannel(teamId, channelId, username, model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckForbiddenStatus(t, resp) CheckForbiddenStatus(t, resp)
_, resp = Client.AutocompleteUsersInTeam(teamId, username, "") _, resp = Client.AutocompleteUsersInTeam(teamId, username, model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckForbiddenStatus(t, resp) CheckForbiddenStatus(t, resp)
_, resp = Client.AutocompleteUsers(username, "") _, resp = Client.AutocompleteUsers(username, model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckNoError(t, resp) CheckNoError(t, resp)
_, resp = th.SystemAdminClient.AutocompleteUsersInChannel(teamId, channelId, username, "") _, resp = th.SystemAdminClient.AutocompleteUsersInChannel(teamId, channelId, username, model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckNoError(t, resp) CheckNoError(t, resp)
_, resp = th.SystemAdminClient.AutocompleteUsersInTeam(teamId, username, "") _, resp = th.SystemAdminClient.AutocompleteUsersInTeam(teamId, username, model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckNoError(t, resp) CheckNoError(t, resp)
_, resp = th.SystemAdminClient.AutocompleteUsers(username, "") _, resp = th.SystemAdminClient.AutocompleteUsers(username, model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckNoError(t, resp) CheckNoError(t, resp)
// Check against privacy config settings // Check against privacy config settings
@@ -852,21 +852,21 @@ func TestAutocompleteUsers(t *testing.T) {
th.LoginBasic() th.LoginBasic()
rusers, resp = Client.AutocompleteUsers(username, "") rusers, resp = Client.AutocompleteUsers(username, model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckNoError(t, resp) CheckNoError(t, resp)
if rusers.Users[0].FirstName != "" || rusers.Users[0].LastName != "" { if rusers.Users[0].FirstName != "" || rusers.Users[0].LastName != "" {
t.Fatal("should not show first/last name") t.Fatal("should not show first/last name")
} }
rusers, resp = Client.AutocompleteUsersInChannel(teamId, channelId, username, "") rusers, resp = Client.AutocompleteUsersInChannel(teamId, channelId, username, model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckNoError(t, resp) CheckNoError(t, resp)
if rusers.Users[0].FirstName != "" || rusers.Users[0].LastName != "" { if rusers.Users[0].FirstName != "" || rusers.Users[0].LastName != "" {
t.Fatal("should not show first/last name") t.Fatal("should not show first/last name")
} }
rusers, resp = Client.AutocompleteUsersInTeam(teamId, username, "") rusers, resp = Client.AutocompleteUsersInTeam(teamId, username, model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckNoError(t, resp) CheckNoError(t, resp)
if rusers.Users[0].FirstName != "" || rusers.Users[0].LastName != "" { if rusers.Users[0].FirstName != "" || rusers.Users[0].LastName != "" {
@@ -874,7 +874,7 @@ func TestAutocompleteUsers(t *testing.T) {
} }
t.Run("user must have access to team id, especially when it does not match channel's team id", func(t *testing.T) { t.Run("user must have access to team id, especially when it does not match channel's team id", func(t *testing.T) {
rusers, resp = Client.AutocompleteUsersInChannel("otherTeamId", channelId, username, "") rusers, resp = Client.AutocompleteUsersInChannel("otherTeamId", channelId, username, model.USER_SEARCH_DEFAULT_LIMIT, "")
CheckErrorMessage(t, resp, "api.context.permissions.app_error") CheckErrorMessage(t, resp, "api.context.permissions.app_error")
}) })
} }

Просмотреть файл

@@ -1469,93 +1469,93 @@ func (a *App) VerifyUserEmail(userId string) *model.AppError {
return (<-a.Srv.Store.User().VerifyEmail(userId)).Err return (<-a.Srv.Store.User().VerifyEmail(userId)).Err
} }
func (a *App) SearchUsers(props *model.UserSearch, searchOptions map[string]bool, asAdmin bool) ([]*model.User, *model.AppError) { func (a *App) SearchUsers(props *model.UserSearch, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
if props.WithoutTeam { if props.WithoutTeam {
return a.SearchUsersWithoutTeam(props.Term, searchOptions, asAdmin) return a.SearchUsersWithoutTeam(props.Term, options)
} else if props.InChannelId != "" { } else if props.InChannelId != "" {
return a.SearchUsersInChannel(props.InChannelId, props.Term, searchOptions, asAdmin) return a.SearchUsersInChannel(props.InChannelId, props.Term, options)
} else if props.NotInChannelId != "" { } else if props.NotInChannelId != "" {
return a.SearchUsersNotInChannel(props.TeamId, props.NotInChannelId, props.Term, searchOptions, asAdmin) return a.SearchUsersNotInChannel(props.TeamId, props.NotInChannelId, props.Term, options)
} else if props.NotInTeamId != "" { } else if props.NotInTeamId != "" {
return a.SearchUsersNotInTeam(props.NotInTeamId, props.Term, searchOptions, asAdmin) return a.SearchUsersNotInTeam(props.NotInTeamId, props.Term, options)
} else { } else {
return a.SearchUsersInTeam(props.TeamId, props.Term, searchOptions, asAdmin) return a.SearchUsersInTeam(props.TeamId, props.Term, options)
} }
} }
func (a *App) SearchUsersInChannel(channelId string, term string, searchOptions map[string]bool, asAdmin bool) ([]*model.User, *model.AppError) { func (a *App) SearchUsersInChannel(channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
if result := <-a.Srv.Store.User().SearchInChannel(channelId, term, searchOptions); result.Err != nil { if result := <-a.Srv.Store.User().SearchInChannel(channelId, term, options); result.Err != nil {
return nil, result.Err return nil, result.Err
} else { } else {
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
for _, user := range users { for _, user := range users {
a.SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, options.IsAdmin)
} }
return users, nil return users, nil
} }
} }
func (a *App) SearchUsersNotInChannel(teamId string, channelId string, term string, searchOptions map[string]bool, asAdmin bool) ([]*model.User, *model.AppError) { func (a *App) SearchUsersNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
if result := <-a.Srv.Store.User().SearchNotInChannel(teamId, channelId, term, searchOptions); result.Err != nil { if result := <-a.Srv.Store.User().SearchNotInChannel(teamId, channelId, term, options); result.Err != nil {
return nil, result.Err return nil, result.Err
} else { } else {
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
for _, user := range users { for _, user := range users {
a.SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, options.IsAdmin)
} }
return users, nil return users, nil
} }
} }
func (a *App) SearchUsersInTeam(teamId string, term string, searchOptions map[string]bool, asAdmin bool) ([]*model.User, *model.AppError) { func (a *App) SearchUsersInTeam(teamId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
if result := <-a.Srv.Store.User().Search(teamId, term, searchOptions); result.Err != nil { if result := <-a.Srv.Store.User().Search(teamId, term, options); result.Err != nil {
return nil, result.Err return nil, result.Err
} else { } else {
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
for _, user := range users { for _, user := range users {
a.SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, options.IsAdmin)
} }
return users, nil return users, nil
} }
} }
func (a *App) SearchUsersNotInTeam(notInTeamId string, term string, searchOptions map[string]bool, asAdmin bool) ([]*model.User, *model.AppError) { func (a *App) SearchUsersNotInTeam(notInTeamId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
if result := <-a.Srv.Store.User().SearchNotInTeam(notInTeamId, term, searchOptions); result.Err != nil { if result := <-a.Srv.Store.User().SearchNotInTeam(notInTeamId, term, options); result.Err != nil {
return nil, result.Err return nil, result.Err
} else { } else {
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
for _, user := range users { for _, user := range users {
a.SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, options.IsAdmin)
} }
return users, nil return users, nil
} }
} }
func (a *App) SearchUsersWithoutTeam(term string, searchOptions map[string]bool, asAdmin bool) ([]*model.User, *model.AppError) { func (a *App) SearchUsersWithoutTeam(term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
if result := <-a.Srv.Store.User().SearchWithoutTeam(term, searchOptions); result.Err != nil { if result := <-a.Srv.Store.User().SearchWithoutTeam(term, options); result.Err != nil {
return nil, result.Err return nil, result.Err
} else { } else {
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
for _, user := range users { for _, user := range users {
a.SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, options.IsAdmin)
} }
return users, nil return users, nil
} }
} }
func (a *App) AutocompleteUsersInChannel(teamId string, channelId string, term string, searchOptions map[string]bool, asAdmin bool) (*model.UserAutocompleteInChannel, *model.AppError) { func (a *App) AutocompleteUsersInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) (*model.UserAutocompleteInChannel, *model.AppError) {
uchan := a.Srv.Store.User().SearchInChannel(channelId, term, searchOptions) uchan := a.Srv.Store.User().SearchInChannel(channelId, term, options)
nuchan := a.Srv.Store.User().SearchNotInChannel(teamId, channelId, term, searchOptions) nuchan := a.Srv.Store.User().SearchNotInChannel(teamId, channelId, term, options)
autocomplete := &model.UserAutocompleteInChannel{} autocomplete := &model.UserAutocompleteInChannel{}
@@ -1565,7 +1565,7 @@ func (a *App) AutocompleteUsersInChannel(teamId string, channelId string, term s
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
for _, user := range users { for _, user := range users {
a.SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, options.IsAdmin)
} }
autocomplete.InChannel = users autocomplete.InChannel = users
@@ -1577,7 +1577,7 @@ func (a *App) AutocompleteUsersInChannel(teamId string, channelId string, term s
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
for _, user := range users { for _, user := range users {
a.SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, options.IsAdmin)
} }
autocomplete.OutOfChannel = users autocomplete.OutOfChannel = users
@@ -1586,16 +1586,16 @@ func (a *App) AutocompleteUsersInChannel(teamId string, channelId string, term s
return autocomplete, nil return autocomplete, nil
} }
func (a *App) AutocompleteUsersInTeam(teamId string, term string, searchOptions map[string]bool, asAdmin bool) (*model.UserAutocompleteInTeam, *model.AppError) { func (a *App) AutocompleteUsersInTeam(teamId string, term string, options *model.UserSearchOptions) (*model.UserAutocompleteInTeam, *model.AppError) {
autocomplete := &model.UserAutocompleteInTeam{} autocomplete := &model.UserAutocompleteInTeam{}
if result := <-a.Srv.Store.User().Search(teamId, term, searchOptions); result.Err != nil { if result := <-a.Srv.Store.User().Search(teamId, term, options); result.Err != nil {
return nil, result.Err return nil, result.Err
} else { } else {
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
for _, user := range users { for _, user := range users {
a.SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, options.IsAdmin)
} }
autocomplete.InTeam = users autocomplete.InTeam = users

Просмотреть файл

@@ -417,6 +417,10 @@ func (c *Client4) DoApiPost(url string, data string) (*http.Response, *AppError)
return c.DoApiRequest(http.MethodPost, c.ApiUrl+url, data, "") return c.DoApiRequest(http.MethodPost, c.ApiUrl+url, data, "")
} }
func (c *Client4) doApiPostBytes(url string, data []byte) (*http.Response, *AppError) {
return c.doApiRequestBytes(http.MethodPost, c.ApiUrl+url, data, "")
}
func (c *Client4) DoApiPut(url string, data string) (*http.Response, *AppError) { func (c *Client4) DoApiPut(url string, data string) (*http.Response, *AppError) {
return c.DoApiRequest(http.MethodPut, c.ApiUrl+url, data, "") return c.DoApiRequest(http.MethodPut, c.ApiUrl+url, data, "")
} }
@@ -426,7 +430,15 @@ func (c *Client4) DoApiDelete(url string) (*http.Response, *AppError) {
} }
func (c *Client4) DoApiRequest(method, url, data, etag string) (*http.Response, *AppError) { func (c *Client4) DoApiRequest(method, url, data, etag string) (*http.Response, *AppError) {
rq, _ := http.NewRequest(method, url, strings.NewReader(data)) return c.doApiRequestReader(method, url, strings.NewReader(data), etag)
}
func (c *Client4) doApiRequestBytes(method, url string, data []byte, etag string) (*http.Response, *AppError) {
return c.doApiRequestReader(method, url, bytes.NewReader(data), etag)
}
func (c *Client4) doApiRequestReader(method, url string, data io.Reader, etag string) (*http.Response, *AppError) {
rq, _ := http.NewRequest(method, url, data)
if len(etag) > 0 { if len(etag) > 0 {
rq.Header.Set(HEADER_ETAG_CLIENT, etag) rq.Header.Set(HEADER_ETAG_CLIENT, etag)
@@ -691,8 +703,8 @@ func (c *Client4) GetUserByEmail(email, etag string) (*User, *Response) {
} }
// AutocompleteUsersInTeam returns the users on a team based on search term. // AutocompleteUsersInTeam returns the users on a team based on search term.
func (c *Client4) AutocompleteUsersInTeam(teamId string, username string, etag string) (*UserAutocomplete, *Response) { func (c *Client4) AutocompleteUsersInTeam(teamId string, username string, limit int, etag string) (*UserAutocomplete, *Response) {
query := fmt.Sprintf("?in_team=%v&name=%v", teamId, username) query := fmt.Sprintf("?in_team=%v&name=%v&limit=%d", teamId, username, limit)
if r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag); err != nil { if r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag); err != nil {
return nil, BuildErrorResponse(r, err) return nil, BuildErrorResponse(r, err)
} else { } else {
@@ -702,8 +714,8 @@ func (c *Client4) AutocompleteUsersInTeam(teamId string, username string, etag s
} }
// AutocompleteUsersInChannel returns the users in a channel based on search term. // AutocompleteUsersInChannel returns the users in a channel based on search term.
func (c *Client4) AutocompleteUsersInChannel(teamId string, channelId string, username string, etag string) (*UserAutocomplete, *Response) { func (c *Client4) AutocompleteUsersInChannel(teamId string, channelId string, username string, limit int, etag string) (*UserAutocomplete, *Response) {
query := fmt.Sprintf("?in_team=%v&in_channel=%v&name=%v", teamId, channelId, username) query := fmt.Sprintf("?in_team=%v&in_channel=%v&name=%v&limit=%d", teamId, channelId, username, limit)
if r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag); err != nil { if r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag); err != nil {
return nil, BuildErrorResponse(r, err) return nil, BuildErrorResponse(r, err)
} else { } else {
@@ -713,8 +725,8 @@ func (c *Client4) AutocompleteUsersInChannel(teamId string, channelId string, us
} }
// AutocompleteUsers returns the users in the system based on search term. // AutocompleteUsers returns the users in the system based on search term.
func (c *Client4) AutocompleteUsers(username string, etag string) (*UserAutocomplete, *Response) { func (c *Client4) AutocompleteUsers(username string, limit int, etag string) (*UserAutocomplete, *Response) {
query := fmt.Sprintf("?name=%v", username) query := fmt.Sprintf("?name=%v&limit=%d", username, limit)
if r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag); err != nil { if r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag); err != nil {
return nil, BuildErrorResponse(r, err) return nil, BuildErrorResponse(r, err)
} else { } else {
@@ -875,7 +887,7 @@ func (c *Client4) GetUsersByUsernames(usernames []string) ([]*User, *Response) {
// SearchUsers returns a list of users based on some search criteria. // SearchUsers returns a list of users based on some search criteria.
func (c *Client4) SearchUsers(search *UserSearch) ([]*User, *Response) { func (c *Client4) SearchUsers(search *UserSearch) ([]*User, *Response) {
if r, err := c.DoApiPost(c.GetUsersRoute()+"/search", search.ToJson()); err != nil { if r, err := c.doApiPostBytes(c.GetUsersRoute()+"/search", search.ToJson()); err != nil {
return nil, BuildErrorResponse(r, err) return nil, BuildErrorResponse(r, err)
} else { } else {
defer closeBody(r) defer closeBody(r)

Просмотреть файл

@@ -8,6 +8,10 @@ import (
"io" "io"
) )
const USER_SEARCH_MAX_LIMIT = 1000
const USER_SEARCH_DEFAULT_LIMIT = 100
// UserSearch captures the parameters provided by a client for initiating a user search.
type UserSearch struct { type UserSearch struct {
Term string `json:"term"` Term string `json:"term"`
TeamId string `json:"team_id"` TeamId string `json:"team_id"`
@@ -16,17 +20,38 @@ type UserSearch struct {
NotInChannelId string `json:"not_in_channel_id"` NotInChannelId string `json:"not_in_channel_id"`
AllowInactive bool `json:"allow_inactive"` AllowInactive bool `json:"allow_inactive"`
WithoutTeam bool `json:"without_team"` WithoutTeam bool `json:"without_team"`
Limit int `json:"limit"`
} }
// ToJson convert a User to a json string // ToJson convert a User to a json string
func (u *UserSearch) ToJson() string { func (u *UserSearch) ToJson() []byte {
b, _ := json.Marshal(u) b, _ := json.Marshal(u)
return string(b) return b
} }
// UserSearchFromJson will decode the input and return a User // UserSearchFromJson will decode the input and return a User
func UserSearchFromJson(data io.Reader) *UserSearch { func UserSearchFromJson(data io.Reader) *UserSearch {
var us *UserSearch var us *UserSearch
json.NewDecoder(data).Decode(&us) json.NewDecoder(data).Decode(&us)
if us.Limit == 0 {
us.Limit = USER_SEARCH_DEFAULT_LIMIT
}
return us return us
} }
// UserSearchOptions captures internal parameters derived from the user's permissions and a
// UserSearch request.
type UserSearchOptions struct {
// IsAdmin tracks whether or not the search is being conducted by an administrator.
IsAdmin bool
// AllowEmails allows search to examine the emails of users.
AllowEmails bool
// AllowFullNames allows search to examine the full names of users, vs. just usernames and nicknames.
AllowFullNames bool
// AllowInactive configures whether or not to return inactive users in the search results.
AllowInactive bool
// Limit limits the total number of results returned.
Limit int
}

Просмотреть файл

@@ -4,14 +4,14 @@
package model package model
import ( import (
"strings" "bytes"
"testing" "testing"
) )
func TestUserSearchJson(t *testing.T) { func TestUserSearchJson(t *testing.T) {
userSearch := UserSearch{Term: NewId(), TeamId: NewId()} userSearch := UserSearch{Term: NewId(), TeamId: NewId()}
json := userSearch.ToJson() json := userSearch.ToJson()
ruserSearch := UserSearchFromJson(strings.NewReader(json)) ruserSearch := UserSearchFromJson(bytes.NewReader(json))
if userSearch.Term != ruserSearch.Term { if userSearch.Term != ruserSearch.Term {
t.Fatal("Terms do not match") t.Fatal("Terms do not match")

Просмотреть файл

@@ -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) { return store.Do(func(result *store.StoreResult) {
searchQuery := "" searchQuery := ""
if teamId == "" { if teamId == "" {
// Id != '' is added because both SEARCH_CLAUSE and INACTIVE_CLAUSE start with an AND // Id != '' is added because both SEARCH_CLAUSE and INACTIVE_CLAUSE start with an AND
searchQuery = ` searchQuery = `
SELECT SELECT
@@ -986,8 +985,8 @@ func (us SqlUserStore) Search(teamId string, term string, options map[string]boo
Id != '' Id != ''
SEARCH_CLAUSE SEARCH_CLAUSE
INACTIVE_CLAUSE INACTIVE_CLAUSE
ORDER BY Username ASC ORDER BY Username ASC
LIMIT 100` LIMIT :Limit`
} else { } else {
searchQuery = ` searchQuery = `
SELECT SELECT
@@ -1000,16 +999,19 @@ func (us SqlUserStore) Search(teamId string, term string, options map[string]boo
AND TeamMembers.DeleteAt = 0 AND TeamMembers.DeleteAt = 0
SEARCH_CLAUSE SEARCH_CLAUSE
INACTIVE_CLAUSE INACTIVE_CLAUSE
ORDER BY Users.Username ASC ORDER BY Users.Username ASC
LIMIT 100` 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) { return store.Do(func(result *store.StoreResult) {
searchQuery := ` searchQuery := `
SELECT SELECT
@@ -1027,14 +1029,16 @@ func (us SqlUserStore) SearchWithoutTeam(term string, options map[string]bool) s
SEARCH_CLAUSE SEARCH_CLAUSE
INACTIVE_CLAUSE INACTIVE_CLAUSE
ORDER BY Username ASC 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) { return store.Do(func(result *store.StoreResult) {
searchQuery := ` searchQuery := `
SELECT SELECT
@@ -1048,14 +1052,17 @@ func (us SqlUserStore) SearchNotInTeam(notInTeamId string, term string, options
SEARCH_CLAUSE SEARCH_CLAUSE
INACTIVE_CLAUSE INACTIVE_CLAUSE
ORDER BY Users.Username ASC 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) { return store.Do(func(result *store.StoreResult) {
searchQuery := "" searchQuery := ""
if teamId == "" { if teamId == "" {
@@ -1071,7 +1078,7 @@ func (us SqlUserStore) SearchNotInChannel(teamId string, channelId string, term
SEARCH_CLAUSE SEARCH_CLAUSE
INACTIVE_CLAUSE INACTIVE_CLAUSE
ORDER BY Users.Username ASC ORDER BY Users.Username ASC
LIMIT 100` LIMIT :Limit`
} else { } else {
searchQuery = ` searchQuery = `
SELECT SELECT
@@ -1089,30 +1096,37 @@ func (us SqlUserStore) SearchNotInChannel(teamId string, channelId string, term
SEARCH_CLAUSE SEARCH_CLAUSE
INACTIVE_CLAUSE INACTIVE_CLAUSE
ORDER BY Users.Username ASC 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) { return store.Do(func(result *store.StoreResult) {
searchQuery := ` searchQuery := `
SELECT SELECT
Users.* Users.*
FROM FROM
Users, ChannelMembers Users, ChannelMembers
WHERE WHERE
ChannelMembers.ChannelId = :ChannelId ChannelMembers.ChannelId = :ChannelId
AND ChannelMembers.UserId = Users.Id AND ChannelMembers.UserId = Users.Id
SEARCH_CLAUSE SEARCH_CLAUSE
INACTIVE_CLAUSE INACTIVE_CLAUSE
ORDER BY Users.Username ASC ORDER BY Users.Username ASC
LIMIT 100` 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) 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{} result := store.StoreResult{}
// These chars must be removed from the like query. // 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) term = strings.Replace(term, c, "*"+c, -1)
} }
searchType := USER_SEARCH_TYPE_ALL searchType := USER_SEARCH_TYPE_NAMES_NO_FULL_NAME
if ok := options[store.USER_SEARCH_OPTION_NAMES_ONLY]; ok { if options.AllowEmails {
searchType = USER_SEARCH_TYPE_NAMES if options.AllowFullNames {
} else if ok = options[store.USER_SEARCH_OPTION_NAMES_ONLY_NO_FULL_NAME]; ok { searchType = USER_SEARCH_TYPE_ALL
searchType = USER_SEARCH_TYPE_NAMES_NO_FULL_NAME } else {
} 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_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) searchQuery = strings.Replace(searchQuery, "INACTIVE_CLAUSE", "", 1)
} else { } else {
searchQuery = strings.Replace(searchQuery, "INACTIVE_CLAUSE", "AND Users.DeleteAt = 0", 1) searchQuery = strings.Replace(searchQuery, "INACTIVE_CLAUSE", "AND Users.DeleteAt = 0", 1)

Просмотреть файл

@@ -272,11 +272,11 @@ type UserStore interface {
GetAnyUnreadPostCountForChannel(userId string, channelId string) StoreChannel GetAnyUnreadPostCountForChannel(userId string, channelId string) StoreChannel
GetRecentlyActiveUsersForTeam(teamId string, offset, limit int) StoreChannel GetRecentlyActiveUsersForTeam(teamId string, offset, limit int) StoreChannel
GetNewUsersForTeam(teamId string, offset, limit int) StoreChannel GetNewUsersForTeam(teamId string, offset, limit int) StoreChannel
Search(teamId string, term string, options map[string]bool) StoreChannel Search(teamId string, term string, options *model.UserSearchOptions) StoreChannel
SearchNotInTeam(notInTeamId string, term string, options map[string]bool) StoreChannel SearchNotInTeam(notInTeamId string, term string, options *model.UserSearchOptions) StoreChannel
SearchInChannel(channelId string, term string, options map[string]bool) StoreChannel SearchInChannel(channelId string, term string, options *model.UserSearchOptions) StoreChannel
SearchNotInChannel(teamId string, channelId string, term string, options map[string]bool) StoreChannel SearchNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) StoreChannel
SearchWithoutTeam(term string, options map[string]bool) StoreChannel SearchWithoutTeam(term string, options *model.UserSearchOptions) StoreChannel
AnalyticsGetInactiveUsersCount() StoreChannel AnalyticsGetInactiveUsersCount() StoreChannel
AnalyticsGetSystemAdminCount() StoreChannel AnalyticsGetSystemAdminCount() StoreChannel
GetProfilesNotInTeam(teamId string, offset int, limit int) StoreChannel GetProfilesNotInTeam(teamId string, offset int, limit int) StoreChannel

Просмотреть файл

@@ -314,6 +314,22 @@ func (_m *ChannelStore) GetChannelMembersForExport(userId string, teamId string)
return r0 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 // GetChannelUnread provides a mock function with given fields: channelId, userId
func (_m *ChannelStore) GetChannelUnread(channelId string, userId string) store.StoreChannel { func (_m *ChannelStore) GetChannelUnread(channelId string, userId string) store.StoreChannel {
ret := _m.Called(channelId, userId) ret := _m.Called(channelId, userId)
@@ -442,21 +458,6 @@ func (_m *ChannelStore) GetMember(channelId string, userId string) store.StoreCh
return r0 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 // GetMemberCount provides a mock function with given fields: channelId, allowFromCache
func (_m *ChannelStore) GetMemberCount(channelId string, allowFromCache bool) store.StoreChannel { func (_m *ChannelStore) GetMemberCount(channelId string, allowFromCache bool) store.StoreChannel {
ret := _m.Called(channelId, allowFromCache) 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 // 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) ret := _m.Called(teamId, term, options)
var r0 store.StoreChannel 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) r0 = rf(teamId, term, options)
} else { } else {
if ret.Get(0) != nil { 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 // 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) ret := _m.Called(channelId, term, options)
var r0 store.StoreChannel 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) r0 = rf(channelId, term, options)
} else { } else {
if ret.Get(0) != nil { 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 // 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) ret := _m.Called(teamId, channelId, term, options)
var r0 store.StoreChannel 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) r0 = rf(teamId, channelId, term, options)
} else { } else {
if ret.Get(0) != nil { 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 // 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) ret := _m.Called(notInTeamId, term, options)
var r0 store.StoreChannel 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) r0 = rf(notInTeamId, term, options)
} else { } else {
if ret.Get(0) != nil { 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 // 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) ret := _m.Called(term, options)
var r0 store.StoreChannel 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) r0 = rf(term, options)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {

Разница между файлами не показана из-за своего большого размера Загрузить разницу