[MM-25648] api4: add user/bot convert endpoints (#14877)

* api4: add user/bot convert endpoints

* api4: add convert user/bot to local mode

* api4: fix linting issues

* api4/bot: reflect review comments

* api4: update convert user endpoint paths

* remove shadow decl

* fix translation problems
Этот коммит содержится в:
Ibrahim Serdar Acikgoz
2020-07-17 10:00:43 +03:00
коммит произвёл GitHub
родитель cb89c53dcc
Коммит 6a4e3293f8
11 изменённых файлов: 258 добавлений и 0 удалений

Просмотреть файл

@@ -21,6 +21,7 @@ func (api *API) InitBot() {
api.BaseRoutes.Bots.Handle("", api.ApiSessionRequired(getBots)).Methods("GET")
api.BaseRoutes.Bot.Handle("/disable", api.ApiSessionRequired(disableBot)).Methods("POST")
api.BaseRoutes.Bot.Handle("/enable", api.ApiSessionRequired(enableBot)).Methods("POST")
api.BaseRoutes.Bot.Handle("/convert_to_user", api.ApiSessionRequired(convertBotToUser)).Methods("POST")
api.BaseRoutes.Bot.Handle("/assign/{user_id:[A-Za-z0-9]+}", api.ApiSessionRequired(assignBot)).Methods("POST")
api.BaseRoutes.Bot.Handle("/icon", api.ApiSessionRequiredTrustRequester(getBotIconImage)).Methods("GET")
@@ -378,3 +379,46 @@ func deleteBotIconImage(c *Context, w http.ResponseWriter, r *http.Request) {
ReturnStatusOK(w)
}
func convertBotToUser(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireBotUserId()
if c.Err != nil {
return
}
bot, err := c.App.GetBot(c.Params.BotUserId, false)
if err != nil {
c.Err = err
return
}
userPatch := model.UserPatchFromJson(r.Body)
if userPatch == nil || userPatch.Password == nil || *userPatch.Password == "" {
c.SetInvalidParam("userPatch")
return
}
systemAdmin, _ := strconv.ParseBool(r.URL.Query().Get("set_system_admin"))
auditRec := c.MakeAuditRecord("convertBotToUser", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("bot", bot)
auditRec.AddMeta("userPatch", userPatch)
auditRec.AddMeta("set_system_admin", systemAdmin)
if c.Params.UserId != c.App.Session().UserId && !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
return
}
user, err := c.App.ConvertBotToUser(bot, userPatch, systemAdmin)
if err != nil {
c.Err = err
return
}
auditRec.Success()
auditRec.AddMeta("convertedTo", user)
w.Write([]byte(user.ToJson()))
}

Просмотреть файл

@@ -4,9 +4,11 @@
package api4
func (api *API) InitBotLocal() {
api.BaseRoutes.Bot.Handle("", api.ApiLocal(getBot)).Methods("GET")
api.BaseRoutes.Bot.Handle("", api.ApiLocal(patchBot)).Methods("PUT")
api.BaseRoutes.Bot.Handle("/disable", api.ApiLocal(disableBot)).Methods("POST")
api.BaseRoutes.Bot.Handle("/enable", api.ApiLocal(enableBot)).Methods("POST")
api.BaseRoutes.Bot.Handle("/convert_to_user", api.ApiLocal(convertBotToUser)).Methods("POST")
api.BaseRoutes.Bot.Handle("/assign/{user_id:[A-Za-z0-9]+}", api.ApiLocal(assignBot)).Methods("POST")
api.BaseRoutes.Bots.Handle("", api.ApiLocal(getBots)).Methods("GET")

Просмотреть файл

@@ -1403,6 +1403,68 @@ func TestDeleteBotIconImage(t *testing.T) {
require.False(t, exists, "icon.svg should not for the user")
}
func TestConvertBotToUser(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
th.AddPermissionToRole(model.PERMISSION_CREATE_BOT.Id, model.TEAM_USER_ROLE_ID)
th.App.UpdateUserRoles(th.BasicUser.Id, model.TEAM_USER_ROLE_ID, false)
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.EnableBotAccountCreation = true
})
bot := &model.Bot{
Username: GenerateTestUsername(),
Description: "bot",
}
bot, resp := th.Client.CreateBot(bot)
CheckCreatedStatus(t, resp)
defer th.App.PermanentDeleteBot(bot.UserId)
_, resp = th.Client.ConvertBotToUser(bot.UserId, &model.UserPatch{}, false)
CheckBadRequestStatus(t, resp)
user, resp := th.Client.ConvertBotToUser(bot.UserId, &model.UserPatch{Password: model.NewString("password")}, false)
CheckForbiddenStatus(t, resp)
require.Nil(t, user)
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
bot := &model.Bot{
Username: GenerateTestUsername(),
Description: "bot",
}
bot, resp := th.SystemAdminClient.CreateBot(bot)
CheckCreatedStatus(t, resp)
user, resp := client.ConvertBotToUser(bot.UserId, &model.UserPatch{}, false)
CheckBadRequestStatus(t, resp)
user, resp = client.ConvertBotToUser(bot.UserId, &model.UserPatch{Password: model.NewString("password")}, false)
CheckNoError(t, resp)
require.NotNil(t, user)
require.Equal(t, bot.UserId, user.Id)
bot, resp = client.GetBot(bot.UserId, "")
CheckNotFoundStatus(t, resp)
bot = &model.Bot{
Username: GenerateTestUsername(),
Description: "systemAdminBot",
}
bot, resp = th.SystemAdminClient.CreateBot(bot)
CheckCreatedStatus(t, resp)
user, resp = client.ConvertBotToUser(bot.UserId, &model.UserPatch{Password: model.NewString("password")}, true)
CheckNoError(t, resp)
require.NotNil(t, user)
require.Equal(t, bot.UserId, user.Id)
require.Contains(t, user.GetRoles(), model.SYSTEM_ADMIN_ROLE_ID)
bot, resp = client.GetBot(bot.UserId, "")
CheckNotFoundStatus(t, resp)
})
}
func sToP(s string) *string {
return &s
}

