* Posts * Add missing translation * Fix internal store marshaling * [MM-22051] Remove To/From JSON (Channels) (#18116) * Channels * Channel members * ChannelSearch * Channel categories, list, sidebar, stats, view * Fix conversions * [MM-22051] Remove To/From JSON (Users) (#18121) * User related structs * Fix return * Team related structures (#18127) * [MM-22051] Remove To/From JSON (Status, Bot, Reaction, Thread, FileInfo) (#18130) * Status * Bot * Reaction * Thread * FileInfo * Some fixes * Translations update from Weblate (#18143) * Translated using Weblate (German) Currently translated at 100.0% (2309 of 2309 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/de/ * Translated using Weblate (Turkish) Currently translated at 100.0% (2309 of 2309 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/tr/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (2309 of 2309 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/hu/ * Update translation files Updated by "Cleanup translation files" hook in Weblate. Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/ Update translation files Updated by "Cleanup translation files" hook in Weblate. Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/ Update translation files Updated by "Cleanup translation files" hook in Weblate. Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/ Update translation files Updated by "Cleanup translation files" hook in Weblate. Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/ * Translated using Weblate (German) Currently translated at 100.0% (2301 of 2301 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/de/ * Translated using Weblate (Turkish) Currently translated at 100.0% (2301 of 2301 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/tr/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (2301 of 2301 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/hu/ * Translated using Weblate (English (Australia)) Currently translated at 100.0% (2301 of 2301 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/en_AU/ * Translated using Weblate (Bulgarian) Currently translated at 100.0% (2301 of 2301 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/bg/ * Translated using Weblate (Japanese) Currently translated at 100.0% (2301 of 2301 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/ja/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (2301 of 2301 strings) Translation: mattermost-languages-shipped/mattermost-server Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/zh_Hans/ Co-authored-by: JtheBAB <srast@bioc.uzh.ch> Co-authored-by: Kaya Zeren <kayazeren@gmail.com> Co-authored-by: Tóth Csaba // Online ERP Hungary Kft <csaba.toth@online-erp.hu> Co-authored-by: Matthew Williams <Matthew.Williams@outlook.com.au> Co-authored-by: Nikolai Zahariev <nikolaiz@yahoo.com> Co-authored-by: kaakaa <stooner.hoe@gmail.com> Co-authored-by: aeomin <lin@aeomin.net> Co-authored-by: Weblate (bot) <hosted@weblate.org> Co-authored-by: JtheBAB <srast@bioc.uzh.ch> Co-authored-by: Kaya Zeren <kayazeren@gmail.com> Co-authored-by: Tóth Csaba // Online ERP Hungary Kft <csaba.toth@online-erp.hu> Co-authored-by: Matthew Williams <Matthew.Williams@outlook.com.au> Co-authored-by: Nikolai Zahariev <nikolaiz@yahoo.com> Co-authored-by: kaakaa <stooner.hoe@gmail.com> Co-authored-by: aeomin <lin@aeomin.net> * [MM-22051] Remove To/From JSON methods from model (#18138) * Scheme * Role * Session * Config * Status * Fix logic * Emoji * GuestsInvite * Group * Command * ClusterInfo * License * Job * System * Plugin * Command2 * IncomingWebhook * OutgoingWebhook * Fix tests * Update traslation * Some fixes * Add missing return * Simplify * Make Config.ToJSONFiltered() return []byte * Make Busy.ToJSON() return []byte * Include error in log * Split logic * [MM-22051] Remove To/From JSON (final) (#18150) * SwitchRequest * PluginEventData * Permalink * PushNotification * SuggestCommand * PluginsResponse * WebSocketMessage * RemoteCluster * SharedChannel * PluginStatuses * InitialLoad * ClusterDiscovery * ClusterStats * MfaSecret * GroupSyncable * SAML * WebSocketRequest * TypingRequest * SecurityBulletin * OAuthApp * IntegrationAction * DataRetention * Preference * FileInfoList * Compliance * Preferences * FileInfoSearchResults * TermsOfService * InstallMarketplacePluginRequest * GitLabUser * UploadSessions * Remove unused helpers * Fix tests * [MM-23280] Fix linting for ToJSON/FromJSON (#18153) * SwitchRequest * PluginEventData * Permalink * PushNotification * SuggestCommand * PluginsResponse * WebSocketMessage * RemoteCluster * SharedChannel * PluginStatuses * InitialLoad * ClusterDiscovery * ClusterStats * MfaSecret * GroupSyncable * SAML * WebSocketRequest * TypingRequest * SecurityBulletin * OAuthApp * IntegrationAction * DataRetention * Preference * FileInfoList * Compliance * Preferences * FileInfoSearchResults * TermsOfService * InstallMarketplacePluginRequest * GitLabUser * UploadSessions * Remove unused helpers * Fix tests * Fix linting for ToJSON/FromJSON * Fix conversions Co-authored-by: Weblate (bot) <hosted@weblate.org> Co-authored-by: JtheBAB <srast@bioc.uzh.ch> Co-authored-by: Kaya Zeren <kayazeren@gmail.com> Co-authored-by: Tóth Csaba // Online ERP Hungary Kft <csaba.toth@online-erp.hu> Co-authored-by: Matthew Williams <Matthew.Williams@outlook.com.au> Co-authored-by: Nikolai Zahariev <nikolaiz@yahoo.com> Co-authored-by: kaakaa <stooner.hoe@gmail.com> Co-authored-by: aeomin <lin@aeomin.net> Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
205 строки
5.7 KiB
Go
205 строки
5.7 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package model
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
const (
|
|
BotDisplayNameMaxRunes = UserFirstNameMaxRunes
|
|
BotDescriptionMaxRunes = 1024
|
|
BotCreatorIdMaxRunes = KeyValuePluginIdMaxRunes // UserId or PluginId
|
|
BotWarnMetricBotUsername = "mattermost-advisor"
|
|
BotSystemBotUsername = "system-bot"
|
|
)
|
|
|
|
// Bot is a special type of User meant for programmatic interactions.
|
|
// Note that the primary key of a bot is the UserId, and matches the primary key of the
|
|
// corresponding user.
|
|
type Bot struct {
|
|
UserId string `json:"user_id"`
|
|
Username string `json:"username"`
|
|
DisplayName string `json:"display_name,omitempty"`
|
|
Description string `json:"description,omitempty"`
|
|
OwnerId string `json:"owner_id"`
|
|
LastIconUpdate int64 `json:"last_icon_update,omitempty"`
|
|
CreateAt int64 `json:"create_at"`
|
|
UpdateAt int64 `json:"update_at"`
|
|
DeleteAt int64 `json:"delete_at"`
|
|
}
|
|
|
|
// BotPatch is a description of what fields to update on an existing bot.
|
|
type BotPatch struct {
|
|
Username *string `json:"username"`
|
|
DisplayName *string `json:"display_name"`
|
|
Description *string `json:"description"`
|
|
}
|
|
|
|
// BotGetOptions acts as a filter on bulk bot fetching queries.
|
|
type BotGetOptions struct {
|
|
OwnerId string
|
|
IncludeDeleted bool
|
|
OnlyOrphaned bool
|
|
Page int
|
|
PerPage int
|
|
}
|
|
|
|
// BotList is a list of bots.
|
|
type BotList []*Bot
|
|
|
|
// Trace describes the minimum information required to identify a bot for the purpose of logging.
|
|
func (b *Bot) Trace() map[string]interface{} {
|
|
return map[string]interface{}{"user_id": b.UserId}
|
|
}
|
|
|
|
// Clone returns a shallow copy of the bot.
|
|
func (b *Bot) Clone() *Bot {
|
|
copy := *b
|
|
return ©
|
|
}
|
|
|
|
// IsValid validates the bot and returns an error if it isn't configured correctly.
|
|
func (b *Bot) IsValid() *AppError {
|
|
if !IsValidId(b.UserId) {
|
|
return NewAppError("Bot.IsValid", "model.bot.is_valid.user_id.app_error", b.Trace(), "", http.StatusBadRequest)
|
|
}
|
|
|
|
if !IsValidUsername(b.Username) {
|
|
return NewAppError("Bot.IsValid", "model.bot.is_valid.username.app_error", b.Trace(), "", http.StatusBadRequest)
|
|
}
|
|
|
|
if utf8.RuneCountInString(b.DisplayName) > BotDisplayNameMaxRunes {
|
|
return NewAppError("Bot.IsValid", "model.bot.is_valid.user_id.app_error", b.Trace(), "", http.StatusBadRequest)
|
|
}
|
|
|
|
if utf8.RuneCountInString(b.Description) > BotDescriptionMaxRunes {
|
|
return NewAppError("Bot.IsValid", "model.bot.is_valid.description.app_error", b.Trace(), "", http.StatusBadRequest)
|
|
}
|
|
|
|
if b.OwnerId == "" || utf8.RuneCountInString(b.OwnerId) > BotCreatorIdMaxRunes {
|
|
return NewAppError("Bot.IsValid", "model.bot.is_valid.creator_id.app_error", b.Trace(), "", http.StatusBadRequest)
|
|
}
|
|
|
|
if b.CreateAt == 0 {
|
|
return NewAppError("Bot.IsValid", "model.bot.is_valid.create_at.app_error", b.Trace(), "", http.StatusBadRequest)
|
|
}
|
|
|
|
if b.UpdateAt == 0 {
|
|
return NewAppError("Bot.IsValid", "model.bot.is_valid.update_at.app_error", b.Trace(), "", http.StatusBadRequest)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// PreSave should be run before saving a new bot to the database.
|
|
func (b *Bot) PreSave() {
|
|
b.CreateAt = GetMillis()
|
|
b.UpdateAt = b.CreateAt
|
|
b.DeleteAt = 0
|
|
}
|
|
|
|
// PreUpdate should be run before saving an updated bot to the database.
|
|
func (b *Bot) PreUpdate() {
|
|
b.UpdateAt = GetMillis()
|
|
}
|
|
|
|
// Etag generates an etag for caching.
|
|
func (b *Bot) Etag() string {
|
|
return Etag(b.UserId, b.UpdateAt)
|
|
}
|
|
|
|
// Patch modifies an existing bot with optional fields from the given patch.
|
|
// TODO 6.0: consider returning a boolean to indicate whether or not the patch
|
|
// applied any changes.
|
|
func (b *Bot) Patch(patch *BotPatch) {
|
|
if patch.Username != nil {
|
|
b.Username = *patch.Username
|
|
}
|
|
|
|
if patch.DisplayName != nil {
|
|
b.DisplayName = *patch.DisplayName
|
|
}
|
|
|
|
if patch.Description != nil {
|
|
b.Description = *patch.Description
|
|
}
|
|
}
|
|
|
|
// WouldPatch returns whether or not the given patch would be applied or not.
|
|
func (b *Bot) WouldPatch(patch *BotPatch) bool {
|
|
if patch == nil {
|
|
return false
|
|
}
|
|
if patch.Username != nil && *patch.Username != b.Username {
|
|
return true
|
|
}
|
|
if patch.DisplayName != nil && *patch.DisplayName != b.DisplayName {
|
|
return true
|
|
}
|
|
if patch.Description != nil && *patch.Description != b.Description {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// UserFromBot returns a user model describing the bot fields stored in the User store.
|
|
func UserFromBot(b *Bot) *User {
|
|
return &User{
|
|
Id: b.UserId,
|
|
Username: b.Username,
|
|
Email: NormalizeEmail(fmt.Sprintf("%s@localhost", b.Username)),
|
|
FirstName: b.DisplayName,
|
|
Roles: SystemUserRoleId,
|
|
}
|
|
}
|
|
|
|
// 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(ShowUsername),
|
|
}
|
|
}
|
|
|
|
// Etag computes the etag for a list of bots.
|
|
func (l *BotList) Etag() string {
|
|
id := "0"
|
|
var t int64 = 0
|
|
var delta int64 = 0
|
|
|
|
for _, v := range *l {
|
|
if v.UpdateAt > t {
|
|
t = v.UpdateAt
|
|
id = v.UserId
|
|
}
|
|
|
|
}
|
|
|
|
return Etag(id, t, delta, len(*l))
|
|
}
|
|
|
|
// MakeBotNotFoundError creates the error returned when a bot does not exist, or when the user isn't allowed to query the bot.
|
|
// The errors must the same in both cases to avoid leaking that a user is a bot.
|
|
func MakeBotNotFoundError(userId string) *AppError {
|
|
return NewAppError("SqlBotStore.Get", "store.sql_bot.get.missing.app_error", map[string]interface{}{"user_id": userId}, "", http.StatusNotFound)
|
|
}
|
|
|
|
func IsBotDMChannel(channel *Channel, botUserID string) bool {
|
|
if channel.Type != ChannelTypeDirect {
|
|
return false
|
|
}
|
|
|
|
if !strings.HasPrefix(channel.Name, botUserID+"__") && !strings.HasSuffix(channel.Name, "__"+botUserID) {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|