github.com/lologarithm/mattermost-server@v5.3.2-0.20181002060438-c82a84ed765b+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  	if !*a.Config().ServiceSettings.EnableEmailInvitations {
   388  		return fmt.Errorf("Email invites are disabled.")
   389  	}
   390  
   391  	a.SendInviteEmails(team, "Administrator", "Mattermost CLI "+model.NewId(), invites, *a.Config().ServiceSettings.SiteURL)
   392  	CommandPrettyPrintln("Invites may or may not have been sent.")
   393  
   394  	return nil
   395  }
   396  
   397  func resetUserPasswordCmdF(command *cobra.Command, args []string) error {
   398  	a, err := InitDBCommandContextCobra(command)
   399  	if err != nil {
   400  		return err
   401  	}
   402  	defer a.Shutdown()
   403  
   404  	if len(args) != 2 {
   405  		return errors.New("Expected two arguments. See help text for details.")
   406  	}
   407  
   408  	user := getUserFromUserArg(a, args[0])
   409  	if user == nil {
   410  		return errors.New("Unable to find user '" + args[0] + "'")
   411  	}
   412  	password := args[1]
   413  
   414  	if result := <-a.Srv.Store.User().UpdatePassword(user.Id, model.HashPassword(password)); result.Err != nil {
   415  		return result.Err
   416  	}
   417  
   418  	return nil
   419  }
   420  
   421  func updateUserEmailCmdF(command *cobra.Command, args []string) error {
   422  	a, err := InitDBCommandContextCobra(command)
   423  	if err != nil {
   424  		return err
   425  	}
   426  	defer a.Shutdown()
   427  
   428  	if len(args) != 2 {
   429  		return errors.New("Expected two arguments. See help text for details.")
   430  	}
   431  
   432  	newEmail := args[1]
   433  
   434  	if !model.IsValidEmail(newEmail) {
   435  		return errors.New("Invalid email: '" + newEmail + "'")
   436  	}
   437  
   438  	if len(args) != 2 {
   439  		return errors.New("Expected two arguments. See help text for details.")
   440  	}
   441  
   442  	user := getUserFromUserArg(a, args[0])
   443  	if user == nil {
   444  		return errors.New("Unable to find user '" + args[0] + "'")
   445  	}
   446  
   447  	user.Email = newEmail
   448  	_, errUpdate := a.UpdateUser(user, true)
   449  	if errUpdate != nil {
   450  		return errors.New(errUpdate.Message)
   451  	}
   452  
   453  	return nil
   454  }
   455  
   456  func resetUserMfaCmdF(command *cobra.Command, args []string) error {
   457  	a, err := InitDBCommandContextCobra(command)
   458  	if err != nil {
   459  		return err
   460  	}
   461  	defer a.Shutdown()
   462  
   463  	if len(args) < 1 {
   464  		return errors.New("Expected at least one argument. See help text for details.")
   465  	}
   466  
   467  	users := getUsersFromUserArgs(a, args)
   468  
   469  	for i, user := range users {
   470  		if user == nil {
   471  			return errors.New("Unable to find user '" + args[i] + "'")
   472  		}
   473  
   474  		if err := a.DeactivateMfa(user.Id); err != nil {
   475  			return err
   476  		}
   477  	}
   478  
   479  	return nil
   480  }
   481  
   482  func deleteUserCmdF(command *cobra.Command, args []string) error {
   483  	a, err := InitDBCommandContextCobra(command)
   484  	if err != nil {
   485  		return err
   486  	}
   487  	defer a.Shutdown()
   488  
   489  	if len(args) < 1 {
   490  		return errors.New("Expected at least one argument. See help text for details.")
   491  	}
   492  
   493  	confirmFlag, _ := command.Flags().GetBool("confirm")
   494  	if !confirmFlag {
   495  		var confirm string
   496  		CommandPrettyPrintln("Have you performed a database backup? (YES/NO): ")
   497  		fmt.Scanln(&confirm)
   498  
   499  		if confirm != "YES" {
   500  			return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
   501  		}
   502  		CommandPrettyPrintln("Are you sure you want to permanently delete the specified users? (YES/NO): ")
   503  		fmt.Scanln(&confirm)
   504  		if confirm != "YES" {
   505  			return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
   506  		}
   507  	}
   508  
   509  	users := getUsersFromUserArgs(a, args)
   510  
   511  	for i, user := range users {
   512  		if user == nil {
   513  			return errors.New("Unable to find user '" + args[i] + "'")
   514  		}
   515  
   516  		if err := a.PermanentDeleteUser(user); err != nil {
   517  			return err
   518  		}
   519  	}
   520  
   521  	return nil
   522  }
   523  
   524  func deleteAllUsersCommandF(command *cobra.Command, args []string) error {
   525  	a, err := InitDBCommandContextCobra(command)
   526  	if err != nil {
   527  		return err
   528  	}
   529  	defer a.Shutdown()
   530  
   531  	if len(args) > 0 {
   532  		return errors.New("Expected zero arguments.")
   533  	}
   534  
   535  	confirmFlag, _ := command.Flags().GetBool("confirm")
   536  	if !confirmFlag {
   537  		var confirm string
   538  		CommandPrettyPrintln("Have you performed a database backup? (YES/NO): ")
   539  		fmt.Scanln(&confirm)
   540  
   541  		if confirm != "YES" {
   542  			return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
   543  		}
   544  		CommandPrettyPrintln("Are you sure you want to permanently delete all user accounts? (YES/NO): ")
   545  		fmt.Scanln(&confirm)
   546  		if confirm != "YES" {
   547  			return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
   548  		}
   549  	}
   550  
   551  	if err := a.PermanentDeleteAllUsers(); err != nil {
   552  		return err
   553  	}
   554  
   555  	CommandPrettyPrintln("All user accounts successfully deleted.")
   556  
   557  	return nil
   558  }
   559  
   560  func migrateAuthCmdF(command *cobra.Command, args []string) error {
   561  	if args[1] == "saml" {
   562  		return migrateAuthToSamlCmdF(command, args)
   563  	}
   564  	return migrateAuthToLdapCmdF(command, args)
   565  }
   566  
   567  func migrateAuthToLdapCmdF(command *cobra.Command, args []string) error {
   568  	a, err := InitDBCommandContextCobra(command)
   569  	if err != nil {
   570  		return err
   571  	}
   572  	defer a.Shutdown()
   573  
   574  	fromAuth := args[0]
   575  	matchField := args[2]
   576  
   577  	if len(fromAuth) == 0 || (fromAuth != "email" && fromAuth != "gitlab" && fromAuth != "saml") {
   578  		return errors.New("Invalid from_auth argument")
   579  	}
   580  
   581  	// Email auth in Mattermost system is represented by ""
   582  	if fromAuth == "email" {
   583  		fromAuth = ""
   584  	}
   585  
   586  	if len(matchField) == 0 || (matchField != "email" && matchField != "username") {
   587  		return errors.New("Invalid match_field argument")
   588  	}
   589  
   590  	forceFlag, _ := command.Flags().GetBool("force")
   591  	dryRunFlag, _ := command.Flags().GetBool("dryRun")
   592  
   593  	if migrate := a.AccountMigration; migrate != nil {
   594  		if err := migrate.MigrateToLdap(fromAuth, matchField, forceFlag, dryRunFlag); err != nil {
   595  			return errors.New("Error while migrating users: " + err.Error())
   596  		}
   597  
   598  		CommandPrettyPrintln("Successfully migrated accounts.")
   599  	}
   600  
   601  	return nil
   602  }
   603  
   604  func migrateAuthToSamlCmdF(command *cobra.Command, args []string) error {
   605  	a, err := InitDBCommandContextCobra(command)
   606  	if err != nil {
   607  		return err
   608  	}
   609  	defer a.Shutdown()
   610  
   611  	dryRunFlag, _ := command.Flags().GetBool("dryRun")
   612  	autoFlag, _ := command.Flags().GetBool("auto")
   613  
   614  	matchesFile := ""
   615  	matches := map[string]string{}
   616  	if !autoFlag {
   617  		matchesFile = args[2]
   618  
   619  		file, e := ioutil.ReadFile(matchesFile)
   620  		if e != nil {
   621  			return errors.New("Invalid users file.")
   622  		}
   623  		if json.Unmarshal(file, &matches) != nil {
   624  			return errors.New("Invalid users file.")
   625  		}
   626  	}
   627  
   628  	fromAuth := args[0]
   629  
   630  	if len(fromAuth) == 0 || (fromAuth != "email" && fromAuth != "gitlab" && fromAuth != "ldap") {
   631  		return errors.New("Invalid from_auth argument")
   632  	}
   633  
   634  	if autoFlag && !dryRunFlag {
   635  		var confirm string
   636  		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):")
   637  		fmt.Scanln(&confirm)
   638  
   639  		if confirm != "YES" {
   640  			return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
   641  		}
   642  	}
   643  
   644  	// Email auth in Mattermost system is represented by ""
   645  	if fromAuth == "email" {
   646  		fromAuth = ""
   647  	}
   648  
   649  	if migrate := a.AccountMigration; migrate != nil {
   650  		if err := migrate.MigrateToSaml(fromAuth, matches, autoFlag, dryRunFlag); err != nil {
   651  			return errors.New("Error while migrating users: " + err.Error())
   652  		}
   653  
   654  		CommandPrettyPrintln("Successfully migrated accounts.")
   655  	}
   656  
   657  	return nil
   658  }
   659  
   660  func verifyUserCmdF(command *cobra.Command, args []string) error {
   661  	a, err := InitDBCommandContextCobra(command)
   662  	if err != nil {
   663  		return err
   664  	}
   665  	defer a.Shutdown()
   666  
   667  	if len(args) < 1 {
   668  		return errors.New("Expected at least one argument. See help text for details.")
   669  	}
   670  
   671  	users := getUsersFromUserArgs(a, args)
   672  
   673  	for i, user := range users {
   674  		if user == nil {
   675  			CommandPrintErrorln("Unable to find user '" + args[i] + "'")
   676  			continue
   677  		}
   678  		if cresult := <-a.Srv.Store.User().VerifyEmail(user.Id); cresult.Err != nil {
   679  			CommandPrintErrorln("Unable to verify '" + args[i] + "' email. Error: " + cresult.Err.Error())
   680  		}
   681  	}
   682  
   683  	return nil
   684  }
   685  
   686  func searchUserCmdF(command *cobra.Command, args []string) error {
   687  	a, err := InitDBCommandContextCobra(command)
   688  	if err != nil {
   689  		return err
   690  	}
   691  	defer a.Shutdown()
   692  
   693  	if len(args) < 1 {
   694  		return errors.New("Expected at least one argument. See help text for details.")
   695  	}
   696  
   697  	users := getUsersFromUserArgs(a, args)
   698  
   699  	for i, user := range users {
   700  		if i > 0 {
   701  			CommandPrettyPrintln("------------------------------")
   702  		}
   703  		if user == nil {
   704  			CommandPrintErrorln("Unable to find user '" + args[i] + "'")
   705  			continue
   706  		}
   707  
   708  		CommandPrettyPrintln("id: " + user.Id)
   709  		CommandPrettyPrintln("username: " + user.Username)
   710  		CommandPrettyPrintln("nickname: " + user.Nickname)
   711  		CommandPrettyPrintln("position: " + user.Position)
   712  		CommandPrettyPrintln("first_name: " + user.FirstName)
   713  		CommandPrettyPrintln("last_name: " + user.LastName)
   714  		CommandPrettyPrintln("email: " + user.Email)
   715  		CommandPrettyPrintln("auth_service: " + user.AuthService)
   716  	}
   717  
   718  	return nil
   719  }