Implement POST /users/search endpoint for APIv4 (#5822)
* Implement POST /users/search endpoint for APIv4 * PLT-2713 Added store functions for searching users that don't have a team * PLT-2713 Added 'without_team' option when searching users * PLT-2713 Added 'without_team' option when searching users (v4)
Этот коммит содержится в:
коммит произвёл
George Goldberg
родитель
7e2e823884
Коммит
2a753949f1
57
api4/user.go
57
api4/user.go
@@ -21,6 +21,7 @@ func InitUser() {
|
||||
BaseRoutes.Users.Handle("", ApiHandler(createUser)).Methods("POST")
|
||||
BaseRoutes.Users.Handle("", ApiSessionRequired(getUsers)).Methods("GET")
|
||||
BaseRoutes.Users.Handle("/ids", ApiSessionRequired(getUsersByIds)).Methods("POST")
|
||||
BaseRoutes.Users.Handle("/search", ApiSessionRequired(searchUsers)).Methods("POST")
|
||||
BaseRoutes.Users.Handle("/autocomplete", ApiSessionRequired(autocompleteUsers)).Methods("GET")
|
||||
|
||||
BaseRoutes.User.Handle("", ApiSessionRequired(getUser)).Methods("GET")
|
||||
@@ -334,6 +335,62 @@ func getUsersByIds(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func searchUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
props := model.UserSearchFromJson(r.Body)
|
||||
if props == nil {
|
||||
c.SetInvalidParam("")
|
||||
return
|
||||
}
|
||||
|
||||
if len(props.Term) == 0 {
|
||||
c.SetInvalidParam("term")
|
||||
return
|
||||
}
|
||||
|
||||
if props.TeamId == "" && props.NotInChannelId != "" {
|
||||
c.SetInvalidParam("team_id")
|
||||
return
|
||||
}
|
||||
|
||||
if props.InChannelId != "" && !app.SessionHasPermissionToChannel(c.Session, props.InChannelId, model.PERMISSION_READ_CHANNEL) {
|
||||
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
||||
return
|
||||
}
|
||||
|
||||
if props.NotInChannelId != "" && !app.SessionHasPermissionToChannel(c.Session, props.NotInChannelId, model.PERMISSION_READ_CHANNEL) {
|
||||
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
||||
return
|
||||
}
|
||||
|
||||
if props.TeamId != "" && !app.SessionHasPermissionToTeam(c.Session, props.TeamId, model.PERMISSION_VIEW_TEAM) {
|
||||
c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
|
||||
return
|
||||
}
|
||||
|
||||
searchOptions := map[string]bool{}
|
||||
searchOptions[store.USER_SEARCH_OPTION_ALLOW_INACTIVE] = props.AllowInactive
|
||||
|
||||
if !app.SessionHasPermissionTo(c.Session, 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
|
||||
}
|
||||
}
|
||||
|
||||
if profiles, err := app.SearchUsers(props, searchOptions, c.IsSystemAdmin()); err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
} else {
|
||||
w.Write([]byte(model.UserListToJson(profiles)))
|
||||
}
|
||||
}
|
||||
|
||||
func autocompleteUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
channelId := r.URL.Query().Get("in_channel")
|
||||
teamId := r.URL.Query().Get("in_team")
|
||||
|
||||
@@ -284,6 +284,156 @@ func TestGetUserByEmail(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSearchUsers(t *testing.T) {
|
||||
th := Setup().InitBasic().InitSystemAdmin()
|
||||
defer TearDown()
|
||||
Client := th.Client
|
||||
|
||||
search := &model.UserSearch{Term: th.BasicUser.Username}
|
||||
|
||||
users, resp := Client.SearchUsers(search)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if !findUserInList(th.BasicUser.Id, users) {
|
||||
t.Fatal("should have found user")
|
||||
}
|
||||
|
||||
_, err := app.UpdateActiveNoLdap(th.BasicUser2.Id, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
search.Term = th.BasicUser2.Username
|
||||
search.AllowInactive = false
|
||||
|
||||
users, resp = Client.SearchUsers(search)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if findUserInList(th.BasicUser2.Id, users) {
|
||||
t.Fatal("should not have found user")
|
||||
}
|
||||
|
||||
search.AllowInactive = true
|
||||
|
||||
users, resp = Client.SearchUsers(search)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if !findUserInList(th.BasicUser2.Id, users) {
|
||||
t.Fatal("should have found user")
|
||||
}
|
||||
|
||||
search.Term = th.BasicUser.Username
|
||||
search.AllowInactive = false
|
||||
search.TeamId = th.BasicTeam.Id
|
||||
|
||||
users, resp = Client.SearchUsers(search)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if !findUserInList(th.BasicUser.Id, users) {
|
||||
t.Fatal("should have found user")
|
||||
}
|
||||
|
||||
search.NotInChannelId = th.BasicChannel.Id
|
||||
|
||||
users, resp = Client.SearchUsers(search)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if findUserInList(th.BasicUser.Id, users) {
|
||||
t.Fatal("should not have found user")
|
||||
}
|
||||
|
||||
search.TeamId = ""
|
||||
search.NotInChannelId = ""
|
||||
search.InChannelId = th.BasicChannel.Id
|
||||
|
||||
users, resp = Client.SearchUsers(search)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if !findUserInList(th.BasicUser.Id, users) {
|
||||
t.Fatal("should have found user")
|
||||
}
|
||||
|
||||
search.InChannelId = ""
|
||||
search.NotInChannelId = th.BasicChannel.Id
|
||||
_, resp = Client.SearchUsers(search)
|
||||
CheckBadRequestStatus(t, resp)
|
||||
|
||||
search.NotInChannelId = model.NewId()
|
||||
search.TeamId = model.NewId()
|
||||
_, resp = Client.SearchUsers(search)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
|
||||
search.NotInChannelId = ""
|
||||
search.TeamId = model.NewId()
|
||||
_, resp = Client.SearchUsers(search)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
|
||||
search.InChannelId = model.NewId()
|
||||
search.TeamId = ""
|
||||
_, resp = Client.SearchUsers(search)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
|
||||
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
|
||||
|
||||
_, err = app.UpdateActiveNoLdap(th.BasicUser2.Id, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
search.InChannelId = ""
|
||||
search.Term = th.BasicUser2.Email
|
||||
users, resp = Client.SearchUsers(search)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if findUserInList(th.BasicUser2.Id, users) {
|
||||
t.Fatal("should not have found user")
|
||||
}
|
||||
|
||||
search.Term = th.BasicUser2.FirstName
|
||||
users, resp = Client.SearchUsers(search)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if findUserInList(th.BasicUser2.Id, users) {
|
||||
t.Fatal("should not have found user")
|
||||
}
|
||||
|
||||
search.Term = th.BasicUser2.LastName
|
||||
users, resp = Client.SearchUsers(search)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if findUserInList(th.BasicUser2.Id, users) {
|
||||
t.Fatal("should not have found user")
|
||||
}
|
||||
|
||||
search.Term = th.BasicUser.FirstName
|
||||
search.InChannelId = th.BasicChannel.Id
|
||||
search.NotInChannelId = th.BasicChannel.Id
|
||||
search.TeamId = th.BasicTeam.Id
|
||||
users, resp = th.SystemAdminClient.SearchUsers(search)
|
||||
CheckNoError(t, resp)
|
||||
|
||||
if !findUserInList(th.BasicUser.Id, users) {
|
||||
t.Fatal("should have found user")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func findUserInList(id string, users []*model.User) bool {
|
||||
for _, user := range users {
|
||||
if user.Id == id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestAutocompleteUsers(t *testing.T) {
|
||||
th := Setup().InitBasic().InitSystemAdmin()
|
||||
defer TearDown()
|
||||
|
||||
Ссылка в новой задаче
Block a user