MM-25263 Add group members to search and get users and create getGroupStats endpoint (#14733)
Add tests for SearchInGroup
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
f6c934d7e0
Коммит
77bee1d4f1
@@ -52,6 +52,10 @@ func (api *API) InitGroup() {
|
||||
api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/{syncable_type:teams|channels}/{syncable_id:[A-Za-z0-9]+}/patch",
|
||||
api.ApiSessionRequired(patchGroupSyncable)).Methods("PUT")
|
||||
|
||||
// GET /api/v4/groups/:group_id/stats
|
||||
api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/stats",
|
||||
api.ApiSessionRequired(getGroupStats)).Methods("GET")
|
||||
|
||||
// GET /api/v4/groups/:group_id/members?page=0&per_page=100
|
||||
api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/members",
|
||||
api.ApiSessionRequired(getGroupMembers)).Methods("GET")
|
||||
@@ -530,6 +534,41 @@ func getGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(b)
|
||||
}
|
||||
|
||||
func getGroupStats(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireGroupId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
|
||||
c.Err = model.NewAppError("Api4.getGroupStats", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
|
||||
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
|
||||
return
|
||||
}
|
||||
|
||||
groupID := c.Params.GroupId
|
||||
count, err := c.App.GetGroupMemberCount(groupID)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
b, marshalErr := json.Marshal(model.GroupStats{
|
||||
GroupID: groupID,
|
||||
TotalMemberCount: count,
|
||||
})
|
||||
if marshalErr != nil {
|
||||
c.Err = model.NewAppError("Api4.getGroupStats", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(b)
|
||||
}
|
||||
|
||||
func getGroupsByUserId(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireUserId()
|
||||
if c.Err != nil {
|
||||
|
||||
@@ -1024,6 +1024,54 @@ func TestGetGroupsByUserId(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestGetGroupStats(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
id := model.NewId()
|
||||
group, err := th.App.CreateGroup(&model.Group{
|
||||
DisplayName: "dn-foo_" + id,
|
||||
Name: model.NewString("name" + id),
|
||||
Source: model.GroupSourceLdap,
|
||||
Description: "description_" + id,
|
||||
RemoteId: model.NewId(),
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
|
||||
var response *model.Response
|
||||
var stats *model.GroupStats
|
||||
|
||||
t.Run("Requires ldap license", func(t *testing.T) {
|
||||
_, response = th.SystemAdminClient.GetGroupStats(group.Id)
|
||||
CheckNotImplementedStatus(t, response)
|
||||
})
|
||||
|
||||
th.App.Srv().SetLicense(model.NewTestLicense("ldap"))
|
||||
|
||||
t.Run("Requires manage system permission to access group stats", func(t *testing.T) {
|
||||
th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
|
||||
_, response = th.Client.GetGroupStats(group.Id)
|
||||
CheckForbiddenStatus(t, response)
|
||||
})
|
||||
|
||||
t.Run("Returns stats for a group with no members", func(t *testing.T) {
|
||||
stats, _ = th.SystemAdminClient.GetGroupStats(group.Id)
|
||||
assert.Equal(t, stats.GroupID, group.Id)
|
||||
assert.Equal(t, stats.TotalMemberCount, int64(0))
|
||||
})
|
||||
|
||||
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)
|
||||
_, err = th.App.UpsertGroupMember(group.Id, user1.Id)
|
||||
assert.Nil(t, err)
|
||||
|
||||
t.Run("Returns stats for a group with members", func(t *testing.T) {
|
||||
stats, _ = th.SystemAdminClient.GetGroupStats(group.Id)
|
||||
assert.Equal(t, stats.GroupID, group.Id)
|
||||
assert.Equal(t, stats.TotalMemberCount, int64(1))
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetGroupsGroupConstrainedParentTeam(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
32
api4/user.go
32
api4/user.go
@@ -527,6 +527,7 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
inTeamId := r.URL.Query().Get("in_team")
|
||||
notInTeamId := r.URL.Query().Get("not_in_team")
|
||||
inChannelId := r.URL.Query().Get("in_channel")
|
||||
inGroupId := r.URL.Query().Get("in_group")
|
||||
notInChannelId := r.URL.Query().Get("not_in_channel")
|
||||
groupConstrained := r.URL.Query().Get("group_constrained")
|
||||
withoutTeam := r.URL.Query().Get("without_team")
|
||||
@@ -546,7 +547,7 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Currently only supports sorting on a team
|
||||
// or sort="status" on inChannelId
|
||||
if (sort == "last_activity_at" || sort == "create_at") && (inTeamId == "" || notInTeamId != "" || inChannelId != "" || notInChannelId != "" || withoutTeam != "") {
|
||||
if (sort == "last_activity_at" || sort == "create_at") && (inTeamId == "" || notInTeamId != "" || inChannelId != "" || notInChannelId != "" || withoutTeam != "" || inGroupId != "") {
|
||||
c.SetInvalidUrlParam("sort")
|
||||
return
|
||||
}
|
||||
@@ -570,6 +571,7 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
InChannelId: inChannelId,
|
||||
NotInTeamId: notInTeamId,
|
||||
NotInChannelId: notInChannelId,
|
||||
InGroupId: inGroupId,
|
||||
GroupConstrained: groupConstrainedBool,
|
||||
WithoutTeam: withoutTeamBool,
|
||||
Inactive: inactiveBool,
|
||||
@@ -637,6 +639,22 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
} else {
|
||||
profiles, err = c.App.GetUsersInChannelPage(inChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin())
|
||||
}
|
||||
} else if len(inGroupId) > 0 {
|
||||
if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
|
||||
c.Err = model.NewAppError("Api4.getUsersInGroup", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
|
||||
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
|
||||
return
|
||||
}
|
||||
|
||||
profiles, _, err = c.App.GetGroupMemberUsersPage(inGroupId, c.Params.Page, c.Params.PerPage)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
} else {
|
||||
userGetOptions, err = c.App.RestrictUsersGetByPermissions(c.App.Session().UserId, userGetOptions)
|
||||
if err != nil {
|
||||
@@ -749,6 +767,18 @@ func searchUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if props.InGroupId != "" {
|
||||
if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.LDAPGroups {
|
||||
c.Err = model.NewAppError("Api4.searchUsers", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
|
||||
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if props.InChannelId != "" && !c.App.SessionHasPermissionToChannel(*c.App.Session(), props.InChannelId, model.PERMISSION_READ_CHANNEL) {
|
||||
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
||||
return
|
||||
|
||||
@@ -1084,6 +1084,44 @@ func TestSearchUsers(t *testing.T) {
|
||||
CheckNoError(t, resp)
|
||||
|
||||
require.True(t, findUserInList(th.BasicUser.Id, users), "should have found user")
|
||||
|
||||
id := model.NewId()
|
||||
group, err := th.App.CreateGroup(&model.Group{
|
||||
DisplayName: "dn-foo_" + id,
|
||||
Name: model.NewString("name" + id),
|
||||
Source: model.GroupSourceLdap,
|
||||
Description: "description_" + id,
|
||||
RemoteId: model.NewId(),
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
|
||||
search = &model.UserSearch{Term: th.BasicUser.Username, InGroupId: group.Id}
|
||||
t.Run("Requires ldap license when searching in group", func(t *testing.T) {
|
||||
_, resp = th.SystemAdminClient.SearchUsers(search)
|
||||
CheckNotImplementedStatus(t, resp)
|
||||
})
|
||||
|
||||
th.App.Srv().SetLicense(model.NewTestLicense("ldap"))
|
||||
|
||||
t.Run("Requires manage system permission when searching for users in a group", func(t *testing.T) {
|
||||
_, resp = th.Client.SearchUsers(search)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("Returns empty list when no users found searching for users in a group", func(t *testing.T) {
|
||||
users, resp = th.SystemAdminClient.SearchUsers(search)
|
||||
CheckNoError(t, resp)
|
||||
require.Empty(t, users)
|
||||
})
|
||||
|
||||
_, err = th.App.UpsertGroupMember(group.Id, th.BasicUser.Id)
|
||||
assert.Nil(t, err)
|
||||
|
||||
t.Run("Returns user in group user found in group", func(t *testing.T) {
|
||||
users, resp = th.SystemAdminClient.SearchUsers(search)
|
||||
CheckNoError(t, resp)
|
||||
require.Equal(t, users[0].Id, th.BasicUser.Id)
|
||||
})
|
||||
}
|
||||
|
||||
func findUserInList(id string, users []*model.User) bool {
|
||||
@@ -2328,6 +2366,54 @@ func TestGetUsersNotInChannel(t *testing.T) {
|
||||
CheckNoError(t, resp)
|
||||
}
|
||||
|
||||
func TestGetUsersInGroup(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
id := model.NewId()
|
||||
group, err := th.App.CreateGroup(&model.Group{
|
||||
DisplayName: "dn-foo_" + id,
|
||||
Name: model.NewString("name" + id),
|
||||
Source: model.GroupSourceLdap,
|
||||
Description: "description_" + id,
|
||||
RemoteId: model.NewId(),
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
|
||||
var response *model.Response
|
||||
var users []*model.User
|
||||
|
||||
t.Run("Requires ldap license", func(t *testing.T) {
|
||||
_, response = th.SystemAdminClient.GetUsersInGroup(group.Id, 0, 60, "")
|
||||
CheckNotImplementedStatus(t, response)
|
||||
})
|
||||
|
||||
th.App.Srv().SetLicense(model.NewTestLicense("ldap"))
|
||||
|
||||
t.Run("Requires manage system permission to access users in group", func(t *testing.T) {
|
||||
th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
|
||||
_, response = th.Client.GetUsersInGroup(group.Id, 0, 60, "")
|
||||
CheckForbiddenStatus(t, response)
|
||||
})
|
||||
|
||||
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)
|
||||
_, err = th.App.UpsertGroupMember(group.Id, user1.Id)
|
||||
assert.Nil(t, err)
|
||||
|
||||
t.Run("Returns users in group when called by system admin", func(t *testing.T) {
|
||||
users, response = th.SystemAdminClient.GetUsersInGroup(group.Id, 0, 60, "")
|
||||
CheckNoError(t, response)
|
||||
assert.Equal(t, users[0].Id, user1.Id)
|
||||
})
|
||||
|
||||
t.Run("Returns no users when pagination out of range", func(t *testing.T) {
|
||||
users, response = th.SystemAdminClient.GetUsersInGroup(group.Id, 5, 60, "")
|
||||
CheckNoError(t, response)
|
||||
assert.Empty(t, users)
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateUserMfa(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
Ссылка в новой задаче
Block a user