[MM-14719] convert users to bots through cmd (#10672)

* [MM-14719] convert users to bots through cmd

* address review comments, add / fix unit tests

* change command from "modify" to "convert"; review comments

* code review comments, clean up
This commit is contained in:
Siyuan Liu
2019-05-06 07:59:51 -07:00
committed by Christopher Speller
parent dce6cb601f
commit fc15eda37f
6 changed files with 137 additions and 0 deletions

View File

@@ -176,3 +176,12 @@ func (a *App) disableUserBots(userId string) *model.AppError {
return nil
}
// ConvertUserToBot converts a user to bot
func (a *App) ConvertUserToBot(user *model.User) (*model.Bot, *model.AppError) {
result := <-a.Srv.Store.Bot().Save(model.BotFromUser(user))
if result.Err != nil {
return nil, result.Err
}
return result.Data.(*model.Bot), nil
}

View File

@@ -544,6 +544,48 @@ func TestDisableUserBots(t *testing.T) {
require.Nil(t, err)
}
func TestConvertUserToBot(t *testing.T) {
t.Run("invalid user", func(t *testing.T) {
t.Run("invalid user id", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
_, err := th.App.ConvertUserToBot(&model.User{
Username: "username",
Id: "",
})
require.NotNil(t, err)
require.Equal(t, "model.bot.is_valid.user_id.app_error", err.Id)
})
t.Run("invalid username", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
_, err := th.App.ConvertUserToBot(&model.User{
Username: "invalid username",
Id: th.BasicUser.Id,
})
require.NotNil(t, err)
require.Equal(t, "model.bot.is_valid.username.app_error", err.Id)
})
})
t.Run("valid user", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
bot, err := th.App.ConvertUserToBot(&model.User{
Username: "username",
Id: th.BasicUser.Id,
})
require.Nil(t, err)
defer th.App.PermanentDeleteBot(bot.UserId)
assert.Equal(t, "username", bot.Username)
assert.Equal(t, th.BasicUser.Id, bot.OwnerId)
})
}
func sToP(s string) *string {
return &s
}

View File

@@ -45,6 +45,15 @@ var UserCreateCmd = &cobra.Command{
RunE: userCreateCmdF,
}
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,
}
var UserInviteCmd = &cobra.Command{
Use: "invite [email] [teams]",
Short: "Send user an email invite to a team.",
@@ -162,6 +171,8 @@ func init() {
UserCreateCmd.Flags().String("locale", "", "Optional. The locale (ex: en, fr) for the new user account.")
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.")
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.")
@@ -234,6 +245,7 @@ Global Flags:
UserActivateCmd,
UserDeactivateCmd,
UserCreateCmd,
UserConvertCmd,
UserInviteCmd,
ResetUserPasswordCmd,
updateUserEmailCmd,
@@ -368,6 +380,44 @@ func userCreateCmdF(command *cobra.Command, args []string) error {
return nil
}
func usersToBots(args []string, a *app.App) {
users := getUsersFromUserArgs(a, args)
for i, user := range users {
if user == nil {
CommandPrintErrorln(fmt.Errorf("Unable to find user \"%s\"", args[i]))
continue
}
bot, err := a.ConvertUserToBot(user)
if err != nil {
CommandPrintErrorln(err.Error())
continue
}
CommandPrettyPrintln(fmt.Sprintf("User %s is converted to bot successfully", bot.UserId))
}
}
func userConvertCmdF(command *cobra.Command, args []string) error {
a, err := InitDBCommandContextCobra(command)
if err != nil {
return err
}
defer a.Shutdown()
toBot, err := command.Flags().GetBool("bot")
if err != nil {
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.")
}
usersToBots(args, a)
return nil
}
func userInviteCmdF(command *cobra.Command, args []string) error {
a, err := InitDBCommandContextCobra(command)
if err != nil {

View File

@@ -116,3 +116,12 @@ func TestChangeUserEmail(t *testing.T) {
require.Error(t, th.RunCommand(t, "user", "email", th.BasicUser.Username, th.BasicUser2.Email))
}
func TestConvertUserToBot(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)
}

View File

@@ -172,6 +172,16 @@ func UserFromBot(b *Bot) *User {
}
}
// BotFromUser returns a bot model given a user model
func BotFromUser(u *User) *Bot {
return &Bot{
OwnerId: u.Id,
UserId: u.Id,
Username: u.Username,
DisplayName: u.GetDisplayName(SHOW_USERNAME),
}
}
// BotListFromJson deserializes a list of bots from json.
func BotListFromJson(data io.Reader) BotList {
var bots BotList

View File

@@ -517,6 +517,23 @@ func TestUserFromBot(t *testing.T) {
}, UserFromBot(bot2))
}
func TestBotFromUser(t *testing.T) {
user := &User{
Id: NewId(),
Username: "username",
CreateAt: 1,
UpdateAt: 2,
DeleteAt: 3,
}
assert.Equal(t, &Bot{
OwnerId: user.Id,
UserId: user.Id,
Username: "username",
DisplayName: "username",
}, BotFromUser(user))
}
func TestBotListToAndFromJson(t *testing.T) {
testCases := []struct {
Description string