Просмотреть файл

@@ -46,6 +46,7 @@ func (api *API) InitUser() {
api.BaseRoutes.User.Handle("/password", api.ApiSessionRequired(updatePassword)).Methods("PUT")
api.BaseRoutes.User.Handle("/promote", api.ApiSessionRequired(promoteGuestToUser)).Methods("POST")
api.BaseRoutes.User.Handle("/demote", api.ApiSessionRequired(demoteUserToGuest)).Methods("POST")
api.BaseRoutes.User.Handle("/convert_to_bot", api.ApiSessionRequired(convertUserToBot)).Methods("POST")
api.BaseRoutes.Users.Handle("/password/reset", api.ApiHandler(resetPassword)).Methods("POST")
api.BaseRoutes.Users.Handle("/password/reset/send", api.ApiHandler(sendPasswordReset)).Methods("POST")
api.BaseRoutes.Users.Handle("/email/verify", api.ApiHandler(verifyUserEmail)).Methods("POST")
@@ -2485,3 +2486,36 @@ func verifyUserEmailWithoutToken(c *Context, w http.ResponseWriter, r *http.Requ
w.Write([]byte(user.ToJson()))
}
func convertUserToBot(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireUserId()
if c.Err != nil {
return
}
user, err := c.App.GetUser(c.Params.UserId)
if err != nil {
c.Err = err
return
}
auditRec := c.MakeAuditRecord("convertUserToBot", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("user", user)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
return
}
bot, err := c.App.ConvertUserToBot(user)
if err != nil {
c.Err = err
return
}
auditRec.Success()
auditRec.AddMeta("convertedTo", bot)
w.Write(bot.ToJson())
}

Просмотреть файл

@@ -22,6 +22,7 @@ func (api *API) InitUserLocal() {
api.BaseRoutes.User.Handle("/roles", api.ApiLocal(updateUserRoles)).Methods("PUT")
api.BaseRoutes.User.Handle("/mfa", api.ApiLocal(updateUserMfa)).Methods("PUT")
api.BaseRoutes.User.Handle("/active", api.ApiLocal(updateUserActive)).Methods("PUT")
api.BaseRoutes.User.Handle("/convert_to_bot", api.ApiLocal(convertUserToBot)).Methods("POST")
api.BaseRoutes.UserByUsername.Handle("", api.ApiLocal(localGetUserByUsername)).Methods("GET")
api.BaseRoutes.UserByEmail.Handle("", api.ApiLocal(localGetUserByEmail)).Methods("GET")

Просмотреть файл

@@ -5075,3 +5075,29 @@ func TestPublishUserTyping(t *testing.T) {
CheckServiceUnavailableStatus(t, resp)
})
}
func TestConvertUserToBot(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
bot, resp := th.Client.ConvertUserToBot(th.BasicUser.Id)
CheckForbiddenStatus(t, resp)
require.Nil(t, bot)
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
user := model.User{Email: th.GenerateTestEmail(), Username: GenerateTestUsername(), Password: "password"}
ruser, resp := client.CreateUser(&user)
CheckNoError(t, resp)
CheckCreatedStatus(t, resp)
bot, resp = client.ConvertUserToBot(ruser.Id)
CheckNoError(t, resp)
require.NotNil(t, bot)
require.Equal(t, bot.UserId, ruser.Id)
bot, resp = client.GetBot(bot.UserId, "")
CheckNoError(t, resp)
require.NotNil(t, bot)
})
}