diff --git a/api4/user.go b/api4/user.go index e0e32708b3..a35d1d6597 100644 --- a/api4/user.go +++ b/api4/user.go @@ -662,13 +662,14 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { return } - if sort != "" && sort != "last_activity_at" && sort != "create_at" && sort != "status" && sort != "admin" { + if sort != "" && sort != "last_activity_at" && sort != "create_at" && sort != "status" && sort != "admin" && sort != "display_name" { c.SetInvalidURLParam("sort") return } // Currently only supports sorting on a team // or sort="status" on inChannelId + // or sort="display_name" on inGroupId if (sort == "last_activity_at" || sort == "create_at") && (inTeamId == "" || notInTeamId != "" || inChannelId != "" || notInChannelId != "" || withoutTeam != "" || inGroupId != "" || notInGroupId != "") { c.SetInvalidURLParam("sort") return @@ -681,6 +682,10 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { c.SetInvalidURLParam("sort") return } + if sort == "display_name" && (inGroupId == "" || notInGroupId != "" || inTeamId != "" || notInTeamId != "" || inChannelId != "" || notInChannelId != "" || withoutTeam != "") { + c.SetInvalidURLParam("sort") + return + } var ( withoutTeamBool, _ = strconv.ParseBool(withoutTeam) @@ -869,10 +874,18 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { return } - profiles, _, appErr = c.App.GetGroupMemberUsersPage(inGroupId, c.Params.Page, c.Params.PerPage, userGetOptions.ViewRestrictions) - if appErr != nil { - c.Err = appErr - return + if sort == "display_name" { + var user *model.User + + user, appErr = c.App.GetUser(c.AppContext.Session().UserId) + if appErr != nil { + c.Err = appErr + return + } + + profiles, _, appErr = c.App.GetGroupMemberUsersSortedPage(inGroupId, c.Params.Page, c.Params.PerPage, userGetOptions.ViewRestrictions, c.App.GetNotificationNameFormat(user)) + } else { + profiles, _, appErr = c.App.GetGroupMemberUsersPage(inGroupId, c.Params.Page, c.Params.PerPage, userGetOptions.ViewRestrictions) } } else if notInGroupId != "" { appErr = requireGroupAccess(c, notInGroupId) diff --git a/api4/user_test.go b/api4/user_test.go index 871f2c56e8..affd768fd7 100644 --- a/api4/user_test.go +++ b/api4/user_test.go @@ -2837,6 +2837,64 @@ func TestGetUsersInGroup(t *testing.T) { } +func TestGetUsersInGroupByDisplayName(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + + id := model.NewId() + group, appErr := th.App.CreateGroup(&model.Group{ + DisplayName: "dn-foo_" + id, + Name: model.NewString("name" + id), + Source: model.GroupSourceLdap, + Description: "description_" + id, + RemoteId: model.NewString(model.NewId()), + }) + assert.Nil(t, appErr) + + user1, err := th.App.CreateUser(th.Context, &model.User{Email: th.GenerateTestEmail(), Nickname: "aaa", Password: "test-password-1", Username: "zzz", Roles: model.SystemUserRoleId}) + assert.Nil(t, err) + + user2, err := th.App.CreateUser(th.Context, &model.User{Email: th.GenerateTestEmail(), Password: "test-password-2", Username: "bbb", Roles: model.SystemUserRoleId}) + assert.Nil(t, err) + + _, err = th.App.UpsertGroupMember(group.Id, user1.Id) + assert.Nil(t, err) + _, err = th.App.UpsertGroupMember(group.Id, user2.Id) + assert.Nil(t, err) + + th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuProfessional)) + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.PrivacySettings.ShowFullName = true + }) + + preference := model.Preference{ + UserId: th.SystemAdminUser.Id, + Category: model.PreferenceCategoryDisplaySettings, + Name: model.PreferenceNameNameFormat, + Value: model.ShowUsername, + } + + err = th.App.UpdatePreferences(th.SystemAdminUser.Id, model.Preferences{preference}) + assert.Nil(t, err) + + t.Run("Returns users in group in right order for username", func(t *testing.T) { + users, _, err := th.SystemAdminClient.GetUsersInGroupByDisplayName(group.Id, 0, 1, "") + require.NoError(t, err) + assert.Equal(t, users[0].Id, user2.Id) + }) + + preference.Value = model.ShowNicknameFullName + err = th.App.UpdatePreferences(th.SystemAdminUser.Id, model.Preferences{preference}) + assert.Nil(t, err) + + t.Run("Returns users in group in right order for nickname", func(t *testing.T) { + users, _, err := th.SystemAdminClient.GetUsersInGroupByDisplayName(group.Id, 0, 1, "") + require.NoError(t, err) + assert.Equal(t, users[0].Id, user1.Id) + }) + +} + func TestUpdateUserMfa(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() diff --git a/app/app_iface.go b/app/app_iface.go index 24f6871775..f10ca2d8b9 100644 --- a/app/app_iface.go +++ b/app/app_iface.go @@ -652,6 +652,7 @@ type AppIface interface { GetGroupMemberCount(groupID string, viewRestrictions *model.ViewUsersRestrictions) (int64, *model.AppError) GetGroupMemberUsers(groupID string) ([]*model.User, *model.AppError) GetGroupMemberUsersPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, int, *model.AppError) + GetGroupMemberUsersSortedPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions, teammateNameDisplay string) ([]*model.User, int, *model.AppError) GetGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) (*model.GroupSyncable, *model.AppError) GetGroupSyncables(groupID string, syncableType model.GroupSyncableType) ([]*model.GroupSyncable, *model.AppError) GetGroups(page, perPage int, opts model.GroupSearchOpts, viewRestrictions *model.ViewUsersRestrictions) ([]*model.Group, *model.AppError) diff --git a/app/group.go b/app/group.go index 6db059b33f..a01b369e41 100644 --- a/app/group.go +++ b/app/group.go @@ -250,8 +250,8 @@ func (a *App) GetGroupMemberUsers(groupID string) ([]*model.User, *model.AppErro return users, nil } -func (a *App) GetGroupMemberUsersPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, int, *model.AppError) { - members, err := a.Srv().Store().Group().GetMemberUsersPage(groupID, page, perPage, viewRestrictions) +func (a *App) GetGroupMemberUsersSortedPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions, teammateNameDisplay string) ([]*model.User, int, *model.AppError) { + members, err := a.Srv().Store().Group().GetMemberUsersSortedPage(groupID, page, perPage, viewRestrictions, teammateNameDisplay) if err != nil { return nil, 0, model.NewAppError("GetGroupMemberUsersPage", "app.select_error", nil, "", http.StatusInternalServerError).Wrap(err) } @@ -263,6 +263,10 @@ func (a *App) GetGroupMemberUsersPage(groupID string, page int, perPage int, vie return a.sanitizeProfiles(members, false), int(count), nil } +func (a *App) GetGroupMemberUsersPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, int, *model.AppError) { + return a.GetGroupMemberUsersSortedPage(groupID, page, perPage, viewRestrictions, model.ShowUsername) +} + func (a *App) GetUsersNotInGroupPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) { members, err := a.Srv().Store().Group().GetNonMemberUsersPage(groupID, page, perPage, viewRestrictions) if err != nil { diff --git a/app/opentracing/opentracing_layer.go b/app/opentracing/opentracing_layer.go index c004aff52b..367d98ec39 100644 --- a/app/opentracing/opentracing_layer.go +++ b/app/opentracing/opentracing_layer.go @@ -6438,6 +6438,28 @@ func (a *OpenTracingAppLayer) GetGroupMemberUsersPage(groupID string, page int, return resultVar0, resultVar1, resultVar2 } +func (a *OpenTracingAppLayer) GetGroupMemberUsersSortedPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions, teammateNameDisplay string) ([]*model.User, int, *model.AppError) { + origCtx := a.ctx + span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetGroupMemberUsersSortedPage") + + 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, resultVar2 := a.app.GetGroupMemberUsersSortedPage(groupID, page, perPage, viewRestrictions, teammateNameDisplay) + + if resultVar2 != nil { + span.LogFields(spanlog.Error(resultVar2)) + ext.Error.Set(span, true) + } + + return resultVar0, resultVar1, resultVar2 +} + func (a *OpenTracingAppLayer) GetGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) (*model.GroupSyncable, *model.AppError) { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetGroupSyncable") diff --git a/model/client4.go b/model/client4.go index d52df99214..48d63e959c 100644 --- a/model/client4.go +++ b/model/client4.go @@ -1258,6 +1258,24 @@ func (c *Client4) GetUsersInGroup(groupID string, page int, perPage int, etag st return list, BuildResponse(r), nil } +// GetUsersInGroup returns a page of users in a group. Page counting starts at 0. +func (c *Client4) GetUsersInGroupByDisplayName(groupID string, page int, perPage int, etag string) ([]*User, *Response, error) { + query := fmt.Sprintf("?sort=display_name&in_group=%v&page=%v&per_page=%v", groupID, page, perPage) + r, err := c.DoAPIGet(c.usersRoute()+query, etag) + if err != nil { + return nil, BuildResponse(r), err + } + defer closeBody(r) + var list []*User + if r.StatusCode == http.StatusNotModified { + return list, BuildResponse(r), nil + } + if err := json.NewDecoder(r.Body).Decode(&list); err != nil { + return nil, nil, NewAppError("GetUsersInGroupByDisplayName", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) + } + return list, BuildResponse(r), nil +} + // GetUsersByIds returns a list of users based on the provided user ids. func (c *Client4) GetUsersByIds(userIds []string) ([]*User, *Response, error) { r, err := c.DoAPIPost(c.usersRoute()+"/ids", ArrayToJSON(userIds)) diff --git a/store/opentracinglayer/opentracinglayer.go b/store/opentracinglayer/opentracinglayer.go index 241f3edf50..87b443640a 100644 --- a/store/opentracinglayer/opentracinglayer.go +++ b/store/opentracinglayer/opentracinglayer.go @@ -4501,6 +4501,24 @@ func (s *OpenTracingLayerGroupStore) GetMemberUsersPage(groupID string, page int return result, err } +func (s *OpenTracingLayerGroupStore) GetMemberUsersSortedPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions, teammateNameDisplay string) ([]*model.User, error) { + origCtx := s.Root.Store.Context() + span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "GroupStore.GetMemberUsersSortedPage") + s.Root.Store.SetContext(newCtx) + defer func() { + s.Root.Store.SetContext(origCtx) + }() + + defer span.Finish() + result, err := s.GroupStore.GetMemberUsersSortedPage(groupID, page, perPage, viewRestrictions, teammateNameDisplay) + if err != nil { + span.LogFields(spanlog.Error(err)) + ext.Error.Set(span, true) + } + + return result, err +} + func (s *OpenTracingLayerGroupStore) GetNonMemberUsersPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, error) { origCtx := s.Root.Store.Context() span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "GroupStore.GetNonMemberUsersPage") diff --git a/store/retrylayer/retrylayer.go b/store/retrylayer/retrylayer.go index dec858bba9..38a3f52dbf 100644 --- a/store/retrylayer/retrylayer.go +++ b/store/retrylayer/retrylayer.go @@ -5070,6 +5070,27 @@ func (s *RetryLayerGroupStore) GetMemberUsersPage(groupID string, page int, perP } +func (s *RetryLayerGroupStore) GetMemberUsersSortedPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions, teammateNameDisplay string) ([]*model.User, error) { + + tries := 0 + for { + result, err := s.GroupStore.GetMemberUsersSortedPage(groupID, page, perPage, viewRestrictions, teammateNameDisplay) + if err == nil { + return result, nil + } + if !isRepeatableError(err) { + return result, err + } + tries++ + if tries >= 3 { + err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures") + return result, err + } + timepkg.Sleep(100 * timepkg.Millisecond) + } + +} + func (s *RetryLayerGroupStore) GetNonMemberUsersPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, error) { tries := 0 diff --git a/store/sqlstore/group_store.go b/store/sqlstore/group_store.go index 64737840b8..8d160ef7a8 100644 --- a/store/sqlstore/group_store.go +++ b/store/sqlstore/group_store.go @@ -421,22 +421,56 @@ func (s *SqlGroupStore) GetMemberUsers(groupID string) ([]*model.User, error) { } func (s *SqlGroupStore) GetMemberUsersPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, error) { + return s.GetMemberUsersSortedPage(groupID, page, perPage, viewRestrictions, model.ShowUsername) +} + +func (s *SqlGroupStore) GetMemberUsersSortedPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions, teammateNameDisplay string) ([]*model.User, error) { groupMembers := []*model.User{} - query := s.getQueryBuilder(). - Select("u.*"). + userQuery := s.getQueryBuilder(). + Select(`u.*`). From("GroupMembers"). Join("Users u ON u.Id = GroupMembers.UserId"). Where(sq.Eq{"GroupMembers.DeleteAt": 0}). Where(sq.Eq{"u.DeleteAt": 0}). - Where(sq.Eq{"GroupId": groupID}). + Where(sq.Eq{"GroupId": groupID}) + + userQuery = applyViewRestrictionsFilter(userQuery, viewRestrictions, true) + queryString, args, err := userQuery.ToSql() + if err != nil { + return nil, errors.Wrap(err, "") + } + + orderQuery := s.getQueryBuilder(). + Select("u.*"). + From("(" + queryString + ") AS u") + + if teammateNameDisplay == model.ShowNicknameFullName { + orderQuery = orderQuery.OrderBy(` + CASE + WHEN u.Nickname != '' THEN u.Nickname + WHEN u.FirstName != '' AND u.LastName != '' THEN CONCAT(u.FirstName, ' ', u.LastName) + WHEN u.FirstName != '' THEN u.FirstName + WHEN u.LastName != '' THEN u.LastName + ELSE u.Username + END`) + } else if teammateNameDisplay == model.ShowFullName { + orderQuery = orderQuery.OrderBy(` + CASE + WHEN u.FirstName != '' AND u.LastName != '' THEN CONCAT(u.FirstName, ' ', u.LastName) + WHEN u.FirstName != '' THEN u.FirstName + WHEN u.LastName != '' THEN u.LastName + ELSE u.Username + END`) + } else { + orderQuery = orderQuery.OrderBy("u.Username") + } + + orderQuery = orderQuery. Limit(uint64(perPage)). - Offset(uint64(page * perPage)). - OrderBy("u.CreateAt DESC") + Offset(uint64(page * perPage)) - query = applyViewRestrictionsFilter(query, viewRestrictions, true) - - queryString, args, err := query.ToSql() + queryString, _, err = orderQuery.ToSql() if err != nil { return nil, errors.Wrap(err, "") } @@ -463,7 +497,7 @@ func (s *SqlGroupStore) GetNonMemberUsersPage(groupID string, page int, perPage Where("(GroupMembers.UserID IS NULL OR GroupMembers.DeleteAt != 0)"). Limit(uint64(perPage)). Offset(uint64(page * perPage)). - OrderBy("u.CreateAt DESC") + OrderBy("u.Username ASC") query = applyViewRestrictionsFilter(query, viewRestrictions, true) diff --git a/store/store.go b/store/store.go index 6a7f386553..49490afdbb 100644 --- a/store/store.go +++ b/store/store.go @@ -842,6 +842,7 @@ type GroupStore interface { GetMemberUsers(groupID string) ([]*model.User, error) GetMemberUsersPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, error) + GetMemberUsersSortedPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions, teammateNameDisplay string) ([]*model.User, error) GetMemberCountWithRestrictions(groupID string, viewRestrictions *model.ViewUsersRestrictions) (int64, error) GetMemberCount(groupID string) (int64, error) diff --git a/store/storetest/group_store.go b/store/storetest/group_store.go index 02d788765d..2b60e829f9 100644 --- a/store/storetest/group_store.go +++ b/store/storetest/group_store.go @@ -36,6 +36,7 @@ func TestGroupStore(t *testing.T, ss store.Store) { t.Run("GetMemberUsers", func(t *testing.T) { testGroupGetMemberUsers(t, ss) }) t.Run("GetMemberUsersPage", func(t *testing.T) { testGroupGetMemberUsersPage(t, ss) }) + t.Run("GetMemberUsersSortedPage", func(t *testing.T) { testGroupGetMemberUsersSortedPage(t, ss) }) t.Run("GetMemberUsersInTeam", func(t *testing.T) { testGroupGetMemberUsersInTeam(t, ss) }) t.Run("GetMemberUsersNotInChannel", func(t *testing.T) { testGroupGetMemberUsersNotInChannel(t, ss) }) @@ -861,7 +862,7 @@ func testGroupGetMemberUsersPage(t *testing.T, ss store.Store) { u1 := &model.User{ Email: MakeEmail(), - Username: model.NewId(), + Username: "user1" + model.NewId(), } user1, nErr := ss.User().Save(u1) require.NoError(t, nErr) @@ -871,7 +872,7 @@ func testGroupGetMemberUsersPage(t *testing.T, ss store.Store) { u2 := &model.User{ Email: MakeEmail(), - Username: model.NewId(), + Username: "user2" + model.NewId(), } user2, nErr := ss.User().Save(u2) require.NoError(t, nErr) @@ -881,7 +882,7 @@ func testGroupGetMemberUsersPage(t *testing.T, ss store.Store) { u3 := &model.User{ Email: MakeEmail(), - Username: model.NewId(), + Username: "user3" + model.NewId(), } user3, nErr := ss.User().Save(u3) require.NoError(t, nErr) @@ -898,13 +899,13 @@ func testGroupGetMemberUsersPage(t *testing.T, ss store.Store) { groupMembers, err = ss.Group().GetMemberUsersPage(group.Id, 0, 2, nil) require.NoError(t, err) require.Equal(t, 2, len(groupMembers)) - require.ElementsMatch(t, []*model.User{user2, user3}, groupMembers) + require.ElementsMatch(t, []*model.User{user1, user2}, groupMembers) // Check page 2 groupMembers, err = ss.Group().GetMemberUsersPage(group.Id, 1, 2, nil) require.NoError(t, err) require.Equal(t, 1, len(groupMembers)) - require.ElementsMatch(t, []*model.User{user1}, groupMembers) + require.ElementsMatch(t, []*model.User{user3}, groupMembers) // Check madeup id groupMembers, err = ss.Group().GetMemberUsersPage(model.NewId(), 0, 100, nil) @@ -921,6 +922,87 @@ func testGroupGetMemberUsersPage(t *testing.T, ss store.Store) { require.Equal(t, 2, len(groupMembers)) } +func testGroupGetMemberUsersSortedPage(t *testing.T, ss store.Store) { + // Save a group + g1 := &model.Group{ + Name: model.NewString(model.NewId()), + DisplayName: model.NewId(), + Description: model.NewId(), + Source: model.GroupSourceLdap, + RemoteId: model.NewString(model.NewId()), + } + group, err := ss.Group().Create(g1) + require.NoError(t, err) + + // First by nickname, third by full name, second by username + u1 := &model.User{ + Email: MakeEmail(), + Username: "y" + model.NewId(), + Nickname: "a" + model.NewId(), + FirstName: "z" + model.NewId(), + LastName: "z" + model.NewId(), + } + user1, nErr := ss.User().Save(u1) + require.NoError(t, nErr) + + _, err = ss.Group().UpsertMember(group.Id, user1.Id) + require.NoError(t, err) + + // Second by nickname, first by full name, third by username + u2 := &model.User{ + Email: MakeEmail(), + Username: "z" + model.NewId(), + FirstName: "b" + model.NewId(), + LastName: "b" + model.NewId(), + } + user2, nErr := ss.User().Save(u2) + require.NoError(t, nErr) + + _, err = ss.Group().UpsertMember(group.Id, user2.Id) + require.NoError(t, err) + + // Third by nickname, second by full name, first by username + u3 := &model.User{ + Email: MakeEmail(), + Username: "d" + model.NewId(), + } + user3, nErr := ss.User().Save(u3) + require.NoError(t, nErr) + + _, err = ss.Group().UpsertMember(group.Id, user3.Id) + require.NoError(t, err) + + // Check nickname ordering, paged + groupMembers, err := ss.Group().GetMemberUsersSortedPage(group.Id, 0, 2, nil, model.ShowNicknameFullName) + require.NoError(t, err) + require.Equal(t, 2, len(groupMembers)) + require.ElementsMatch(t, []*model.User{user1, user2}, groupMembers) + groupMembers, err = ss.Group().GetMemberUsersSortedPage(group.Id, 1, 2, nil, model.ShowNicknameFullName) + require.NoError(t, err) + require.Equal(t, 1, len(groupMembers)) + require.ElementsMatch(t, []*model.User{user3}, groupMembers) + + // Check full name ordering, paged + groupMembers, err = ss.Group().GetMemberUsersSortedPage(group.Id, 0, 2, nil, model.ShowFullName) + require.NoError(t, err) + require.Equal(t, 2, len(groupMembers)) + require.ElementsMatch(t, []*model.User{user2, user3}, groupMembers) + groupMembers, err = ss.Group().GetMemberUsersSortedPage(group.Id, 1, 2, nil, model.ShowFullName) + require.NoError(t, err) + require.Equal(t, 1, len(groupMembers)) + require.ElementsMatch(t, []*model.User{user1}, groupMembers) + + // Check username ordering + groupMembers, err = ss.Group().GetMemberUsersSortedPage(group.Id, 0, 2, nil, model.ShowUsername) + require.NoError(t, err) + require.Equal(t, 2, len(groupMembers)) + require.ElementsMatch(t, []*model.User{user3, user1}, groupMembers) + groupMembers, err = ss.Group().GetMemberUsersSortedPage(group.Id, 1, 2, nil, model.ShowUsername) + require.NoError(t, err) + require.Equal(t, 1, len(groupMembers)) + require.ElementsMatch(t, []*model.User{user2}, groupMembers) +} + func testGroupGetMemberUsersInTeam(t *testing.T, ss store.Store) { // Save a team team := &model.Team{ diff --git a/store/storetest/mocks/GroupStore.go b/store/storetest/mocks/GroupStore.go index 7f54c5487b..e77e2a8628 100644 --- a/store/storetest/mocks/GroupStore.go +++ b/store/storetest/mocks/GroupStore.go @@ -826,6 +826,29 @@ func (_m *GroupStore) GetMemberUsersPage(groupID string, page int, perPage int, return r0, r1 } +// GetMemberUsersSortedPage provides a mock function with given fields: groupID, page, perPage, viewRestrictions, teammateNameDisplay +func (_m *GroupStore) GetMemberUsersSortedPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions, teammateNameDisplay string) ([]*model.User, error) { + ret := _m.Called(groupID, page, perPage, viewRestrictions, teammateNameDisplay) + + var r0 []*model.User + if rf, ok := ret.Get(0).(func(string, int, int, *model.ViewUsersRestrictions, string) []*model.User); ok { + r0 = rf(groupID, page, perPage, viewRestrictions, teammateNameDisplay) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*model.User) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(string, int, int, *model.ViewUsersRestrictions, string) error); ok { + r1 = rf(groupID, page, perPage, viewRestrictions, teammateNameDisplay) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetNonMemberUsersPage provides a mock function with given fields: groupID, page, perPage, viewRestrictions func (_m *GroupStore) GetNonMemberUsersPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, error) { ret := _m.Called(groupID, page, perPage, viewRestrictions) diff --git a/store/timerlayer/timerlayer.go b/store/timerlayer/timerlayer.go index 55415d1c47..02be7b110d 100644 --- a/store/timerlayer/timerlayer.go +++ b/store/timerlayer/timerlayer.go @@ -4098,6 +4098,22 @@ func (s *TimerLayerGroupStore) GetMemberUsersPage(groupID string, page int, perP return result, err } +func (s *TimerLayerGroupStore) GetMemberUsersSortedPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions, teammateNameDisplay string) ([]*model.User, error) { + start := time.Now() + + result, err := s.GroupStore.GetMemberUsersSortedPage(groupID, page, perPage, viewRestrictions, teammateNameDisplay) + + elapsed := float64(time.Since(start)) / float64(time.Second) + if s.Root.Metrics != nil { + success := "false" + if err == nil { + success = "true" + } + s.Root.Metrics.ObserveStoreMethodDuration("GroupStore.GetMemberUsersSortedPage", success, elapsed) + } + return result, err +} + func (s *TimerLayerGroupStore) GetNonMemberUsersPage(groupID string, page int, perPage int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, error) { start := time.Now()