diff options
-rw-r--r-- | api/user.go | 33 | ||||
-rw-r--r-- | api/user_test.go | 137 | ||||
-rw-r--r-- | store/sql_user_store.go | 26 |
3 files changed, 186 insertions, 10 deletions
diff --git a/api/user.go b/api/user.go index f5f2582b3..e5d00ea36 100644 --- a/api/user.go +++ b/api/user.go @@ -2648,6 +2648,21 @@ func searchUsers(c *Context, w http.ResponseWriter, r *http.Request) { searchOptions := map[string]bool{} searchOptions[store.USER_SEARCH_OPTION_ALLOW_INACTIVE] = props.AllowInactive + if !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) { + hideFullName := !utils.Cfg.PrivacySettings.ShowFullName + hideEmail := !utils.Cfg.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 + } + + c.Err = nil + } + var uchan store.StoreChannel if props.InChannelId != "" { uchan = Srv.Store.User().SearchInChannel(props.InChannelId, props.Term, searchOptions) @@ -2711,7 +2726,14 @@ func autocompleteUsersInChannel(c *Context, w http.ResponseWriter, r *http.Reque } searchOptions := map[string]bool{} - searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true + + hideFullName := !utils.Cfg.PrivacySettings.ShowFullName + if hideFullName && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) { + searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY_NO_FULL_NAME] = true + c.Err = nil + } else { + searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true + } uchan := Srv.Store.User().SearchInChannel(channelId, term, searchOptions) nuchan := Srv.Store.User().SearchNotInChannel(teamId, channelId, term, searchOptions) @@ -2760,7 +2782,14 @@ func autocompleteUsersInTeam(c *Context, w http.ResponseWriter, r *http.Request) } searchOptions := map[string]bool{} - searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true + + hideFullName := !utils.Cfg.PrivacySettings.ShowFullName + if hideFullName && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM) { + searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY_NO_FULL_NAME] = true + c.Err = nil + } else { + searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true + } uchan := Srv.Store.User().Search(teamId, term, searchOptions) diff --git a/api/user_test.go b/api/user_test.go index 02ea71c83..13ae45f6e 100644 --- a/api/user_test.go +++ b/api/user_test.go @@ -2240,6 +2240,112 @@ func TestSearchUsers(t *testing.T) { } } + emailPrivacy := utils.Cfg.PrivacySettings.ShowEmailAddress + namePrivacy := utils.Cfg.PrivacySettings.ShowFullName + defer func() { + utils.Cfg.PrivacySettings.ShowEmailAddress = emailPrivacy + utils.Cfg.PrivacySettings.ShowFullName = namePrivacy + }() + utils.Cfg.PrivacySettings.ShowEmailAddress = false + utils.Cfg.PrivacySettings.ShowFullName = false + + privacyEmailPrefix := strings.ToLower(model.NewId()) + privacyUser := &model.User{Email: privacyEmailPrefix + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1", FirstName: model.NewId(), LastName: "Jimmers"} + privacyUser = Client.Must(Client.CreateUser(privacyUser, "")).Data.(*model.User) + LinkUserToTeam(privacyUser, th.BasicTeam) + + if result, err := Client.SearchUsers(model.UserSearch{Term: privacyUser.FirstName}); err != nil { + t.Fatal(err) + } else { + users := result.Data.([]*model.User) + + found := false + for _, user := range users { + if user.Id == privacyUser.Id { + found = true + } + } + + if found { + t.Fatal("should not have found profile") + } + } + + utils.Cfg.PrivacySettings.ShowEmailAddress = true + + if result, err := Client.SearchUsers(model.UserSearch{Term: privacyUser.FirstName}); err != nil { + t.Fatal(err) + } else { + users := result.Data.([]*model.User) + + found := false + for _, user := range users { + if user.Id == privacyUser.Id { + found = true + } + } + + if found { + t.Fatal("should not have found profile") + } + } + + utils.Cfg.PrivacySettings.ShowEmailAddress = false + utils.Cfg.PrivacySettings.ShowFullName = true + + if result, err := Client.SearchUsers(model.UserSearch{Term: privacyUser.FirstName}); err != nil { + t.Fatal(err) + } else { + users := result.Data.([]*model.User) + + found := false + for _, user := range users { + if user.Id == privacyUser.Id { + found = true + } + } + + if !found { + t.Fatal("should have found profile") + } + } + + if result, err := Client.SearchUsers(model.UserSearch{Term: privacyEmailPrefix}); err != nil { + t.Fatal(err) + } else { + users := result.Data.([]*model.User) + + found := false + for _, user := range users { + if user.Id == privacyUser.Id { + found = true + } + } + + if found { + t.Fatal("should not have found profile") + } + } + + utils.Cfg.PrivacySettings.ShowEmailAddress = true + + if result, err := Client.SearchUsers(model.UserSearch{Term: privacyEmailPrefix}); err != nil { + t.Fatal(err) + } else { + users := result.Data.([]*model.User) + + found := false + for _, user := range users { + if user.Id == privacyUser.Id { + found = true + } + } + + if !found { + t.Fatal("should have found profile") + } + } + th.LoginBasic2() if result, err := Client.SearchUsers(model.UserSearch{Term: th.BasicUser.Username}); err != nil { @@ -2364,6 +2470,37 @@ func TestAutocompleteUsers(t *testing.T) { } } + namePrivacy := utils.Cfg.PrivacySettings.ShowFullName + defer func() { + utils.Cfg.PrivacySettings.ShowFullName = namePrivacy + }() + utils.Cfg.PrivacySettings.ShowFullName = false + + privacyUser := &model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "passwd1", FirstName: model.NewId(), LastName: "Jimmers"} + privacyUser = Client.Must(Client.CreateUser(privacyUser, "")).Data.(*model.User) + LinkUserToTeam(privacyUser, th.BasicTeam) + + if result, err := Client.AutocompleteUsersInChannel(privacyUser.FirstName, th.BasicChannel.Id); err != nil { + t.Fatal(err) + } else { + autocomplete := result.Data.(*model.UserAutocompleteInChannel) + if len(autocomplete.InChannel) != 0 { + t.Fatal("should have returned no users") + } + if len(autocomplete.OutOfChannel) != 0 { + t.Fatal("should have returned no users") + } + } + + if result, err := Client.AutocompleteUsersInTeam(privacyUser.FirstName); err != nil { + t.Fatal(err) + } else { + autocomplete := result.Data.(*model.UserAutocompleteInTeam) + if len(autocomplete.InTeam) != 0 { + t.Fatal("should have returned no users") + } + } + if _, err := Client.AutocompleteUsersInChannel("", "junk"); err == nil { t.Fatal("should have errored - bad channel id") } diff --git a/store/sql_user_store.go b/store/sql_user_store.go index b09b479a9..1eea1fdc2 100644 --- a/store/sql_user_store.go +++ b/store/sql_user_store.go @@ -15,14 +15,18 @@ import ( ) const ( - MISSING_ACCOUNT_ERROR = "store.sql_user.missing_account.const" - MISSING_AUTH_ACCOUNT_ERROR = "store.sql_user.get_by_auth.missing_account.app_error" - PROFILES_IN_CHANNEL_CACHE_SIZE = 5000 - PROFILES_IN_CHANNEL_CACHE_SEC = 900 // 15 mins - USER_SEARCH_OPTION_NAMES_ONLY = "names_only" - USER_SEARCH_OPTION_ALLOW_INACTIVE = "allow_inactive" - USER_SEARCH_TYPE_NAMES = "Username, FirstName, LastName, Nickname" - USER_SEARCH_TYPE_ALL = "Username, FirstName, LastName, Nickname, Email" + MISSING_ACCOUNT_ERROR = "store.sql_user.missing_account.const" + MISSING_AUTH_ACCOUNT_ERROR = "store.sql_user.get_by_auth.missing_account.app_error" + PROFILES_IN_CHANNEL_CACHE_SIZE = 5000 + PROFILES_IN_CHANNEL_CACHE_SEC = 900 // 15 mins + USER_SEARCH_OPTION_NAMES_ONLY = "names_only" + USER_SEARCH_OPTION_NAMES_ONLY_NO_FULL_NAME = "names_only_no_full_name" + USER_SEARCH_OPTION_ALL_NO_FULL_NAME = "all_no_full_name" + USER_SEARCH_OPTION_ALLOW_INACTIVE = "allow_inactive" + USER_SEARCH_TYPE_NAMES_NO_FULL_NAME = "Username, Nickname" + USER_SEARCH_TYPE_NAMES = "Username, FirstName, LastName, Nickname" + USER_SEARCH_TYPE_ALL_NO_FULL_NAME = "Username, Nickname, Email" + USER_SEARCH_TYPE_ALL = "Username, FirstName, LastName, Nickname, Email" ) type SqlUserStore struct { @@ -62,7 +66,9 @@ func (us SqlUserStore) CreateIndexesIfNotExists() { us.CreateIndexIfNotExists("idx_users_delete_at", "Users", "DeleteAt") us.CreateFullTextIndexIfNotExists("idx_users_all_txt", "Users", USER_SEARCH_TYPE_ALL) + us.CreateFullTextIndexIfNotExists("idx_users_all_no_full_name_txt", "Users", USER_SEARCH_TYPE_ALL_NO_FULL_NAME) us.CreateFullTextIndexIfNotExists("idx_users_names_txt", "Users", USER_SEARCH_TYPE_NAMES) + us.CreateFullTextIndexIfNotExists("idx_users_names_no_full_name_txt", "Users", USER_SEARCH_TYPE_NAMES_NO_FULL_NAME) } func (us SqlUserStore) Save(user *model.User) StoreChannel { @@ -1241,6 +1247,10 @@ func (us SqlUserStore) performSearch(searchQuery string, term string, options ma searchType := USER_SEARCH_TYPE_ALL if ok := options[USER_SEARCH_OPTION_NAMES_ONLY]; ok { searchType = USER_SEARCH_TYPE_NAMES + } else if ok = options[USER_SEARCH_OPTION_NAMES_ONLY_NO_FULL_NAME]; ok { + searchType = USER_SEARCH_TYPE_NAMES_NO_FULL_NAME + } else if ok = options[USER_SEARCH_OPTION_ALL_NO_FULL_NAME]; ok { + searchType = USER_SEARCH_TYPE_ALL_NO_FULL_NAME } if ok := options[USER_SEARCH_OPTION_ALLOW_INACTIVE]; ok { |