From 7ff2aef7facdeb025a1651ef411fceb3d81932c1 Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Fri, 3 Feb 2017 15:17:34 -0500 Subject: Implement GET /users endpoint for APIv4 (#5277) --- api4/apitestlib.go | 2 + api4/channel_test.go | 12 ++-- api4/params.go | 23 +++++++ api4/user.go | 62 +++++++++++++++++++ api4/user_test.go | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 265 insertions(+), 6 deletions(-) (limited to 'api4') diff --git a/api4/apitestlib.go b/api4/apitestlib.go index 6229c8a08..f647ffa9c 100644 --- a/api4/apitestlib.go +++ b/api4/apitestlib.go @@ -97,6 +97,8 @@ func (me *TestHelper) InitBasic() *TestHelper { LinkUserToTeam(me.BasicUser, me.BasicTeam) me.BasicUser2 = me.CreateUser() LinkUserToTeam(me.BasicUser2, me.BasicTeam) + app.AddUserToChannel(me.BasicUser, me.BasicChannel) + app.AddUserToChannel(me.BasicUser2, me.BasicChannel) app.UpdateUserRoles(me.BasicUser.Id, model.ROLE_SYSTEM_USER.Id) me.LoginBasic() diff --git a/api4/channel_test.go b/api4/channel_test.go index 5123d7730..237d57f01 100644 --- a/api4/channel_test.go +++ b/api4/channel_test.go @@ -77,17 +77,17 @@ func TestCreateChannel(t *testing.T) { // Check permissions with policy config changes isLicensed := utils.IsLicensed license := utils.License - restrictPublicChannel := *utils.Cfg.TeamSettings.RestrictPublicChannelManagement - restrictPrivateChannel := *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement + restrictPublicChannel := *utils.Cfg.TeamSettings.RestrictPublicChannelCreation + restrictPrivateChannel := *utils.Cfg.TeamSettings.RestrictPrivateChannelCreation defer func() { - *utils.Cfg.TeamSettings.RestrictPublicChannelManagement = restrictPublicChannel - *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = restrictPrivateChannel + *utils.Cfg.TeamSettings.RestrictPublicChannelCreation = restrictPublicChannel + *utils.Cfg.TeamSettings.RestrictPrivateChannelCreation = restrictPrivateChannel utils.IsLicensed = isLicensed utils.License = license utils.SetDefaultRolesBasedOnConfig() }() - *utils.Cfg.TeamSettings.RestrictPublicChannelManagement = model.PERMISSIONS_ALL - *utils.Cfg.TeamSettings.RestrictPrivateChannelManagement = model.PERMISSIONS_ALL + *utils.Cfg.TeamSettings.RestrictPublicChannelCreation = model.PERMISSIONS_ALL + *utils.Cfg.TeamSettings.RestrictPrivateChannelCreation = model.PERMISSIONS_ALL utils.SetDefaultRolesBasedOnConfig() utils.IsLicensed = true utils.License = &model.License{Features: &model.Features{}} diff --git a/api4/params.go b/api4/params.go index 452b9ba21..1c0c153ea 100644 --- a/api4/params.go +++ b/api4/params.go @@ -5,10 +5,17 @@ package api4 import ( "net/http" + "strconv" "github.com/gorilla/mux" ) +const ( + PAGE_DEFAULT = 0 + PER_PAGE_DEFAULT = 60 + PER_PAGE_MAXIMUM = 200 +) + type ApiParams struct { UserId string TeamId string @@ -18,6 +25,8 @@ type ApiParams struct { CommandId string HookId string EmojiId string + Page int + PerPage int } func ApiParamsFromRequest(r *http.Request) *ApiParams { @@ -57,5 +66,19 @@ func ApiParamsFromRequest(r *http.Request) *ApiParams { params.EmojiId = val } + if val, err := strconv.Atoi(r.URL.Query().Get("page")); err != nil { + params.Page = PAGE_DEFAULT + } else { + params.Page = val + } + + if val, err := strconv.Atoi(r.URL.Query().Get("per_page")); err != nil { + params.PerPage = PER_PAGE_DEFAULT + } else if val > PER_PAGE_MAXIMUM { + params.PerPage = PER_PAGE_MAXIMUM + } else { + params.PerPage = val + } + return params } diff --git a/api4/user.go b/api4/user.go index 19d3446fb..74983aa54 100644 --- a/api4/user.go +++ b/api4/user.go @@ -16,6 +16,7 @@ func InitUser() { l4g.Debug(utils.T("api.user.init.debug")) BaseRoutes.Users.Handle("", ApiHandler(createUser)).Methods("POST") + BaseRoutes.Users.Handle("", ApiSessionRequired(getUsers)).Methods("GET") BaseRoutes.Users.Handle("/ids", ApiSessionRequired(getUsersByIds)).Methods("POST") BaseRoutes.User.Handle("", ApiSessionRequired(getUser)).Methods("GET") @@ -86,6 +87,67 @@ func getUser(c *Context, w http.ResponseWriter, r *http.Request) { } } +func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { + inTeamId := r.URL.Query().Get("in_team") + inChannelId := r.URL.Query().Get("in_channel") + notInChannelId := r.URL.Query().Get("not_in_channel") + + if len(notInChannelId) > 0 && len(inTeamId) == 0 { + c.SetInvalidParam("team_id") + return + } + + var profiles []*model.User + var err *model.AppError + etag := "" + + if len(notInChannelId) > 0 { + if !app.SessionHasPermissionToChannel(c.Session, notInChannelId, model.PERMISSION_READ_CHANNEL) { + c.SetPermissionError(model.PERMISSION_READ_CHANNEL) + return + } + + profiles, err = app.GetUsersNotInChannelPage(inTeamId, notInChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin()) + } else if len(inTeamId) > 0 { + if !app.SessionHasPermissionToTeam(c.Session, inTeamId, model.PERMISSION_VIEW_TEAM) { + c.SetPermissionError(model.PERMISSION_VIEW_TEAM) + return + } + + etag = app.GetUsersInTeamEtag(inTeamId) + if HandleEtag(etag, "Get Users in Team", w, r) { + return + } + + profiles, err = app.GetUsersInTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin()) + } else if len(inChannelId) > 0 { + if !app.SessionHasPermissionToChannel(c.Session, inChannelId, model.PERMISSION_READ_CHANNEL) { + c.SetPermissionError(model.PERMISSION_READ_CHANNEL) + return + } + + profiles, err = app.GetUsersInChannelPage(inChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin()) + } else { + // No permission check required + + etag = app.GetUsersEtag() + if HandleEtag(etag, "Get Users", w, r) { + return + } + profiles, err = app.GetUsersPage(c.Params.Page, c.Params.PerPage, c.IsSystemAdmin()) + } + + if err != nil { + c.Err = err + return + } else { + if len(etag) > 0 { + w.Header().Set(model.HEADER_ETAG_SERVER, etag) + } + w.Write([]byte(model.UserListToJson(profiles))) + } +} + func getUsersByIds(c *Context, w http.ResponseWriter, r *http.Request) { userIds := model.ArrayFromJson(r.Body) diff --git a/api4/user_test.go b/api4/user_test.go index 54aae4e49..082b48dd6 100644 --- a/api4/user_test.go +++ b/api4/user_test.go @@ -242,3 +242,175 @@ func TestUpdateUserRoles(t *testing.T) { _, resp = SystemAdminClient.UpdateUserRoles(model.NewId(), model.ROLE_SYSTEM_USER.Id) CheckBadRequestStatus(t, resp) } + +func TestGetUsers(t *testing.T) { + th := Setup().InitBasic() + defer TearDown() + Client := th.Client + + rusers, resp := Client.GetUsers(0, 60, "") + CheckNoError(t, resp) + for _, u := range rusers { + CheckUserSanitization(t, u) + } + + rusers, resp = Client.GetUsers(0, 60, resp.Etag) + CheckEtag(t, rusers, resp) + + rusers, resp = Client.GetUsers(0, 1, "") + CheckNoError(t, resp) + if len(rusers) != 1 { + t.Fatal("should be 1 per page") + } + + rusers, resp = Client.GetUsers(1, 1, "") + CheckNoError(t, resp) + if len(rusers) != 1 { + t.Fatal("should be 1 per page") + } + + rusers, resp = Client.GetUsers(10000, 100, "") + CheckNoError(t, resp) + if len(rusers) != 0 { + t.Fatal("should be no users") + } + + // Check default params for page and per_page + if _, err := Client.DoApiGet("/users", ""); err != nil { + t.Fatal("should not have errored") + } + + Client.Logout() + _, resp = Client.GetUsers(0, 60, "") + CheckUnauthorizedStatus(t, resp) +} + +func TestGetUsersInTeam(t *testing.T) { + th := Setup().InitBasic().InitSystemAdmin() + defer TearDown() + Client := th.Client + teamId := th.BasicTeam.Id + + rusers, resp := Client.GetUsersInTeam(teamId, 0, 60, "") + CheckNoError(t, resp) + for _, u := range rusers { + CheckUserSanitization(t, u) + } + + rusers, resp = Client.GetUsersInTeam(teamId, 0, 60, resp.Etag) + CheckEtag(t, rusers, resp) + + rusers, resp = Client.GetUsersInTeam(teamId, 0, 1, "") + CheckNoError(t, resp) + if len(rusers) != 1 { + t.Fatal("should be 1 per page") + } + + rusers, resp = Client.GetUsersInTeam(teamId, 1, 1, "") + CheckNoError(t, resp) + if len(rusers) != 1 { + t.Fatal("should be 1 per page") + } + + rusers, resp = Client.GetUsersInTeam(teamId, 10000, 100, "") + CheckNoError(t, resp) + if len(rusers) != 0 { + t.Fatal("should be no users") + } + + Client.Logout() + _, resp = Client.GetUsersInTeam(teamId, 0, 60, "") + CheckUnauthorizedStatus(t, resp) + + user := th.CreateUser() + Client.Login(user.Email, user.Password) + _, resp = Client.GetUsersInTeam(teamId, 0, 60, "") + CheckForbiddenStatus(t, resp) + + _, resp = th.SystemAdminClient.GetUsersInTeam(teamId, 0, 60, "") + CheckNoError(t, resp) +} + +func TestGetUsersInChannel(t *testing.T) { + th := Setup().InitBasic().InitSystemAdmin() + defer TearDown() + Client := th.Client + channelId := th.BasicChannel.Id + + rusers, resp := Client.GetUsersInChannel(channelId, 0, 60, "") + CheckNoError(t, resp) + for _, u := range rusers { + CheckUserSanitization(t, u) + } + + rusers, resp = Client.GetUsersInChannel(channelId, 0, 1, "") + CheckNoError(t, resp) + if len(rusers) != 1 { + t.Fatal("should be 1 per page") + } + + rusers, resp = Client.GetUsersInChannel(channelId, 1, 1, "") + CheckNoError(t, resp) + if len(rusers) != 1 { + t.Fatal("should be 1 per page") + } + + rusers, resp = Client.GetUsersInChannel(channelId, 10000, 100, "") + CheckNoError(t, resp) + if len(rusers) != 0 { + t.Fatal("should be no users") + } + + Client.Logout() + _, resp = Client.GetUsersInChannel(channelId, 0, 60, "") + CheckUnauthorizedStatus(t, resp) + + user := th.CreateUser() + Client.Login(user.Email, user.Password) + _, resp = Client.GetUsersInChannel(channelId, 0, 60, "") + CheckForbiddenStatus(t, resp) + + _, resp = th.SystemAdminClient.GetUsersInChannel(channelId, 0, 60, "") + CheckNoError(t, resp) +} + +func TestGetUsersNotInChannel(t *testing.T) { + th := Setup().InitBasic().InitSystemAdmin() + defer TearDown() + Client := th.Client + teamId := th.BasicTeam.Id + channelId := th.BasicChannel.Id + + user := th.CreateUser() + LinkUserToTeam(user, th.BasicTeam) + + rusers, resp := Client.GetUsersNotInChannel(teamId, channelId, 0, 60, "") + CheckNoError(t, resp) + for _, u := range rusers { + CheckUserSanitization(t, u) + } + + rusers, resp = Client.GetUsersNotInChannel(teamId, channelId, 0, 1, "") + CheckNoError(t, resp) + if len(rusers) != 1 { + t.Log(len(rusers)) + t.Fatal("should be 1 per page") + } + + rusers, resp = Client.GetUsersNotInChannel(teamId, channelId, 10000, 100, "") + CheckNoError(t, resp) + if len(rusers) != 0 { + t.Fatal("should be no users") + } + + Client.Logout() + _, resp = Client.GetUsersNotInChannel(teamId, channelId, 0, 60, "") + CheckUnauthorizedStatus(t, resp) + + Client.Login(user.Email, user.Password) + _, resp = Client.GetUsersNotInChannel(teamId, channelId, 0, 60, "") + CheckForbiddenStatus(t, resp) + + _, resp = th.SystemAdminClient.GetUsersNotInChannel(teamId, channelId, 0, 60, "") + CheckNoError(t, resp) +} -- cgit v1.2.3-1-g7c22