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