diff options
author | Christopher Speller <crspeller@gmail.com> | 2016-12-06 10:49:34 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-06 10:49:34 -0500 |
commit | 026553e4f87bfc647a5c03129752e30fc523fa07 (patch) | |
tree | d5403c760151c0fa26fc6d020f7f4326ea9d6f8a /cmd/platform/user.go | |
parent | dcf11a14d8363c79ab62aefca46834d6daa615ab (diff) | |
download | chat-026553e4f87bfc647a5c03129752e30fc523fa07.tar.gz chat-026553e4f87bfc647a5c03129752e30fc523fa07.tar.bz2 chat-026553e4f87bfc647a5c03129752e30fc523fa07.zip |
Improving command line interface (#4689)
Diffstat (limited to 'cmd/platform/user.go')
-rw-r--r-- | cmd/platform/user.go | 432 |
1 files changed, 432 insertions, 0 deletions
diff --git a/cmd/platform/user.go b/cmd/platform/user.go new file mode 100644 index 000000000..43a00e68d --- /dev/null +++ b/cmd/platform/user.go @@ -0,0 +1,432 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. +package main + +import ( + "errors" + "fmt" + + "github.com/mattermost/platform/api" + "github.com/mattermost/platform/einterfaces" + "github.com/mattermost/platform/model" + "github.com/mattermost/platform/utils" + "github.com/spf13/cobra" +) + +var userCmd = &cobra.Command{ + Use: "user", + Short: "Management of users", +} + +var userActivateCmd = &cobra.Command{ + Use: "activate [emails, usernames, userIds]", + Short: "Activate users", + Long: "Activate users that have been deactivated.", + Example: ` user activate user@example.com + user activate username`, + RunE: userActivateCmdF, +} + +var userDeactivateCmd = &cobra.Command{ + Use: "deactivate [emails, usernames, userIds]", + Short: "Deactivate users", + Long: "Deactivate users. Deactivated users are immediately logged out of all sessions and are unable to log back in.", + Example: ` user deactivate user@example.com + user deactivate username`, + RunE: userDeactivateCmdF, +} + +var userCreateCmd = &cobra.Command{ + Use: "create", + Short: "Create a user", + Long: "Create a user", + Example: ` user create --email user@example.com --username userexample --password Password1 + user create --firstname Joe --system_admin --email joe@example.com --username joe --password Password1`, + RunE: userCreateCmdF, +} + +var userInviteCmd = &cobra.Command{ + Use: "invite [email] [teams]", + Short: "Send user an email invite to a team.", + Long: `Send user an email invite to a team. +You can invite a user to multiple teams by listing them. +You can specify teams by name or ID.`, + Example: ` user invite user@example.com myteam + user invite user@example.com myteam1 myteam2`, + RunE: userInviteCmdF, +} + +var resetUserPasswordCmd = &cobra.Command{ + Use: "password [user] [password]", + Short: "Set a user's password", + Long: "Set a user's password", + Example: " user password user@example.com Password1", + RunE: resetUserPasswordCmdF, +} + +var resetUserMfaCmd = &cobra.Command{ + Use: "resetmfa [users]", + Short: "Turn off MFA", + Long: `Turn off multi-factor authentication for a user. +If MFA enforcement is enabled, the user will be forced to re-enable MFA as soon as they login.`, + Example: " user resetmfa user@example.com", + RunE: resetUserMfaCmdF, +} + +var deleteUserCmd = &cobra.Command{ + Use: "delete [users]", + Short: "Delete users and all posts", + Long: "Permanently delete user and all related information including posts.", + Example: " user delete user@example.com", + RunE: deleteUserCmdF, +} + +var deleteAllUsersCmd = &cobra.Command{ + Use: "deleteall", + Short: "Delete all users and all posts", + Long: "Permanently delete all users and all related information including posts.", + Example: " user deleteall", + RunE: deleteUserCmdF, +} + +var migrateAuthCmd = &cobra.Command{ + Use: "migrate_auth [from_auth] [to_auth] [match_field]", + Short: "Mass migrate user accounts authentication type", + Long: `Migrates accounts from one authentication provider to another. For example, you can upgrade your authentication provider from email to ldap. + +from_auth: + The authentication service to migrate users accounts from. + Supported options: email, gitlab, saml. + +to_auth: + The authentication service to migrate users to. + Supported options: ldap. + +match_field: + The field that is guaranteed to be the same in both authentication services. For example, if the users emails are consistent set to email. + Supported options: email, username. + +Will display any accounts that are not migrated successfully.`, + Example: " user migrate_auth email ladp email", + RunE: migrateAuthCmdF, +} + +var verifyUserCmd = &cobra.Command{ + Use: "verify [users]", + Short: "Verify email of users", + Long: "Verify the emails of some users.", + Example: " user verify user1", + RunE: verifyUserCmdF, +} + +func init() { + userCreateCmd.Flags().String("username", "", "Username") + userCreateCmd.Flags().String("email", "", "Email") + userCreateCmd.Flags().String("password", "", "Password") + userCreateCmd.Flags().String("nickname", "", "Nickname") + userCreateCmd.Flags().String("firstname", "", "First Name") + userCreateCmd.Flags().String("lastname", "", "Last Name") + userCreateCmd.Flags().String("locale", "", "Locale (ex: en, fr)") + userCreateCmd.Flags().Bool("system_admin", false, "Make the user a system administrator") + + deleteUserCmd.Flags().Bool("confirm", false, "Confirm you really want to delete the user and a DB backup has been performed.") + + deleteAllUsersCmd.Flags().Bool("confirm", false, "Confirm you really want to delete the user and a DB backup has been performed.") + + userCmd.AddCommand( + userActivateCmd, + userDeactivateCmd, + userCreateCmd, + userInviteCmd, + resetUserPasswordCmd, + resetUserMfaCmd, + deleteUserCmd, + deleteAllUsersCmd, + migrateAuthCmd, + verifyUserCmd, + ) +} + +func userActivateCmdF(cmd *cobra.Command, args []string) error { + initDBCommandContextCobra(cmd) + + if len(args) < 1 { + return errors.New("Enter user(s) to activate.") + } + + changeUsersActiveStatus(args, true) + return nil +} + +func changeUsersActiveStatus(userArgs []string, active bool) { + users := getUsersFromUserArgs(userArgs) + for i, user := range users { + changeUserActiveStatus(user, userArgs[i], active) + } +} + +func changeUserActiveStatus(user *model.User, userArg string, activate bool) { + if user == nil { + CommandPrintErrorln("Can't find user '" + userArg + "'") + return + } + if user.IsLDAPUser() { + CommandPrintErrorln(utils.T("api.user.update_active.no_deactivate_ldap.app_error")) + return + } + if _, err := api.UpdateActive(user, activate); err != nil { + CommandPrintErrorln("Unable to change activation status of user: " + userArg) + } +} + +func userDeactivateCmdF(cmd *cobra.Command, args []string) error { + initDBCommandContextCobra(cmd) + + if len(args) < 1 { + return errors.New("Enter user(s) to deactivate.") + } + + changeUsersActiveStatus(args, false) + return nil +} + +func userCreateCmdF(cmd *cobra.Command, args []string) error { + initDBCommandContextCobra(cmd) + username, erru := cmd.Flags().GetString("username") + if erru != nil || username == "" { + return errors.New("Username is required") + } + email, erre := cmd.Flags().GetString("email") + if erre != nil || email == "" { + return errors.New("Email is required") + } + password, errp := cmd.Flags().GetString("password") + if errp != nil || password == "" { + return errors.New("Password is required") + } + nickname, _ := cmd.Flags().GetString("nickname") + firstname, _ := cmd.Flags().GetString("firstname") + lastname, _ := cmd.Flags().GetString("lastname") + locale, _ := cmd.Flags().GetString("locale") + system_admin, _ := cmd.Flags().GetBool("system_admin") + + user := &model.User{ + Username: username, + Email: email, + Password: password, + Nickname: nickname, + FirstName: firstname, + LastName: lastname, + Locale: locale, + } + + ruser, err := api.CreateUser(user) + if err != nil { + return errors.New("Unable to create user. Error: " + err.Error()) + } + + if system_admin { + api.UpdateUserRoles(ruser, "system_user system_admin") + } + + CommandPrettyPrintln("Created User") + + return nil +} + +func userInviteCmdF(cmd *cobra.Command, args []string) error { + initDBCommandContextCobra(cmd) + utils.InitHTML() + + if len(args) < 2 { + return errors.New("Not enough arguments.") + } + + email := args[0] + if !model.IsValidEmail(email) { + return errors.New("Invalid email") + } + + teams := getTeamsFromTeamArgs(args[1:]) + for i, team := range teams { + inviteUser(email, team, args[i+1]) + } + + return nil +} + +func inviteUser(email string, team *model.Team, teamArg string) { + invites := []string{email} + if team == nil { + CommandPrintErrorln("Can't find team '" + teamArg + "'") + return + } + api.InviteMembers(team, "Administrator", invites) + CommandPrettyPrintln("Invites may or may not have been sent.") +} + +func resetUserPasswordCmdF(cmd *cobra.Command, args []string) error { + initDBCommandContextCobra(cmd) + if len(args) != 2 { + return errors.New("Incorect number of arguments.") + } + + user := getUserFromUserArg(args[0]) + if user == nil { + return errors.New("Unable to find user '" + args[0] + "'") + } + password := args[1] + + if result := <-api.Srv.Store.User().UpdatePassword(user.Id, model.HashPassword(password)); result.Err != nil { + return result.Err + } + + return nil +} + +func resetUserMfaCmdF(cmd *cobra.Command, args []string) error { + initDBCommandContextCobra(cmd) + if len(args) < 1 { + return errors.New("Enter at least one user.") + } + + users := getUsersFromUserArgs(args) + + for i, user := range users { + if user == nil { + return errors.New("Unable to find user '" + args[i] + "'") + } + + if err := api.DeactivateMfa(user.Id); err != nil { + return err + } + } + + return nil +} + +func deleteUserCmdF(cmd *cobra.Command, args []string) error { + initDBCommandContextCobra(cmd) + if len(args) < 1 { + return errors.New("Enter at least one user.") + } + + confirmFlag, _ := cmd.Flags().GetBool("confirm") + if !confirmFlag { + var confirm string + CommandPrettyPrintln("Have you performed a database backup? (YES/NO): ") + fmt.Scanln(&confirm) + + if confirm != "YES" { + return errors.New("ABORTED: You did not answer YES exactly, in all capitals.") + } + CommandPrettyPrintln("Are you sure you want to delete the teams specified? All data will be permanently deleted? (YES/NO): ") + fmt.Scanln(&confirm) + if confirm != "YES" { + return errors.New("ABORTED: You did not answer YES exactly, in all capitals.") + } + } + + users := getUsersFromUserArgs(args) + + for i, user := range users { + if user == nil { + return errors.New("Unable to find user '" + args[i] + "'") + } + + if err := api.PermanentDeleteUser(user); err != nil { + return err + } + } + + return nil +} + +func deleteAllUsersCommandF(cmd *cobra.Command, args []string) error { + initDBCommandContextCobra(cmd) + if len(args) > 0 { + return errors.New("Don't enter any agruments.") + } + + confirmFlag, _ := cmd.Flags().GetBool("confirm") + if !confirmFlag { + var confirm string + CommandPrettyPrintln("Have you performed a database backup? (YES/NO): ") + fmt.Scanln(&confirm) + + if confirm != "YES" { + return errors.New("ABORTED: You did not answer YES exactly, in all capitals.") + } + CommandPrettyPrintln("Are you sure you want to delete the teams specified? All data will be permanently deleted? (YES/NO): ") + fmt.Scanln(&confirm) + if confirm != "YES" { + return errors.New("ABORTED: You did not answer YES exactly, in all capitals.") + } + } + + if err := api.PermanentDeleteAllUsers(); err != nil { + return err + } else { + CommandPrettyPrintln("Sucsessfull. All users deleted.") + } + + return nil +} + +func migrateAuthCmdF(cmd *cobra.Command, args []string) error { + initDBCommandContextCobra(cmd) + if len(args) != 3 { + return errors.New("Enter the correct number of arguments.") + } + + fromAuth := args[0] + toAuth := args[1] + matchField := args[2] + + if len(fromAuth) == 0 || (fromAuth != "email" && fromAuth != "gitlab" && fromAuth != "saml") { + return errors.New("Invalid from_auth argument") + } + + if len(toAuth) == 0 || toAuth != "ldap" { + return errors.New("Invalid to_auth argument") + } + + // Email auth in Mattermost system is represented by "" + if fromAuth == "email" { + fromAuth = "" + } + + if len(matchField) == 0 || (matchField != "email" && matchField != "username") { + return errors.New("Invalid match_field argument") + } + + if migrate := einterfaces.GetAccountMigrationInterface(); migrate != nil { + if err := migrate.MigrateToLdap(fromAuth, matchField); err != nil { + return errors.New("Error while migrating users: " + err.Error()) + } else { + CommandPrettyPrintln("Sucessfully migrated accounts.") + } + } + + return nil +} + +func verifyUserCmdF(cmd *cobra.Command, args []string) error { + initDBCommandContextCobra(cmd) + if len(args) < 1 { + return errors.New("Enter at least one user.") + } + + users := getUsersFromUserArgs(args) + + for i, user := range users { + if user == nil { + CommandPrintErrorln("Unable to find user '" + args[i] + "'") + } + if cresult := <-api.Srv.Store.User().VerifyEmail(user.Id); cresult.Err != nil { + CommandPrintErrorln("Unable to verify '" + args[i] + "' email. Error: " + cresult.Err.Error()) + } + } + + return nil +} |