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