mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
[GH-10800] convert bot account to user account (#10803)
* [10800] convert bot account to user account * check password validity first * review comments
This commit is contained in:
committed by
Miguel de la Cruz
parent
a68ad55151
commit
2130e9f0b1
@@ -46,12 +46,13 @@ var UserCreateCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
var UserConvertCmd = &cobra.Command{
|
||||
Use: "convert [emails, usernames, userIds] --bot",
|
||||
Short: "Convert users to bots",
|
||||
Long: "Convert users to bots",
|
||||
Example: ` user convert user@example.com anotherUser --bot`,
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: userConvertCmdF,
|
||||
Use: "convert [emails, usernames, userIds] --bot",
|
||||
Short: "Convert users to bots, or a bot to a user",
|
||||
Long: "Convert users to bots, or a bot to a user",
|
||||
Example: ` user convert user@example.com anotherUser --bot
|
||||
user convert botusername --email new.email@email.com --password password --user`,
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: userConvertCmdF,
|
||||
}
|
||||
|
||||
var UserInviteCmd = &cobra.Command{
|
||||
@@ -172,6 +173,15 @@ func init() {
|
||||
UserCreateCmd.Flags().Bool("system_admin", false, "Optional. If supplied, the new user will be a system administrator. Defaults to false.")
|
||||
|
||||
UserConvertCmd.Flags().Bool("bot", false, "If supplied, convert users to bots.")
|
||||
UserConvertCmd.Flags().Bool("user", false, "If supplied, convert a bot to a user.")
|
||||
UserConvertCmd.Flags().String("password", "", "The password for converted new user account. Required when \"user\" flag is set.")
|
||||
UserConvertCmd.Flags().String("username", "", "Username for the converted user account. Ignored when \"user\" flag is missing.")
|
||||
UserConvertCmd.Flags().String("email", "", "The email address for the converted user account. Ignored when \"user\" flag is missing.")
|
||||
UserConvertCmd.Flags().String("nickname", "", "The nickname for the converted user account. Ignored when \"user\" flag is missing.")
|
||||
UserConvertCmd.Flags().String("firstname", "", "The first name for the converted user account. Ignored when \"user\" flag is missing.")
|
||||
UserConvertCmd.Flags().String("lastname", "", "The last name for the converted user account. Ignored when \"user\" flag is missing.")
|
||||
UserConvertCmd.Flags().String("locale", "", "The locale (ex: en, fr) for converted new user account. Ignored when \"user\" flag is missing.")
|
||||
UserConvertCmd.Flags().Bool("system_admin", false, "If supplied, the converted user will be a system administrator. Defaults to false. Ignored when \"user\" flag is missing.")
|
||||
|
||||
DeleteUserCmd.Flags().Bool("confirm", false, "Confirm you really want to delete the user and a DB backup has been performed.")
|
||||
|
||||
@@ -398,6 +408,126 @@ func usersToBots(args []string, a *app.App) {
|
||||
}
|
||||
}
|
||||
|
||||
func getUpdatedPassword(command *cobra.Command, a *app.App, user *model.User) (string, error) {
|
||||
password, err := command.Flags().GetString("password")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unable to read password. Error: %s", err.Error())
|
||||
}
|
||||
|
||||
if password == "" {
|
||||
return "", errors.New("Password is required.")
|
||||
}
|
||||
|
||||
return password, nil
|
||||
}
|
||||
|
||||
func getUpdatedUserModel(command *cobra.Command, a *app.App, user *model.User) (*model.User, error) {
|
||||
username, _ := command.Flags().GetString("username")
|
||||
if username == "" {
|
||||
if user.Username == "" {
|
||||
return nil, errors.New("Invalid username. Username is empty.")
|
||||
}
|
||||
} else {
|
||||
user.Username = username
|
||||
}
|
||||
|
||||
email, _ := command.Flags().GetString("email")
|
||||
if email == "" {
|
||||
if user.Email == "" {
|
||||
return nil, errors.New("Invalid email. Email is empty.")
|
||||
}
|
||||
} else {
|
||||
user.Email = email
|
||||
}
|
||||
|
||||
nickname, _ := command.Flags().GetString("nickname")
|
||||
if nickname != "" {
|
||||
user.Nickname = nickname
|
||||
}
|
||||
|
||||
firstname, _ := command.Flags().GetString("firstname")
|
||||
if firstname != "" {
|
||||
user.FirstName = firstname
|
||||
}
|
||||
|
||||
lastname, _ := command.Flags().GetString("lastname")
|
||||
if lastname != "" {
|
||||
user.LastName = lastname
|
||||
}
|
||||
|
||||
locale, _ := command.Flags().GetString("locale")
|
||||
if locale != "" {
|
||||
user.Locale = locale
|
||||
}
|
||||
|
||||
if !user.IsLDAPUser() && !user.IsSAMLUser() && !app.CheckUserDomain(user, *a.Config().TeamSettings.RestrictCreationToDomains) {
|
||||
return nil, errors.New("The email does not belong to an accepted domain.")
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func botToUser(command *cobra.Command, args []string, a *app.App) error {
|
||||
if len(args) != 1 {
|
||||
return errors.New("Expect 1 argument. See help text for more details.")
|
||||
}
|
||||
|
||||
user := getUserFromUserArg(a, args[0])
|
||||
if user == nil {
|
||||
return errors.New("Unable to find bot.")
|
||||
}
|
||||
|
||||
_, appErr := a.GetBot(user.Id, false)
|
||||
if appErr != nil {
|
||||
return fmt.Errorf("Unable to find bot. Error: %s", appErr.Error())
|
||||
}
|
||||
|
||||
password, err := getUpdatedPassword(command, a, user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user, err = getUpdatedUserModel(command, a, user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user, appErr = a.UpdateUser(user, false)
|
||||
if appErr != nil {
|
||||
return fmt.Errorf("Unable to update user. Error: %s" + appErr.Error())
|
||||
}
|
||||
|
||||
appErr = a.UpdatePassword(user, password)
|
||||
if appErr != nil {
|
||||
return fmt.Errorf("Unable to update password. Error: %s", appErr.Error())
|
||||
}
|
||||
|
||||
systemAdmin, _ := command.Flags().GetBool("system_admin")
|
||||
if systemAdmin && !user.IsInRole(model.SYSTEM_ADMIN_ROLE_ID) {
|
||||
if _, appErr = a.UpdateUserRoles(
|
||||
user.Id,
|
||||
fmt.Sprintf("%s %s", user.Roles, model.SYSTEM_ADMIN_ROLE_ID),
|
||||
false); appErr != nil {
|
||||
return fmt.Errorf("Unable to make user system admin. Error: %s" + appErr.Error())
|
||||
}
|
||||
}
|
||||
|
||||
result := <-a.Srv.Store.Bot().PermanentDelete(user.Id)
|
||||
if result.Err != nil {
|
||||
return fmt.Errorf("Unable to delete bot. Error: %s", result.Err.Error())
|
||||
}
|
||||
|
||||
CommandPrettyPrintln("id: " + user.Id)
|
||||
CommandPrettyPrintln("username: " + user.Username)
|
||||
CommandPrettyPrintln("email: " + user.Email)
|
||||
CommandPrettyPrintln("nickname: " + user.Nickname)
|
||||
CommandPrettyPrintln("first_name: " + user.FirstName)
|
||||
CommandPrettyPrintln("last_name: " + user.LastName)
|
||||
CommandPrettyPrintln("roles: " + user.Roles)
|
||||
CommandPrettyPrintln("locale: " + user.Locale)
|
||||
return nil
|
||||
}
|
||||
|
||||
func userConvertCmdF(command *cobra.Command, args []string) error {
|
||||
a, err := InitDBCommandContextCobra(command)
|
||||
if err != nil {
|
||||
@@ -410,8 +540,21 @@ func userConvertCmdF(command *cobra.Command, args []string) error {
|
||||
return errors.New("Invalid command. See help text for details.")
|
||||
}
|
||||
|
||||
if !toBot {
|
||||
return errors.New("Expect \"bot\" flag to be set. See help text for details.")
|
||||
toUser, err := command.Flags().GetBool("user")
|
||||
if err != nil {
|
||||
return errors.New("Invalid command. See help text for details.")
|
||||
}
|
||||
|
||||
if !(toUser || toBot) {
|
||||
return errors.New("Expect either \"user\" flag or \"bot\" flag. See help text for details.")
|
||||
}
|
||||
|
||||
if toUser && toBot {
|
||||
return errors.New("Expect either \"user\" flag or \"bot\" flag but not both. See help text for details.")
|
||||
}
|
||||
|
||||
if toUser {
|
||||
return botToUser(command, args, a)
|
||||
}
|
||||
|
||||
usersToBots(args, a)
|
||||
|
||||
@@ -117,11 +117,77 @@ func TestChangeUserEmail(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestConvertUserToBot(t *testing.T) {
|
||||
func TestConvertUser(t *testing.T) {
|
||||
th := Setup().InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
th.CheckCommand(t, "user", "convert", th.BasicUser.Username, "anotherinvaliduser", "--bot")
|
||||
result := <-th.App.Srv.Store.Bot().Get(th.BasicUser.Id, false)
|
||||
require.Nil(t, result.Err)
|
||||
t.Run("Invalid command line input", func(t *testing.T) {
|
||||
err := th.RunCommand(t, "user", "convert", th.BasicUser.Username)
|
||||
require.NotNil(t, err)
|
||||
|
||||
err = th.RunCommand(t, "user", "convert", th.BasicUser.Username, "--user", "--bot")
|
||||
require.NotNil(t, err)
|
||||
|
||||
err = th.RunCommand(t, "user", "convert", "--bot")
|
||||
require.NotNil(t, err)
|
||||
})
|
||||
|
||||
t.Run("Convert to bot from username", func(t *testing.T) {
|
||||
th.CheckCommand(t, "user", "convert", th.BasicUser.Username, "anotherinvaliduser", "--bot")
|
||||
result := <-th.App.Srv.Store.Bot().Get(th.BasicUser.Id, false)
|
||||
require.Nil(t, result.Err)
|
||||
})
|
||||
|
||||
t.Run("Unable to convert to user with missing password", func(t *testing.T) {
|
||||
err := th.RunCommand(t, "user", "convert", th.BasicUser.Username, "--user")
|
||||
require.NotNil(t, err)
|
||||
})
|
||||
|
||||
t.Run("Unable to convert to user with invalid email", func(t *testing.T) {
|
||||
err := th.RunCommand(t, "user", "convert", th.BasicUser.Username, "--user",
|
||||
"--password", "password",
|
||||
"--email", "invalidEmail")
|
||||
require.NotNil(t, err)
|
||||
})
|
||||
|
||||
t.Run("Convert to user with minimum flags", func(t *testing.T) {
|
||||
err := th.RunCommand(t, "user", "convert", th.BasicUser.Username, "--user",
|
||||
"--password", "password")
|
||||
require.Nil(t, err)
|
||||
result := <-th.App.Srv.Store.Bot().Get(th.BasicUser.Id, false)
|
||||
require.NotNil(t, result.Err)
|
||||
})
|
||||
|
||||
t.Run("Convert to bot from email", func(t *testing.T) {
|
||||
th.CheckCommand(t, "user", "convert", th.BasicUser2.Email, "--bot")
|
||||
result := <-th.App.Srv.Store.Bot().Get(th.BasicUser2.Id, false)
|
||||
require.Nil(t, result.Err)
|
||||
})
|
||||
|
||||
t.Run("Convert to user with all flags", func(t *testing.T) {
|
||||
err := th.RunCommand(t, "user", "convert", th.BasicUser2.Username, "--user",
|
||||
"--password", "password",
|
||||
"--username", "newusername",
|
||||
"--email", "valid@email.com",
|
||||
"--nickname", "newNickname",
|
||||
"--firstname", "newFirstName",
|
||||
"--lastname", "newLastName",
|
||||
"--locale", "en_CA",
|
||||
"--system_admin")
|
||||
require.Nil(t, err)
|
||||
|
||||
result := <-th.App.Srv.Store.Bot().Get(th.BasicUser2.Id, false)
|
||||
require.NotNil(t, result.Err)
|
||||
|
||||
user, appErr := th.App.Srv.Store.User().Get(th.BasicUser2.Id)
|
||||
require.Nil(t, appErr)
|
||||
require.Equal(t, "newusername", user.Username)
|
||||
require.Equal(t, "valid@email.com", user.Email)
|
||||
require.Equal(t, "newNickname", user.Nickname)
|
||||
require.Equal(t, "newFirstName", user.FirstName)
|
||||
require.Equal(t, "newLastName", user.LastName)
|
||||
require.Equal(t, "en_CA", user.Locale)
|
||||
require.True(t, user.IsInRole("system_admin"))
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -233,12 +233,6 @@ func (us SqlBotStore) Update(bot *model.Bot) store.StoreChannel {
|
||||
// If the corresponding user is to be deleted, it must be done via the user store.
|
||||
func (us SqlBotStore) PermanentDelete(botUserId string) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
userResult := <-us.User().PermanentDelete(botUserId)
|
||||
if userResult.Err != nil {
|
||||
result.Err = userResult.Err
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := us.GetMaster().Exec(`
|
||||
DELETE FROM
|
||||
Bots
|
||||
|
||||
@@ -48,6 +48,7 @@ func testBotStoreGet(t *testing.T, ss store.Store) {
|
||||
DeleteAt: 0,
|
||||
})
|
||||
store.Must(ss.Bot().PermanentDelete(permanentlyDeletedBot.UserId))
|
||||
defer func() { store.Must(ss.User().PermanentDelete(permanentlyDeletedBot.UserId)) }()
|
||||
|
||||
b1, _ := makeBotWithUser(ss, &model.Bot{
|
||||
Username: "b1",
|
||||
@@ -123,6 +124,7 @@ func testBotStoreGetAll(t *testing.T, ss store.Store) {
|
||||
DeleteAt: 0,
|
||||
})
|
||||
store.Must(ss.Bot().PermanentDelete(permanentlyDeletedBot.UserId))
|
||||
defer func() { store.Must(ss.User().PermanentDelete(permanentlyDeletedBot.UserId)) }()
|
||||
|
||||
b1, _ := makeBotWithUser(ss, &model.Bot{
|
||||
Username: "b1",
|
||||
|
||||
Reference in New Issue
Block a user