github.com/qichengzx/mattermost-server@v4.5.1-0.20180604164826-2c75247c97d0+incompatible/cmd/mattermost/commands/user.go (about)

     1  // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package commands
     5  
     6  import (
     7  	"encoding/json"
     8  	"errors"
     9  	"fmt"
    10  	"io/ioutil"
    11  
    12  	"github.com/mattermost/mattermost-server/app"
    13  	"github.com/mattermost/mattermost-server/model"
    14  	"github.com/spf13/cobra"
    15  )
    16  
    17  var UserCmd = &cobra.Command{
    18  	Use:   "user",
    19  	Short: "Management of users",
    20  }
    21  
    22  var UserActivateCmd = &cobra.Command{
    23  	Use:   "activate [emails, usernames, userIds]",
    24  	Short: "Activate users",
    25  	Long:  "Activate users that have been deactivated.",
    26  	Example: `  user activate user@example.com
    27    user activate username`,
    28  	RunE: userActivateCmdF,
    29  }
    30  
    31  var UserDeactivateCmd = &cobra.Command{
    32  	Use:   "deactivate [emails, usernames, userIds]",
    33  	Short: "Deactivate users",
    34  	Long:  "Deactivate users. Deactivated users are immediately logged out of all sessions and are unable to log back in.",
    35  	Example: `  user deactivate user@example.com
    36    user deactivate username`,
    37  	RunE: userDeactivateCmdF,
    38  }
    39  
    40  var UserCreateCmd = &cobra.Command{
    41  	Use:     "create",
    42  	Short:   "Create a user",
    43  	Long:    "Create a user",
    44  	Example: `  user create --email user@example.com --username userexample --password Password1`,
    45  	RunE:    userCreateCmdF,
    46  }
    47  
    48  var UserInviteCmd = &cobra.Command{
    49  	Use:   "invite [email] [teams]",
    50  	Short: "Send user an email invite to a team.",
    51  	Long: `Send user an email invite to a team.
    52  You can invite a user to multiple teams by listing them.
    53  You can specify teams by name or ID.`,
    54  	Example: `  user invite user@example.com myteam
    55    user invite user@example.com myteam1 myteam2`,
    56  	RunE: userInviteCmdF,
    57  }
    58  
    59  var ResetUserPasswordCmd = &cobra.Command{
    60  	Use:     "password [user] [password]",
    61  	Short:   "Set a user's password",
    62  	Long:    "Set a user's password",
    63  	Example: "  user password user@example.com Password1",
    64  	RunE:    resetUserPasswordCmdF,
    65  }
    66  
    67  var updateUserEmailCmd = &cobra.Command{
    68  	Use:   "email [user] [new email]",
    69  	Short: "Change email of the user",
    70  	Long:  "Change email of the user.",
    71  	Example: `  user email test user@example.com
    72    user activate username`,
    73  	RunE: updateUserEmailCmdF,
    74  }
    75  
    76  var ResetUserMfaCmd = &cobra.Command{
    77  	Use:   "resetmfa [users]",
    78  	Short: "Turn off MFA",
    79  	Long: `Turn off multi-factor authentication for a user.
    80  If MFA enforcement is enabled, the user will be forced to re-enable MFA as soon as they login.`,
    81  	Example: "  user resetmfa user@example.com",
    82  	RunE:    resetUserMfaCmdF,
    83  }
    84  
    85  var DeleteUserCmd = &cobra.Command{
    86  	Use:     "delete [users]",
    87  	Short:   "Delete users and all posts",
    88  	Long:    "Permanently delete user and all related information including posts.",
    89  	Example: "  user delete user@example.com",
    90  	RunE:    deleteUserCmdF,
    91  }
    92  
    93  var DeleteAllUsersCmd = &cobra.Command{
    94  	Use:     "deleteall",
    95  	Short:   "Delete all users and all posts",
    96  	Long:    "Permanently delete all users and all related information including posts.",
    97  	Example: "  user deleteall",
    98  	RunE:    deleteAllUsersCommandF,
    99  }
   100  
   101  var MigrateAuthCmd = &cobra.Command{
   102  	Use:     "migrate_auth [from_auth] [to_auth] [migration-options]",
   103  	Short:   "Mass migrate user accounts authentication type",
   104  	Long:    `Migrates accounts from one authentication provider to another. For example, you can upgrade your authentication provider from email to ldap.`,
   105  	Example: "  user migrate_auth email saml users.json",
   106  	Args: func(command *cobra.Command, args []string) error {
   107  		if len(args) < 2 {
   108  			return errors.New("Auth migration requires at least 2 arguments.")
   109  		}
   110  
   111  		toAuth := args[1]
   112  
   113  		if toAuth != "ldap" && toAuth != "saml" {
   114  			return errors.New("Invalid to_auth parameter, must be saml or ldap.")
   115  		}
   116  
   117  		if toAuth == "ldap" && len(args) != 3 {
   118  			return errors.New("Ldap migration requires 3 arguments.")
   119  		}
   120  
   121  		autoFlag, _ := command.Flags().GetBool("auto")
   122  
   123  		if toAuth == "saml" && autoFlag {
   124  			if len(args) != 2 {
   125  				return errors.New("Saml migration requires two arguments when using the --auto flag. See help text for details.")
   126  			}
   127  		}
   128  
   129  		if toAuth == "saml" && !autoFlag {
   130  			if len(args) != 3 {
   131  				return errors.New("Saml migration requires three arguments when not using the --auto flag. See help text for details.")
   132  			}
   133  		}
   134  		return nil
   135  	},
   136  	RunE: migrateAuthCmdF,
   137  }
   138  
   139  var VerifyUserCmd = &cobra.Command{
   140  	Use:     "verify [users]",
   141  	Short:   "Verify email of users",
   142  	Long:    "Verify the emails of some users.",
   143  	Example: "  user verify user1",
   144  	RunE:    verifyUserCmdF,
   145  }
   146  
   147  var SearchUserCmd = &cobra.Command{
   148  	Use:     "search [users]",
   149  	Short:   "Search for users",
   150  	Long:    "Search for users based on username, email, or user ID.",
   151  	Example: "  user search user1@mail.com user2@mail.com",
   152  	RunE:    searchUserCmdF,
   153  }
   154  
   155  func init() {
   156  	UserCreateCmd.Flags().String("username", "", "Required. Username for the new user account.")
   157  	UserCreateCmd.Flags().String("email", "", "Required. The email address for the new user account.")
   158  	UserCreateCmd.Flags().String("password", "", "Required. The password for the new user account.")
   159  	UserCreateCmd.Flags().String("nickname", "", "Optional. The nickname for the new user account.")
   160  	UserCreateCmd.Flags().String("firstname", "", "Optional. The first name for the new user account.")
   161  	UserCreateCmd.Flags().String("lastname", "", "Optional. The last name for the new user account.")
   162  	UserCreateCmd.Flags().String("locale", "", "Optional. The locale (ex: en, fr) for the new user account.")
   163  	UserCreateCmd.Flags().Bool("system_admin", false, "Optional. If supplied, the new user will be a system administrator. Defaults to false.")
   164  
   165  	DeleteUserCmd.Flags().Bool("confirm", false, "Confirm you really want to delete the user and a DB backup has been performed.")
   166  
   167  	DeleteAllUsersCmd.Flags().Bool("confirm", false, "Confirm you really want to delete the user and a DB backup has been performed.")
   168  
   169  	MigrateAuthCmd.Flags().Bool("force", false, "Force the migration to occur even if there are duplicates on the LDAP server. Duplicates will not be migrated. (ldap only)")
   170  	MigrateAuthCmd.Flags().Bool("auto", false, "Automatically migrate all users. Assumes the usernames and emails are identical between Mattermost and SAML services. (saml only)")
   171  	MigrateAuthCmd.Flags().Bool("dryRun", false, "Run a simulation of the migration process without changing the database.")
   172  	MigrateAuthCmd.SetUsageTemplate(`Usage:
   173    mattermost user migrate_auth [from_auth] [to_auth] [migration-options] [flags]
   174  
   175  Examples:
   176  {{.Example}}
   177  
   178  Arguments:
   179    from_auth:
   180      The authentication service to migrate users accounts from.
   181      Supported options: email, gitlab, ldap, saml.
   182  
   183    to_auth:
   184      The authentication service to migrate users to.
   185      Supported options: ldap, saml.
   186  
   187    migration-options:
   188      Migration specific options, full command help for more information.
   189  
   190  Flags:
   191  {{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}
   192  
   193  Global Flags:
   194  {{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}
   195  `)
   196  	MigrateAuthCmd.SetHelpTemplate(`Usage:
   197    mattermost user migrate_auth [from_auth] [to_auth] [migration-options] [flags]
   198  
   199  Examples:
   200  {{.Example}}
   201  
   202  Arguments:
   203    from_auth:
   204      The authentication service to migrate users accounts from.
   205      Supported options: email, gitlab, ldap, saml.
   206  
   207    to_auth:
   208      The authentication service to migrate users to.
   209      Supported options: ldap, saml.
   210  
   211    migration-options (ldap):
   212      match_field:
   213        The field that is guaranteed to be the same in both authentication services. For example, if the users emails are consistent set to email.
   214        Supported options: email, username.
   215  
   216    migration-options (saml):
   217      users_file:
   218        The path of a json file with the usernames and emails of all users to migrate to SAML. The username and email must be the same that the SAML service provider store. And the email must match with the email in mattermost database.
   219  
   220        Example json content:
   221          {
   222            "usr1@email.com": "usr.one",
   223            "usr2@email.com": "usr.two"
   224          }
   225  
   226  Flags:
   227  {{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}
   228  
   229  Global Flags:
   230  {{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}
   231  `)
   232  
   233  	UserCmd.AddCommand(
   234  		UserActivateCmd,
   235  		UserDeactivateCmd,
   236  		UserCreateCmd,
   237  		UserInviteCmd,
   238  		ResetUserPasswordCmd,
   239  		updateUserEmailCmd,
   240  		ResetUserMfaCmd,
   241  		DeleteUserCmd,
   242  		DeleteAllUsersCmd,
   243  		MigrateAuthCmd,
   244  		VerifyUserCmd,
   245  		SearchUserCmd,
   246  	)
   247  	RootCmd.AddCommand(UserCmd)
   248  }
   249  
   250  func userActivateCmdF(command *cobra.Command, args []string) error {
   251  	a, err := InitDBCommandContextCobra(command)
   252  	if err != nil {
   253  		return err
   254  	}
   255  	defer a.Shutdown()
   256  
   257  	if len(args) < 1 {
   258  		return errors.New("Expected at least one argument. See help text for details.")
   259  	}
   260  
   261  	changeUsersActiveStatus(a, args, true)
   262  
   263  	return nil
   264  }
   265  
   266  func changeUsersActiveStatus(a *app.App, userArgs []string, active bool) {
   267  	users := getUsersFromUserArgs(a, userArgs)
   268  	for i, user := range users {
   269  		err := changeUserActiveStatus(a, user, userArgs[i], active)
   270  
   271  		if err != nil {
   272  			CommandPrintErrorln(err.Error())
   273  		}
   274  	}
   275  }
   276  
   277  func changeUserActiveStatus(a *app.App, user *model.User, userArg string, activate bool) error {
   278  	if user == nil {
   279  		return fmt.Errorf("Can't find user '%v'", userArg)
   280  	}
   281  	if user.IsSSOUser() {
   282  		fmt.Println("You must also deactivate this user in the SSO provider or they will be reactivated on next login or sync.")
   283  	}
   284  	if _, err := a.UpdateActive(user, activate); err != nil {
   285  		return fmt.Errorf("Unable to change activation status of user: %v", userArg)
   286  	}
   287  
   288  	return nil
   289  }
   290  
   291  func userDeactivateCmdF(command *cobra.Command, args []string) error {
   292  	a, err := InitDBCommandContextCobra(command)
   293  	if err != nil {
   294  		return err
   295  	}
   296  	defer a.Shutdown()
   297  
   298  	if len(args) < 1 {
   299  		return errors.New("Expected at least one argument. See help text for details.")
   300  	}
   301  
   302  	changeUsersActiveStatus(a, args, false)
   303  
   304  	return nil
   305  }
   306  
   307  func userCreateCmdF(command *cobra.Command, args []string) error {
   308  	a, err := InitDBCommandContextCobra(command)
   309  	if err != nil {
   310  		return err
   311  	}
   312  	defer a.Shutdown()
   313  
   314  	username, erru := command.Flags().GetString("username")
   315  	if erru != nil || username == "" {
   316  		return errors.New("Username is required")
   317  	}
   318  	email, erre := command.Flags().GetString("email")
   319  	if erre != nil || email == "" {
   320  		return errors.New("Email is required")
   321  	}
   322  	password, errp := command.Flags().GetString("password")
   323  	if errp != nil || password == "" {
   324  		return errors.New("Password is required")
   325  	}
   326  	nickname, _ := command.Flags().GetString("nickname")
   327  	firstname, _ := command.Flags().GetString("firstname")
   328  	lastname, _ := command.Flags().GetString("lastname")
   329  	locale, _ := command.Flags().GetString("locale")
   330  	systemAdmin, _ := command.Flags().GetBool("system_admin")
   331  
   332  	user := &model.User{
   333  		Username:  username,
   334  		Email:     email,
   335  		Password:  password,
   336  		Nickname:  nickname,
   337  		FirstName: firstname,
   338  		LastName:  lastname,
   339  		Locale:    locale,
   340  	}
   341  
   342  	if ruser, err := a.CreateUser(user); err != nil {
   343  		return errors.New("Unable to create user. Error: " + err.Error())
   344  	} else if systemAdmin {
   345  		a.UpdateUserRoles(ruser.Id, "system_user system_admin", false)
   346  	}
   347  
   348  	CommandPrettyPrintln("Created User")
   349  
   350  	return nil
   351  }
   352  
   353  func userInviteCmdF(command *cobra.Command, args []string) error {
   354  	a, err := InitDBCommandContextCobra(command)
   355  	if err != nil {
   356  		return err
   357  	}
   358  	defer a.Shutdown()
   359  
   360  	if len(args) < 2 {
   361  		return errors.New("Expected at least two arguments. See help text for details.")
   362  	}
   363  
   364  	email := args[0]
   365  	if !model.IsValidEmail(email) {
   366  		return errors.New("Invalid email")
   367  	}
   368  
   369  	teams := getTeamsFromTeamArgs(a, args[1:])
   370  	for i, team := range teams {
   371  		err := inviteUser(a, email, team, args[i+1])
   372  
   373  		if err != nil {
   374  			CommandPrintErrorln(err.Error())
   375  		}
   376  	}
   377  
   378  	return nil
   379  }
   380  
   381  func inviteUser(a *app.App, email string, team *model.Team, teamArg string) error {
   382  	invites := []string{email}
   383  	if team == nil {
   384  		return fmt.Errorf("Can't find team '%v'", teamArg)
   385  	}
   386  
   387  	a.SendInviteEmails(team, "Administrator", invites, *a.Config().ServiceSettings.SiteURL)
   388  	CommandPrettyPrintln("Invites may or may not have been sent.")
   389  
   390  	return nil
   391  }
   392  
   393  func resetUserPasswordCmdF(command *cobra.Command, args []string) error {
   394  	a, err := InitDBCommandContextCobra(command)
   395  	if err != nil {
   396  		return err
   397  	}
   398  	defer a.Shutdown()
   399  
   400  	if len(args) != 2 {
   401  		return errors.New("Expected two arguments. See help text for details.")
   402  	}
   403  
   404  	user := getUserFromUserArg(a, args[0])
   405  	if user == nil {
   406  		return errors.New("Unable to find user '" + args[0] + "'")
   407  	}
   408  	password := args[1]
   409  
   410  	if result := <-a.Srv.Store.User().UpdatePassword(user.Id, model.HashPassword(password)); result.Err != nil {
   411  		return result.Err
   412  	}
   413  
   414  	return nil
   415  }
   416  
   417  func updateUserEmailCmdF(command *cobra.Command, args []string) error {
   418  	a, err := InitDBCommandContextCobra(command)
   419  	if err != nil {
   420  		return err
   421  	}
   422  	defer a.Shutdown()
   423  
   424  	if len(args) != 2 {
   425  		return errors.New("Expected two arguments. See help text for details.")
   426  	}
   427  
   428  	newEmail := args[1]
   429  
   430  	if !model.IsValidEmail(newEmail) {
   431  		return errors.New("Invalid email: '" + newEmail + "'")
   432  	}
   433  
   434  	if len(args) != 2 {
   435  		return errors.New("Expected two arguments. See help text for details.")
   436  	}
   437  
   438  	user := getUserFromUserArg(a, args[0])
   439  	if user == nil {
   440  		return errors.New("Unable to find user '" + args[0] + "'")
   441  	}
   442  
   443  	user.Email = newEmail
   444  	_, errUpdate := a.UpdateUser(user, true)
   445  	if errUpdate != nil {
   446  		return errors.New(errUpdate.Message)
   447  	}
   448  
   449  	return nil
   450  }
   451  
   452  func resetUserMfaCmdF(command *cobra.Command, args []string) error {
   453  	a, err := InitDBCommandContextCobra(command)
   454  	if err != nil {
   455  		return err
   456  	}
   457  	defer a.Shutdown()
   458  
   459  	if len(args) < 1 {
   460  		return errors.New("Expected at least one argument. See help text for details.")
   461  	}
   462  
   463  	users := getUsersFromUserArgs(a, args)
   464  
   465  	for i, user := range users {
   466  		if user == nil {
   467  			return errors.New("Unable to find user '" + args[i] + "'")
   468  		}
   469  
   470  		if err := a.DeactivateMfa(user.Id); err != nil {
   471  			return err
   472  		}
   473  	}
   474  
   475  	return nil
   476  }
   477  
   478  func deleteUserCmdF(command *cobra.Command, args []string) error {
   479  	a, err := InitDBCommandContextCobra(command)
   480  	if err != nil {
   481  		return err
   482  	}
   483  	defer a.Shutdown()
   484  
   485  	if len(args) < 1 {
   486  		return errors.New("Expected at least one argument. See help text for details.")
   487  	}
   488  
   489  	confirmFlag, _ := command.Flags().GetBool("confirm")
   490  	if !confirmFlag {
   491  		var confirm string
   492  		CommandPrettyPrintln("Have you performed a database backup? (YES/NO): ")
   493  		fmt.Scanln(&confirm)
   494  
   495  		if confirm != "YES" {
   496  			return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
   497  		}
   498  		CommandPrettyPrintln("Are you sure you want to permanently delete the specified users? (YES/NO): ")
   499  		fmt.Scanln(&confirm)
   500  		if confirm != "YES" {
   501  			return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
   502  		}
   503  	}
   504  
   505  	users := getUsersFromUserArgs(a, args)
   506  
   507  	for i, user := range users {
   508  		if user == nil {
   509  			return errors.New("Unable to find user '" + args[i] + "'")
   510  		}
   511  
   512  		if err := a.PermanentDeleteUser(user); err != nil {
   513  			return err
   514  		}
   515  	}
   516  
   517  	return nil
   518  }
   519  
   520  func deleteAllUsersCommandF(command *cobra.Command, args []string) error {
   521  	a, err := InitDBCommandContextCobra(command)
   522  	if err != nil {
   523  		return err
   524  	}
   525  	defer a.Shutdown()
   526  
   527  	if len(args) > 0 {
   528  		return errors.New("Expected zero arguments.")
   529  	}
   530  
   531  	confirmFlag, _ := command.Flags().GetBool("confirm")
   532  	if !confirmFlag {
   533  		var confirm string
   534  		CommandPrettyPrintln("Have you performed a database backup? (YES/NO): ")
   535  		fmt.Scanln(&confirm)
   536  
   537  		if confirm != "YES" {
   538  			return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
   539  		}
   540  		CommandPrettyPrintln("Are you sure you want to permanently delete all user accounts? (YES/NO): ")
   541  		fmt.Scanln(&confirm)
   542  		if confirm != "YES" {
   543  			return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
   544  		}
   545  	}
   546  
   547  	if err := a.PermanentDeleteAllUsers(); err != nil {
   548  		return err
   549  	}
   550  
   551  	CommandPrettyPrintln("All user accounts successfully deleted.")
   552  
   553  	return nil
   554  }
   555  
   556  func migrateAuthCmdF(command *cobra.Command, args []string) error {
   557  	if args[1] == "saml" {
   558  		return migrateAuthToSamlCmdF(command, args)
   559  	}
   560  	return migrateAuthToLdapCmdF(command, args)
   561  }
   562  
   563  func migrateAuthToLdapCmdF(command *cobra.Command, args []string) error {
   564  	a, err := InitDBCommandContextCobra(command)
   565  	if err != nil {
   566  		return err
   567  	}
   568  	defer a.Shutdown()
   569  
   570  	fromAuth := args[0]
   571  	matchField := args[2]
   572  
   573  	if len(fromAuth) == 0 || (fromAuth != "email" && fromAuth != "gitlab" && fromAuth != "saml") {
   574  		return errors.New("Invalid from_auth argument")
   575  	}
   576  
   577  	// Email auth in Mattermost system is represented by ""
   578  	if fromAuth == "email" {
   579  		fromAuth = ""
   580  	}
   581  
   582  	if len(matchField) == 0 || (matchField != "email" && matchField != "username") {
   583  		return errors.New("Invalid match_field argument")
   584  	}
   585  
   586  	forceFlag, _ := command.Flags().GetBool("force")
   587  	dryRunFlag, _ := command.Flags().GetBool("dryRun")
   588  
   589  	if migrate := a.AccountMigration; migrate != nil {
   590  		if err := migrate.MigrateToLdap(fromAuth, matchField, forceFlag, dryRunFlag); err != nil {
   591  			return errors.New("Error while migrating users: " + err.Error())
   592  		}
   593  
   594  		CommandPrettyPrintln("Successfully migrated accounts.")
   595  	}
   596  
   597  	return nil
   598  }
   599  
   600  func migrateAuthToSamlCmdF(command *cobra.Command, args []string) error {
   601  	a, err := InitDBCommandContextCobra(command)
   602  	if err != nil {
   603  		return err
   604  	}
   605  	defer a.Shutdown()
   606  
   607  	dryRunFlag, _ := command.Flags().GetBool("dryRun")
   608  	autoFlag, _ := command.Flags().GetBool("auto")
   609  
   610  	matchesFile := ""
   611  	matches := map[string]string{}
   612  	if !autoFlag {
   613  		matchesFile = args[2]
   614  
   615  		file, e := ioutil.ReadFile(matchesFile)
   616  		if e != nil {
   617  			return errors.New("Invalid users file.")
   618  		}
   619  		if json.Unmarshal(file, &matches) != nil {
   620  			return errors.New("Invalid users file.")
   621  		}
   622  	}
   623  
   624  	fromAuth := args[0]
   625  
   626  	if len(fromAuth) == 0 || (fromAuth != "email" && fromAuth != "gitlab" && fromAuth != "ldap") {
   627  		return errors.New("Invalid from_auth argument")
   628  	}
   629  
   630  	if autoFlag && !dryRunFlag {
   631  		var confirm string
   632  		CommandPrettyPrintln("You are about to perform an automatic \"" + fromAuth + " to saml\" migration. This must only be done if your current Mattermost users with " + fromAuth + " auth have the same username and email in your SAML service. Otherwise, provide the usernames and emails from your SAML Service using the \"users file\" without the \"--auto\" option.\n\nDo you want to proceed with automatic migration anyway? (YES/NO):")
   633  		fmt.Scanln(&confirm)
   634  
   635  		if confirm != "YES" {
   636  			return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
   637  		}
   638  	}
   639  
   640  	// Email auth in Mattermost system is represented by ""
   641  	if fromAuth == "email" {
   642  		fromAuth = ""
   643  	}
   644  
   645  	if migrate := a.AccountMigration; migrate != nil {
   646  		if err := migrate.MigrateToSaml(fromAuth, matches, autoFlag, dryRunFlag); err != nil {
   647  			return errors.New("Error while migrating users: " + err.Error())
   648  		}
   649  
   650  		CommandPrettyPrintln("Successfully migrated accounts.")
   651  	}
   652  
   653  	return nil
   654  }
   655  
   656  func verifyUserCmdF(command *cobra.Command, args []string) error {
   657  	a, err := InitDBCommandContextCobra(command)
   658  	if err != nil {
   659  		return err
   660  	}
   661  	defer a.Shutdown()
   662  
   663  	if len(args) < 1 {
   664  		return errors.New("Expected at least one argument. See help text for details.")
   665  	}
   666  
   667  	users := getUsersFromUserArgs(a, args)
   668  
   669  	for i, user := range users {
   670  		if user == nil {
   671  			CommandPrintErrorln("Unable to find user '" + args[i] + "'")
   672  			continue
   673  		}
   674  		if cresult := <-a.Srv.Store.User().VerifyEmail(user.Id); cresult.Err != nil {
   675  			CommandPrintErrorln("Unable to verify '" + args[i] + "' email. Error: " + cresult.Err.Error())
   676  		}
   677  	}
   678  
   679  	return nil
   680  }
   681  
   682  func searchUserCmdF(command *cobra.Command, args []string) error {
   683  	a, err := InitDBCommandContextCobra(command)
   684  	if err != nil {
   685  		return err
   686  	}
   687  	defer a.Shutdown()
   688  
   689  	if len(args) < 1 {
   690  		return errors.New("Expected at least one argument. See help text for details.")
   691  	}
   692  
   693  	users := getUsersFromUserArgs(a, args)
   694  
   695  	for i, user := range users {
   696  		if i > 0 {
   697  			CommandPrettyPrintln("------------------------------")
   698  		}
   699  		if user == nil {
   700  			CommandPrintErrorln("Unable to find user '" + args[i] + "'")
   701  			continue
   702  		}
   703  
   704  		CommandPrettyPrintln("id: " + user.Id)
   705  		CommandPrettyPrintln("username: " + user.Username)
   706  		CommandPrettyPrintln("nickname: " + user.Nickname)
   707  		CommandPrettyPrintln("position: " + user.Position)
   708  		CommandPrettyPrintln("first_name: " + user.FirstName)
   709  		CommandPrettyPrintln("last_name: " + user.LastName)
   710  		CommandPrettyPrintln("email: " + user.Email)
   711  		CommandPrettyPrintln("auth_service: " + user.AuthService)
   712  	}
   713  
   714  	return nil
   715  }