diff --git a/server/cmd/mmctl/client/client.go b/server/cmd/mmctl/client/client.go index 0a0b1fff47..8f5aeaa5d9 100644 --- a/server/cmd/mmctl/client/client.go +++ b/server/cmd/mmctl/client/client.go @@ -97,6 +97,7 @@ type Client interface { SyncLdap(ctx context.Context, includeRemovedMembers bool) (*model.Response, error) MigrateIdLdap(ctx context.Context, toAttribute string) (*model.Response, error) GetUsers(ctx context.Context, page, perPage int, etag string) ([]*model.User, *model.Response, error) + GetUsersWithCustomQueryParameters(ctx context.Context, page, perPage int, queryParameters string, etag string) ([]*model.User, *model.Response, error) GetUsersByIds(ctx context.Context, userIDs []string) ([]*model.User, *model.Response, error) GetUsersInTeam(ctx context.Context, teamID string, page, perPage int, etag string) ([]*model.User, *model.Response, error) UpdateUserActive(ctx context.Context, userID string, activate bool) (*model.Response, error) diff --git a/server/cmd/mmctl/commands/user.go b/server/cmd/mmctl/commands/user.go index 210ec9a727..47b4baca0b 100644 --- a/server/cmd/mmctl/commands/user.go +++ b/server/cmd/mmctl/commands/user.go @@ -8,6 +8,7 @@ import ( "encoding/json" "fmt" "net/http" + "net/url" "os" "sort" @@ -320,6 +321,7 @@ func init() { ListUsersCmd.Flags().Int("per-page", DefaultPageSize, "Number of users to be fetched") ListUsersCmd.Flags().Bool("all", false, "Fetch all users. --page flag will be ignore if provided") ListUsersCmd.Flags().String("team", "", "If supplied, only users belonging to this team will be listed") + ListUsersCmd.Flags().Bool("inactive", false, "If supplied, only users which are inactive will be fetch") UserConvertCmd.Flags().Bool("bot", false, "If supplied, convert users to bots") UserConvertCmd.Flags().Bool("user", false, "If supplied, convert a bot to a user") @@ -798,6 +800,16 @@ auth_service: {{.AuthService}}` return nil } +func ResetListUsersCmd() *cobra.Command { + ListUsersCmd.Flags().Set("page", "0") + ListUsersCmd.Flags().Set("per-page", "200") + ListUsersCmd.Flags().Set("all", "false") + ListUsersCmd.Flags().Set("team", "") + ListUsersCmd.Flags().Set("inactive", "false") + + return ListUsersCmd +} + func listUsersCmdF(c client.Client, command *cobra.Command, args []string) error { page, err := command.Flags().GetInt("page") if err != nil { @@ -815,6 +827,11 @@ func listUsersCmdF(c client.Client, command *cobra.Command, args []string) error if err != nil { return err } + // if inactive, DeletedAt != 0 + inactive, err := command.Flags().GetBool("inactive") + if err != nil { + return err + } if showAll { page = 0 @@ -829,21 +846,21 @@ func listUsersCmdF(c client.Client, command *cobra.Command, args []string) error } } + params := url.Values{} + if inactive { + params.Add("inactive", "true") + } + if team != nil { + params.Add("in_team", team.Id) + } + tpl := `{{.Id}}: {{.Username}} ({{.Email}})` for { - var users []*model.User - var err error - if team != nil { - users, _, err = c.GetUsersInTeam(context.TODO(), team.Id, page, perPage, "") - if err != nil { - return errors.Wrap(err, fmt.Sprintf("Failed to fetch users for team %s", teamName)) - } - } else { - users, _, err = c.GetUsers(context.TODO(), page, perPage, "") - if err != nil { - return errors.Wrap(err, "Failed to fetch users") - } + users, _, err := c.GetUsersWithCustomQueryParameters(context.TODO(), page, perPage, params.Encode(), "") + if err != nil { + return errors.Wrap(err, "Failed to fetch users") } + if len(users) == 0 { break } diff --git a/server/cmd/mmctl/commands/user_e2e_test.go b/server/cmd/mmctl/commands/user_e2e_test.go index 45fce2d3f0..a0b1d5ef49 100644 --- a/server/cmd/mmctl/commands/user_e2e_test.go +++ b/server/cmd/mmctl/commands/user_e2e_test.go @@ -164,18 +164,26 @@ func (s *MmctlE2ETestSuite) TestListUserCmd() { userPool = append(userPool, usr.Username) } + inactivePool := []string{} + // create inactive users + for i := 0; i < 2; i++ { + userData := model.User{ + Username: "fakeuser" + model.NewRandomString(10), + Password: "Pa$$word11", + Email: s.th.GenerateTestEmail(), + DeleteAt: model.GetMillis(), + } + usr, err := s.th.App.CreateUser(s.th.Context, &userData) + s.Require().Nil(err) + userPool = append(userPool, usr.Username) + inactivePool = append(inactivePool, usr.Username) + } + s.RunForAllClients("Get some random user", func(c client.Client) { printer.Clean() - var page int - var all bool - perpage := 5 - team := "" - cmd := &cobra.Command{} - cmd.Flags().IntVar(&page, "page", page, "page") - cmd.Flags().IntVar(&perpage, "per-page", perpage, "perpage") - cmd.Flags().BoolVar(&all, "all", all, "all") - cmd.Flags().StringVar(&team, "team", team, "team") + cmd := ResetListUsersCmd() + cmd.Flags().Set("per-page", "5") err := listUsersCmdF(c, cmd, []string{}) s.Require().Nil(err) @@ -191,25 +199,103 @@ func (s *MmctlE2ETestSuite) TestListUserCmd() { s.RunForAllClients("Get list of all user", func(c client.Client) { printer.Clean() - var page int - perpage := 10 - all := true - team := "" - cmd := &cobra.Command{} - cmd.Flags().IntVar(&page, "page", page, "page") - cmd.Flags().IntVar(&perpage, "per-page", perpage, "perpage") - cmd.Flags().BoolVar(&all, "all", all, "all") - cmd.Flags().StringVar(&team, "team", team, "team") + cmd := ResetListUsersCmd() + cmd.Flags().Set("per-page", "12") + cmd.Flags().Set("all", "true") err := listUsersCmdF(c, cmd, []string{}) s.Require().Nil(err) - s.Require().GreaterOrEqual(len(printer.GetLines()), 14) + s.Require().GreaterOrEqual(len(printer.GetLines()), 16) s.Len(printer.GetErrorLines(), 0) for _, each := range printer.GetLines() { user := each.(*model.User) s.Require().Contains(userPool, user.Username) } }) + + s.RunForAllClients("Get list of inactive users", func(c client.Client) { + printer.Clean() + + cmd := ResetListUsersCmd() + cmd.Flags().Set("per-page", "12") + cmd.Flags().Set("all", "true") + cmd.Flags().Set("inactive", "true") + + err := listUsersCmdF(c, cmd, []string{}) + s.Require().Nil(err) + s.Require().GreaterOrEqual(len(printer.GetLines()), 2) + s.Len(printer.GetErrorLines(), 0) + for _, each := range printer.GetLines() { + user := each.(*model.User) + s.Require().Contains(inactivePool, user.Username) + } + }) + + // create users with team + for i := 0; i < 10; i++ { + userData := model.User{ + Username: "teamuser" + model.NewRandomString(10), + Password: "Pa$$word11", + Email: s.th.GenerateTestEmail(), + } + usr, err := s.th.App.CreateUser(s.th.Context, &userData) + s.Require().Nil(err) + userPool = append(userPool, usr.Username) + s.th.LinkUserToTeam(usr, s.th.BasicTeam) + } + + s.RunForAllClients("Get list users given team", func(c client.Client) { + printer.Clean() + + cmd := ResetListUsersCmd() + cmd.Flags().Set("per-page", "40") + cmd.Flags().Set("all", "true") + cmd.Flags().Set("team", s.th.BasicTeam.Name) + + err := listUsersCmdF(c, cmd, []string{}) + s.Require().Nil(err) + s.Require().GreaterOrEqual(len(printer.GetLines()), 10) + s.Len(printer.GetErrorLines(), 0) + for _, each := range printer.GetLines() { + user := each.(*model.User) + s.Require().Contains(userPool, user.Username) + } + }) + + // create inactive users with team + inactiveUserPool := []string{} + + for i := 0; i < 10; i++ { + userData := model.User{ + Username: "inactiveteamuser" + model.NewRandomString(10), + Password: "Pa$$word11", + Email: s.th.GenerateTestEmail(), + DeleteAt: model.GetMillis(), + } + usr, err := s.th.App.CreateUser(s.th.Context, &userData) + s.Require().Nil(err) + inactiveUserPool = append(inactiveUserPool, usr.Username) + s.th.LinkUserToTeam(usr, s.th.BasicTeam) + } + + s.RunForAllClients("Get list of inactive users given team", func(c client.Client) { + printer.Clean() + + cmd := ResetListUsersCmd() + cmd.Flags().Set("per-page", "40") + cmd.Flags().Set("all", "true") + cmd.Flags().Set("team", s.th.BasicTeam.Name) + cmd.Flags().Set("inactive", "true") + + err := listUsersCmdF(c, cmd, []string{}) + s.Require().Nil(err) + s.Require().GreaterOrEqual(len(printer.GetLines()), 10) + s.Len(printer.GetErrorLines(), 0) + for _, each := range printer.GetLines() { + user := each.(*model.User) + s.Require().Contains(inactiveUserPool, user.Username) + } + }) } func (s *MmctlE2ETestSuite) TestUserInviteCmdf() { diff --git a/server/cmd/mmctl/commands/user_test.go b/server/cmd/mmctl/commands/user_test.go index 775080d879..5e061d82fd 100644 --- a/server/cmd/mmctl/commands/user_test.go +++ b/server/cmd/mmctl/commands/user_test.go @@ -9,7 +9,6 @@ import ( "fmt" "net/http" "os" - "strconv" "strings" "github.com/mattermost/mattermost/server/public/model" @@ -1866,28 +1865,18 @@ func (s *MmctlUnitTestSuite) TestResetUserMfaCmd() { } func (s *MmctlUnitTestSuite) TestListUserCmdF() { - cmd := &cobra.Command{} - cmd.Flags().Int("page", 0, "") - cmd.Flags().Int("per-page", 200, "") - cmd.Flags().Bool("all", false, "") - cmd.Flags().String("team", "", "") - s.Run("Listing users with paging", func() { printer.Clean() email := "example@example.com" mockUser := model.User{Username: "ExampleUser", Email: email} - page := 0 - perPage := 1 - showAll := false - _ = cmd.Flags().Set("page", strconv.Itoa(page)) - _ = cmd.Flags().Set("per-page", strconv.Itoa(perPage)) - _ = cmd.Flags().Set("all", strconv.FormatBool(showAll)) + cmd := ResetListUsersCmd() + cmd.Flags().Set("per-page", "1") s.client. EXPECT(). - GetUsers(context.TODO(), page, perPage, ""). + GetUsersWithCustomQueryParameters(context.TODO(), 0, 1, "", ""). Return([]*model.User{&mockUser}, &model.Response{}, nil). Times(1) @@ -1905,28 +1894,25 @@ func (s *MmctlUnitTestSuite) TestListUserCmdF() { email2 := "example2@example.com" mockUser2 := model.User{Username: "ExampleUser2", Email: email2} - page := 0 - perPage := 1 - showAll := true - _ = cmd.Flags().Set("page", strconv.Itoa(page)) - _ = cmd.Flags().Set("per-page", strconv.Itoa(perPage)) - _ = cmd.Flags().Set("all", strconv.FormatBool(showAll)) + cmd := ResetListUsersCmd() + cmd.Flags().Set("per-page", "1") + cmd.Flags().Set("all", "true") s.client. EXPECT(). - GetUsers(context.TODO(), 0, perPage, ""). + GetUsersWithCustomQueryParameters(context.TODO(), 0, 1, "", ""). Return([]*model.User{&mockUser1}, &model.Response{}, nil). Times(1) s.client. EXPECT(). - GetUsers(context.TODO(), 1, perPage, ""). + GetUsersWithCustomQueryParameters(context.TODO(), 1, 1, "", ""). Return([]*model.User{&mockUser2}, &model.Response{}, nil). Times(1) s.client. EXPECT(). - GetUsers(context.TODO(), 2, perPage, ""). + GetUsersWithCustomQueryParameters(context.TODO(), 2, 1, "", ""). Return([]*model.User{}, &model.Response{}, nil). Times(1) @@ -1937,19 +1923,116 @@ func (s *MmctlUnitTestSuite) TestListUserCmdF() { s.Require().Equal(&mockUser2, printer.GetLines()[1]) }) - s.Run("Try to list all the users when there are no uses in store", func() { + s.Run("Listing all users including inactive", func() { printer.Clean() - page := 0 - perPage := 1 - showAll := false - _ = cmd.Flags().Set("page", strconv.Itoa(page)) - _ = cmd.Flags().Set("per-page", strconv.Itoa(perPage)) - _ = cmd.Flags().Set("all", strconv.FormatBool(showAll)) + email1 := "example1@example.com" + mockUser1 := model.User{Username: "ExampleUser1", Email: email1} + email2 := "example2@example.com" + mockUser2 := model.User{Username: "ExampleUser2", Email: email2, DeleteAt: model.GetMillis()} + + cmd := ResetListUsersCmd() + cmd.Flags().Set("per-page", "1") + cmd.Flags().Set("all", "true") s.client. EXPECT(). - GetUsers(context.TODO(), page, perPage, ""). + GetUsersWithCustomQueryParameters(context.TODO(), 0, 1, "", ""). + Return([]*model.User{&mockUser1}, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetUsersWithCustomQueryParameters(context.TODO(), 1, 1, "", ""). + Return([]*model.User{&mockUser2}, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetUsersWithCustomQueryParameters(context.TODO(), 2, 1, "", ""). + Return([]*model.User{}, &model.Response{}, nil). + Times(1) + + err := listUsersCmdF(s.client, cmd, []string{}) + s.Require().Nil(err) + s.Require().Len(printer.GetLines(), 2) + s.Require().Equal(&mockUser1, printer.GetLines()[0]) + s.Require().Equal(&mockUser2, printer.GetLines()[1]) + }) + + s.Run("Listing all inactive users", func() { + printer.Clean() + + email2 := "example2@example.com" + mockUser2 := model.User{Username: "ExampleUser2", Email: email2, DeleteAt: model.GetMillis()} + email3 := "example3@example.com" + mockUser3 := model.User{Username: "ExampleUser3", Email: email3, DeleteAt: model.GetMillis()} + + cmd := ResetListUsersCmd() + cmd.Flags().Set("per-page", "1") + cmd.Flags().Set("all", "true") + cmd.Flags().Set("inactive", "true") + + s.client. + EXPECT(). + GetUsersWithCustomQueryParameters(context.TODO(), 0, 1, "inactive=true", ""). + Return([]*model.User{&mockUser2}, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetUsersWithCustomQueryParameters(context.TODO(), 1, 1, "inactive=true", ""). + Return([]*model.User{&mockUser3}, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetUsersWithCustomQueryParameters(context.TODO(), 2, 1, "inactive=true", ""). + Return([]*model.User{}, &model.Response{}, nil). + Times(1) + + err := listUsersCmdF(s.client, cmd, []string{}) + s.Require().Nil(err) + s.Require().Len(printer.GetLines(), 2) + s.Require().Equal(&mockUser2, printer.GetLines()[0]) + s.Require().Equal(&mockUser3, printer.GetLines()[1]) + }) + + s.Run("Listing inactive users with paging skipping 1 page", func() { + printer.Clean() + + email := "del@example.com" + _ = model.User{Username: "ExampleUser", Email: email, DeleteAt: model.GetMillis()} + email1 := "del1@example.com" + mockUser1 := model.User{Username: "ExampleUser1", Email: email1, DeleteAt: model.GetMillis()} + + cmd := ResetListUsersCmd() + cmd.Flags().Set("page", "1") + cmd.Flags().Set("per-page", "1") + cmd.Flags().Set("inactive", "true") + + s.client. + EXPECT(). + GetUsersWithCustomQueryParameters(context.TODO(), 1, 1, "inactive=true", ""). + Return([]*model.User{&mockUser1}, &model.Response{}, nil). + Times(1) + + err := listUsersCmdF(s.client, cmd, []string{}) + s.Require().Nil(err) + s.Require().Len(printer.GetLines(), 1) + s.Require().Equal(&mockUser1, printer.GetLines()[0]) + }) + + s.Run("Try to list all the users when there are no uses in store", func() { + printer.Clean() + + cmd := ResetListUsersCmd() + cmd.Flags().Set("page", "0") + cmd.Flags().Set("per-page", "1") + + s.client. + EXPECT(). + GetUsersWithCustomQueryParameters(context.TODO(), 0, 1, "", ""). Return([]*model.User{}, &model.Response{}, nil). Times(1) @@ -1958,22 +2041,19 @@ func (s *MmctlUnitTestSuite) TestListUserCmdF() { s.Require().Len(printer.GetLines(), 0) }) - s.Run("Return an error from GetUsers call and verify that error is properly returned", func() { + s.Run("Return an error from GetUsersWithCustomQueryParameters call and verify that error is properly returned", func() { printer.Clean() - page := 0 - perPage := 1 - showAll := false - _ = cmd.Flags().Set("page", strconv.Itoa(page)) - _ = cmd.Flags().Set("per-page", strconv.Itoa(perPage)) - _ = cmd.Flags().Set("all", strconv.FormatBool(showAll)) + cmd := ResetListUsersCmd() + cmd.Flags().Set("page", "0") + cmd.Flags().Set("per-page", "1") mockError := errors.New("mock error") mockErrorW := errors.Wrap(mockError, "Failed to fetch users") s.client. EXPECT(). - GetUsers(context.TODO(), page, perPage, ""). + GetUsersWithCustomQueryParameters(context.TODO(), 0, 1, "", ""). Return(nil, &model.Response{}, mockError). Times(1) @@ -1988,16 +2068,13 @@ func (s *MmctlUnitTestSuite) TestListUserCmdF() { email := "example@example.com" mockUser := model.User{Username: "ExampleUser", Email: email} - page := 2 - perPage := 1 - showAll := false - _ = cmd.Flags().Set("page", strconv.Itoa(page)) - _ = cmd.Flags().Set("per-page", strconv.Itoa(perPage)) - _ = cmd.Flags().Set("all", strconv.FormatBool(showAll)) + cmd := ResetListUsersCmd() + cmd.Flags().Set("page", "2") + cmd.Flags().Set("per-page", "1") s.client. EXPECT(). - GetUsers(context.TODO(), page, perPage, ""). + GetUsersWithCustomQueryParameters(context.TODO(), 2, 1, "", ""). Return([]*model.User{&mockUser}, &model.Response{}, nil). Times(1) @@ -2012,16 +2089,14 @@ func (s *MmctlUnitTestSuite) TestListUserCmdF() { email := "example@example.com" mockUser := model.User{Username: "ExampleUser", Email: email} - resultID := "teamId" - page := 0 - perPage := 1 - showAll := false + resultID := "teamId" team := "teamName" - _ = cmd.Flags().Set("page", strconv.Itoa(page)) - _ = cmd.Flags().Set("per-page", strconv.Itoa(perPage)) - _ = cmd.Flags().Set("all", strconv.FormatBool(showAll)) - _ = cmd.Flags().Set("team", team) + + cmd := ResetListUsersCmd() + cmd.Flags().Set("page", "0") + cmd.Flags().Set("per-page", "1") + cmd.Flags().Set("team", team) s.client. EXPECT(). @@ -2031,7 +2106,7 @@ func (s *MmctlUnitTestSuite) TestListUserCmdF() { s.client. EXPECT(). - GetUsersInTeam(context.TODO(), resultID, page, perPage, ""). + GetUsersWithCustomQueryParameters(context.TODO(), 0, 1, "in_team="+resultID, ""). Return([]*model.User{&mockUser}, &model.Response{}, nil). Times(1) @@ -2040,6 +2115,90 @@ func (s *MmctlUnitTestSuite) TestListUserCmdF() { s.Require().Len(printer.GetLines(), 1) s.Require().Equal(&mockUser, printer.GetLines()[0]) }) + + s.Run("Listing inactive users for given team", func() { + printer.Clean() + + email := "example@example.com" + _ = model.User{Username: "ExampleUser", Email: email} + email1 := "example1@example.com" + mockUser1 := model.User{Username: "ExampleUser1", Email: email1, DeleteAt: model.GetMillis()} + + resultID := "teamId" + team := "teamName" + + cmd := ResetListUsersCmd() + cmd.Flags().Set("page", "0") + cmd.Flags().Set("per-page", "1") + cmd.Flags().Set("team", team) + + s.client. + EXPECT(). + GetTeamByName(context.TODO(), team, ""). + Return(&model.Team{Id: resultID}, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetUsersWithCustomQueryParameters(context.TODO(), 0, 1, "in_team="+resultID, ""). + Return([]*model.User{&mockUser1}, &model.Response{}, nil). + Times(1) + + err := listUsersCmdF(s.client, cmd, []string{}) + s.Require().Nil(err) + s.Require().Len(printer.GetLines(), 1) + s.Require().Equal(&mockUser1, printer.GetLines()[0]) + }) + + s.Run("Listing all inactive users for given team", func() { + printer.Clean() + + email := "example@example.com" + _ = model.User{Username: "ExampleUser", Email: email} + email1 := "example1@example.com" + mockUser1 := model.User{Username: "ExampleUser1", Email: email1, DeleteAt: model.GetMillis()} + email2 := "example2@example.com" + mockUser2 := model.User{Username: "ExampleUser2", Email: email2, DeleteAt: model.GetMillis()} + + resultID := "teamId" + team := "teamName" + + cmd := ResetListUsersCmd() + cmd.Flags().Set("page", "0") + cmd.Flags().Set("per-page", "1") + cmd.Flags().Set("team", team) + cmd.Flags().Set("all", "true") + + s.client. + EXPECT(). + GetTeamByName(context.TODO(), team, ""). + Return(&model.Team{Id: resultID}, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetUsersWithCustomQueryParameters(context.TODO(), 0, 1, "in_team="+resultID, ""). + Return([]*model.User{&mockUser1}, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetUsersWithCustomQueryParameters(context.TODO(), 1, 1, "in_team="+resultID, ""). + Return([]*model.User{&mockUser2}, &model.Response{}, nil). + Times(1) + + s.client. + EXPECT(). + GetUsersWithCustomQueryParameters(context.TODO(), 2, 1, "in_team="+resultID, ""). + Return([]*model.User{}, &model.Response{}, nil). + Times(1) + + err := listUsersCmdF(s.client, cmd, []string{}) + s.Require().Nil(err) + s.Require().Len(printer.GetLines(), 2) + s.Require().Equal(&mockUser1, printer.GetLines()[0]) + s.Require().Equal(&mockUser2, printer.GetLines()[1]) + }) } func (s *MmctlUnitTestSuite) TestUserDeactivateCmd() { diff --git a/server/cmd/mmctl/docs/mmctl_user_list.rst b/server/cmd/mmctl/docs/mmctl_user_list.rst index 2e8c26d5d2..ba6a05391c 100644 --- a/server/cmd/mmctl/docs/mmctl_user_list.rst +++ b/server/cmd/mmctl/docs/mmctl_user_list.rst @@ -29,6 +29,7 @@ Options --all Fetch all users. --page flag will be ignore if provided -h, --help help for list + --inactive If supplied, only users which are inactive will be fetch --page int Page number to fetch for the list of users --per-page int Number of users to be fetched (default 200) --team string If supplied, only users belonging to this team will be listed diff --git a/server/public/model/client4.go b/server/public/model/client4.go index 74345ddb66..33f90417d9 100644 --- a/server/public/model/client4.go +++ b/server/public/model/client4.go @@ -1094,7 +1094,7 @@ func (c *Client4) GetUsers(ctx context.Context, page int, perPage int, etag stri return list, BuildResponse(r), nil } -// GetUsersWithChannelRoles returns a page of users on the system. Page counting starts at 0. +// GetUsersWithCustomQueryParameters returns a page of users on the system. Page counting starts at 0. func (c *Client4) GetUsersWithCustomQueryParameters(ctx context.Context, page int, perPage int, queryParameters, etag string) ([]*User, *Response, error) { query := fmt.Sprintf("?page=%v&per_page=%v&%v", page, perPage, queryParameters) r, err := c.DoAPIGet(ctx, c.usersRoute()+query, etag) @@ -1107,7 +1107,7 @@ func (c *Client4) GetUsersWithCustomQueryParameters(ctx context.Context, page in return list, BuildResponse(r), nil } if err := json.NewDecoder(r.Body).Decode(&list); err != nil { - return nil, nil, NewAppError("GetUsers", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) + return nil, nil, NewAppError("GetUsersWithCustomQueryParameters", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err) } return list, BuildResponse(r), nil }