From bdd0e9febbeeef4533b3762d7ec942538f723acd Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Thu, 7 May 2020 13:35:56 -0600 Subject: [PATCH] MM-24694: Add getGroupsByUserId to API layer (#14443) * add getGroupsByUserId to API layer * update for lint errors * add check for contextId = userId or ManageSystem Permission Co-authored-by: mattermod --- api4/group.go | 35 ++++++++++++++++++++++++++ api4/group_test.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++ model/client4.go | 16 ++++++++++++ 3 files changed, 113 insertions(+) diff --git a/api4/group.go b/api4/group.go index dcf088c1ce..597da6962f 100644 --- a/api4/group.go +++ b/api4/group.go @@ -55,6 +55,10 @@ func (api *API) InitGroup() { api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/members", api.ApiSessionRequired(getGroupMembers)).Methods("GET") + // GET /api/v4/users/:user_id/groups?page=0&per_page=100 + api.BaseRoutes.Users.Handle("/{user_id:[A-Za-z0-9]+}/groups", + api.ApiSessionRequired(getGroupsByUserId)).Methods("GET") + // GET /api/v4/channels/:channel_id/groups?page=0&per_page=100 api.BaseRoutes.Channels.Handle("/{channel_id:[A-Za-z0-9]+}/groups", api.ApiSessionRequired(getGroupsByChannel)).Methods("GET") @@ -505,6 +509,37 @@ func getGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) { w.Write(b) } +func getGroupsByUserId(c *Context, w http.ResponseWriter, r *http.Request) { + c.RequireUserId() + if c.Err != nil { + return + } + + if c.App.Session().UserId != c.Params.UserId && !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) { + c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) + return + } + + if c.App.License() == nil || !*c.App.License().Features.LDAPGroups { + c.Err = model.NewAppError("Api4.getGroupsByUserId", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented) + return + } + + groups, err := c.App.GetGroupsByUserId(c.Params.UserId) + if err != nil { + c.Err = err + return + } + + b, marshalErr := json.Marshal(groups) + if marshalErr != nil { + c.Err = model.NewAppError("Api4.getGroupsByUserId", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError) + return + } + + w.Write(b) +} + func getGroupsByChannel(c *Context, w http.ResponseWriter, r *http.Request) { c.RequireChannelId() if c.Err != nil { diff --git a/api4/group_test.go b/api4/group_test.go index 1ade5f7e46..e7e4c65019 100644 --- a/api4/group_test.go +++ b/api4/group_test.go @@ -912,3 +912,65 @@ func TestGetGroups(t *testing.T) { _, response = th.Client.GetGroups(opts) assert.Nil(t, response.Error) } + +func TestGetGroupsByUserId(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + + id := model.NewId() + group1, err := th.App.CreateGroup(&model.Group{ + DisplayName: "dn-foo_" + id, + Name: "name" + id, + Source: model.GroupSourceLdap, + Description: "description_" + id, + RemoteId: model.NewId(), + }) + assert.Nil(t, err) + + user1, err := th.App.CreateUser(&model.User{Email: th.GenerateTestEmail(), Nickname: "test user1", Password: "test-password-1", Username: "test-user-1", Roles: model.SYSTEM_USER_ROLE_ID}) + assert.Nil(t, err) + user1.Password = "test-password-1" + _, err = th.App.UpsertGroupMember(group1.Id, user1.Id) + assert.Nil(t, err) + + id = model.NewId() + group2, err := th.App.CreateGroup(&model.Group{ + DisplayName: "dn-foo_" + id, + Name: "name" + id, + Source: model.GroupSourceLdap, + Description: "description_" + id, + RemoteId: model.NewId(), + }) + assert.Nil(t, err) + + _, err = th.App.UpsertGroupMember(group2.Id, user1.Id) + assert.Nil(t, err) + + th.App.SetLicense(nil) + _, response := th.SystemAdminClient.GetGroupsByUserId(user1.Id) + CheckNotImplementedStatus(t, response) + + th.App.SetLicense(model.NewTestLicense("ldap")) + _, response = th.SystemAdminClient.GetGroupsByUserId("") + CheckBadRequestStatus(t, response) + + _, response = th.SystemAdminClient.GetGroupsByUserId("notvaliduserid") + CheckBadRequestStatus(t, response) + + groups, response := th.SystemAdminClient.GetGroupsByUserId(user1.Id) + require.Nil(t, response.Error) + assert.ElementsMatch(t, []*model.Group{group1, group2}, groups) + + // test permissions + th.Client.Logout() + th.Client.Login(th.BasicUser.Email, th.BasicUser.Password) + _, response = th.Client.GetGroupsByUserId(user1.Id) + CheckForbiddenStatus(t, response) + + th.Client.Logout() + th.Client.Login(user1.Email, user1.Password) + groups, response = th.Client.GetGroupsByUserId(user1.Id) + require.Nil(t, response.Error) + assert.ElementsMatch(t, []*model.Group{group1, group2}, groups) + +} diff --git a/model/client4.go b/model/client4.go index 1a27400e96..0a8907657d 100644 --- a/model/client4.go +++ b/model/client4.go @@ -3793,6 +3793,22 @@ func (c *Client4) GetGroups(opts GroupSearchOpts) ([]*Group, *Response) { return GroupsFromJson(r.Body), BuildResponse(r) } +// GetGroupsByUserId retrieves Mattermost Groups for a user +func (c *Client4) GetGroupsByUserId(userId string) ([]*Group, *Response) { + path := fmt.Sprintf( + "%s/%v/groups", + c.GetUsersRoute(), + userId, + ) + + r, appErr := c.DoApiGet(path, "") + if appErr != nil { + return nil, BuildErrorResponse(r, appErr) + } + defer closeBody(r) + return GroupsFromJson(r.Body), BuildResponse(r) +} + // Audits Section // GetAudits returns a list of audits for the whole system.