MM-25263 Add group members to search and get users and create getGroupStats endpoint (#14733)
Add tests for SearchInGroup
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
f6c934d7e0
Коммит
77bee1d4f1
@@ -8225,6 +8225,24 @@ func (s *OpenTracingLayerUserStore) SearchInChannel(channelId string, term strin
|
||||
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) {
|
||||
origCtx := s.Root.Store.Context()
|
||||
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)
|
||||
}
|
||||
|
||||
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{
|
||||
"<",
|
||||
">",
|
||||
|
||||
@@ -322,6 +322,7 @@ type UserStore interface {
|
||||
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)
|
||||
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)
|
||||
AnalyticsGetSystemAdminCount() (int64, *model.AppError)
|
||||
AnalyticsGetGuestCount() (int64, *model.AppError)
|
||||
|
||||
@@ -1164,6 +1164,31 @@ func (_m *UserStore) SearchInChannel(channelId string, term string, options *mod
|
||||
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
|
||||
func (_m *UserStore) SearchNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError) {
|
||||
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("SearchNotInTeam", func(t *testing.T) { testUserStoreSearchNotInTeam(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("ClearAllCustomRoleAssignments", func(t *testing.T) { testUserStoreClearAllCustomRoleAssignments(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) {
|
||||
// Regular
|
||||
teamId := model.NewId()
|
||||
|
||||
@@ -7444,6 +7444,22 @@ func (s *TimerLayerUserStore) SearchInChannel(channelId string, term string, opt
|
||||
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) {
|
||||
start := timemodule.Now()
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user