diff --git a/server/cmd/mmctl/client/client.go b/server/cmd/mmctl/client/client.go index c673cd3d5d..0a0b1fff47 100644 --- a/server/cmd/mmctl/client/client.go +++ b/server/cmd/mmctl/client/client.go @@ -63,6 +63,7 @@ type Client interface { GetUser(ctx context.Context, userID, etag string) (*model.User, *model.Response, error) GetUserByUsername(ctx context.Context, userName, etag string) (*model.User, *model.Response, error) GetUserByEmail(ctx context.Context, email, etag string) (*model.User, *model.Response, error) + GetUsersWithCustomQueryParameters(ctx context.Context, page int, perPage int, queryParameters, etag string) ([]*model.User, *model.Response, error) PermanentDeleteUser(ctx context.Context, userID string) (*model.Response, error) PermanentDeleteAllUsers(ctx context.Context) (*model.Response, error) CreateUser(ctx context.Context, user *model.User) (*model.User, *model.Response, error) diff --git a/server/cmd/mmctl/commands/user.go b/server/cmd/mmctl/commands/user.go index 651b98e1f8..210ec9a727 100644 --- a/server/cmd/mmctl/commands/user.go +++ b/server/cmd/mmctl/commands/user.go @@ -32,8 +32,9 @@ var UserActivateCmd = &cobra.Command{ Long: "Activate users that have been deactivated.", Example: ` user activate user@example.com user activate username`, - RunE: withClient(userActivateCmdF), - Args: cobra.MinimumNArgs(1), + ValidArgsFunction: validateArgsWithClient(userActivateCompletionF), + Args: cobra.MinimumNArgs(1), + RunE: withClient(userActivateCmdF), } var UserDeactivateCmd = &cobra.Command{ @@ -42,8 +43,9 @@ var UserDeactivateCmd = &cobra.Command{ Long: "Deactivate users. Deactivated users are immediately logged out of all sessions and are unable to log back in.", Example: ` user deactivate user@example.com user deactivate username`, - RunE: withClient(userDeactivateCmdF), - Args: cobra.MinimumNArgs(1), + ValidArgsFunction: validateArgsWithClient(userDeactivateCompletionF), + Args: cobra.MinimumNArgs(1), + RunE: withClient(userDeactivateCmdF), } var UserCreateCmd = &cobra.Command{ @@ -427,6 +429,15 @@ func userActivateCmdF(c client.Client, command *cobra.Command, args []string) er return changeUsersActiveStatus(c, args, true) } +func userActivateCompletionF(ctx context.Context, c client.Client, cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return fetchAndComplete( + func(ctx context.Context, c client.Client, page, perPage int) ([]*model.User, *model.Response, error) { + return c.GetUsersWithCustomQueryParameters(ctx, page, perPage, "inactive=true", "") + }, + func(u *model.User) []string { return []string{u.Id, u.Username, u.Email} }, + )(ctx, c, cmd, args, toComplete) +} + func changeUsersActiveStatus(c client.Client, userArgs []string, active bool) error { var multiErr *multierror.Error users, err := getUsersFromArgs(c, userArgs) @@ -458,6 +469,15 @@ func userDeactivateCmdF(c client.Client, cmd *cobra.Command, args []string) erro return changeUsersActiveStatus(c, args, false) } +func userDeactivateCompletionF(ctx context.Context, c client.Client, cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return fetchAndComplete( + func(ctx context.Context, c client.Client, page, perPage int) ([]*model.User, *model.Response, error) { + return c.GetUsersWithCustomQueryParameters(ctx, page, perPage, "active=true", "") + }, + func(u *model.User) []string { return []string{u.Id, u.Username, u.Email} }, + )(ctx, c, cmd, args, toComplete) +} + func userCreateCmdF(c client.Client, cmd *cobra.Command, args []string) error { printer.SetSingle(true) diff --git a/server/cmd/mmctl/commands/user_test.go b/server/cmd/mmctl/commands/user_test.go index b1c7b75c5f..775080d879 100644 --- a/server/cmd/mmctl/commands/user_test.go +++ b/server/cmd/mmctl/commands/user_test.go @@ -179,6 +179,38 @@ func (s *MmctlUnitTestSuite) TestUserActivateCmd() { s.Require().Equal(fmt.Sprintf("1 error occurred:\n\t* user %s not found\n\n", emailArgs[1]), printer.GetErrorLines()[0]) s.Require().Equal(fmt.Sprintf("unable to change activation status of user: %v", mockUser3.Id), printer.GetErrorLines()[1]) }) + + s.Run("shell completion", func() { + s.Run("one element matches", func() { + mockUsers := []*model.User{ + { + Id: "0_id", + Username: "0_username", + Email: "0_email@example.org", + }, + { + Id: "1_id", + Username: "1_username", + Email: "1_email@example.org", + }, + { + Id: "2_id", + Username: "2_username", + Email: "2_email@example.org", + }, + } + + s.client. + EXPECT(). + GetUsersWithCustomQueryParameters(context.Background(), 0, DefaultPageSize, "inactive=true", ""). + Return(mockUsers, &model.Response{}, nil). + Times(1) + + r, dir := userActivateCompletionF(context.Background(), s.client, nil, nil, "1") + s.Equal(cobra.ShellCompDirectiveNoFileComp, dir) + s.Equal([]string{"1_id"}, r) + }) + }) } func (s *MmctlUnitTestSuite) TestDeactivateUserCmd() { diff --git a/server/cmd/mmctl/mocks/client_mock.go b/server/cmd/mmctl/mocks/client_mock.go index 1585c52d5f..59b3cc2fb8 100644 --- a/server/cmd/mmctl/mocks/client_mock.go +++ b/server/cmd/mmctl/mocks/client_mock.go @@ -1438,6 +1438,22 @@ func (mr *MockClientMockRecorder) GetUsersInTeam(arg0, arg1, arg2, arg3, arg4 in return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUsersInTeam", reflect.TypeOf((*MockClient)(nil).GetUsersInTeam), arg0, arg1, arg2, arg3, arg4) } +// GetUsersWithCustomQueryParameters mocks base method. +func (m *MockClient) GetUsersWithCustomQueryParameters(arg0 context.Context, arg1, arg2 int, arg3, arg4 string) ([]*model.User, *model.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetUsersWithCustomQueryParameters", arg0, arg1, arg2, arg3, arg4) + ret0, _ := ret[0].([]*model.User) + ret1, _ := ret[1].(*model.Response) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetUsersWithCustomQueryParameters indicates an expected call of GetUsersWithCustomQueryParameters. +func (mr *MockClientMockRecorder) GetUsersWithCustomQueryParameters(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUsersWithCustomQueryParameters", reflect.TypeOf((*MockClient)(nil).GetUsersWithCustomQueryParameters), arg0, arg1, arg2, arg3, arg4) +} + // InstallMarketplacePlugin mocks base method. func (m *MockClient) InstallMarketplacePlugin(arg0 context.Context, arg1 *model.InstallMarketplacePluginRequest) (*model.Manifest, *model.Response, error) { m.ctrl.T.Helper()