From ea74613444c65e965a76a6ad7640f6c011c2c69b Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Sat, 25 Mar 2017 02:38:24 -0400 Subject: Implement some team endpoints for APIv4 (#5870) * Implement GET /users/{user_id}/teams/members endpoint for APIv4 * Implement DELETE /teams/{team_id}/members/{user_id} endpoint for APIv4 --- api4/api.go | 16 +++++++------ api4/team.go | 43 ++++++++++++++++++++++++++++++++++ api4/team_test.go | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 7 deletions(-) (limited to 'api4') diff --git a/api4/api.go b/api4/api.go index 6a55fbcbb..c967537ee 100644 --- a/api4/api.go +++ b/api4/api.go @@ -25,13 +25,14 @@ type Routes struct { UserByUsername *mux.Router // 'api/v4/users/username/{username:[A-Za-z0-9_-\.]+}' UserByEmail *mux.Router // 'api/v4/users/email/{email}' - Teams *mux.Router // 'api/v4/teams' - TeamsForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/teams' - Team *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}' - TeamForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/teams/{team_id:[A-Za-z0-9]+}' - TeamByName *mux.Router // 'api/v4/teams/name/{team_name:[A-Za-z0-9_-]+}' - TeamMembers *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9_-]+}/members' - TeamMember *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9_-]+}/members/{user_id:[A-Za-z0-9_-]+}' + Teams *mux.Router // 'api/v4/teams' + TeamsForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/teams' + Team *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}' + TeamForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/teams/{team_id:[A-Za-z0-9]+}' + TeamByName *mux.Router // 'api/v4/teams/name/{team_name:[A-Za-z0-9_-]+}' + TeamMembers *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9_-]+}/members' + TeamMember *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9_-]+}/members/{user_id:[A-Za-z0-9_-]+}' + TeamMembersForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/teams/members' Channels *mux.Router // 'api/v4/channels' Channel *mux.Router // 'api/v4/channels/{channel_id:[A-Za-z0-9]+}' @@ -111,6 +112,7 @@ func InitApi(full bool) { BaseRoutes.TeamByName = BaseRoutes.Teams.PathPrefix("/name/{team_name:[A-Za-z0-9_-]+}").Subrouter() BaseRoutes.TeamMembers = BaseRoutes.Team.PathPrefix("/members").Subrouter() BaseRoutes.TeamMember = BaseRoutes.TeamMembers.PathPrefix("/{user_id:[A-Za-z0-9]+}").Subrouter() + BaseRoutes.TeamMembersForUser = BaseRoutes.User.PathPrefix("/teams/members").Subrouter() BaseRoutes.Channels = BaseRoutes.ApiRoot.PathPrefix("/channels").Subrouter() BaseRoutes.Channel = BaseRoutes.Channels.PathPrefix("/{channel_id:[A-Za-z0-9]+}").Subrouter() diff --git a/api4/team.go b/api4/team.go index a9be5c8ab..489265251 100644 --- a/api4/team.go +++ b/api4/team.go @@ -26,7 +26,9 @@ func InitTeam() { BaseRoutes.Team.Handle("/stats", ApiSessionRequired(getTeamStats)).Methods("GET") BaseRoutes.TeamMembers.Handle("", ApiSessionRequired(getTeamMembers)).Methods("GET") BaseRoutes.TeamMembers.Handle("/ids", ApiSessionRequired(getTeamMembersByIds)).Methods("POST") + BaseRoutes.TeamMembersForUser.Handle("", ApiSessionRequired(getTeamMembersForUser)).Methods("GET") BaseRoutes.TeamMembers.Handle("", ApiSessionRequired(addTeamMember)).Methods("POST") + BaseRoutes.TeamMember.Handle("", ApiSessionRequired(removeTeamMember)).Methods("DELETE") BaseRoutes.TeamForUser.Handle("/unread", ApiSessionRequired(getTeamUnread)).Methods("GET") @@ -239,6 +241,26 @@ func getTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { } } +func getTeamMembersForUser(c *Context, w http.ResponseWriter, r *http.Request) { + c.RequireUserId() + if c.Err != nil { + return + } + + if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) { + c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS) + return + } + + members, err := app.GetTeamMembersForUser(c.Params.UserId) + if err != nil { + c.Err = err + return + } + + w.Write([]byte(model.TeamMembersToJson(members))) +} + func getTeamMembersByIds(c *Context, w http.ResponseWriter, r *http.Request) { c.RequireTeamId() if c.Err != nil { @@ -317,6 +339,27 @@ func addTeamMember(c *Context, w http.ResponseWriter, r *http.Request) { w.Write([]byte(member.ToJson())) } +func removeTeamMember(c *Context, w http.ResponseWriter, r *http.Request) { + c.RequireTeamId().RequireUserId() + if c.Err != nil { + return + } + + if c.Session.UserId != c.Params.UserId { + if !app.SessionHasPermissionToTeam(c.Session, c.Params.TeamId, model.PERMISSION_REMOVE_USER_FROM_TEAM) { + c.SetPermissionError(model.PERMISSION_REMOVE_USER_FROM_TEAM) + return + } + } + + if err := app.RemoveUserFromTeam(c.Params.TeamId, c.Params.UserId); err != nil { + c.Err = err + return + } + + ReturnStatusOK(w) +} + func getTeamUnread(c *Context, w http.ResponseWriter, r *http.Request) { c.RequireTeamId().RequireUserId() if c.Err != nil { diff --git a/api4/team_test.go b/api4/team_test.go index 1f1e031b3..36d6df147 100644 --- a/api4/team_test.go +++ b/api4/team_test.go @@ -534,6 +534,44 @@ func TestGetTeamMembers(t *testing.T) { CheckNoError(t, resp) } +func TestGetTeamMembersForUser(t *testing.T) { + th := Setup().InitBasic().InitSystemAdmin() + defer TearDown() + Client := th.Client + + members, resp := Client.GetTeamMembersForUser(th.BasicUser.Id, "") + CheckNoError(t, resp) + + found := false + for _, m := range members { + if m.TeamId == th.BasicTeam.Id { + found = true + } + } + + if !found { + t.Fatal("missing team member") + } + + _, resp = Client.GetTeamMembersForUser("junk", "") + CheckBadRequestStatus(t, resp) + + _, resp = Client.GetTeamMembersForUser(model.NewId(), "") + CheckForbiddenStatus(t, resp) + + Client.Logout() + _, resp = Client.GetTeamMembersForUser(th.BasicUser.Id, "") + CheckUnauthorizedStatus(t, resp) + + user := th.CreateUser() + Client.Login(user.Email, user.Password) + _, resp = Client.GetTeamMembersForUser(th.BasicUser.Id, "") + CheckForbiddenStatus(t, resp) + + _, resp = th.SystemAdminClient.GetTeamMembersForUser(th.BasicUser.Id, "") + CheckNoError(t, resp) +} + func TestGetTeamMembersByIds(t *testing.T) { th := Setup().InitBasic() defer TearDown() @@ -706,6 +744,37 @@ func TestAddTeamMember(t *testing.T) { CheckNotFoundStatus(t, resp) } +func TestRemoveTeamMember(t *testing.T) { + th := Setup().InitBasic().InitSystemAdmin() + defer TearDown() + Client := th.Client + + pass, resp := Client.RemoveTeamMember(th.BasicTeam.Id, th.BasicUser.Id) + CheckNoError(t, resp) + + if !pass { + t.Fatal("should have passed") + } + + _, resp = th.SystemAdminClient.AddTeamMember(th.BasicTeam.Id, th.BasicUser.Id, "", "", "") + CheckNoError(t, resp) + + _, resp = Client.RemoveTeamMember(th.BasicTeam.Id, "junk") + CheckBadRequestStatus(t, resp) + + _, resp = Client.RemoveTeamMember("junk", th.BasicUser2.Id) + CheckBadRequestStatus(t, resp) + + _, resp = Client.RemoveTeamMember(th.BasicTeam.Id, th.BasicUser2.Id) + CheckForbiddenStatus(t, resp) + + _, resp = Client.RemoveTeamMember(model.NewId(), th.BasicUser.Id) + CheckNotFoundStatus(t, resp) + + _, resp = th.SystemAdminClient.RemoveTeamMember(th.BasicTeam.Id, th.BasicUser.Id) + CheckNoError(t, resp) +} + func TestGetTeamStats(t *testing.T) { th := Setup().InitBasic().InitSystemAdmin() defer TearDown() -- cgit v1.2.3-1-g7c22