mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
* When patching a bot, perform these two additional steps: 1. Update the user.UpdateAt value for the user/bot. 2. send the websocket event so all clients know a user update has occured. This will tell clients to update the displayname * Add check for UpdateAt. Check that createdBot.UpdateAt is not equal to patchedBot.UpdateAt * re-add unintentional empty line delete in previous commit * Don't create a fake updateAt time. Let the Update() method handle the change. User the returned updateUser for sending updated user event
278 lines
7.3 KiB
Go
278 lines
7.3 KiB
Go
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
|
// See License.txt for license information.
|
|
|
|
package app
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"mime/multipart"
|
|
"net/http"
|
|
|
|
"github.com/mattermost/mattermost-server/mlog"
|
|
"github.com/mattermost/mattermost-server/model"
|
|
"github.com/mattermost/mattermost-server/store"
|
|
"github.com/mattermost/mattermost-server/utils"
|
|
)
|
|
|
|
// CreateBot creates the given bot and corresponding user.
|
|
func (a *App) CreateBot(bot *model.Bot) (*model.Bot, *model.AppError) {
|
|
user, err := a.Srv.Store.User().Save(model.UserFromBot(bot))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
bot.UserId = user.Id
|
|
|
|
savedBot, err := a.Srv.Store.Bot().Save(bot)
|
|
if err != nil {
|
|
a.Srv.Store.User().PermanentDelete(bot.UserId)
|
|
return nil, err
|
|
}
|
|
|
|
// Get the owner of the bot, if one exists. If not, don't send a message
|
|
ownerUser, err := a.Srv.Store.User().Get(bot.OwnerId)
|
|
if err != nil && err.Id != store.MISSING_ACCOUNT_ERROR {
|
|
mlog.Error(err.Error())
|
|
return nil, err
|
|
} else if ownerUser != nil {
|
|
// Send a message to the bot's creator to inform them that the bot needs to be added
|
|
// to a team and channel after it's created
|
|
channel, err := a.GetOrCreateDirectChannel(savedBot.UserId, bot.OwnerId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
T := utils.GetUserTranslations(ownerUser.Locale)
|
|
botAddPost := &model.Post{
|
|
Type: model.POST_ADD_BOT_TEAMS_CHANNELS,
|
|
UserId: savedBot.UserId,
|
|
ChannelId: channel.Id,
|
|
Message: T("api.bot.teams_channels.add_message_mobile"),
|
|
}
|
|
|
|
if _, err := a.CreatePostAsUser(botAddPost, a.Session.Id); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return savedBot, nil
|
|
}
|
|
|
|
// PatchBot applies the given patch to the bot and corresponding user.
|
|
func (a *App) PatchBot(botUserId string, botPatch *model.BotPatch) (*model.Bot, *model.AppError) {
|
|
bot, err := a.GetBot(botUserId, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
bot.Patch(botPatch)
|
|
|
|
user, err := a.Srv.Store.User().Get(botUserId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
patchedUser := model.UserFromBot(bot)
|
|
user.Id = patchedUser.Id
|
|
user.Username = patchedUser.Username
|
|
user.Email = patchedUser.Email
|
|
user.FirstName = patchedUser.FirstName
|
|
|
|
userUpdate, err := a.Srv.Store.User().Update(user, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ruser := userUpdate.New
|
|
a.sendUpdatedUserEvent(*ruser)
|
|
|
|
return a.Srv.Store.Bot().Update(bot)
|
|
}
|
|
|
|
// GetBot returns the given bot.
|
|
func (a *App) GetBot(botUserId string, includeDeleted bool) (*model.Bot, *model.AppError) {
|
|
return a.Srv.Store.Bot().Get(botUserId, includeDeleted)
|
|
}
|
|
|
|
// GetBots returns the requested page of bots.
|
|
func (a *App) GetBots(options *model.BotGetOptions) (model.BotList, *model.AppError) {
|
|
return a.Srv.Store.Bot().GetAll(options)
|
|
}
|
|
|
|
// UpdateBotActive marks a bot as active or inactive, along with its corresponding user.
|
|
func (a *App) UpdateBotActive(botUserId string, active bool) (*model.Bot, *model.AppError) {
|
|
user, err := a.Srv.Store.User().Get(botUserId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if _, err = a.UpdateActive(user, active); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
bot, err := a.Srv.Store.Bot().Get(botUserId, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
changed := true
|
|
if active && bot.DeleteAt != 0 {
|
|
bot.DeleteAt = 0
|
|
} else if !active && bot.DeleteAt == 0 {
|
|
bot.DeleteAt = model.GetMillis()
|
|
} else {
|
|
changed = false
|
|
}
|
|
|
|
if changed {
|
|
bot, err = a.Srv.Store.Bot().Update(bot)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return bot, nil
|
|
}
|
|
|
|
// PermanentDeleteBot permanently deletes a bot and its corresponding user.
|
|
func (a *App) PermanentDeleteBot(botUserId string) *model.AppError {
|
|
if err := a.Srv.Store.Bot().PermanentDelete(botUserId); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := a.Srv.Store.User().PermanentDelete(botUserId); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// UpdateBotOwner changes a bot's owner to the given value.
|
|
func (a *App) UpdateBotOwner(botUserId, newOwnerId string) (*model.Bot, *model.AppError) {
|
|
bot, err := a.Srv.Store.Bot().Get(botUserId, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
bot.OwnerId = newOwnerId
|
|
|
|
bot, err = a.Srv.Store.Bot().Update(bot)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return bot, nil
|
|
}
|
|
|
|
// disableUserBots disables all bots owned by the given user.
|
|
func (a *App) disableUserBots(userId string) *model.AppError {
|
|
perPage := 20
|
|
for {
|
|
options := &model.BotGetOptions{
|
|
OwnerId: userId,
|
|
IncludeDeleted: false,
|
|
OnlyOrphaned: false,
|
|
Page: 0,
|
|
PerPage: perPage,
|
|
}
|
|
userBots, err := a.GetBots(options)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, bot := range userBots {
|
|
_, err := a.UpdateBotActive(bot.UserId, false)
|
|
if err != nil {
|
|
mlog.Error("Unable to deactivate bot.", mlog.String("bot_user_id", bot.UserId), mlog.Err(err))
|
|
}
|
|
}
|
|
|
|
// Get next set of bots if we got the max number of bots
|
|
if len(userBots) == perPage {
|
|
options.Page += 1
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ConvertUserToBot converts a user to bot.
|
|
func (a *App) ConvertUserToBot(user *model.User) (*model.Bot, *model.AppError) {
|
|
return a.Srv.Store.Bot().Save(model.BotFromUser(user))
|
|
}
|
|
|
|
// SetBotIconImageFromMultiPartFile sets LHS icon for a bot.
|
|
func (a *App) SetBotIconImageFromMultiPartFile(botUserId string, imageData *multipart.FileHeader) *model.AppError {
|
|
file, err := imageData.Open()
|
|
if err != nil {
|
|
return model.NewAppError("SetBotIconImage", "api.bot.set_bot_icon_image.open.app_error", nil, err.Error(), http.StatusBadRequest)
|
|
}
|
|
defer file.Close()
|
|
|
|
file.Seek(0, 0)
|
|
return a.SetBotIconImage(botUserId, file)
|
|
}
|
|
|
|
// SetBotIconImage sets LHS icon for a bot.
|
|
func (a *App) SetBotIconImage(botUserId string, file io.ReadSeeker) *model.AppError {
|
|
if _, err := a.GetBot(botUserId, true); err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := parseSVG(file); err != nil {
|
|
return model.NewAppError("SetBotIconImage", "api.bot.set_bot_icon_image.parse.app_error", nil, err.Error(), http.StatusBadRequest)
|
|
}
|
|
|
|
// Set icon
|
|
file.Seek(0, 0)
|
|
if _, err := a.WriteFile(file, getBotIconPath(botUserId)); err != nil {
|
|
return model.NewAppError("SetBotIconImage", "api.bot.set_bot_icon_image.app_error", nil, err.Error(), http.StatusInternalServerError)
|
|
}
|
|
|
|
if err := a.Srv.Store.User().UpdateLastPictureUpdate(botUserId); err != nil {
|
|
mlog.Error(err.Error())
|
|
}
|
|
a.invalidateUserCacheAndPublish(botUserId)
|
|
|
|
return nil
|
|
}
|
|
|
|
// DeleteBotIconImage deletes LHS icon for a bot.
|
|
func (a *App) DeleteBotIconImage(botUserId string) *model.AppError {
|
|
if _, err := a.GetBot(botUserId, true); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Delete icon
|
|
if err := a.RemoveFile(getBotIconPath(botUserId)); err != nil {
|
|
return model.NewAppError("DeleteBotIconImage", "api.bot.delete_bot_icon_image.app_error", nil, err.Error(), http.StatusInternalServerError)
|
|
}
|
|
|
|
if err := a.Srv.Store.User().UpdateLastPictureUpdate(botUserId); err != nil {
|
|
mlog.Error(err.Error())
|
|
}
|
|
a.invalidateUserCacheAndPublish(botUserId)
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetBotIconImage retrieves LHS icon for a bot.
|
|
func (a *App) GetBotIconImage(botUserId string) ([]byte, *model.AppError) {
|
|
if _, err := a.GetBot(botUserId, true); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
data, err := a.ReadFile(getBotIconPath(botUserId))
|
|
if err != nil {
|
|
return nil, model.NewAppError("GetBotIconImage", "api.bot.get_bot_icon_image.read.app_error", nil, err.Error(), http.StatusNotFound)
|
|
}
|
|
|
|
return data, nil
|
|
}
|
|
|
|
func getBotIconPath(botUserId string) string {
|
|
return fmt.Sprintf("bots/%v/icon.svg", botUserId)
|
|
}
|