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.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")
|
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
|
// GET /api/v4/groups/:group_id/members?page=0&per_page=100
|
||||||
api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/members",
|
api.BaseRoutes.Groups.Handle("/{group_id:[A-Za-z0-9]+}/members",
|
||||||
api.ApiSessionRequired(getGroupMembers)).Methods("GET")
|
api.ApiSessionRequired(getGroupMembers)).Methods("GET")
|
||||||
@@ -530,6 +534,41 @@ func getGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Write(b)
|
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) {
|
func getGroupsByUserId(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
c.RequireUserId()
|
c.RequireUserId()
|
||||||
if c.Err != nil {
|
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) {
|
func TestGetGroupsGroupConstrainedParentTeam(t *testing.T) {
|
||||||
th := Setup(t).InitBasic()
|
th := Setup(t).InitBasic()
|
||||||
defer th.TearDown()
|
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")
|
inTeamId := r.URL.Query().Get("in_team")
|
||||||
notInTeamId := r.URL.Query().Get("not_in_team")
|
notInTeamId := r.URL.Query().Get("not_in_team")
|
||||||
inChannelId := r.URL.Query().Get("in_channel")
|
inChannelId := r.URL.Query().Get("in_channel")
|
||||||
|
inGroupId := r.URL.Query().Get("in_group")
|
||||||
notInChannelId := r.URL.Query().Get("not_in_channel")
|
notInChannelId := r.URL.Query().Get("not_in_channel")
|
||||||
groupConstrained := r.URL.Query().Get("group_constrained")
|
groupConstrained := r.URL.Query().Get("group_constrained")
|
||||||
withoutTeam := r.URL.Query().Get("without_team")
|
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
|
// Currently only supports sorting on a team
|
||||||
// or sort="status" on inChannelId
|
// 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")
|
c.SetInvalidUrlParam("sort")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -570,6 +571,7 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
InChannelId: inChannelId,
|
InChannelId: inChannelId,
|
||||||
NotInTeamId: notInTeamId,
|
NotInTeamId: notInTeamId,
|
||||||
NotInChannelId: notInChannelId,
|
NotInChannelId: notInChannelId,
|
||||||
|
InGroupId: inGroupId,
|
||||||
GroupConstrained: groupConstrainedBool,
|
GroupConstrained: groupConstrainedBool,
|
||||||
WithoutTeam: withoutTeamBool,
|
WithoutTeam: withoutTeamBool,
|
||||||
Inactive: inactiveBool,
|
Inactive: inactiveBool,
|
||||||
@@ -637,6 +639,22 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
} else {
|
} else {
|
||||||
profiles, err = c.App.GetUsersInChannelPage(inChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin())
|
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 {
|
} else {
|
||||||
userGetOptions, err = c.App.RestrictUsersGetByPermissions(c.App.Session().UserId, userGetOptions)
|
userGetOptions, err = c.App.RestrictUsersGetByPermissions(c.App.Session().UserId, userGetOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -749,6 +767,18 @@ func searchUsers(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
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) {
|
if props.InChannelId != "" && !c.App.SessionHasPermissionToChannel(*c.App.Session(), props.InChannelId, model.PERMISSION_READ_CHANNEL) {
|
||||||
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1084,6 +1084,44 @@ func TestSearchUsers(t *testing.T) {
|
|||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
|
|
||||||
require.True(t, findUserInList(th.BasicUser.Id, users), "should have found user")
|
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 {
|
func findUserInList(id string, users []*model.User) bool {
|
||||||
@@ -2328,6 +2366,54 @@ func TestGetUsersNotInChannel(t *testing.T) {
|
|||||||
CheckNoError(t, resp)
|
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) {
|
func TestUpdateUserMfa(t *testing.T) {
|
||||||
th := Setup(t).InitBasic()
|
th := Setup(t).InitBasic()
|
||||||
defer th.TearDown()
|
defer th.TearDown()
|
||||||
|
|||||||
@@ -541,6 +541,7 @@ type AppIface interface {
|
|||||||
GetGroupByName(name string, opts model.GroupSearchOpts) (*model.Group, *model.AppError)
|
GetGroupByName(name string, opts model.GroupSearchOpts) (*model.Group, *model.AppError)
|
||||||
GetGroupByRemoteID(remoteID string, groupSource model.GroupSource) (*model.Group, *model.AppError)
|
GetGroupByRemoteID(remoteID string, groupSource model.GroupSource) (*model.Group, *model.AppError)
|
||||||
GetGroupChannel(userIds []string) (*model.Channel, *model.AppError)
|
GetGroupChannel(userIds []string) (*model.Channel, *model.AppError)
|
||||||
|
GetGroupMemberCount(groupID string) (int64, *model.AppError)
|
||||||
GetGroupMemberUsers(groupID string) ([]*model.User, *model.AppError)
|
GetGroupMemberUsers(groupID string) ([]*model.User, *model.AppError)
|
||||||
GetGroupMemberUsersPage(groupID string, page int, perPage int) ([]*model.User, int, *model.AppError)
|
GetGroupMemberUsersPage(groupID string, page int, perPage int) ([]*model.User, int, *model.AppError)
|
||||||
GetGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) (*model.GroupSyncable, *model.AppError)
|
GetGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) (*model.GroupSyncable, *model.AppError)
|
||||||
@@ -836,6 +837,7 @@ type AppIface interface {
|
|||||||
SearchUserAccessTokens(term string) ([]*model.UserAccessToken, *model.AppError)
|
SearchUserAccessTokens(term string) ([]*model.UserAccessToken, *model.AppError)
|
||||||
SearchUsers(props *model.UserSearch, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
SearchUsers(props *model.UserSearch, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
||||||
SearchUsersInChannel(channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
SearchUsersInChannel(channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
||||||
|
SearchUsersInGroup(groupID string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
||||||
SearchUsersInTeam(teamId, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
SearchUsersInTeam(teamId, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
||||||
SearchUsersNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
SearchUsersNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
||||||
SearchUsersNotInTeam(notInTeamId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
SearchUsersNotInTeam(notInTeamId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ func (a *App) DeleteGroup(groupID string) (*model.Group, *model.AppError) {
|
|||||||
return deletedGroup, err
|
return deletedGroup, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) GetGroupMemberCount(groupID string) (int64, *model.AppError) {
|
||||||
|
return a.Srv().Store.Group().GetMemberCount(groupID)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *App) GetGroupMemberUsers(groupID string) ([]*model.User, *model.AppError) {
|
func (a *App) GetGroupMemberUsers(groupID string) ([]*model.User, *model.AppError) {
|
||||||
return a.Srv().Store.Group().GetMemberUsers(groupID)
|
return a.Srv().Store.Group().GetMemberUsers(groupID)
|
||||||
}
|
}
|
||||||
@@ -69,7 +73,7 @@ func (a *App) GetGroupMemberUsersPage(groupID string, page int, perPage int) ([]
|
|||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
count, err := a.Srv().Store.Group().GetMemberCount(groupID)
|
count, err := a.GetGroupMemberCount(groupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5311,6 +5311,28 @@ func (a *OpenTracingAppLayer) GetGroupChannel(userIds []string) (*model.Channel,
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *OpenTracingAppLayer) GetGroupMemberCount(groupID string) (int64, *model.AppError) {
|
||||||
|
origCtx := a.ctx
|
||||||
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetGroupMemberCount")
|
||||||
|
|
||||||
|
a.ctx = newCtx
|
||||||
|
a.app.Srv().Store.SetContext(newCtx)
|
||||||
|
defer func() {
|
||||||
|
a.app.Srv().Store.SetContext(origCtx)
|
||||||
|
a.ctx = origCtx
|
||||||
|
}()
|
||||||
|
|
||||||
|
defer span.Finish()
|
||||||
|
resultVar0, resultVar1 := a.app.GetGroupMemberCount(groupID)
|
||||||
|
|
||||||
|
if resultVar1 != nil {
|
||||||
|
span.LogFields(spanlog.Error(resultVar1))
|
||||||
|
ext.Error.Set(span, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultVar0, resultVar1
|
||||||
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) GetGroupMemberUsers(groupID string) ([]*model.User, *model.AppError) {
|
func (a *OpenTracingAppLayer) GetGroupMemberUsers(groupID string) ([]*model.User, *model.AppError) {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetGroupMemberUsers")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetGroupMemberUsers")
|
||||||
@@ -12120,6 +12142,28 @@ func (a *OpenTracingAppLayer) SearchUsersInChannel(channelId string, term string
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *OpenTracingAppLayer) SearchUsersInGroup(groupID string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
|
||||||
|
origCtx := a.ctx
|
||||||
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SearchUsersInGroup")
|
||||||
|
|
||||||
|
a.ctx = newCtx
|
||||||
|
a.app.Srv().Store.SetContext(newCtx)
|
||||||
|
defer func() {
|
||||||
|
a.app.Srv().Store.SetContext(origCtx)
|
||||||
|
a.ctx = origCtx
|
||||||
|
}()
|
||||||
|
|
||||||
|
defer span.Finish()
|
||||||
|
resultVar0, resultVar1 := a.app.SearchUsersInGroup(groupID, term, options)
|
||||||
|
|
||||||
|
if resultVar1 != nil {
|
||||||
|
span.LogFields(spanlog.Error(resultVar1))
|
||||||
|
ext.Error.Set(span, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultVar0, resultVar1
|
||||||
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) SearchUsersInTeam(teamId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
|
func (a *OpenTracingAppLayer) SearchUsersInTeam(teamId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SearchUsersInTeam")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SearchUsersInTeam")
|
||||||
|
|||||||
17
app/user.go
17
app/user.go
@@ -1693,6 +1693,9 @@ func (a *App) SearchUsers(props *model.UserSearch, options *model.UserSearchOpti
|
|||||||
if props.NotInTeamId != "" {
|
if props.NotInTeamId != "" {
|
||||||
return a.SearchUsersNotInTeam(props.NotInTeamId, props.Term, options)
|
return a.SearchUsersNotInTeam(props.NotInTeamId, props.Term, options)
|
||||||
}
|
}
|
||||||
|
if props.InGroupId != "" {
|
||||||
|
return a.SearchUsersInGroup(props.InGroupId, props.Term, options)
|
||||||
|
}
|
||||||
return a.SearchUsersInTeam(props.TeamId, props.Term, options)
|
return a.SearchUsersInTeam(props.TeamId, props.Term, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1768,6 +1771,20 @@ func (a *App) SearchUsersWithoutTeam(term string, options *model.UserSearchOptio
|
|||||||
return users, nil
|
return users, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) SearchUsersInGroup(groupID string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
|
||||||
|
term = strings.TrimSpace(term)
|
||||||
|
users, err := a.Srv().Store.User().SearchInGroup(groupID, term, options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, user := range users {
|
||||||
|
a.SanitizeProfile(user, options.IsAdmin)
|
||||||
|
}
|
||||||
|
|
||||||
|
return users, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *App) AutocompleteUsersInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) (*model.UserAutocompleteInChannel, *model.AppError) {
|
func (a *App) AutocompleteUsersInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) (*model.UserAutocompleteInChannel, *model.AppError) {
|
||||||
term = strings.TrimSpace(term)
|
term = strings.TrimSpace(term)
|
||||||
|
|
||||||
|
|||||||
@@ -994,6 +994,17 @@ func (c *Client4) GetUsersWithoutTeam(page int, perPage int, etag string) ([]*Us
|
|||||||
return UserListFromJson(r.Body), BuildResponse(r)
|
return UserListFromJson(r.Body), BuildResponse(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUsersInGroup returns a page of users in a group. Page counting starts at 0.
|
||||||
|
func (c *Client4) GetUsersInGroup(groupID string, page int, perPage int, etag string) ([]*User, *Response) {
|
||||||
|
query := fmt.Sprintf("?in_group=%v&page=%v&per_page=%v", groupID, page, perPage)
|
||||||
|
r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
|
||||||
|
if err != nil {
|
||||||
|
return nil, BuildErrorResponse(r, err)
|
||||||
|
}
|
||||||
|
defer closeBody(r)
|
||||||
|
return UserListFromJson(r.Body), BuildResponse(r)
|
||||||
|
}
|
||||||
|
|
||||||
// GetUsersByIds returns a list of users based on the provided user ids.
|
// GetUsersByIds returns a list of users based on the provided user ids.
|
||||||
func (c *Client4) GetUsersByIds(userIds []string) ([]*User, *Response) {
|
func (c *Client4) GetUsersByIds(userIds []string) ([]*User, *Response) {
|
||||||
r, err := c.DoApiPost(c.GetUsersRoute()+"/ids", ArrayToJson(userIds))
|
r, err := c.DoApiPost(c.GetUsersRoute()+"/ids", ArrayToJson(userIds))
|
||||||
@@ -5127,3 +5138,13 @@ func (c *Client4) RequestTrialLicense(users int) (bool, *Response) {
|
|||||||
defer closeBody(r)
|
defer closeBody(r)
|
||||||
return CheckStatusOK(r), BuildResponse(r)
|
return CheckStatusOK(r), BuildResponse(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetGroupStats retrieves stats for a Mattermost Group
|
||||||
|
func (c *Client4) GetGroupStats(groupID string) (*GroupStats, *Response) {
|
||||||
|
r, appErr := c.DoApiGet(c.GetGroupRoute(groupID)+"/stats", "")
|
||||||
|
if appErr != nil {
|
||||||
|
return nil, BuildErrorResponse(r, appErr)
|
||||||
|
}
|
||||||
|
defer closeBody(r)
|
||||||
|
return GroupStatsFromJson(r.Body), BuildResponse(r)
|
||||||
|
}
|
||||||
|
|||||||
@@ -94,6 +94,11 @@ type PageOpts struct {
|
|||||||
PerPage int
|
PerPage int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GroupStats struct {
|
||||||
|
GroupID string `json:"group_id"`
|
||||||
|
TotalMemberCount int64 `json:"total_member_count"`
|
||||||
|
}
|
||||||
|
|
||||||
func (group *Group) Patch(patch *GroupPatch) {
|
func (group *Group) Patch(patch *GroupPatch) {
|
||||||
if patch.Name != nil {
|
if patch.Name != nil {
|
||||||
group.Name = patch.Name
|
group.Name = patch.Name
|
||||||
@@ -208,3 +213,9 @@ func GroupPatchFromJson(data io.Reader) *GroupPatch {
|
|||||||
json.NewDecoder(data).Decode(&groupPatch)
|
json.NewDecoder(data).Decode(&groupPatch)
|
||||||
return groupPatch
|
return groupPatch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GroupStatsFromJson(data io.Reader) *GroupStats {
|
||||||
|
var groupStats *GroupStats
|
||||||
|
json.NewDecoder(data).Decode(&groupStats)
|
||||||
|
return groupStats
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ type UserGetOptions struct {
|
|||||||
InChannelId string
|
InChannelId string
|
||||||
// Filters the users not in the channel
|
// Filters the users not in the channel
|
||||||
NotInChannelId string
|
NotInChannelId string
|
||||||
|
// Filters the users in the group
|
||||||
|
InGroupId string
|
||||||
// Filters the users group constrained
|
// Filters the users group constrained
|
||||||
GroupConstrained bool
|
GroupConstrained bool
|
||||||
// Filters the users without a team
|
// Filters the users without a team
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ type UserSearch struct {
|
|||||||
NotInTeamId string `json:"not_in_team_id"`
|
NotInTeamId string `json:"not_in_team_id"`
|
||||||
InChannelId string `json:"in_channel_id"`
|
InChannelId string `json:"in_channel_id"`
|
||||||
NotInChannelId string `json:"not_in_channel_id"`
|
NotInChannelId string `json:"not_in_channel_id"`
|
||||||
|
InGroupId string `json:"in_group_id"`
|
||||||
GroupConstrained bool `json:"group_constrained"`
|
GroupConstrained bool `json:"group_constrained"`
|
||||||
AllowInactive bool `json:"allow_inactive"`
|
AllowInactive bool `json:"allow_inactive"`
|
||||||
WithoutTeam bool `json:"without_team"`
|
WithoutTeam bool `json:"without_team"`
|
||||||
|
|||||||
@@ -8225,6 +8225,24 @@ func (s *OpenTracingLayerUserStore) SearchInChannel(channelId string, term strin
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *OpenTracingLayerUserStore) SearchInGroup(groupID string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
|
||||||
|
origCtx := s.Root.Store.Context()
|
||||||
|
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "UserStore.SearchInGroup")
|
||||||
|
s.Root.Store.SetContext(newCtx)
|
||||||
|
defer func() {
|
||||||
|
s.Root.Store.SetContext(origCtx)
|
||||||
|
}()
|
||||||
|
|
||||||
|
defer span.Finish()
|
||||||
|
resultVar0, resultVar1 := s.UserStore.SearchInGroup(groupID, term, options)
|
||||||
|
if resultVar1 != nil {
|
||||||
|
span.LogFields(spanlog.Error(resultVar1))
|
||||||
|
ext.Error.Set(span, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultVar0, resultVar1
|
||||||
|
}
|
||||||
|
|
||||||
func (s *OpenTracingLayerUserStore) SearchNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
|
func (s *OpenTracingLayerUserStore) SearchNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
|
||||||
origCtx := s.Root.Store.Context()
|
origCtx := s.Root.Store.Context()
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "UserStore.SearchNotInChannel")
|
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "UserStore.SearchNotInChannel")
|
||||||
|
|||||||
@@ -1240,6 +1240,15 @@ func (us SqlUserStore) SearchInChannel(channelId string, term string, options *m
|
|||||||
return us.performSearch(query, term, options)
|
return us.performSearch(query, term, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (us SqlUserStore) SearchInGroup(groupID string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
|
||||||
|
query := us.usersQuery.
|
||||||
|
Join("GroupMembers gm ON ( gm.UserId = u.Id AND gm.GroupId = ? )", groupID).
|
||||||
|
OrderBy("Username ASC").
|
||||||
|
Limit(uint64(options.Limit))
|
||||||
|
|
||||||
|
return us.performSearch(query, term, options)
|
||||||
|
}
|
||||||
|
|
||||||
var spaceFulltextSearchChar = []string{
|
var spaceFulltextSearchChar = []string{
|
||||||
"<",
|
"<",
|
||||||
">",
|
">",
|
||||||
|
|||||||
@@ -322,6 +322,7 @@ type UserStore interface {
|
|||||||
SearchInChannel(channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
SearchInChannel(channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
||||||
SearchNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
SearchNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
||||||
SearchWithoutTeam(term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
SearchWithoutTeam(term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
||||||
|
SearchInGroup(groupID string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
||||||
AnalyticsGetInactiveUsersCount() (int64, *model.AppError)
|
AnalyticsGetInactiveUsersCount() (int64, *model.AppError)
|
||||||
AnalyticsGetSystemAdminCount() (int64, *model.AppError)
|
AnalyticsGetSystemAdminCount() (int64, *model.AppError)
|
||||||
AnalyticsGetGuestCount() (int64, *model.AppError)
|
AnalyticsGetGuestCount() (int64, *model.AppError)
|
||||||
|
|||||||
@@ -1164,6 +1164,31 @@ func (_m *UserStore) SearchInChannel(channelId string, term string, options *mod
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SearchInGroup provides a mock function with given fields: groupID, term, options
|
||||||
|
func (_m *UserStore) SearchInGroup(groupID string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
|
||||||
|
ret := _m.Called(groupID, term, options)
|
||||||
|
|
||||||
|
var r0 []*model.User
|
||||||
|
if rf, ok := ret.Get(0).(func(string, string, *model.UserSearchOptions) []*model.User); ok {
|
||||||
|
r0 = rf(groupID, term, options)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]*model.User)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *model.AppError
|
||||||
|
if rf, ok := ret.Get(1).(func(string, string, *model.UserSearchOptions) *model.AppError); ok {
|
||||||
|
r1 = rf(groupID, term, options)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*model.AppError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
// SearchNotInChannel provides a mock function with given fields: teamId, channelId, term, options
|
// SearchNotInChannel provides a mock function with given fields: teamId, channelId, term, options
|
||||||
func (_m *UserStore) SearchNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
|
func (_m *UserStore) SearchNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
|
||||||
ret := _m.Called(teamId, channelId, term, options)
|
ret := _m.Called(teamId, channelId, term, options)
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ func TestUserStore(t *testing.T, ss store.Store, s SqlSupplier) {
|
|||||||
t.Run("SearchInChannel", func(t *testing.T) { testUserStoreSearchInChannel(t, ss) })
|
t.Run("SearchInChannel", func(t *testing.T) { testUserStoreSearchInChannel(t, ss) })
|
||||||
t.Run("SearchNotInTeam", func(t *testing.T) { testUserStoreSearchNotInTeam(t, ss) })
|
t.Run("SearchNotInTeam", func(t *testing.T) { testUserStoreSearchNotInTeam(t, ss) })
|
||||||
t.Run("SearchWithoutTeam", func(t *testing.T) { testUserStoreSearchWithoutTeam(t, ss) })
|
t.Run("SearchWithoutTeam", func(t *testing.T) { testUserStoreSearchWithoutTeam(t, ss) })
|
||||||
|
t.Run("SearchInGroup", func(t *testing.T) { testUserStoreSearchInGroup(t, ss) })
|
||||||
t.Run("GetProfilesNotInTeam", func(t *testing.T) { testUserStoreGetProfilesNotInTeam(t, ss) })
|
t.Run("GetProfilesNotInTeam", func(t *testing.T) { testUserStoreGetProfilesNotInTeam(t, ss) })
|
||||||
t.Run("ClearAllCustomRoleAssignments", func(t *testing.T) { testUserStoreClearAllCustomRoleAssignments(t, ss) })
|
t.Run("ClearAllCustomRoleAssignments", func(t *testing.T) { testUserStoreClearAllCustomRoleAssignments(t, ss) })
|
||||||
t.Run("GetAllAfter", func(t *testing.T) { testUserStoreGetAllAfter(t, ss) })
|
t.Run("GetAllAfter", func(t *testing.T) { testUserStoreGetAllAfter(t, ss) })
|
||||||
@@ -2918,6 +2919,146 @@ func testUserStoreSearchWithoutTeam(t *testing.T, ss store.Store) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testUserStoreSearchInGroup(t *testing.T, ss store.Store) {
|
||||||
|
u1 := &model.User{
|
||||||
|
Username: "jimbo1" + model.NewId(),
|
||||||
|
FirstName: "Tim",
|
||||||
|
LastName: "Bill",
|
||||||
|
Nickname: "Rob",
|
||||||
|
Email: "harold" + model.NewId() + "@simulator.amazonses.com",
|
||||||
|
}
|
||||||
|
_, err := ss.User().Save(u1)
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer func() { require.Nil(t, ss.User().PermanentDelete(u1.Id)) }()
|
||||||
|
|
||||||
|
u2 := &model.User{
|
||||||
|
Username: "jim-bobby" + model.NewId(),
|
||||||
|
Email: MakeEmail(),
|
||||||
|
}
|
||||||
|
_, err = ss.User().Save(u2)
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer func() { require.Nil(t, ss.User().PermanentDelete(u2.Id)) }()
|
||||||
|
|
||||||
|
u3 := &model.User{
|
||||||
|
Username: "jimbo3" + model.NewId(),
|
||||||
|
Email: MakeEmail(),
|
||||||
|
DeleteAt: 1,
|
||||||
|
}
|
||||||
|
_, err = ss.User().Save(u3)
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer func() { require.Nil(t, ss.User().PermanentDelete(u3.Id)) }()
|
||||||
|
|
||||||
|
// The users returned from the database will have AuthData as an empty string.
|
||||||
|
nilAuthData := model.NewString("")
|
||||||
|
|
||||||
|
u1.AuthData = nilAuthData
|
||||||
|
u2.AuthData = nilAuthData
|
||||||
|
u3.AuthData = nilAuthData
|
||||||
|
|
||||||
|
g1 := &model.Group{
|
||||||
|
Name: model.NewString(model.NewId()),
|
||||||
|
DisplayName: model.NewId(),
|
||||||
|
Description: model.NewId(),
|
||||||
|
Source: model.GroupSourceLdap,
|
||||||
|
RemoteId: model.NewId(),
|
||||||
|
}
|
||||||
|
_, err = ss.Group().Create(g1)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
g2 := &model.Group{
|
||||||
|
Name: model.NewString(model.NewId()),
|
||||||
|
DisplayName: model.NewId(),
|
||||||
|
Description: model.NewId(),
|
||||||
|
Source: model.GroupSourceLdap,
|
||||||
|
RemoteId: model.NewId(),
|
||||||
|
}
|
||||||
|
_, err = ss.Group().Create(g2)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = ss.Group().UpsertMember(g1.Id, u1.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = ss.Group().UpsertMember(g2.Id, u2.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = ss.Group().UpsertMember(g1.Id, u3.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
Description string
|
||||||
|
GroupId string
|
||||||
|
Term string
|
||||||
|
Options *model.UserSearchOptions
|
||||||
|
Expected []*model.User
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"search jimb, group 1",
|
||||||
|
g1.Id,
|
||||||
|
"jimb",
|
||||||
|
&model.UserSearchOptions{
|
||||||
|
AllowFullNames: true,
|
||||||
|
Limit: model.USER_SEARCH_DEFAULT_LIMIT,
|
||||||
|
},
|
||||||
|
[]*model.User{u1},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"search jimb, group 1, allow inactive",
|
||||||
|
g1.Id,
|
||||||
|
"jimb",
|
||||||
|
&model.UserSearchOptions{
|
||||||
|
AllowFullNames: true,
|
||||||
|
AllowInactive: true,
|
||||||
|
Limit: model.USER_SEARCH_DEFAULT_LIMIT,
|
||||||
|
},
|
||||||
|
[]*model.User{u1, u3},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"search jimb, group 1, limit 1",
|
||||||
|
g1.Id,
|
||||||
|
"jimb",
|
||||||
|
&model.UserSearchOptions{
|
||||||
|
AllowFullNames: true,
|
||||||
|
AllowInactive: true,
|
||||||
|
Limit: 1,
|
||||||
|
},
|
||||||
|
[]*model.User{u1},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"search jimb, group 2",
|
||||||
|
g2.Id,
|
||||||
|
"jimb",
|
||||||
|
&model.UserSearchOptions{
|
||||||
|
AllowFullNames: true,
|
||||||
|
Limit: model.USER_SEARCH_DEFAULT_LIMIT,
|
||||||
|
},
|
||||||
|
[]*model.User{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"search jimb, allow inactive, group 2",
|
||||||
|
g2.Id,
|
||||||
|
"jimb",
|
||||||
|
&model.UserSearchOptions{
|
||||||
|
AllowFullNames: true,
|
||||||
|
AllowInactive: true,
|
||||||
|
Limit: model.USER_SEARCH_DEFAULT_LIMIT,
|
||||||
|
},
|
||||||
|
[]*model.User{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.Description, func(t *testing.T) {
|
||||||
|
users, err := ss.User().SearchInGroup(
|
||||||
|
testCase.GroupId,
|
||||||
|
testCase.Term,
|
||||||
|
testCase.Options,
|
||||||
|
)
|
||||||
|
require.Nil(t, err)
|
||||||
|
assertUsers(t, testCase.Expected, users)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testCount(t *testing.T, ss store.Store) {
|
func testCount(t *testing.T, ss store.Store) {
|
||||||
// Regular
|
// Regular
|
||||||
teamId := model.NewId()
|
teamId := model.NewId()
|
||||||
|
|||||||
@@ -7444,6 +7444,22 @@ func (s *TimerLayerUserStore) SearchInChannel(channelId string, term string, opt
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *TimerLayerUserStore) SearchInGroup(groupID string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
|
||||||
|
start := timemodule.Now()
|
||||||
|
|
||||||
|
resultVar0, resultVar1 := s.UserStore.SearchInGroup(groupID, term, options)
|
||||||
|
|
||||||
|
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||||
|
if s.Root.Metrics != nil {
|
||||||
|
success := "false"
|
||||||
|
if resultVar1 == nil {
|
||||||
|
success = "true"
|
||||||
|
}
|
||||||
|
s.Root.Metrics.ObserveStoreMethodDuration("UserStore.SearchInGroup", success, elapsed)
|
||||||
|
}
|
||||||
|
return resultVar0, resultVar1
|
||||||
|
}
|
||||||
|
|
||||||
func (s *TimerLayerUserStore) SearchNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
|
func (s *TimerLayerUserStore) SearchNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
|
||||||
start := timemodule.Now()
|
start := timemodule.Now()
|
||||||
|
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user