diff options
author | Wim <wim@42.be> | 2018-02-09 00:11:04 +0100 |
---|---|---|
committer | Wim <wim@42.be> | 2018-02-09 00:11:04 +0100 |
commit | 5aab158c0b0db64b6136fe2fdaca8b8e9e3bd811 (patch) | |
tree | 09bcb3f02f968867c2ca84db1f28594dd0afb967 /vendor/github.com/mattermost/platform/model | |
parent | 1d33e60e36fa7b0e361990ac347ee8d620d67dcc (diff) | |
download | matterbridge-msglm-5aab158c0b0db64b6136fe2fdaca8b8e9e3bd811.tar.gz matterbridge-msglm-5aab158c0b0db64b6136fe2fdaca8b8e9e3bd811.tar.bz2 matterbridge-msglm-5aab158c0b0db64b6136fe2fdaca8b8e9e3bd811.zip |
Update vendor (github.com/mattermost)
Diffstat (limited to 'vendor/github.com/mattermost/platform/model')
46 files changed, 2653 insertions, 1329 deletions
diff --git a/vendor/github.com/mattermost/platform/model/access.go b/vendor/github.com/mattermost/platform/model/access.go index 9e16ed58..551ef930 100644 --- a/vendor/github.com/mattermost/platform/model/access.go +++ b/vendor/github.com/mattermost/platform/model/access.go @@ -6,6 +6,7 @@ package model import ( "encoding/json" "io" + "net/http" ) const ( @@ -37,23 +38,23 @@ type AccessResponse struct { func (ad *AccessData) IsValid() *AppError { if len(ad.ClientId) == 0 || len(ad.ClientId) > 26 { - return NewLocAppError("AccessData.IsValid", "model.access.is_valid.client_id.app_error", nil, "") + return NewAppError("AccessData.IsValid", "model.access.is_valid.client_id.app_error", nil, "", http.StatusBadRequest) } if len(ad.UserId) == 0 || len(ad.UserId) > 26 { - return NewLocAppError("AccessData.IsValid", "model.access.is_valid.user_id.app_error", nil, "") + return NewAppError("AccessData.IsValid", "model.access.is_valid.user_id.app_error", nil, "", http.StatusBadRequest) } if len(ad.Token) != 26 { - return NewLocAppError("AccessData.IsValid", "model.access.is_valid.access_token.app_error", nil, "") + return NewAppError("AccessData.IsValid", "model.access.is_valid.access_token.app_error", nil, "", http.StatusBadRequest) } if len(ad.RefreshToken) > 26 { - return NewLocAppError("AccessData.IsValid", "model.access.is_valid.refresh_token.app_error", nil, "") + return NewAppError("AccessData.IsValid", "model.access.is_valid.refresh_token.app_error", nil, "", http.StatusBadRequest) } if len(ad.RedirectUri) == 0 || len(ad.RedirectUri) > 256 || !IsValidHttpUrl(ad.RedirectUri) { - return NewLocAppError("AccessData.IsValid", "model.access.is_valid.redirect_uri.app_error", nil, "") + return NewAppError("AccessData.IsValid", "model.access.is_valid.redirect_uri.app_error", nil, "", http.StatusBadRequest) } return nil diff --git a/vendor/github.com/mattermost/platform/model/authorization.go b/vendor/github.com/mattermost/platform/model/authorization.go index d413e294..9f4e36ea 100644 --- a/vendor/github.com/mattermost/platform/model/authorization.go +++ b/vendor/github.com/mattermost/platform/model/authorization.go @@ -69,24 +69,24 @@ var PERMISSION_REVOKE_USER_ACCESS_TOKEN *Permission // admin functions but not others var PERMISSION_MANAGE_SYSTEM *Permission -var ROLE_SYSTEM_USER *Role -var ROLE_SYSTEM_ADMIN *Role -var ROLE_SYSTEM_POST_ALL *Role -var ROLE_SYSTEM_POST_ALL_PUBLIC *Role -var ROLE_SYSTEM_USER_ACCESS_TOKEN *Role +const ( + SYSTEM_USER_ROLE_ID = "system_user" + SYSTEM_ADMIN_ROLE_ID = "system_admin" + SYSTEM_POST_ALL_ROLE_ID = "system_post_all" + SYSTEM_POST_ALL_PUBLIC_ROLE_ID = "system_post_all_public" + SYSTEM_USER_ACCESS_TOKEN_ROLE_ID = "system_user_access_token" -var ROLE_TEAM_USER *Role -var ROLE_TEAM_ADMIN *Role -var ROLE_TEAM_POST_ALL *Role -var ROLE_TEAM_POST_ALL_PUBLIC *Role + TEAM_USER_ROLE_ID = "team_user" + TEAM_ADMIN_ROLE_ID = "team_admin" + TEAM_POST_ALL_ROLE_ID = "team_post_all" + TEAM_POST_ALL_PUBLIC_ROLE_ID = "team_post_all_public" -var ROLE_CHANNEL_USER *Role -var ROLE_CHANNEL_ADMIN *Role -var ROLE_CHANNEL_GUEST *Role + CHANNEL_USER_ROLE_ID = "channel_user" + CHANNEL_ADMIN_ROLE_ID = "channel_admin" + CHANNEL_GUEST_ROLE_ID = "guest" +) -var BuiltInRoles map[string]*Role - -func InitalizePermissions() { +func initializePermissions() { PERMISSION_INVITE_USER = &Permission{ "invite_user", "authentication.permissions.team_invite_user.name", @@ -329,11 +329,12 @@ func InitalizePermissions() { } } -func InitalizeRoles() { - InitalizePermissions() - BuiltInRoles = make(map[string]*Role) +var DefaultRoles map[string]*Role + +func initializeDefaultRoles() { + DefaultRoles = make(map[string]*Role) - ROLE_CHANNEL_USER = &Role{ + DefaultRoles[CHANNEL_USER_ROLE_ID] = &Role{ "channel_user", "authentication.roles.channel_user.name", "authentication.roles.channel_user.description", @@ -347,8 +348,8 @@ func InitalizeRoles() { PERMISSION_USE_SLASH_COMMANDS.Id, }, } - BuiltInRoles[ROLE_CHANNEL_USER.Id] = ROLE_CHANNEL_USER - ROLE_CHANNEL_ADMIN = &Role{ + + DefaultRoles[CHANNEL_ADMIN_ROLE_ID] = &Role{ "channel_admin", "authentication.roles.channel_admin.name", "authentication.roles.channel_admin.description", @@ -356,16 +357,15 @@ func InitalizeRoles() { PERMISSION_MANAGE_CHANNEL_ROLES.Id, }, } - BuiltInRoles[ROLE_CHANNEL_ADMIN.Id] = ROLE_CHANNEL_ADMIN - ROLE_CHANNEL_GUEST = &Role{ + + DefaultRoles[CHANNEL_GUEST_ROLE_ID] = &Role{ "guest", "authentication.roles.global_guest.name", "authentication.roles.global_guest.description", []string{}, } - BuiltInRoles[ROLE_CHANNEL_GUEST.Id] = ROLE_CHANNEL_GUEST - ROLE_TEAM_USER = &Role{ + DefaultRoles[TEAM_USER_ROLE_ID] = &Role{ "team_user", "authentication.roles.team_user.name", "authentication.roles.team_user.description", @@ -376,9 +376,8 @@ func InitalizeRoles() { PERMISSION_VIEW_TEAM.Id, }, } - BuiltInRoles[ROLE_TEAM_USER.Id] = ROLE_TEAM_USER - ROLE_TEAM_POST_ALL = &Role{ + DefaultRoles[TEAM_POST_ALL_ROLE_ID] = &Role{ "team_post_all", "authentication.roles.team_post_all.name", "authentication.roles.team_post_all.description", @@ -386,9 +385,8 @@ func InitalizeRoles() { PERMISSION_CREATE_POST.Id, }, } - BuiltInRoles[ROLE_TEAM_POST_ALL.Id] = ROLE_TEAM_POST_ALL - ROLE_TEAM_POST_ALL_PUBLIC = &Role{ + DefaultRoles[TEAM_POST_ALL_PUBLIC_ROLE_ID] = &Role{ "team_post_all_public", "authentication.roles.team_post_all_public.name", "authentication.roles.team_post_all_public.description", @@ -396,9 +394,8 @@ func InitalizeRoles() { PERMISSION_CREATE_POST_PUBLIC.Id, }, } - BuiltInRoles[ROLE_TEAM_POST_ALL_PUBLIC.Id] = ROLE_TEAM_POST_ALL_PUBLIC - ROLE_TEAM_ADMIN = &Role{ + DefaultRoles[TEAM_ADMIN_ROLE_ID] = &Role{ "team_admin", "authentication.roles.team_admin.name", "authentication.roles.team_admin.description", @@ -415,9 +412,8 @@ func InitalizeRoles() { PERMISSION_MANAGE_WEBHOOKS.Id, }, } - BuiltInRoles[ROLE_TEAM_ADMIN.Id] = ROLE_TEAM_ADMIN - ROLE_SYSTEM_USER = &Role{ + DefaultRoles[SYSTEM_USER_ROLE_ID] = &Role{ "system_user", "authentication.roles.global_user.name", "authentication.roles.global_user.description", @@ -427,9 +423,8 @@ func InitalizeRoles() { PERMISSION_PERMANENT_DELETE_USER.Id, }, } - BuiltInRoles[ROLE_SYSTEM_USER.Id] = ROLE_SYSTEM_USER - ROLE_SYSTEM_POST_ALL = &Role{ + DefaultRoles[SYSTEM_POST_ALL_ROLE_ID] = &Role{ "system_post_all", "authentication.roles.system_post_all.name", "authentication.roles.system_post_all.description", @@ -437,9 +432,8 @@ func InitalizeRoles() { PERMISSION_CREATE_POST.Id, }, } - BuiltInRoles[ROLE_SYSTEM_POST_ALL.Id] = ROLE_SYSTEM_POST_ALL - ROLE_SYSTEM_POST_ALL_PUBLIC = &Role{ + DefaultRoles[SYSTEM_POST_ALL_PUBLIC_ROLE_ID] = &Role{ "system_post_all_public", "authentication.roles.system_post_all_public.name", "authentication.roles.system_post_all_public.description", @@ -447,9 +441,8 @@ func InitalizeRoles() { PERMISSION_CREATE_POST_PUBLIC.Id, }, } - BuiltInRoles[ROLE_SYSTEM_POST_ALL_PUBLIC.Id] = ROLE_SYSTEM_POST_ALL_PUBLIC - ROLE_SYSTEM_USER_ACCESS_TOKEN = &Role{ + DefaultRoles[SYSTEM_USER_ACCESS_TOKEN_ROLE_ID] = &Role{ "system_user_access_token", "authentication.roles.system_user_access_token.name", "authentication.roles.system_user_access_token.description", @@ -459,9 +452,8 @@ func InitalizeRoles() { PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id, }, } - BuiltInRoles[ROLE_SYSTEM_USER_ACCESS_TOKEN.Id] = ROLE_SYSTEM_USER_ACCESS_TOKEN - ROLE_SYSTEM_ADMIN = &Role{ + DefaultRoles[SYSTEM_ADMIN_ROLE_ID] = &Role{ "system_admin", "authentication.roles.global_admin.name", "authentication.roles.global_admin.description", @@ -500,17 +492,15 @@ func InitalizeRoles() { PERMISSION_READ_USER_ACCESS_TOKEN.Id, PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id, }, - ROLE_TEAM_USER.Permissions..., + DefaultRoles[TEAM_USER_ROLE_ID].Permissions..., ), - ROLE_CHANNEL_USER.Permissions..., + DefaultRoles[CHANNEL_USER_ROLE_ID].Permissions..., ), - ROLE_TEAM_ADMIN.Permissions..., + DefaultRoles[TEAM_ADMIN_ROLE_ID].Permissions..., ), - ROLE_CHANNEL_ADMIN.Permissions..., + DefaultRoles[CHANNEL_ADMIN_ROLE_ID].Permissions..., ), } - BuiltInRoles[ROLE_SYSTEM_ADMIN.Id] = ROLE_SYSTEM_ADMIN - } func RoleIdsToString(roles []string) string { @@ -527,5 +517,6 @@ func RoleIdsToString(roles []string) string { } func init() { - InitalizeRoles() + initializePermissions() + initializeDefaultRoles() } diff --git a/vendor/github.com/mattermost/platform/model/authorize.go b/vendor/github.com/mattermost/platform/model/authorize.go index 460b7082..df07ff14 100644 --- a/vendor/github.com/mattermost/platform/model/authorize.go +++ b/vendor/github.com/mattermost/platform/model/authorize.go @@ -39,35 +39,35 @@ type AuthorizeRequest struct { func (ad *AuthData) IsValid() *AppError { if len(ad.ClientId) != 26 { - return NewLocAppError("AuthData.IsValid", "model.authorize.is_valid.client_id.app_error", nil, "") + return NewAppError("AuthData.IsValid", "model.authorize.is_valid.client_id.app_error", nil, "", http.StatusBadRequest) } if len(ad.UserId) != 26 { - return NewLocAppError("AuthData.IsValid", "model.authorize.is_valid.user_id.app_error", nil, "") + return NewAppError("AuthData.IsValid", "model.authorize.is_valid.user_id.app_error", nil, "", http.StatusBadRequest) } if len(ad.Code) == 0 || len(ad.Code) > 128 { - return NewLocAppError("AuthData.IsValid", "model.authorize.is_valid.auth_code.app_error", nil, "client_id="+ad.ClientId) + return NewAppError("AuthData.IsValid", "model.authorize.is_valid.auth_code.app_error", nil, "client_id="+ad.ClientId, http.StatusBadRequest) } if ad.ExpiresIn == 0 { - return NewLocAppError("AuthData.IsValid", "model.authorize.is_valid.expires.app_error", nil, "") + return NewAppError("AuthData.IsValid", "model.authorize.is_valid.expires.app_error", nil, "", http.StatusBadRequest) } if ad.CreateAt <= 0 { - return NewLocAppError("AuthData.IsValid", "model.authorize.is_valid.create_at.app_error", nil, "client_id="+ad.ClientId) + return NewAppError("AuthData.IsValid", "model.authorize.is_valid.create_at.app_error", nil, "client_id="+ad.ClientId, http.StatusBadRequest) } if len(ad.RedirectUri) == 0 || len(ad.RedirectUri) > 256 || !IsValidHttpUrl(ad.RedirectUri) { - return NewLocAppError("AuthData.IsValid", "model.authorize.is_valid.redirect_uri.app_error", nil, "client_id="+ad.ClientId) + return NewAppError("AuthData.IsValid", "model.authorize.is_valid.redirect_uri.app_error", nil, "client_id="+ad.ClientId, http.StatusBadRequest) } if len(ad.State) > 128 { - return NewLocAppError("AuthData.IsValid", "model.authorize.is_valid.state.app_error", nil, "client_id="+ad.ClientId) + return NewAppError("AuthData.IsValid", "model.authorize.is_valid.state.app_error", nil, "client_id="+ad.ClientId, http.StatusBadRequest) } if len(ad.Scope) > 128 { - return NewLocAppError("AuthData.IsValid", "model.authorize.is_valid.scope.app_error", nil, "client_id="+ad.ClientId) + return NewAppError("AuthData.IsValid", "model.authorize.is_valid.scope.app_error", nil, "client_id="+ad.ClientId, http.StatusBadRequest) } return nil @@ -155,10 +155,5 @@ func AuthorizeRequestFromJson(data io.Reader) *AuthorizeRequest { } func (ad *AuthData) IsExpired() bool { - - if GetMillis() > ad.CreateAt+int64(ad.ExpiresIn*1000) { - return true - } - - return false + return GetMillis() > ad.CreateAt+int64(ad.ExpiresIn*1000) } diff --git a/vendor/github.com/mattermost/platform/model/builtin.go b/vendor/github.com/mattermost/platform/model/builtin.go new file mode 100644 index 00000000..5dd00a96 --- /dev/null +++ b/vendor/github.com/mattermost/platform/model/builtin.go @@ -0,0 +1,9 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +func NewBool(b bool) *bool { return &b } +func NewInt(n int) *int { return &n } +func NewInt64(n int64) *int64 { return &n } +func NewString(s string) *string { return &s } diff --git a/vendor/github.com/mattermost/platform/model/bundle_info.go b/vendor/github.com/mattermost/platform/model/bundle_info.go new file mode 100644 index 00000000..6965159c --- /dev/null +++ b/vendor/github.com/mattermost/platform/model/bundle_info.go @@ -0,0 +1,23 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +type BundleInfo struct { + Path string + + Manifest *Manifest + ManifestPath string + ManifestError error +} + +// Returns bundle info for the given path. The return value is never nil. +func BundleInfoForPath(path string) *BundleInfo { + m, mpath, err := FindManifest(path) + return &BundleInfo{ + Path: path, + Manifest: m, + ManifestPath: mpath, + ManifestError: err, + } +} diff --git a/vendor/github.com/mattermost/platform/model/channel.go b/vendor/github.com/mattermost/platform/model/channel.go index 50d48755..a4c733c3 100644 --- a/vendor/github.com/mattermost/platform/model/channel.go +++ b/vendor/github.com/mattermost/platform/model/channel.go @@ -8,6 +8,7 @@ import ( "encoding/hex" "encoding/json" "io" + "net/http" "sort" "strings" "unicode/utf8" @@ -24,6 +25,7 @@ const ( CHANNEL_DISPLAY_NAME_MAX_RUNES = 64 CHANNEL_NAME_MIN_LENGTH = 2 CHANNEL_NAME_MAX_LENGTH = 64 + CHANNEL_NAME_UI_MAX_LENGTH = 22 CHANNEL_HEADER_MAX_RUNES = 1024 CHANNEL_PURPOSE_MAX_RUNES = 250 CHANNEL_CACHE_SIZE = 25000 @@ -53,6 +55,11 @@ type ChannelPatch struct { Purpose *string `json:"purpose"` } +func (o *Channel) DeepCopy() *Channel { + copy := *o + return © +} + func (o *Channel) ToJson() string { b, err := json.Marshal(o) if err != nil { @@ -104,39 +111,39 @@ func (o *Channel) StatsEtag() string { func (o *Channel) IsValid() *AppError { if len(o.Id) != 26 { - return NewLocAppError("Channel.IsValid", "model.channel.is_valid.id.app_error", nil, "") + return NewAppError("Channel.IsValid", "model.channel.is_valid.id.app_error", nil, "", http.StatusBadRequest) } if o.CreateAt == 0 { - return NewLocAppError("Channel.IsValid", "model.channel.is_valid.create_at.app_error", nil, "id="+o.Id) + return NewAppError("Channel.IsValid", "model.channel.is_valid.create_at.app_error", nil, "id="+o.Id, http.StatusBadRequest) } if o.UpdateAt == 0 { - return NewLocAppError("Channel.IsValid", "model.channel.is_valid.update_at.app_error", nil, "id="+o.Id) + return NewAppError("Channel.IsValid", "model.channel.is_valid.update_at.app_error", nil, "id="+o.Id, http.StatusBadRequest) } if utf8.RuneCountInString(o.DisplayName) > CHANNEL_DISPLAY_NAME_MAX_RUNES { - return NewLocAppError("Channel.IsValid", "model.channel.is_valid.display_name.app_error", nil, "id="+o.Id) + return NewAppError("Channel.IsValid", "model.channel.is_valid.display_name.app_error", nil, "id="+o.Id, http.StatusBadRequest) } if !IsValidChannelIdentifier(o.Name) { - return NewLocAppError("Channel.IsValid", "model.channel.is_valid.2_or_more.app_error", nil, "id="+o.Id) + return NewAppError("Channel.IsValid", "model.channel.is_valid.2_or_more.app_error", nil, "id="+o.Id, http.StatusBadRequest) } if !(o.Type == CHANNEL_OPEN || o.Type == CHANNEL_PRIVATE || o.Type == CHANNEL_DIRECT || o.Type == CHANNEL_GROUP) { - return NewLocAppError("Channel.IsValid", "model.channel.is_valid.type.app_error", nil, "id="+o.Id) + return NewAppError("Channel.IsValid", "model.channel.is_valid.type.app_error", nil, "id="+o.Id, http.StatusBadRequest) } if utf8.RuneCountInString(o.Header) > CHANNEL_HEADER_MAX_RUNES { - return NewLocAppError("Channel.IsValid", "model.channel.is_valid.header.app_error", nil, "id="+o.Id) + return NewAppError("Channel.IsValid", "model.channel.is_valid.header.app_error", nil, "id="+o.Id, http.StatusBadRequest) } if utf8.RuneCountInString(o.Purpose) > CHANNEL_PURPOSE_MAX_RUNES { - return NewLocAppError("Channel.IsValid", "model.channel.is_valid.purpose.app_error", nil, "id="+o.Id) + return NewAppError("Channel.IsValid", "model.channel.is_valid.purpose.app_error", nil, "id="+o.Id, http.StatusBadRequest) } if len(o.CreatorId) > 26 { - return NewLocAppError("Channel.IsValid", "model.channel.is_valid.creator_id.app_error", nil, "") + return NewAppError("Channel.IsValid", "model.channel.is_valid.creator_id.app_error", nil, "", http.StatusBadRequest) } return nil diff --git a/vendor/github.com/mattermost/platform/model/channel_member.go b/vendor/github.com/mattermost/platform/model/channel_member.go index f6d58519..e7ad8232 100644 --- a/vendor/github.com/mattermost/platform/model/channel_member.go +++ b/vendor/github.com/mattermost/platform/model/channel_member.go @@ -6,6 +6,7 @@ package model import ( "encoding/json" "io" + "net/http" "strings" ) @@ -101,36 +102,32 @@ func ChannelMemberFromJson(data io.Reader) *ChannelMember { func (o *ChannelMember) IsValid() *AppError { if len(o.ChannelId) != 26 { - return NewLocAppError("ChannelMember.IsValid", "model.channel_member.is_valid.channel_id.app_error", nil, "") + return NewAppError("ChannelMember.IsValid", "model.channel_member.is_valid.channel_id.app_error", nil, "", http.StatusBadRequest) } if len(o.UserId) != 26 { - return NewLocAppError("ChannelMember.IsValid", "model.channel_member.is_valid.user_id.app_error", nil, "") + return NewAppError("ChannelMember.IsValid", "model.channel_member.is_valid.user_id.app_error", nil, "", http.StatusBadRequest) } notifyLevel := o.NotifyProps[DESKTOP_NOTIFY_PROP] if len(notifyLevel) > 20 || !IsChannelNotifyLevelValid(notifyLevel) { - return NewLocAppError("ChannelMember.IsValid", "model.channel_member.is_valid.notify_level.app_error", - nil, "notify_level="+notifyLevel) + return NewAppError("ChannelMember.IsValid", "model.channel_member.is_valid.notify_level.app_error", nil, "notify_level="+notifyLevel, http.StatusBadRequest) } markUnreadLevel := o.NotifyProps[MARK_UNREAD_NOTIFY_PROP] if len(markUnreadLevel) > 20 || !IsChannelMarkUnreadLevelValid(markUnreadLevel) { - return NewLocAppError("ChannelMember.IsValid", "model.channel_member.is_valid.unread_level.app_error", - nil, "mark_unread_level="+markUnreadLevel) + return NewAppError("ChannelMember.IsValid", "model.channel_member.is_valid.unread_level.app_error", nil, "mark_unread_level="+markUnreadLevel, http.StatusBadRequest) } if pushLevel, ok := o.NotifyProps[PUSH_NOTIFY_PROP]; ok { if len(pushLevel) > 20 || !IsChannelNotifyLevelValid(pushLevel) { - return NewLocAppError("ChannelMember.IsValid", "model.channel_member.is_valid.push_level.app_error", - nil, "push_notification_level="+pushLevel) + return NewAppError("ChannelMember.IsValid", "model.channel_member.is_valid.push_level.app_error", nil, "push_notification_level="+pushLevel, http.StatusBadRequest) } } if sendEmail, ok := o.NotifyProps[EMAIL_NOTIFY_PROP]; ok { if len(sendEmail) > 20 || !IsSendEmailValid(sendEmail) { - return NewLocAppError("ChannelMember.IsValid", "model.channel_member.is_valid.email_value.app_error", - nil, "push_notification_level="+sendEmail) + return NewAppError("ChannelMember.IsValid", "model.channel_member.is_valid.email_value.app_error", nil, "push_notification_level="+sendEmail, http.StatusBadRequest) } } diff --git a/vendor/github.com/mattermost/platform/model/channel_member_history.go b/vendor/github.com/mattermost/platform/model/channel_member_history.go new file mode 100644 index 00000000..bc71b580 --- /dev/null +++ b/vendor/github.com/mattermost/platform/model/channel_member_history.go @@ -0,0 +1,12 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +type ChannelMemberHistory struct { + ChannelId string + UserId string + UserEmail string `db:"Email"` + JoinTime int64 + LeaveTime *int64 +} diff --git a/vendor/github.com/mattermost/platform/model/channel_view.go b/vendor/github.com/mattermost/platform/model/channel_view.go index 8a7ead76..e7b1de30 100644 --- a/vendor/github.com/mattermost/platform/model/channel_view.go +++ b/vendor/github.com/mattermost/platform/model/channel_view.go @@ -32,3 +32,28 @@ func ChannelViewFromJson(data io.Reader) *ChannelView { return nil } } + +type ChannelViewResponse struct { + Status string `json:"status"` + LastViewedAtTimes map[string]int64 `json:"last_viewed_at_times"` +} + +func (o *ChannelViewResponse) ToJson() string { + b, err := json.Marshal(o) + if err != nil { + return "" + } else { + return string(b) + } +} + +func ChannelViewResponseFromJson(data io.Reader) *ChannelViewResponse { + decoder := json.NewDecoder(data) + var o ChannelViewResponse + err := decoder.Decode(&o) + if err == nil { + return &o + } else { + return nil + } +} diff --git a/vendor/github.com/mattermost/platform/model/client.go b/vendor/github.com/mattermost/platform/model/client.go index 564aa2e4..ef890b59 100644 --- a/vendor/github.com/mattermost/platform/model/client.go +++ b/vendor/github.com/mattermost/platform/model/client.go @@ -18,6 +18,8 @@ import ( l4g "github.com/alecthomas/log4go" ) +var UsedApiV3 *int32 = new(int32) + const ( HEADER_REQUEST_ID = "X-Request-ID" HEADER_VERSION_ID = "X-Version-ID" @@ -37,7 +39,7 @@ const ( STATUS_FAIL = "FAIL" STATUS_REMOVE = "REMOVE" - CLIENT_DIR = "webapp/dist" + CLIENT_DIR = "client" API_URL_SUFFIX_V1 = "/api/v1" API_URL_SUFFIX_V3 = "/api/v3" @@ -144,7 +146,7 @@ func (c *Client) DoPost(url, data, contentType string) (*http.Response, *AppErro rq.Close = true if rp, err := c.HttpClient.Do(rq); err != nil { - return nil, NewLocAppError(url, "model.client.connecting.app_error", nil, err.Error()) + return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0) } else if rp.StatusCode >= 300 { defer closeBody(rp) return nil, AppErrorFromJson(rp.Body) @@ -162,7 +164,7 @@ func (c *Client) DoApiPost(url string, data string) (*http.Response, *AppError) } if rp, err := c.HttpClient.Do(rq); err != nil { - return nil, NewLocAppError(url, "model.client.connecting.app_error", nil, err.Error()) + return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0) } else if rp.StatusCode >= 300 { defer closeBody(rp) return nil, AppErrorFromJson(rp.Body) @@ -184,7 +186,7 @@ func (c *Client) DoApiGet(url string, data string, etag string) (*http.Response, } if rp, err := c.HttpClient.Do(rq); err != nil { - return nil, NewLocAppError(url, "model.client.connecting.app_error", nil, err.Error()) + return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0) } else if rp.StatusCode == 304 { return rp, nil } else if rp.StatusCode >= 300 { @@ -429,7 +431,7 @@ func (c *Client) UpdateTeam(team *Team) (*Result, *AppError) { } else { defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), - r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil + r.Header.Get(HEADER_ETAG_SERVER), TeamFromJson(r.Body)}, nil } } @@ -677,7 +679,7 @@ func (c *Client) login(m map[string]string) (*Result, *AppError) { sessionToken := getCookie(SESSION_COOKIE_TOKEN, r) if c.AuthToken != sessionToken.Value { - NewLocAppError("/users/login", "model.client.login.app_error", nil, "") + NewAppError("/users/login", "model.client.login.app_error", nil, "", 0) } defer closeBody(r) @@ -1054,7 +1056,7 @@ func (c *Client) DownloadComplianceReport(id string) (*Result, *AppError) { } if rp, err := c.HttpClient.Do(rq); err != nil { - return nil, NewLocAppError("/admin/download_compliance_report", "model.client.connecting.app_error", nil, err.Error()) + return nil, NewAppError("/admin/download_compliance_report", "model.client.connecting.app_error", nil, err.Error(), 0) } else if rp.StatusCode >= 300 { defer rp.Body.Close() return nil, AppErrorFromJson(rp.Body) @@ -1527,19 +1529,19 @@ func (c *Client) UploadPostAttachment(data []byte, channelId string, filename st writer := multipart.NewWriter(body) if part, err := writer.CreateFormFile("files", filename); err != nil { - return nil, NewLocAppError("UploadPostAttachment", "model.client.upload_post_attachment.file.app_error", nil, err.Error()) + return nil, NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), 0) } else if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { - return nil, NewLocAppError("UploadPostAttachment", "model.client.upload_post_attachment.file.app_error", nil, err.Error()) + return nil, NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), 0) } if part, err := writer.CreateFormField("channel_id"); err != nil { - return nil, NewLocAppError("UploadPostAttachment", "model.client.upload_post_attachment.channel_id.app_error", nil, err.Error()) + return nil, NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.channel_id.app_error", nil, err.Error(), 0) } else if _, err = io.Copy(part, strings.NewReader(channelId)); err != nil { - return nil, NewLocAppError("UploadPostAttachment", "model.client.upload_post_attachment.channel_id.app_error", nil, err.Error()) + return nil, NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.channel_id.app_error", nil, err.Error(), 0) } if err := writer.Close(); err != nil { - return nil, NewLocAppError("UploadPostAttachment", "model.client.upload_post_attachment.writer.app_error", nil, err.Error()) + return nil, NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.writer.app_error", nil, err.Error(), 0) } if result, err := c.uploadFile(c.ApiUrl+c.GetTeamRoute()+"/files/upload", body.Bytes(), writer.FormDataContentType()); err != nil { @@ -1559,7 +1561,7 @@ func (c *Client) uploadFile(url string, data []byte, contentType string) (*Resul } if rp, err := c.HttpClient.Do(rq); err != nil { - return nil, NewLocAppError(url, "model.client.connecting.app_error", nil, err.Error()) + return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0) } else if rp.StatusCode >= 300 { return nil, AppErrorFromJson(rp.Body) } else { @@ -2175,17 +2177,17 @@ func (c *Client) CreateEmoji(emoji *Emoji, image []byte, filename string) (*Emoj writer := multipart.NewWriter(body) if part, err := writer.CreateFormFile("image", filename); err != nil { - return nil, NewLocAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error()) + return nil, NewAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error(), 0) } else if _, err = io.Copy(part, bytes.NewBuffer(image)); err != nil { - return nil, NewLocAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error()) + return nil, NewAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error(), 0) } if err := writer.WriteField("emoji", emoji.ToJson()); err != nil { - return nil, NewLocAppError("CreateEmoji", "model.client.create_emoji.emoji.app_error", nil, err.Error()) + return nil, NewAppError("CreateEmoji", "model.client.create_emoji.emoji.app_error", nil, err.Error(), 0) } if err := writer.Close(); err != nil { - return nil, NewLocAppError("CreateEmoji", "model.client.create_emoji.writer.app_error", nil, err.Error()) + return nil, NewAppError("CreateEmoji", "model.client.create_emoji.writer.app_error", nil, err.Error(), 0) } rq, _ := http.NewRequest("POST", c.ApiUrl+c.GetEmojiRoute()+"/create", body) @@ -2197,7 +2199,7 @@ func (c *Client) CreateEmoji(emoji *Emoji, image []byte, filename string) (*Emoj } if r, err := c.HttpClient.Do(rq); err != nil { - return nil, NewLocAppError("CreateEmoji", "model.client.connecting.app_error", nil, err.Error()) + return nil, NewAppError("CreateEmoji", "model.client.connecting.app_error", nil, err.Error(), 0) } else if r.StatusCode >= 300 { return nil, AppErrorFromJson(r.Body) } else { @@ -2241,7 +2243,7 @@ func (c *Client) UploadCertificateFile(data []byte, contentType string) *AppErro } if rp, err := c.HttpClient.Do(rq); err != nil { - return NewLocAppError(url, "model.client.connecting.app_error", nil, err.Error()) + return NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0) } else if rp.StatusCode >= 300 { return AppErrorFromJson(rp.Body) } else { diff --git a/vendor/github.com/mattermost/platform/model/client4.go b/vendor/github.com/mattermost/platform/model/client4.go index 0f757853..e84a23e5 100644 --- a/vendor/github.com/mattermost/platform/model/client4.go +++ b/vendor/github.com/mattermost/platform/model/client4.go @@ -44,7 +44,7 @@ func BuildErrorResponse(r *http.Response, err *AppError) *Response { header = r.Header } else { statusCode = 0 - header = make(http.Header, 0) + header = make(http.Header) } return &Response{ @@ -178,6 +178,14 @@ func (c *Client4) GetFileRoute(fileId string) string { return fmt.Sprintf(c.GetFilesRoute()+"/%v", fileId) } +func (c *Client4) GetPluginsRoute() string { + return fmt.Sprintf("/plugins") +} + +func (c *Client4) GetPluginRoute(pluginId string) string { + return fmt.Sprintf(c.GetPluginsRoute()+"/%v", pluginId) +} + func (c *Client4) GetSystemRoute() string { return fmt.Sprintf("/system") } @@ -246,6 +254,10 @@ func (c *Client4) GetBrandRoute() string { return fmt.Sprintf("/brand") } +func (c *Client4) GetDataRetentionRoute() string { + return fmt.Sprintf("/data_retention") +} + func (c *Client4) GetElasticsearchRoute() string { return fmt.Sprintf("/elasticsearch") } @@ -319,7 +331,7 @@ func (c *Client4) DoApiRequest(method, url, data, etag string) (*http.Response, } if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil { - return nil, NewLocAppError(url, "model.client.connecting.app_error", nil, err.Error()) + return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0) } else if rp.StatusCode == 304 { return rp, nil } else if rp.StatusCode >= 300 { @@ -754,6 +766,16 @@ func (c *Client4) PatchUser(userId string, patch *UserPatch) (*User, *Response) } } +// UpdateUserAuth updates a user AuthData (uthData, authService and password) in the system. +func (c *Client4) UpdateUserAuth(userId string, userAuth *UserAuth) (*UserAuth, *Response) { + if r, err := c.DoApiPut(c.GetUserRoute(userId)+"/auth", userAuth.ToJson()); err != nil { + return nil, BuildErrorResponse(r, err) + } else { + defer closeBody(r) + return UserAuthFromJson(r.Body), BuildResponse(r) + } +} + // UpdateUserMfa activates multi-factor authentication for a user if activate // is true and a valid code is provided. If activate is false, then code is not // required and multi-factor authentication is disabled for the user. @@ -889,6 +911,16 @@ func (c *Client4) RevokeSession(userId, sessionId string) (bool, *Response) { } } +// RevokeAllSessions revokes all sessions for the provided user id string. +func (c *Client4) RevokeAllSessions(userId string) (bool, *Response) { + if r, err := c.DoApiPost(c.GetUserRoute(userId)+"/sessions/revoke/all", ""); err != nil { + return false, BuildErrorResponse(r, err) + } else { + defer closeBody(r) + return CheckStatusOK(r), BuildResponse(r) + } +} + // AttachDeviceId attaches a mobile device ID to the current session. func (c *Client4) AttachDeviceId(deviceId string) (bool, *Response) { requestBody := map[string]string{"device_id": deviceId} @@ -1043,6 +1075,32 @@ func (c *Client4) RevokeUserAccessToken(tokenId string) (bool, *Response) { } } +// DisableUserAccessToken will disable a user access token by id. Must have the +// 'revoke_user_access_token' permission and if disabling for another user, must have the +// 'edit_other_users' permission. +func (c *Client4) DisableUserAccessToken(tokenId string) (bool, *Response) { + requestBody := map[string]string{"token_id": tokenId} + if r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/disable", MapToJson(requestBody)); err != nil { + return false, BuildErrorResponse(r, err) + } else { + defer closeBody(r) + return CheckStatusOK(r), BuildResponse(r) + } +} + +// EnableUserAccessToken will enable a user access token by id. Must have the +// 'create_user_access_token' permission and if enabling for another user, must have the +// 'edit_other_users' permission. +func (c *Client4) EnableUserAccessToken(tokenId string) (bool, *Response) { + requestBody := map[string]string{"token_id": tokenId} + if r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/enable", MapToJson(requestBody)); err != nil { + return false, BuildErrorResponse(r, err) + } else { + defer closeBody(r) + return CheckStatusOK(r), BuildResponse(r) + } +} + // Team Section // CreateTeam creates a team in the system based on the provided team struct. @@ -1562,13 +1620,13 @@ func (c *Client4) GetChannelMembersForUser(userId, teamId, etag string) (*Channe } // ViewChannel performs a view action for a user. Synonymous with switching channels or marking channels as read by a user. -func (c *Client4) ViewChannel(userId string, view *ChannelView) (bool, *Response) { +func (c *Client4) ViewChannel(userId string, view *ChannelView) (*ChannelViewResponse, *Response) { url := fmt.Sprintf(c.GetChannelsRoute()+"/members/%v/view", userId) if r, err := c.DoApiPost(url, view.ToJson()); err != nil { - return false, BuildErrorResponse(r, err) + return nil, BuildErrorResponse(r, err) } else { defer closeBody(r) - return CheckStatusOK(r), BuildResponse(r) + return ChannelViewResponseFromJson(r.Body), BuildResponse(r) } } @@ -1615,6 +1673,17 @@ func (c *Client4) AddChannelMember(channelId, userId string) (*ChannelMember, *R } } +// AddChannelMemberWithRootId adds user to channel and return a channel member. Post add to channel message has the postRootId. +func (c *Client4) AddChannelMemberWithRootId(channelId, userId, postRootId string) (*ChannelMember, *Response) { + requestBody := map[string]string{"user_id": userId, "post_root_id": postRootId} + if r, err := c.DoApiPost(c.GetChannelMembersRoute(channelId)+"", MapToJson(requestBody)); err != nil { + return nil, BuildErrorResponse(r, err) + } else { + defer closeBody(r) + return ChannelMemberFromJson(r.Body), BuildResponse(r) + } +} + // RemoveUserFromChannel will delete the channel member object for a user, effectively removing the user from a channel. func (c *Client4) RemoveUserFromChannel(channelId, userId string) (bool, *Response) { if r, err := c.DoApiDelete(c.GetChannelMemberRoute(channelId, userId)); err != nil { @@ -1803,6 +1872,16 @@ func (c *Client4) SearchPosts(teamId string, terms string, isOrSearch bool) (*Po } } +// DoPostAction performs a post action. +func (c *Client4) DoPostAction(postId, actionId string) (bool, *Response) { + if r, err := c.DoApiPost(c.GetPostRoute(postId)+"/actions/"+actionId, ""); err != nil { + return false, BuildErrorResponse(r, err) + } else { + defer closeBody(r) + return CheckStatusOK(r), BuildResponse(r) + } +} + // File Section // UploadFile will upload a file to a channel, to be later attached to a post. @@ -2580,7 +2659,7 @@ func (c *Client4) UploadBrandImage(data []byte) (bool, *Response) { // GetLogs page of logs as a string array. func (c *Client4) GetLogs(page, perPage int) ([]string, *Response) { - query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) + query := fmt.Sprintf("?page=%v&logs_per_page=%v", page, perPage) if r, err := c.DoApiGet("/logs"+query, ""); err != nil { return nil, BuildErrorResponse(r, err) } else { @@ -2613,6 +2692,16 @@ func (c *Client4) CreateOAuthApp(app *OAuthApp) (*OAuthApp, *Response) { } } +// UpdateOAuthApp +func (c *Client4) UpdateOAuthApp(app *OAuthApp) (*OAuthApp, *Response) { + if r, err := c.DoApiPut(c.GetOAuthAppRoute(app.Id), app.ToJson()); err != nil { + return nil, BuildErrorResponse(r, err) + } else { + defer closeBody(r) + return OAuthAppFromJson(r.Body), BuildResponse(r) + } +} + // GetOAuthApps gets a page of registered OAuth 2.0 client applications with Mattermost acting as an OAuth 2.0 service provider. func (c *Client4) GetOAuthApps(page, perPage int) ([]*OAuthApp, *Response) { query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) @@ -2711,7 +2800,7 @@ func (c *Client4) TestElasticsearch() (bool, *Response) { // PurgeElasticsearchIndexes immediately deletes all Elasticsearch indexes. func (c *Client4) PurgeElasticsearchIndexes() (bool, *Response) { - if r, err := c.DoApiPost(c.GetElasticsearchRoute()+"/test", ""); err != nil { + if r, err := c.DoApiPost(c.GetElasticsearchRoute()+"/purge_indexes", ""); err != nil { return false, BuildErrorResponse(r, err) } else { defer closeBody(r) @@ -2719,6 +2808,18 @@ func (c *Client4) PurgeElasticsearchIndexes() (bool, *Response) { } } +// Data Retention Section + +// GetDataRetentionPolicy will get the current server data retention policy details. +func (c *Client4) GetDataRetentionPolicy() (*DataRetentionPolicy, *Response) { + if r, err := c.DoApiGet(c.GetDataRetentionRoute()+"/policy", ""); err != nil { + return nil, BuildErrorResponse(r, err) + } else { + defer closeBody(r) + return DataRetentionPolicyFromJson(r.Body), BuildResponse(r) + } +} + // Commands Section // CreateCommand will create a new command if the user have the right permissions. @@ -2762,9 +2863,28 @@ func (c *Client4) ListCommands(teamId string, customOnly bool) ([]*Command, *Res } } -// ExecuteCommand executes a given command. +// ExecuteCommand executes a given slash command. func (c *Client4) ExecuteCommand(channelId, command string) (*CommandResponse, *Response) { - commandArgs := &CommandArgs{ChannelId: channelId, Command: command} + commandArgs := &CommandArgs{ + ChannelId: channelId, + Command: command, + } + if r, err := c.DoApiPost(c.GetCommandsRoute()+"/execute", commandArgs.ToJson()); err != nil { + return nil, BuildErrorResponse(r, err) + } else { + defer closeBody(r) + return CommandResponseFromJson(r.Body), BuildResponse(r) + } +} + +// ExecuteCommand executes a given slash command against the specified team +// Use this when executing slash commands in a DM/GM, since the team id cannot be inferred in that case +func (c *Client4) ExecuteCommandWithTeam(channelId, teamId, command string) (*CommandResponse, *Response) { + commandArgs := &CommandArgs{ + ChannelId: channelId, + TeamId: teamId, + Command: command, + } if r, err := c.DoApiPost(c.GetCommandsRoute()+"/execute", commandArgs.ToJson()); err != nil { return nil, BuildErrorResponse(r, err) } else { @@ -2849,17 +2969,17 @@ func (c *Client4) CreateEmoji(emoji *Emoji, image []byte, filename string) (*Emo writer := multipart.NewWriter(body) if part, err := writer.CreateFormFile("image", filename); err != nil { - return nil, &Response{StatusCode: http.StatusForbidden, Error: NewLocAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error())} + return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error(), 0)} } else if _, err = io.Copy(part, bytes.NewBuffer(image)); err != nil { - return nil, &Response{StatusCode: http.StatusForbidden, Error: NewLocAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error())} + return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error(), 0)} } if err := writer.WriteField("emoji", emoji.ToJson()); err != nil { - return nil, &Response{StatusCode: http.StatusForbidden, Error: NewLocAppError("CreateEmoji", "model.client.create_emoji.emoji.app_error", nil, err.Error())} + return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.emoji.app_error", nil, err.Error(), 0)} } if err := writer.Close(); err != nil { - return nil, &Response{StatusCode: http.StatusForbidden, Error: NewLocAppError("CreateEmoji", "model.client.create_emoji.writer.app_error", nil, err.Error())} + return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.writer.app_error", nil, err.Error(), 0)} } return c.DoEmojiUploadFile(c.GetEmojisRoute(), body.Bytes(), writer.FormDataContentType()) @@ -3009,3 +3129,97 @@ func (c *Client4) CancelJob(jobId string) (bool, *Response) { return CheckStatusOK(r), BuildResponse(r) } } + +// Plugin Section + +// UploadPlugin takes an io.Reader stream pointing to the contents of a .tar.gz plugin. +// WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. +func (c *Client4) UploadPlugin(file io.Reader) (*Manifest, *Response) { + body := new(bytes.Buffer) + writer := multipart.NewWriter(body) + + if part, err := writer.CreateFormFile("plugin", "plugin.tar.gz"); err != nil { + return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)} + } else if _, err = io.Copy(part, file); err != nil { + return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)} + } + + if err := writer.Close(); err != nil { + return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)} + } + + rq, _ := http.NewRequest("POST", c.ApiUrl+c.GetPluginsRoute(), body) + rq.Header.Set("Content-Type", writer.FormDataContentType()) + rq.Close = true + + if len(c.AuthToken) > 0 { + rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) + } + + if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil { + return nil, BuildErrorResponse(rp, NewAppError("UploadPlugin", "model.client.connecting.app_error", nil, err.Error(), 0)) + } else { + defer closeBody(rp) + + if rp.StatusCode >= 300 { + return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) + } else { + return ManifestFromJson(rp.Body), BuildResponse(rp) + } + } +} + +// GetPlugins will return a list of plugin manifests for currently active plugins. +// WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. +func (c *Client4) GetPlugins() (*PluginsResponse, *Response) { + if r, err := c.DoApiGet(c.GetPluginsRoute(), ""); err != nil { + return nil, BuildErrorResponse(r, err) + } else { + defer closeBody(r) + return PluginsResponseFromJson(r.Body), BuildResponse(r) + } +} + +// RemovePlugin will deactivate and delete a plugin. +// WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. +func (c *Client4) RemovePlugin(id string) (bool, *Response) { + if r, err := c.DoApiDelete(c.GetPluginRoute(id)); err != nil { + return false, BuildErrorResponse(r, err) + } else { + defer closeBody(r) + return CheckStatusOK(r), BuildResponse(r) + } +} + +// GetWebappPlugins will return a list of plugins that the webapp should download. +// WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. +func (c *Client4) GetWebappPlugins() ([]*Manifest, *Response) { + if r, err := c.DoApiGet(c.GetPluginsRoute()+"/webapp", ""); err != nil { + return nil, BuildErrorResponse(r, err) + } else { + defer closeBody(r) + return ManifestListFromJson(r.Body), BuildResponse(r) + } +} + +// ActivatePlugin will activate an plugin installed. +// WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. +func (c *Client4) ActivatePlugin(id string) (bool, *Response) { + if r, err := c.DoApiPost(c.GetPluginRoute(id)+"/activate", ""); err != nil { + return false, BuildErrorResponse(r, err) + } else { + defer closeBody(r) + return CheckStatusOK(r), BuildResponse(r) + } +} + +// DeactivatePlugin will deactivate an active plugin. +// WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. +func (c *Client4) DeactivatePlugin(id string) (bool, *Response) { + if r, err := c.DoApiPost(c.GetPluginRoute(id)+"/deactivate", ""); err != nil { + return false, BuildErrorResponse(r, err) + } else { + defer closeBody(r) + return CheckStatusOK(r), BuildResponse(r) + } +} diff --git a/vendor/github.com/mattermost/platform/model/cluster_discovery.go b/vendor/github.com/mattermost/platform/model/cluster_discovery.go index 4b926965..89e5fc95 100644 --- a/vendor/github.com/mattermost/platform/model/cluster_discovery.go +++ b/vendor/github.com/mattermost/platform/model/cluster_discovery.go @@ -6,6 +6,7 @@ package model import ( "encoding/json" "io" + "net/http" "os" ) @@ -85,27 +86,27 @@ func FilterClusterDiscovery(vs []*ClusterDiscovery, f func(*ClusterDiscovery) bo func (o *ClusterDiscovery) IsValid() *AppError { if len(o.Id) != 26 { - return NewLocAppError("Channel.IsValid", "model.channel.is_valid.id.app_error", nil, "") + return NewAppError("Channel.IsValid", "model.channel.is_valid.id.app_error", nil, "", http.StatusBadRequest) } if len(o.ClusterName) == 0 { - return NewLocAppError("ClusterDiscovery.IsValid", "ClusterName must be set", nil, "") + return NewAppError("ClusterDiscovery.IsValid", "ClusterName must be set", nil, "", http.StatusBadRequest) } if len(o.Type) == 0 { - return NewLocAppError("ClusterDiscovery.IsValid", "Type must be set", nil, "") + return NewAppError("ClusterDiscovery.IsValid", "Type must be set", nil, "", http.StatusBadRequest) } if len(o.Hostname) == 0 { - return NewLocAppError("ClusterDiscovery.IsValid", "Hostname must be set", nil, "") + return NewAppError("ClusterDiscovery.IsValid", "Hostname must be set", nil, "", http.StatusBadRequest) } if o.CreateAt == 0 { - return NewLocAppError("ClusterDiscovery.IsValid", "CreateAt must be set", nil, "") + return NewAppError("ClusterDiscovery.IsValid", "CreateAt must be set", nil, "", http.StatusBadRequest) } if o.LastPingAt == 0 { - return NewLocAppError("ClusterDiscovery.IsValid", "LastPingAt must be set", nil, "") + return NewAppError("ClusterDiscovery.IsValid", "LastPingAt must be set", nil, "", http.StatusBadRequest) } return nil diff --git a/vendor/github.com/mattermost/platform/model/cluster_info.go b/vendor/github.com/mattermost/platform/model/cluster_info.go index 1e468044..c4f7e89a 100644 --- a/vendor/github.com/mattermost/platform/model/cluster_info.go +++ b/vendor/github.com/mattermost/platform/model/cluster_info.go @@ -10,6 +10,7 @@ import ( ) type ClusterInfo struct { + Id string `json:"id"` Version string `json:"version"` ConfigHash string `json:"config_hash"` IpAddress string `json:"ipaddress"` diff --git a/vendor/github.com/mattermost/platform/model/command.go b/vendor/github.com/mattermost/platform/model/command.go index 47378bbe..69da41c1 100644 --- a/vendor/github.com/mattermost/platform/model/command.go +++ b/vendor/github.com/mattermost/platform/model/command.go @@ -6,6 +6,7 @@ package model import ( "encoding/json" "io" + "net/http" "strings" ) @@ -79,51 +80,51 @@ func CommandListFromJson(data io.Reader) []*Command { func (o *Command) IsValid() *AppError { if len(o.Id) != 26 { - return NewLocAppError("Command.IsValid", "model.command.is_valid.id.app_error", nil, "") + return NewAppError("Command.IsValid", "model.command.is_valid.id.app_error", nil, "", http.StatusBadRequest) } if len(o.Token) != 26 { - return NewLocAppError("Command.IsValid", "model.command.is_valid.token.app_error", nil, "") + return NewAppError("Command.IsValid", "model.command.is_valid.token.app_error", nil, "", http.StatusBadRequest) } if o.CreateAt == 0 { - return NewLocAppError("Command.IsValid", "model.command.is_valid.create_at.app_error", nil, "") + return NewAppError("Command.IsValid", "model.command.is_valid.create_at.app_error", nil, "", http.StatusBadRequest) } if o.UpdateAt == 0 { - return NewLocAppError("Command.IsValid", "model.command.is_valid.update_at.app_error", nil, "") + return NewAppError("Command.IsValid", "model.command.is_valid.update_at.app_error", nil, "", http.StatusBadRequest) } if len(o.CreatorId) != 26 { - return NewLocAppError("Command.IsValid", "model.command.is_valid.user_id.app_error", nil, "") + return NewAppError("Command.IsValid", "model.command.is_valid.user_id.app_error", nil, "", http.StatusBadRequest) } if len(o.TeamId) != 26 { - return NewLocAppError("Command.IsValid", "model.command.is_valid.team_id.app_error", nil, "") + return NewAppError("Command.IsValid", "model.command.is_valid.team_id.app_error", nil, "", http.StatusBadRequest) } if len(o.Trigger) < MIN_TRIGGER_LENGTH || len(o.Trigger) > MAX_TRIGGER_LENGTH || strings.Index(o.Trigger, "/") == 0 || strings.Contains(o.Trigger, " ") { - return NewLocAppError("Command.IsValid", "model.command.is_valid.trigger.app_error", nil, "") + return NewAppError("Command.IsValid", "model.command.is_valid.trigger.app_error", nil, "", http.StatusBadRequest) } if len(o.URL) == 0 || len(o.URL) > 1024 { - return NewLocAppError("Command.IsValid", "model.command.is_valid.url.app_error", nil, "") + return NewAppError("Command.IsValid", "model.command.is_valid.url.app_error", nil, "", http.StatusBadRequest) } if !IsValidHttpUrl(o.URL) { - return NewLocAppError("Command.IsValid", "model.command.is_valid.url_http.app_error", nil, "") + return NewAppError("Command.IsValid", "model.command.is_valid.url_http.app_error", nil, "", http.StatusBadRequest) } if !(o.Method == COMMAND_METHOD_GET || o.Method == COMMAND_METHOD_POST) { - return NewLocAppError("Command.IsValid", "model.command.is_valid.method.app_error", nil, "") + return NewAppError("Command.IsValid", "model.command.is_valid.method.app_error", nil, "", http.StatusBadRequest) } if len(o.DisplayName) > 64 { - return NewLocAppError("Command.IsValid", "model.command.is_valid.display_name.app_error", nil, "") + return NewAppError("Command.IsValid", "model.command.is_valid.display_name.app_error", nil, "", http.StatusBadRequest) } if len(o.Description) > 128 { - return NewLocAppError("Command.IsValid", "model.command.is_valid.description.app_error", nil, "") + return NewAppError("Command.IsValid", "model.command.is_valid.description.app_error", nil, "", http.StatusBadRequest) } return nil diff --git a/vendor/github.com/mattermost/platform/model/command_response.go b/vendor/github.com/mattermost/platform/model/command_response.go index 27d39e17..a3a171ce 100644 --- a/vendor/github.com/mattermost/platform/model/command_response.go +++ b/vendor/github.com/mattermost/platform/model/command_response.go @@ -6,6 +6,8 @@ package model import ( "encoding/json" "io" + "io/ioutil" + "strings" ) const ( @@ -18,6 +20,8 @@ type CommandResponse struct { Text string `json:"text"` Username string `json:"username"` IconURL string `json:"icon_url"` + Type string `json:"type"` + Props StringInterface `json:"props"` GotoLocation string `json:"goto_location"` Attachments []*SlackAttachment `json:"attachments"` } @@ -31,6 +35,22 @@ func (o *CommandResponse) ToJson() string { } } +func CommandResponseFromHTTPBody(contentType string, body io.Reader) *CommandResponse { + if strings.TrimSpace(strings.Split(contentType, ";")[0]) == "application/json" { + return CommandResponseFromJson(body) + } + if b, err := ioutil.ReadAll(body); err == nil { + return CommandResponseFromPlainText(string(b)) + } + return nil +} + +func CommandResponseFromPlainText(text string) *CommandResponse { + return &CommandResponse{ + Text: text, + } +} + func CommandResponseFromJson(data io.Reader) *CommandResponse { decoder := json.NewDecoder(data) var o CommandResponse @@ -39,8 +59,7 @@ func CommandResponseFromJson(data io.Reader) *CommandResponse { return nil } - o.Text = ExpandAnnouncement(o.Text) - o.Attachments = ProcessSlackAttachments(o.Attachments) + o.Attachments = StringifySlackFieldValue(o.Attachments) return &o } diff --git a/vendor/github.com/mattermost/platform/model/command_webhook.go b/vendor/github.com/mattermost/platform/model/command_webhook.go new file mode 100644 index 00000000..0b00e00b --- /dev/null +++ b/vendor/github.com/mattermost/platform/model/command_webhook.go @@ -0,0 +1,65 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "net/http" +) + +type CommandWebhook struct { + Id string + CreateAt int64 + CommandId string + UserId string + ChannelId string + RootId string + ParentId string + UseCount int +} + +const ( + COMMAND_WEBHOOK_LIFETIME = 1000 * 60 * 30 +) + +func (o *CommandWebhook) PreSave() { + if o.Id == "" { + o.Id = NewId() + } + + if o.CreateAt == 0 { + o.CreateAt = GetMillis() + } +} + +func (o *CommandWebhook) IsValid() *AppError { + if len(o.Id) != 26 { + return NewAppError("CommandWebhook.IsValid", "model.command_hook.id.app_error", nil, "", http.StatusBadRequest) + } + + if o.CreateAt == 0 { + return NewAppError("CommandWebhook.IsValid", "model.command_hook.create_at.app_error", nil, "id="+o.Id, http.StatusBadRequest) + } + + if len(o.CommandId) != 26 { + return NewAppError("CommandWebhook.IsValid", "model.command_hook.command_id.app_error", nil, "", http.StatusBadRequest) + } + + if len(o.UserId) != 26 { + return NewAppError("CommandWebhook.IsValid", "model.command_hook.user_id.app_error", nil, "", http.StatusBadRequest) + } + + if len(o.ChannelId) != 26 { + return NewAppError("CommandWebhook.IsValid", "model.command_hook.channel_id.app_error", nil, "", http.StatusBadRequest) + } + + if len(o.RootId) != 0 && len(o.RootId) != 26 { + return NewAppError("CommandWebhook.IsValid", "model.command_hook.root_id.app_error", nil, "", http.StatusBadRequest) + } + + if len(o.ParentId) != 0 && len(o.ParentId) != 26 { + return NewAppError("CommandWebhook.IsValid", "model.command_hook.parent_id.app_error", nil, "", http.StatusBadRequest) + } + + return nil +} diff --git a/vendor/github.com/mattermost/platform/model/compliance.go b/vendor/github.com/mattermost/platform/model/compliance.go index 14f8f4a5..3134ddba 100644 --- a/vendor/github.com/mattermost/platform/model/compliance.go +++ b/vendor/github.com/mattermost/platform/model/compliance.go @@ -6,6 +6,7 @@ package model import ( "encoding/json" "io" + "net/http" "strings" ) @@ -75,27 +76,27 @@ func (me *Compliance) JobName() string { func (me *Compliance) IsValid() *AppError { if len(me.Id) != 26 { - return NewLocAppError("Compliance.IsValid", "model.compliance.is_valid.id.app_error", nil, "") + return NewAppError("Compliance.IsValid", "model.compliance.is_valid.id.app_error", nil, "", http.StatusBadRequest) } if me.CreateAt == 0 { - return NewLocAppError("Compliance.IsValid", "model.compliance.is_valid.create_at.app_error", nil, "") + return NewAppError("Compliance.IsValid", "model.compliance.is_valid.create_at.app_error", nil, "", http.StatusBadRequest) } if len(me.Desc) > 512 || len(me.Desc) == 0 { - return NewLocAppError("Compliance.IsValid", "model.compliance.is_valid.desc.app_error", nil, "") + return NewAppError("Compliance.IsValid", "model.compliance.is_valid.desc.app_error", nil, "", http.StatusBadRequest) } if me.StartAt == 0 { - return NewLocAppError("Compliance.IsValid", "model.compliance.is_valid.start_at.app_error", nil, "") + return NewAppError("Compliance.IsValid", "model.compliance.is_valid.start_at.app_error", nil, "", http.StatusBadRequest) } if me.EndAt == 0 { - return NewLocAppError("Compliance.IsValid", "model.compliance.is_valid.end_at.app_error", nil, "") + return NewAppError("Compliance.IsValid", "model.compliance.is_valid.end_at.app_error", nil, "", http.StatusBadRequest) } if me.EndAt <= me.StartAt { - return NewLocAppError("Compliance.IsValid", "model.compliance.is_valid.start_end_at.app_error", nil, "") + return NewAppError("Compliance.IsValid", "model.compliance.is_valid.start_end_at.app_error", nil, "", http.StatusBadRequest) } return nil diff --git a/vendor/github.com/mattermost/platform/model/config.go b/vendor/github.com/mattermost/platform/model/config.go index 1717d61a..fb34d1a0 100644 --- a/vendor/github.com/mattermost/platform/model/config.go +++ b/vendor/github.com/mattermost/platform/model/config.go @@ -8,6 +8,8 @@ import ( "io" "net/http" "net/url" + "strings" + "time" ) const ( @@ -22,6 +24,10 @@ const ( DATABASE_DRIVER_MYSQL = "mysql" DATABASE_DRIVER_POSTGRES = "postgres" + MINIO_ACCESS_KEY = "minioaccesskey" + MINIO_SECRET_KEY = "miniosecretkey" + MINIO_BUCKET = "mattermost-test" + PASSWORD_MAXIMUM_LENGTH = 64 PASSWORD_MINIMUM_LENGTH = 5 @@ -71,17 +77,22 @@ const ( SITENAME_MAX_LENGTH = 30 - SERVICE_SETTINGS_DEFAULT_SITE_URL = "" - SERVICE_SETTINGS_DEFAULT_TLS_CERT_FILE = "" - SERVICE_SETTINGS_DEFAULT_TLS_KEY_FILE = "" - SERVICE_SETTINGS_DEFAULT_READ_TIMEOUT = 300 - SERVICE_SETTINGS_DEFAULT_WRITE_TIMEOUT = 300 - SERVICE_SETTINGS_DEFAULT_ALLOW_CORS_FROM = "" + SERVICE_SETTINGS_DEFAULT_SITE_URL = "" + SERVICE_SETTINGS_DEFAULT_TLS_CERT_FILE = "" + SERVICE_SETTINGS_DEFAULT_TLS_KEY_FILE = "" + SERVICE_SETTINGS_DEFAULT_READ_TIMEOUT = 300 + SERVICE_SETTINGS_DEFAULT_WRITE_TIMEOUT = 300 + SERVICE_SETTINGS_DEFAULT_MAX_LOGIN_ATTEMPTS = 10 + SERVICE_SETTINGS_DEFAULT_ALLOW_CORS_FROM = "" + SERVICE_SETTINGS_DEFAULT_LISTEN_AND_ADDRESS = ":8065" + TEAM_SETTINGS_DEFAULT_MAX_USERS_PER_TEAM = 50 TEAM_SETTINGS_DEFAULT_CUSTOM_BRAND_TEXT = "" TEAM_SETTINGS_DEFAULT_CUSTOM_DESCRIPTION_TEXT = "" TEAM_SETTINGS_DEFAULT_USER_STATUS_AWAY_TIMEOUT = 300 + SQL_SETTINGS_DEFAULT_DATA_SOURCE = "mmuser:mostest@tcp(dockerhost:3306)/mattermost_test?charset=utf8mb4,utf8&readTimeout=30s&writeTimeout=30s" + EMAIL_SETTINGS_DEFAULT_FEEDBACK_ORGANIZATION = "" SUPPORT_SETTINGS_DEFAULT_TERMS_OF_SERVICE_LINK = "https://about.mattermost.com/default-terms/" @@ -123,17 +134,32 @@ const ( ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_COLOR = "#f2a93b" ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_TEXT_COLOR = "#333333" - ELASTICSEARCH_SETTINGS_DEFAULT_CONNECTION_URL = "" - ELASTICSEARCH_SETTINGS_DEFAULT_USERNAME = "" - ELASTICSEARCH_SETTINGS_DEFAULT_PASSWORD = "" - ELASTICSEARCH_SETTINGS_DEFAULT_POST_INDEX_REPLICAS = 1 - ELASTICSEARCH_SETTINGS_DEFAULT_POST_INDEX_SHARDS = 1 + TEAM_SETTINGS_DEFAULT_TEAM_TEXT = "default" + + ELASTICSEARCH_SETTINGS_DEFAULT_CONNECTION_URL = "" + ELASTICSEARCH_SETTINGS_DEFAULT_USERNAME = "" + ELASTICSEARCH_SETTINGS_DEFAULT_PASSWORD = "" + ELASTICSEARCH_SETTINGS_DEFAULT_POST_INDEX_REPLICAS = 1 + ELASTICSEARCH_SETTINGS_DEFAULT_POST_INDEX_SHARDS = 1 + ELASTICSEARCH_SETTINGS_DEFAULT_AGGREGATE_POSTS_AFTER_DAYS = 365 + ELASTICSEARCH_SETTINGS_DEFAULT_POSTS_AGGREGATOR_JOB_START_TIME = "03:00" + ELASTICSEARCH_SETTINGS_DEFAULT_INDEX_PREFIX = "" + ELASTICSEARCH_SETTINGS_DEFAULT_LIVE_INDEXING_BATCH_SIZE = 1 + ELASTICSEARCH_SETTINGS_DEFAULT_BULK_INDEXING_TIME_WINDOW_SECONDS = 3600 + ELASTICSEARCH_SETTINGS_DEFAULT_REQUEST_TIMEOUT_SECONDS = 30 + + DATA_RETENTION_SETTINGS_DEFAULT_MESSAGE_RETENTION_DAYS = 365 + DATA_RETENTION_SETTINGS_DEFAULT_FILE_RETENTION_DAYS = 365 + DATA_RETENTION_SETTINGS_DEFAULT_DELETION_JOB_START_TIME = "02:00" + + PLUGIN_SETTINGS_DEFAULT_DIRECTORY = "./plugins" + PLUGIN_SETTINGS_DEFAULT_CLIENT_DIRECTORY = "./client/plugins" ) type ServiceSettings struct { SiteURL *string LicenseFileLocation *string - ListenAddress string + ListenAddress *string ConnectionSecurity *string TLSCertFile *string TLSKeyFile *string @@ -142,7 +168,7 @@ type ServiceSettings struct { Forward80To443 *bool ReadTimeout *int WriteTimeout *int - MaximumLoginAttempts int + MaximumLoginAttempts *int GoroutineHealthThreshold *int GoogleDeveloperKey string EnableOAuthServiceProvider bool @@ -158,6 +184,7 @@ type ServiceSettings struct { EnableDeveloper *bool EnableSecurityFixAlert *bool EnableInsecureOutgoingConnections *bool + AllowedUntrustedInternalConnections *string EnableMultifactorAuthentication *bool EnforceMultifactorAuthentication *bool EnableUserAccessTokens *bool @@ -166,6 +193,7 @@ type ServiceSettings struct { SessionLengthMobileInDays *int SessionLengthSSOInDays *int SessionCacheInMinutes *int + SessionIdleTimeoutInMinutes *int WebsocketSecurePort *int WebsocketPort *int WebserverMode *string @@ -180,7 +208,211 @@ type ServiceSettings struct { EnableUserTypingMessages *bool EnableChannelViewedMessages *bool EnableUserStatuses *bool + ExperimentalEnableAuthenticationTransfer *bool ClusterLogTimeoutMilliseconds *int + CloseUnusedDirectMessages *bool + EnablePreviewFeatures *bool + EnableTutorial *bool +} + +func (s *ServiceSettings) SetDefaults() { + if s.SiteURL == nil { + s.SiteURL = NewString(SERVICE_SETTINGS_DEFAULT_SITE_URL) + } + + if s.LicenseFileLocation == nil { + s.LicenseFileLocation = NewString("") + } + + if s.ListenAddress == nil { + s.ListenAddress = NewString(SERVICE_SETTINGS_DEFAULT_LISTEN_AND_ADDRESS) + } + + if s.EnableAPIv3 == nil { + s.EnableAPIv3 = NewBool(true) + } + + if s.EnableLinkPreviews == nil { + s.EnableLinkPreviews = NewBool(false) + } + + if s.EnableDeveloper == nil { + s.EnableDeveloper = NewBool(false) + } + + if s.EnableSecurityFixAlert == nil { + s.EnableSecurityFixAlert = NewBool(true) + } + + if s.EnableInsecureOutgoingConnections == nil { + s.EnableInsecureOutgoingConnections = NewBool(false) + } + + if s.AllowedUntrustedInternalConnections == nil { + s.AllowedUntrustedInternalConnections = new(string) + } + + if s.EnableMultifactorAuthentication == nil { + s.EnableMultifactorAuthentication = NewBool(false) + } + + if s.EnforceMultifactorAuthentication == nil { + s.EnforceMultifactorAuthentication = NewBool(false) + } + + if s.EnableUserAccessTokens == nil { + s.EnableUserAccessTokens = NewBool(false) + } + + if s.GoroutineHealthThreshold == nil { + s.GoroutineHealthThreshold = NewInt(-1) + } + + if s.ConnectionSecurity == nil { + s.ConnectionSecurity = NewString("") + } + + if s.TLSKeyFile == nil { + s.TLSKeyFile = NewString(SERVICE_SETTINGS_DEFAULT_TLS_KEY_FILE) + } + + if s.TLSCertFile == nil { + s.TLSCertFile = NewString(SERVICE_SETTINGS_DEFAULT_TLS_CERT_FILE) + } + + if s.UseLetsEncrypt == nil { + s.UseLetsEncrypt = NewBool(false) + } + + if s.LetsEncryptCertificateCacheFile == nil { + s.LetsEncryptCertificateCacheFile = NewString("./config/letsencrypt.cache") + } + + if s.ReadTimeout == nil { + s.ReadTimeout = NewInt(SERVICE_SETTINGS_DEFAULT_READ_TIMEOUT) + } + + if s.WriteTimeout == nil { + s.WriteTimeout = NewInt(SERVICE_SETTINGS_DEFAULT_WRITE_TIMEOUT) + } + + if s.MaximumLoginAttempts == nil { + s.MaximumLoginAttempts = NewInt(SERVICE_SETTINGS_DEFAULT_MAX_LOGIN_ATTEMPTS) + } + + if s.Forward80To443 == nil { + s.Forward80To443 = NewBool(false) + } + + if s.TimeBetweenUserTypingUpdatesMilliseconds == nil { + s.TimeBetweenUserTypingUpdatesMilliseconds = NewInt64(5000) + } + + if s.EnablePostSearch == nil { + s.EnablePostSearch = NewBool(true) + } + + if s.EnableUserTypingMessages == nil { + s.EnableUserTypingMessages = NewBool(true) + } + + if s.EnableChannelViewedMessages == nil { + s.EnableChannelViewedMessages = NewBool(true) + } + + if s.EnableUserStatuses == nil { + s.EnableUserStatuses = NewBool(true) + } + + if s.ClusterLogTimeoutMilliseconds == nil { + s.ClusterLogTimeoutMilliseconds = NewInt(2000) + } + + if s.CloseUnusedDirectMessages == nil { + s.CloseUnusedDirectMessages = NewBool(false) + } + + if s.EnableTutorial == nil { + s.EnableTutorial = NewBool(true) + } + + if s.SessionLengthWebInDays == nil { + s.SessionLengthWebInDays = NewInt(30) + } + + if s.SessionLengthMobileInDays == nil { + s.SessionLengthMobileInDays = NewInt(30) + } + + if s.SessionLengthSSOInDays == nil { + s.SessionLengthSSOInDays = NewInt(30) + } + + if s.SessionCacheInMinutes == nil { + s.SessionCacheInMinutes = NewInt(10) + } + + if s.SessionIdleTimeoutInMinutes == nil { + s.SessionIdleTimeoutInMinutes = NewInt(0) + } + + if s.EnableCommands == nil { + s.EnableCommands = NewBool(false) + } + + if s.EnableOnlyAdminIntegrations == nil { + s.EnableOnlyAdminIntegrations = NewBool(true) + } + + if s.WebsocketPort == nil { + s.WebsocketPort = NewInt(80) + } + + if s.WebsocketSecurePort == nil { + s.WebsocketSecurePort = NewInt(443) + } + + if s.AllowCorsFrom == nil { + s.AllowCorsFrom = NewString(SERVICE_SETTINGS_DEFAULT_ALLOW_CORS_FROM) + } + + if s.WebserverMode == nil { + s.WebserverMode = NewString("gzip") + } else if *s.WebserverMode == "regular" { + *s.WebserverMode = "gzip" + } + + if s.EnableCustomEmoji == nil { + s.EnableCustomEmoji = NewBool(false) + } + + if s.EnableEmojiPicker == nil { + s.EnableEmojiPicker = NewBool(true) + } + + if s.RestrictCustomEmojiCreation == nil { + s.RestrictCustomEmojiCreation = NewString(RESTRICT_EMOJI_CREATION_ALL) + } + + if s.RestrictPostDelete == nil { + s.RestrictPostDelete = NewString(PERMISSIONS_DELETE_POST_ALL) + } + + if s.AllowEditPost == nil { + s.AllowEditPost = NewString(ALLOW_EDIT_POST_ALWAYS) + } + + if s.ExperimentalEnableAuthenticationTransfer == nil { + s.ExperimentalEnableAuthenticationTransfer = NewBool(true) + } + + if s.PostEditTimeLimit == nil { + s.PostEditTimeLimit = NewInt(300) + } + + if s.EnablePreviewFeatures == nil { + s.EnablePreviewFeatures = NewBool(true) + } } type ClusterSettings struct { @@ -194,16 +426,70 @@ type ClusterSettings struct { StreamingPort *int } +func (s *ClusterSettings) SetDefaults() { + if s.Enable == nil { + s.Enable = NewBool(false) + } + + if s.ClusterName == nil { + s.ClusterName = NewString("") + } + + if s.OverrideHostname == nil { + s.OverrideHostname = NewString("") + } + + if s.UseIpAddress == nil { + s.UseIpAddress = NewBool(true) + } + + if s.UseExperimentalGossip == nil { + s.UseExperimentalGossip = NewBool(false) + } + + if s.ReadOnlyConfig == nil { + s.ReadOnlyConfig = NewBool(true) + } + + if s.GossipPort == nil { + s.GossipPort = NewInt(8074) + } + + if s.StreamingPort == nil { + s.StreamingPort = NewInt(8075) + } +} + type MetricsSettings struct { Enable *bool BlockProfileRate *int ListenAddress *string } +func (s *MetricsSettings) SetDefaults() { + if s.ListenAddress == nil { + s.ListenAddress = NewString(":8067") + } + + if s.Enable == nil { + s.Enable = NewBool(false) + } + + if s.BlockProfileRate == nil { + s.BlockProfileRate = NewInt(0) + } +} + type AnalyticsSettings struct { MaxUsersForStatistics *int } +func (s *AnalyticsSettings) SetDefaults() { + if s.MaxUsersForStatistics == nil { + s.MaxUsersForStatistics = NewInt(ANALYTICS_SETTINGS_DEFAULT_MAX_USERS_FOR_STATISTICS) + } +} + type SSOSettings struct { Enable bool Secret string @@ -215,17 +501,43 @@ type SSOSettings struct { } type SqlSettings struct { - DriverName string - DataSource string + DriverName *string + DataSource *string DataSourceReplicas []string DataSourceSearchReplicas []string - MaxIdleConns int - MaxOpenConns int + MaxIdleConns *int + MaxOpenConns *int Trace bool AtRestEncryptKey string QueryTimeout *int } +func (s *SqlSettings) SetDefaults() { + if s.DriverName == nil { + s.DriverName = NewString(DATABASE_DRIVER_MYSQL) + } + + if s.DataSource == nil { + s.DataSource = NewString(SQL_SETTINGS_DEFAULT_DATA_SOURCE) + } + + if len(s.AtRestEncryptKey) == 0 { + s.AtRestEncryptKey = NewRandomString(32) + } + + if s.MaxIdleConns == nil { + s.MaxIdleConns = NewInt(20) + } + + if s.MaxOpenConns == nil { + s.MaxOpenConns = NewInt(300) + } + + if s.QueryTimeout == nil { + s.QueryTimeout = NewInt(30) + } +} + type LogSettings struct { EnableConsole bool ConsoleLevel string @@ -237,6 +549,12 @@ type LogSettings struct { EnableDiagnostics *bool } +func (s *LogSettings) SetDefaults() { + if s.EnableDiagnostics == nil { + s.EnableDiagnostics = NewBool(true) + } +} + type PasswordSettings struct { MinimumLength *int Lowercase *bool @@ -245,12 +563,34 @@ type PasswordSettings struct { Symbol *bool } +func (s *PasswordSettings) SetDefaults() { + if s.MinimumLength == nil { + s.MinimumLength = NewInt(PASSWORD_MINIMUM_LENGTH) + } + + if s.Lowercase == nil { + s.Lowercase = NewBool(false) + } + + if s.Number == nil { + s.Number = NewBool(false) + } + + if s.Uppercase == nil { + s.Uppercase = NewBool(false) + } + + if s.Symbol == nil { + s.Symbol = NewBool(false) + } +} + type FileSettings struct { EnableFileAttachments *bool EnableMobileUpload *bool EnableMobileDownload *bool MaxFileSize *int64 - DriverName string + DriverName *string Directory string EnablePublicLink bool PublicLinkSalt *string @@ -263,6 +603,64 @@ type FileSettings struct { AmazonS3SSL *bool AmazonS3SignV2 *bool AmazonS3SSE *bool + AmazonS3Trace *bool +} + +func (s *FileSettings) SetDefaults() { + if s.DriverName == nil { + s.DriverName = NewString(IMAGE_DRIVER_LOCAL) + } + + if s.AmazonS3Endpoint == "" { + // Defaults to "s3.amazonaws.com" + s.AmazonS3Endpoint = "s3.amazonaws.com" + } + + if s.AmazonS3SSL == nil { + s.AmazonS3SSL = NewBool(true) // Secure by default. + } + + if s.AmazonS3SignV2 == nil { + s.AmazonS3SignV2 = new(bool) + // Signature v2 is not enabled by default. + } + + if s.AmazonS3SSE == nil { + s.AmazonS3SSE = NewBool(false) // Not Encrypted by default. + } + + if s.AmazonS3Trace == nil { + s.AmazonS3Trace = NewBool(false) + } + + if s.EnableFileAttachments == nil { + s.EnableFileAttachments = NewBool(true) + } + + if s.EnableMobileUpload == nil { + s.EnableMobileUpload = NewBool(true) + } + + if s.EnableMobileDownload == nil { + s.EnableMobileDownload = NewBool(true) + } + + if s.MaxFileSize == nil { + s.MaxFileSize = NewInt64(52428800) // 50 MB + } + + if s.PublicLinkSalt == nil || len(*s.PublicLinkSalt) == 0 { + s.PublicLinkSalt = NewString(NewRandomString(32)) + } + + if s.InitialFont == "" { + // Defaults to "luximbi.ttf" + s.InitialFont = "luximbi.ttf" + } + + if s.Directory == "" { + s.Directory = "./data/" + } } type EmailSettings struct { @@ -270,6 +668,7 @@ type EmailSettings struct { EnableSignInWithEmail *bool EnableSignInWithUsername *bool SendEmailNotifications bool + UseChannelInEmailNotifications *bool RequireEmailVerification bool FeedbackName string FeedbackEmail string @@ -289,1412 +688,1441 @@ type EmailSettings struct { EmailBatchingInterval *int SkipServerCertificateVerification *bool EmailNotificationContentsType *string + LoginButtonColor *string + LoginButtonBorderColor *string + LoginButtonTextColor *string } -type RateLimitSettings struct { - Enable *bool - PerSec int - MaxBurst *int - MemoryStoreSize int - VaryByRemoteAddr bool - VaryByHeader string -} - -type PrivacySettings struct { - ShowEmailAddress bool - ShowFullName bool -} - -type SupportSettings struct { - TermsOfServiceLink *string - PrivacyPolicyLink *string - AboutLink *string - HelpLink *string - ReportAProblemLink *string - AdministratorsGuideLink *string - TroubleshootingForumLink *string - CommercialSupportLink *string - SupportEmail *string -} - -type AnnouncementSettings struct { - EnableBanner *bool - BannerText *string - BannerColor *string - BannerTextColor *string - AllowBannerDismissal *bool -} - -type TeamSettings struct { - SiteName string - MaxUsersPerTeam int - EnableTeamCreation bool - EnableUserCreation bool - EnableOpenServer *bool - RestrictCreationToDomains string - EnableCustomBrand *bool - CustomBrandText *string - CustomDescriptionText *string - RestrictDirectMessage *string - RestrictTeamInvite *string - RestrictPublicChannelManagement *string - RestrictPrivateChannelManagement *string - RestrictPublicChannelCreation *string - RestrictPrivateChannelCreation *string - RestrictPublicChannelDeletion *string - RestrictPrivateChannelDeletion *string - RestrictPrivateChannelManageMembers *string - UserStatusAwayTimeout *int64 - MaxChannelsPerTeam *int64 - MaxNotificationsPerChannel *int64 - TeammateNameDisplay *string -} - -type LdapSettings struct { - // Basic - Enable *bool - LdapServer *string - LdapPort *int - ConnectionSecurity *string - BaseDN *string - BindUsername *string - BindPassword *string - - // Filtering - UserFilter *string - - // User Mapping - FirstNameAttribute *string - LastNameAttribute *string - EmailAttribute *string - UsernameAttribute *string - NicknameAttribute *string - IdAttribute *string - PositionAttribute *string - - // Syncronization - SyncIntervalMinutes *int - - // Advanced - SkipCertificateVerification *bool - QueryTimeout *int - MaxPageSize *int - - // Customization - LoginFieldName *string -} - -type ComplianceSettings struct { - Enable *bool - Directory *string - EnableDaily *bool -} +func (s *EmailSettings) SetDefaults() { + if len(s.InviteSalt) == 0 { + s.InviteSalt = NewRandomString(32) + } -type LocalizationSettings struct { - DefaultServerLocale *string - DefaultClientLocale *string - AvailableLocales *string -} + if s.EnableSignInWithEmail == nil { + s.EnableSignInWithEmail = NewBool(s.EnableSignUpWithEmail) + } -type SamlSettings struct { - // Basic - Enable *bool - Verify *bool - Encrypt *bool + if s.EnableSignInWithUsername == nil { + s.EnableSignInWithUsername = NewBool(false) + } - IdpUrl *string - IdpDescriptorUrl *string - AssertionConsumerServiceURL *string + if s.UseChannelInEmailNotifications == nil { + s.UseChannelInEmailNotifications = NewBool(false) + } - IdpCertificateFile *string - PublicCertificateFile *string - PrivateKeyFile *string + if s.SendPushNotifications == nil { + s.SendPushNotifications = NewBool(false) + } - // User Mapping - FirstNameAttribute *string - LastNameAttribute *string - EmailAttribute *string - UsernameAttribute *string - NicknameAttribute *string - LocaleAttribute *string - PositionAttribute *string + if s.PushNotificationServer == nil { + s.PushNotificationServer = NewString("") + } - LoginButtonText *string -} + if s.PushNotificationContents == nil { + s.PushNotificationContents = NewString(GENERIC_NOTIFICATION) + } -type NativeAppSettings struct { - AppDownloadLink *string - AndroidAppDownloadLink *string - IosAppDownloadLink *string -} + if s.FeedbackOrganization == nil { + s.FeedbackOrganization = NewString(EMAIL_SETTINGS_DEFAULT_FEEDBACK_ORGANIZATION) + } -type WebrtcSettings struct { - Enable *bool - GatewayWebsocketUrl *string - GatewayAdminUrl *string - GatewayAdminSecret *string - StunURI *string - TurnURI *string - TurnUsername *string - TurnSharedKey *string -} + if s.EnableEmailBatching == nil { + s.EnableEmailBatching = NewBool(false) + } -type ElasticsearchSettings struct { - ConnectionUrl *string - Username *string - Password *string - EnableIndexing *bool - EnableSearching *bool - Sniff *bool - PostIndexReplicas *int - PostIndexShards *int -} + if s.EmailBatchingBufferSize == nil { + s.EmailBatchingBufferSize = NewInt(EMAIL_BATCHING_BUFFER_SIZE) + } -type DataRetentionSettings struct { - Enable *bool -} + if s.EmailBatchingInterval == nil { + s.EmailBatchingInterval = NewInt(EMAIL_BATCHING_INTERVAL) + } -type JobSettings struct { - RunJobs *bool - RunScheduler *bool -} + if s.EnableSMTPAuth == nil { + s.EnableSMTPAuth = new(bool) + if s.ConnectionSecurity == CONN_SECURITY_NONE { + *s.EnableSMTPAuth = false + } else { + *s.EnableSMTPAuth = true + } + } -type PluginSettings struct { - Plugins map[string]interface{} -} + if s.ConnectionSecurity == CONN_SECURITY_PLAIN { + s.ConnectionSecurity = CONN_SECURITY_NONE + } -type Config struct { - ServiceSettings ServiceSettings - TeamSettings TeamSettings - SqlSettings SqlSettings - LogSettings LogSettings - PasswordSettings PasswordSettings - FileSettings FileSettings - EmailSettings EmailSettings - RateLimitSettings RateLimitSettings - PrivacySettings PrivacySettings - SupportSettings SupportSettings - AnnouncementSettings AnnouncementSettings - GitLabSettings SSOSettings - GoogleSettings SSOSettings - Office365Settings SSOSettings - LdapSettings LdapSettings - ComplianceSettings ComplianceSettings - LocalizationSettings LocalizationSettings - SamlSettings SamlSettings - NativeAppSettings NativeAppSettings - ClusterSettings ClusterSettings - MetricsSettings MetricsSettings - AnalyticsSettings AnalyticsSettings - WebrtcSettings WebrtcSettings - ElasticsearchSettings ElasticsearchSettings - DataRetentionSettings DataRetentionSettings - JobSettings JobSettings - PluginSettings PluginSettings -} + if s.SkipServerCertificateVerification == nil { + s.SkipServerCertificateVerification = NewBool(false) + } -func (o *Config) ToJson() string { - b, err := json.Marshal(o) - if err != nil { - return "" - } else { - return string(b) + if s.EmailNotificationContentsType == nil { + s.EmailNotificationContentsType = NewString(EMAIL_NOTIFICATION_CONTENTS_FULL) } -} -func (o *Config) GetSSOService(service string) *SSOSettings { - switch service { - case SERVICE_GITLAB: - return &o.GitLabSettings - case SERVICE_GOOGLE: - return &o.GoogleSettings - case SERVICE_OFFICE365: - return &o.Office365Settings + if s.LoginButtonColor == nil { + s.LoginButtonColor = NewString("#0000") } - return nil -} + if s.LoginButtonBorderColor == nil { + s.LoginButtonBorderColor = NewString("#2389D7") + } -func ConfigFromJson(data io.Reader) *Config { - decoder := json.NewDecoder(data) - var o Config - err := decoder.Decode(&o) - if err == nil { - return &o - } else { - return nil + if s.LoginButtonTextColor == nil { + s.LoginButtonTextColor = NewString("#2389D7") } } -func (o *Config) SetDefaults() { +type RateLimitSettings struct { + Enable *bool + PerSec *int + MaxBurst *int + MemoryStoreSize *int + VaryByRemoteAddr bool + VaryByHeader string +} - if len(o.SqlSettings.AtRestEncryptKey) == 0 { - o.SqlSettings.AtRestEncryptKey = NewRandomString(32) +func (s *RateLimitSettings) SetDefaults() { + if s.Enable == nil { + s.Enable = NewBool(false) } - if o.SqlSettings.QueryTimeout == nil { - o.SqlSettings.QueryTimeout = new(int) - *o.SqlSettings.QueryTimeout = 30 + if s.PerSec == nil { + s.PerSec = NewInt(10) } - if o.FileSettings.AmazonS3Endpoint == "" { - // Defaults to "s3.amazonaws.com" - o.FileSettings.AmazonS3Endpoint = "s3.amazonaws.com" + if s.MaxBurst == nil { + s.MaxBurst = NewInt(100) } - if o.FileSettings.AmazonS3SSL == nil { - o.FileSettings.AmazonS3SSL = new(bool) - *o.FileSettings.AmazonS3SSL = true // Secure by default. + if s.MemoryStoreSize == nil { + s.MemoryStoreSize = NewInt(10000) } +} - if o.FileSettings.AmazonS3SignV2 == nil { - o.FileSettings.AmazonS3SignV2 = new(bool) - // Signature v2 is not enabled by default. - } +type PrivacySettings struct { + ShowEmailAddress bool + ShowFullName bool +} - if o.FileSettings.AmazonS3SSE == nil { - o.FileSettings.AmazonS3SSE = new(bool) - *o.FileSettings.AmazonS3SSE = false // Not Encrypted by default. - } +type SupportSettings struct { + TermsOfServiceLink *string + PrivacyPolicyLink *string + AboutLink *string + HelpLink *string + ReportAProblemLink *string + SupportEmail *string +} - if o.FileSettings.EnableFileAttachments == nil { - o.FileSettings.EnableFileAttachments = new(bool) - *o.FileSettings.EnableFileAttachments = true +func (s *SupportSettings) SetDefaults() { + if !IsSafeLink(s.TermsOfServiceLink) { + *s.TermsOfServiceLink = SUPPORT_SETTINGS_DEFAULT_TERMS_OF_SERVICE_LINK } - if o.FileSettings.EnableMobileUpload == nil { - o.FileSettings.EnableMobileUpload = new(bool) - *o.FileSettings.EnableMobileUpload = true + if s.TermsOfServiceLink == nil { + s.TermsOfServiceLink = NewString(SUPPORT_SETTINGS_DEFAULT_TERMS_OF_SERVICE_LINK) } - if o.FileSettings.EnableMobileDownload == nil { - o.FileSettings.EnableMobileDownload = new(bool) - *o.FileSettings.EnableMobileDownload = true + if !IsSafeLink(s.PrivacyPolicyLink) { + *s.PrivacyPolicyLink = "" } - if o.FileSettings.MaxFileSize == nil { - o.FileSettings.MaxFileSize = new(int64) - *o.FileSettings.MaxFileSize = 52428800 // 50 MB + if s.PrivacyPolicyLink == nil { + s.PrivacyPolicyLink = NewString(SUPPORT_SETTINGS_DEFAULT_PRIVACY_POLICY_LINK) } - if o.FileSettings.PublicLinkSalt == nil || len(*o.FileSettings.PublicLinkSalt) == 0 { - o.FileSettings.PublicLinkSalt = new(string) - *o.FileSettings.PublicLinkSalt = NewRandomString(32) + if !IsSafeLink(s.AboutLink) { + *s.AboutLink = "" } - if o.FileSettings.InitialFont == "" { - // Defaults to "luximbi.ttf" - o.FileSettings.InitialFont = "luximbi.ttf" + if s.AboutLink == nil { + s.AboutLink = NewString(SUPPORT_SETTINGS_DEFAULT_ABOUT_LINK) } - if o.FileSettings.Directory == "" { - o.FileSettings.Directory = "./data/" + if !IsSafeLink(s.HelpLink) { + *s.HelpLink = "" } - if len(o.EmailSettings.InviteSalt) == 0 { - o.EmailSettings.InviteSalt = NewRandomString(32) + if s.HelpLink == nil { + s.HelpLink = NewString(SUPPORT_SETTINGS_DEFAULT_HELP_LINK) } - if o.ServiceSettings.SiteURL == nil { - o.ServiceSettings.SiteURL = new(string) - *o.ServiceSettings.SiteURL = SERVICE_SETTINGS_DEFAULT_SITE_URL + if !IsSafeLink(s.ReportAProblemLink) { + *s.ReportAProblemLink = "" } - if o.ServiceSettings.LicenseFileLocation == nil { - o.ServiceSettings.LicenseFileLocation = new(string) + if s.ReportAProblemLink == nil { + s.ReportAProblemLink = NewString(SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK) } - if o.ServiceSettings.EnableAPIv3 == nil { - o.ServiceSettings.EnableAPIv3 = new(bool) - *o.ServiceSettings.EnableAPIv3 = true + if s.SupportEmail == nil { + s.SupportEmail = NewString(SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL) } +} - if o.ServiceSettings.EnableLinkPreviews == nil { - o.ServiceSettings.EnableLinkPreviews = new(bool) - *o.ServiceSettings.EnableLinkPreviews = false - } +type AnnouncementSettings struct { + EnableBanner *bool + BannerText *string + BannerColor *string + BannerTextColor *string + AllowBannerDismissal *bool +} - if o.ServiceSettings.EnableDeveloper == nil { - o.ServiceSettings.EnableDeveloper = new(bool) - *o.ServiceSettings.EnableDeveloper = false +func (s *AnnouncementSettings) SetDefaults() { + if s.EnableBanner == nil { + s.EnableBanner = NewBool(false) } - if o.ServiceSettings.EnableSecurityFixAlert == nil { - o.ServiceSettings.EnableSecurityFixAlert = new(bool) - *o.ServiceSettings.EnableSecurityFixAlert = true + if s.BannerText == nil { + s.BannerText = NewString("") } - if o.ServiceSettings.EnableInsecureOutgoingConnections == nil { - o.ServiceSettings.EnableInsecureOutgoingConnections = new(bool) - *o.ServiceSettings.EnableInsecureOutgoingConnections = false + if s.BannerColor == nil { + s.BannerColor = NewString(ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_COLOR) } - if o.ServiceSettings.EnableMultifactorAuthentication == nil { - o.ServiceSettings.EnableMultifactorAuthentication = new(bool) - *o.ServiceSettings.EnableMultifactorAuthentication = false + if s.BannerTextColor == nil { + s.BannerTextColor = NewString(ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_TEXT_COLOR) } - if o.ServiceSettings.EnforceMultifactorAuthentication == nil { - o.ServiceSettings.EnforceMultifactorAuthentication = new(bool) - *o.ServiceSettings.EnforceMultifactorAuthentication = false + if s.AllowBannerDismissal == nil { + s.AllowBannerDismissal = NewBool(true) } +} - if o.ServiceSettings.EnableUserAccessTokens == nil { - o.ServiceSettings.EnableUserAccessTokens = new(bool) - *o.ServiceSettings.EnableUserAccessTokens = false - } +type ThemeSettings struct { + EnableThemeSelection *bool + DefaultTheme *string + AllowCustomThemes *bool + AllowedThemes []string +} - if o.PasswordSettings.MinimumLength == nil { - o.PasswordSettings.MinimumLength = new(int) - *o.PasswordSettings.MinimumLength = PASSWORD_MINIMUM_LENGTH +func (s *ThemeSettings) SetDefaults() { + if s.EnableThemeSelection == nil { + s.EnableThemeSelection = NewBool(true) } - if o.PasswordSettings.Lowercase == nil { - o.PasswordSettings.Lowercase = new(bool) - *o.PasswordSettings.Lowercase = false + if s.DefaultTheme == nil { + s.DefaultTheme = NewString(TEAM_SETTINGS_DEFAULT_TEAM_TEXT) } - if o.PasswordSettings.Number == nil { - o.PasswordSettings.Number = new(bool) - *o.PasswordSettings.Number = false + if s.AllowCustomThemes == nil { + s.AllowCustomThemes = NewBool(true) } - if o.PasswordSettings.Uppercase == nil { - o.PasswordSettings.Uppercase = new(bool) - *o.PasswordSettings.Uppercase = false + if s.AllowedThemes == nil { + s.AllowedThemes = []string{} } +} + +type TeamSettings struct { + SiteName string + MaxUsersPerTeam *int + EnableTeamCreation bool + EnableUserCreation bool + EnableOpenServer *bool + RestrictCreationToDomains string + EnableCustomBrand *bool + CustomBrandText *string + CustomDescriptionText *string + RestrictDirectMessage *string + RestrictTeamInvite *string + RestrictPublicChannelManagement *string + RestrictPrivateChannelManagement *string + RestrictPublicChannelCreation *string + RestrictPrivateChannelCreation *string + RestrictPublicChannelDeletion *string + RestrictPrivateChannelDeletion *string + RestrictPrivateChannelManageMembers *string + EnableXToLeaveChannelsFromLHS *bool + UserStatusAwayTimeout *int64 + MaxChannelsPerTeam *int64 + MaxNotificationsPerChannel *int64 + EnableConfirmNotificationsToChannel *bool + TeammateNameDisplay *string + ExperimentalTownSquareIsReadOnly *bool + ExperimentalPrimaryTeam *string +} - if o.PasswordSettings.Symbol == nil { - o.PasswordSettings.Symbol = new(bool) - *o.PasswordSettings.Symbol = false +func (s *TeamSettings) SetDefaults() { + if s.MaxUsersPerTeam == nil { + s.MaxUsersPerTeam = NewInt(TEAM_SETTINGS_DEFAULT_MAX_USERS_PER_TEAM) } - if o.TeamSettings.EnableCustomBrand == nil { - o.TeamSettings.EnableCustomBrand = new(bool) - *o.TeamSettings.EnableCustomBrand = false + if s.EnableCustomBrand == nil { + s.EnableCustomBrand = NewBool(false) } - if o.TeamSettings.CustomBrandText == nil { - o.TeamSettings.CustomBrandText = new(string) - *o.TeamSettings.CustomBrandText = TEAM_SETTINGS_DEFAULT_CUSTOM_BRAND_TEXT + if s.CustomBrandText == nil { + s.CustomBrandText = NewString(TEAM_SETTINGS_DEFAULT_CUSTOM_BRAND_TEXT) } - if o.TeamSettings.CustomDescriptionText == nil { - o.TeamSettings.CustomDescriptionText = new(string) - *o.TeamSettings.CustomDescriptionText = TEAM_SETTINGS_DEFAULT_CUSTOM_DESCRIPTION_TEXT + if s.CustomDescriptionText == nil { + s.CustomDescriptionText = NewString(TEAM_SETTINGS_DEFAULT_CUSTOM_DESCRIPTION_TEXT) } - if o.TeamSettings.EnableOpenServer == nil { - o.TeamSettings.EnableOpenServer = new(bool) - *o.TeamSettings.EnableOpenServer = false + if s.EnableOpenServer == nil { + s.EnableOpenServer = NewBool(false) } - if o.TeamSettings.RestrictDirectMessage == nil { - o.TeamSettings.RestrictDirectMessage = new(string) - *o.TeamSettings.RestrictDirectMessage = DIRECT_MESSAGE_ANY + if s.RestrictDirectMessage == nil { + s.RestrictDirectMessage = NewString(DIRECT_MESSAGE_ANY) } - if o.TeamSettings.RestrictTeamInvite == nil { - o.TeamSettings.RestrictTeamInvite = new(string) - *o.TeamSettings.RestrictTeamInvite = PERMISSIONS_ALL + if s.RestrictTeamInvite == nil { + s.RestrictTeamInvite = NewString(PERMISSIONS_ALL) } - if o.TeamSettings.RestrictPublicChannelManagement == nil { - o.TeamSettings.RestrictPublicChannelManagement = new(string) - *o.TeamSettings.RestrictPublicChannelManagement = PERMISSIONS_ALL + if s.RestrictPublicChannelManagement == nil { + s.RestrictPublicChannelManagement = NewString(PERMISSIONS_ALL) } - if o.TeamSettings.RestrictPrivateChannelManagement == nil { - o.TeamSettings.RestrictPrivateChannelManagement = new(string) - *o.TeamSettings.RestrictPrivateChannelManagement = PERMISSIONS_ALL + if s.RestrictPrivateChannelManagement == nil { + s.RestrictPrivateChannelManagement = NewString(PERMISSIONS_ALL) } - if o.TeamSettings.RestrictPublicChannelCreation == nil { - o.TeamSettings.RestrictPublicChannelCreation = new(string) + if s.RestrictPublicChannelCreation == nil { + s.RestrictPublicChannelCreation = new(string) // If this setting does not exist, assume migration from <3.6, so use management setting as default. - if *o.TeamSettings.RestrictPublicChannelManagement == PERMISSIONS_CHANNEL_ADMIN { - *o.TeamSettings.RestrictPublicChannelCreation = PERMISSIONS_TEAM_ADMIN + if *s.RestrictPublicChannelManagement == PERMISSIONS_CHANNEL_ADMIN { + *s.RestrictPublicChannelCreation = PERMISSIONS_TEAM_ADMIN } else { - *o.TeamSettings.RestrictPublicChannelCreation = *o.TeamSettings.RestrictPublicChannelManagement + *s.RestrictPublicChannelCreation = *s.RestrictPublicChannelManagement } } - if o.TeamSettings.RestrictPrivateChannelCreation == nil { - o.TeamSettings.RestrictPrivateChannelCreation = new(string) + if s.RestrictPrivateChannelCreation == nil { // If this setting does not exist, assume migration from <3.6, so use management setting as default. - if *o.TeamSettings.RestrictPrivateChannelManagement == PERMISSIONS_CHANNEL_ADMIN { - *o.TeamSettings.RestrictPrivateChannelCreation = PERMISSIONS_TEAM_ADMIN + if *s.RestrictPrivateChannelManagement == PERMISSIONS_CHANNEL_ADMIN { + s.RestrictPrivateChannelCreation = NewString(PERMISSIONS_TEAM_ADMIN) } else { - *o.TeamSettings.RestrictPrivateChannelCreation = *o.TeamSettings.RestrictPrivateChannelManagement + s.RestrictPrivateChannelCreation = NewString(*s.RestrictPrivateChannelManagement) } } - if o.TeamSettings.RestrictPublicChannelDeletion == nil { - o.TeamSettings.RestrictPublicChannelDeletion = new(string) + if s.RestrictPublicChannelDeletion == nil { // If this setting does not exist, assume migration from <3.6, so use management setting as default. - *o.TeamSettings.RestrictPublicChannelDeletion = *o.TeamSettings.RestrictPublicChannelManagement + s.RestrictPublicChannelDeletion = NewString(*s.RestrictPublicChannelManagement) } - if o.TeamSettings.RestrictPrivateChannelDeletion == nil { - o.TeamSettings.RestrictPrivateChannelDeletion = new(string) + if s.RestrictPrivateChannelDeletion == nil { // If this setting does not exist, assume migration from <3.6, so use management setting as default. - *o.TeamSettings.RestrictPrivateChannelDeletion = *o.TeamSettings.RestrictPrivateChannelManagement + s.RestrictPrivateChannelDeletion = NewString(*s.RestrictPrivateChannelManagement) } - if o.TeamSettings.RestrictPrivateChannelManageMembers == nil { - o.TeamSettings.RestrictPrivateChannelManageMembers = new(string) - *o.TeamSettings.RestrictPrivateChannelManageMembers = PERMISSIONS_ALL + if s.RestrictPrivateChannelManageMembers == nil { + s.RestrictPrivateChannelManageMembers = NewString(PERMISSIONS_ALL) } - if o.TeamSettings.UserStatusAwayTimeout == nil { - o.TeamSettings.UserStatusAwayTimeout = new(int64) - *o.TeamSettings.UserStatusAwayTimeout = TEAM_SETTINGS_DEFAULT_USER_STATUS_AWAY_TIMEOUT + if s.EnableXToLeaveChannelsFromLHS == nil { + s.EnableXToLeaveChannelsFromLHS = NewBool(false) } - if o.TeamSettings.MaxChannelsPerTeam == nil { - o.TeamSettings.MaxChannelsPerTeam = new(int64) - *o.TeamSettings.MaxChannelsPerTeam = 2000 + if s.UserStatusAwayTimeout == nil { + s.UserStatusAwayTimeout = NewInt64(TEAM_SETTINGS_DEFAULT_USER_STATUS_AWAY_TIMEOUT) } - if o.TeamSettings.MaxNotificationsPerChannel == nil { - o.TeamSettings.MaxNotificationsPerChannel = new(int64) - *o.TeamSettings.MaxNotificationsPerChannel = 1000 + if s.MaxChannelsPerTeam == nil { + s.MaxChannelsPerTeam = NewInt64(2000) } - if o.EmailSettings.EnableSignInWithEmail == nil { - o.EmailSettings.EnableSignInWithEmail = new(bool) - - if o.EmailSettings.EnableSignUpWithEmail == true { - *o.EmailSettings.EnableSignInWithEmail = true - } else { - *o.EmailSettings.EnableSignInWithEmail = false - } + if s.MaxNotificationsPerChannel == nil { + s.MaxNotificationsPerChannel = NewInt64(1000) } - if o.EmailSettings.EnableSignInWithUsername == nil { - o.EmailSettings.EnableSignInWithUsername = new(bool) - *o.EmailSettings.EnableSignInWithUsername = false + if s.EnableConfirmNotificationsToChannel == nil { + s.EnableConfirmNotificationsToChannel = NewBool(true) } - if o.EmailSettings.SendPushNotifications == nil { - o.EmailSettings.SendPushNotifications = new(bool) - *o.EmailSettings.SendPushNotifications = false + if s.ExperimentalTownSquareIsReadOnly == nil { + s.ExperimentalTownSquareIsReadOnly = NewBool(false) } - if o.EmailSettings.PushNotificationServer == nil { - o.EmailSettings.PushNotificationServer = new(string) - *o.EmailSettings.PushNotificationServer = "" + if s.ExperimentalPrimaryTeam == nil { + s.ExperimentalPrimaryTeam = NewString("") } +} - if o.EmailSettings.PushNotificationContents == nil { - o.EmailSettings.PushNotificationContents = new(string) - *o.EmailSettings.PushNotificationContents = GENERIC_NOTIFICATION - } +type ClientRequirements struct { + AndroidLatestVersion string + AndroidMinVersion string + DesktopLatestVersion string + DesktopMinVersion string + IosLatestVersion string + IosMinVersion string +} - if o.EmailSettings.FeedbackOrganization == nil { - o.EmailSettings.FeedbackOrganization = new(string) - *o.EmailSettings.FeedbackOrganization = EMAIL_SETTINGS_DEFAULT_FEEDBACK_ORGANIZATION - } +type LdapSettings struct { + // Basic + Enable *bool + EnableSync *bool + LdapServer *string + LdapPort *int + ConnectionSecurity *string + BaseDN *string + BindUsername *string + BindPassword *string - if o.EmailSettings.EnableEmailBatching == nil { - o.EmailSettings.EnableEmailBatching = new(bool) - *o.EmailSettings.EnableEmailBatching = false - } + // Filtering + UserFilter *string - if o.EmailSettings.EmailBatchingBufferSize == nil { - o.EmailSettings.EmailBatchingBufferSize = new(int) - *o.EmailSettings.EmailBatchingBufferSize = EMAIL_BATCHING_BUFFER_SIZE - } + // User Mapping + FirstNameAttribute *string + LastNameAttribute *string + EmailAttribute *string + UsernameAttribute *string + NicknameAttribute *string + IdAttribute *string + PositionAttribute *string - if o.EmailSettings.EmailBatchingInterval == nil { - o.EmailSettings.EmailBatchingInterval = new(int) - *o.EmailSettings.EmailBatchingInterval = EMAIL_BATCHING_INTERVAL - } + // Syncronization + SyncIntervalMinutes *int - if o.EmailSettings.EnableSMTPAuth == nil { - o.EmailSettings.EnableSMTPAuth = new(bool) - if o.EmailSettings.ConnectionSecurity == CONN_SECURITY_NONE { - *o.EmailSettings.EnableSMTPAuth = false - } else { - *o.EmailSettings.EnableSMTPAuth = true - } - } + // Advanced + SkipCertificateVerification *bool + QueryTimeout *int + MaxPageSize *int - if o.EmailSettings.ConnectionSecurity == CONN_SECURITY_PLAIN { - o.EmailSettings.ConnectionSecurity = CONN_SECURITY_NONE - } + // Customization + LoginFieldName *string - if o.EmailSettings.SkipServerCertificateVerification == nil { - o.EmailSettings.SkipServerCertificateVerification = new(bool) - *o.EmailSettings.SkipServerCertificateVerification = false - } + LoginButtonColor *string + LoginButtonBorderColor *string + LoginButtonTextColor *string +} - if o.EmailSettings.EmailNotificationContentsType == nil { - o.EmailSettings.EmailNotificationContentsType = new(string) - *o.EmailSettings.EmailNotificationContentsType = EMAIL_NOTIFICATION_CONTENTS_FULL +func (s *LdapSettings) SetDefaults() { + if s.Enable == nil { + s.Enable = NewBool(false) } - if !IsSafeLink(o.SupportSettings.TermsOfServiceLink) { - *o.SupportSettings.TermsOfServiceLink = SUPPORT_SETTINGS_DEFAULT_TERMS_OF_SERVICE_LINK + // When unset should default to LDAP Enabled + if s.EnableSync == nil { + s.EnableSync = NewBool(*s.Enable) } - if o.SupportSettings.TermsOfServiceLink == nil { - o.SupportSettings.TermsOfServiceLink = new(string) - *o.SupportSettings.TermsOfServiceLink = SUPPORT_SETTINGS_DEFAULT_TERMS_OF_SERVICE_LINK + if s.LdapServer == nil { + s.LdapServer = NewString("") } - if !IsSafeLink(o.SupportSettings.PrivacyPolicyLink) { - *o.SupportSettings.PrivacyPolicyLink = "" + if s.LdapPort == nil { + s.LdapPort = NewInt(389) } - if o.SupportSettings.PrivacyPolicyLink == nil { - o.SupportSettings.PrivacyPolicyLink = new(string) - *o.SupportSettings.PrivacyPolicyLink = SUPPORT_SETTINGS_DEFAULT_PRIVACY_POLICY_LINK + if s.ConnectionSecurity == nil { + s.ConnectionSecurity = NewString("") } - if !IsSafeLink(o.SupportSettings.AboutLink) { - *o.SupportSettings.AboutLink = "" + if s.BaseDN == nil { + s.BaseDN = NewString("") } - if o.SupportSettings.AboutLink == nil { - o.SupportSettings.AboutLink = new(string) - *o.SupportSettings.AboutLink = SUPPORT_SETTINGS_DEFAULT_ABOUT_LINK + if s.BindUsername == nil { + s.BindUsername = NewString("") } - if !IsSafeLink(o.SupportSettings.HelpLink) { - *o.SupportSettings.HelpLink = "" + if s.BindPassword == nil { + s.BindPassword = NewString("") } - if o.SupportSettings.HelpLink == nil { - o.SupportSettings.HelpLink = new(string) - *o.SupportSettings.HelpLink = SUPPORT_SETTINGS_DEFAULT_HELP_LINK + if s.UserFilter == nil { + s.UserFilter = NewString("") } - if !IsSafeLink(o.SupportSettings.ReportAProblemLink) { - *o.SupportSettings.ReportAProblemLink = "" + if s.FirstNameAttribute == nil { + s.FirstNameAttribute = NewString(LDAP_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE) } - if o.SupportSettings.ReportAProblemLink == nil { - o.SupportSettings.ReportAProblemLink = new(string) - *o.SupportSettings.ReportAProblemLink = SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK + if s.LastNameAttribute == nil { + s.LastNameAttribute = NewString(LDAP_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE) } - if !IsSafeLink(o.SupportSettings.AdministratorsGuideLink) { - *o.SupportSettings.AdministratorsGuideLink = "" + if s.EmailAttribute == nil { + s.EmailAttribute = NewString(LDAP_SETTINGS_DEFAULT_EMAIL_ATTRIBUTE) } - if o.SupportSettings.AdministratorsGuideLink == nil { - o.SupportSettings.AdministratorsGuideLink = new(string) - *o.SupportSettings.AdministratorsGuideLink = SUPPORT_SETTINGS_DEFAULT_ADMINISTRATORS_GUIDE_LINK + if s.UsernameAttribute == nil { + s.UsernameAttribute = NewString(LDAP_SETTINGS_DEFAULT_USERNAME_ATTRIBUTE) } - if !IsSafeLink(o.SupportSettings.TroubleshootingForumLink) { - *o.SupportSettings.TroubleshootingForumLink = "" + if s.NicknameAttribute == nil { + s.NicknameAttribute = NewString(LDAP_SETTINGS_DEFAULT_NICKNAME_ATTRIBUTE) } - if o.SupportSettings.TroubleshootingForumLink == nil { - o.SupportSettings.TroubleshootingForumLink = new(string) - *o.SupportSettings.TroubleshootingForumLink = SUPPORT_SETTINGS_DEFAULT_TROUBLESHOOTING_FORUM_LINK + if s.IdAttribute == nil { + s.IdAttribute = NewString(LDAP_SETTINGS_DEFAULT_ID_ATTRIBUTE) } - if !IsSafeLink(o.SupportSettings.CommercialSupportLink) { - *o.SupportSettings.CommercialSupportLink = "" + if s.PositionAttribute == nil { + s.PositionAttribute = NewString(LDAP_SETTINGS_DEFAULT_POSITION_ATTRIBUTE) } - if o.SupportSettings.CommercialSupportLink == nil { - o.SupportSettings.CommercialSupportLink = new(string) - *o.SupportSettings.CommercialSupportLink = SUPPORT_SETTINGS_DEFAULT_COMMERCIAL_SUPPORT_LINK + if s.SyncIntervalMinutes == nil { + s.SyncIntervalMinutes = NewInt(60) } - if o.SupportSettings.SupportEmail == nil { - o.SupportSettings.SupportEmail = new(string) - *o.SupportSettings.SupportEmail = SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL + if s.SkipCertificateVerification == nil { + s.SkipCertificateVerification = NewBool(false) } - if o.AnnouncementSettings.EnableBanner == nil { - o.AnnouncementSettings.EnableBanner = new(bool) - *o.AnnouncementSettings.EnableBanner = false + if s.QueryTimeout == nil { + s.QueryTimeout = NewInt(60) } - if o.AnnouncementSettings.BannerText == nil { - o.AnnouncementSettings.BannerText = new(string) - *o.AnnouncementSettings.BannerText = "" + if s.MaxPageSize == nil { + s.MaxPageSize = NewInt(0) } - if o.AnnouncementSettings.BannerColor == nil { - o.AnnouncementSettings.BannerColor = new(string) - *o.AnnouncementSettings.BannerColor = ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_COLOR + if s.LoginFieldName == nil { + s.LoginFieldName = NewString(LDAP_SETTINGS_DEFAULT_LOGIN_FIELD_NAME) } - if o.AnnouncementSettings.BannerTextColor == nil { - o.AnnouncementSettings.BannerTextColor = new(string) - *o.AnnouncementSettings.BannerTextColor = ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_TEXT_COLOR + if s.LoginButtonColor == nil { + s.LoginButtonColor = NewString("#0000") } - if o.AnnouncementSettings.AllowBannerDismissal == nil { - o.AnnouncementSettings.AllowBannerDismissal = new(bool) - *o.AnnouncementSettings.AllowBannerDismissal = true + if s.LoginButtonBorderColor == nil { + s.LoginButtonBorderColor = NewString("#2389D7") } - if o.LdapSettings.Enable == nil { - o.LdapSettings.Enable = new(bool) - *o.LdapSettings.Enable = false + if s.LoginButtonTextColor == nil { + s.LoginButtonTextColor = NewString("#2389D7") } +} - if o.LdapSettings.LdapServer == nil { - o.LdapSettings.LdapServer = new(string) - *o.LdapSettings.LdapServer = "" - } +type ComplianceSettings struct { + Enable *bool + Directory *string + EnableDaily *bool +} - if o.LdapSettings.LdapPort == nil { - o.LdapSettings.LdapPort = new(int) - *o.LdapSettings.LdapPort = 389 +func (s *ComplianceSettings) SetDefaults() { + if s.Enable == nil { + s.Enable = NewBool(false) } - if o.LdapSettings.ConnectionSecurity == nil { - o.LdapSettings.ConnectionSecurity = new(string) - *o.LdapSettings.ConnectionSecurity = "" + if s.Directory == nil { + s.Directory = NewString("./data/") } - if o.LdapSettings.BaseDN == nil { - o.LdapSettings.BaseDN = new(string) - *o.LdapSettings.BaseDN = "" + if s.EnableDaily == nil { + s.EnableDaily = NewBool(false) } +} - if o.LdapSettings.BindUsername == nil { - o.LdapSettings.BindUsername = new(string) - *o.LdapSettings.BindUsername = "" - } +type LocalizationSettings struct { + DefaultServerLocale *string + DefaultClientLocale *string + AvailableLocales *string +} - if o.LdapSettings.BindPassword == nil { - o.LdapSettings.BindPassword = new(string) - *o.LdapSettings.BindPassword = "" +func (s *LocalizationSettings) SetDefaults() { + if s.DefaultServerLocale == nil { + s.DefaultServerLocale = NewString(DEFAULT_LOCALE) } - if o.LdapSettings.UserFilter == nil { - o.LdapSettings.UserFilter = new(string) - *o.LdapSettings.UserFilter = "" + if s.DefaultClientLocale == nil { + s.DefaultClientLocale = NewString(DEFAULT_LOCALE) } - if o.LdapSettings.FirstNameAttribute == nil { - o.LdapSettings.FirstNameAttribute = new(string) - *o.LdapSettings.FirstNameAttribute = LDAP_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE + if s.AvailableLocales == nil { + s.AvailableLocales = NewString("") } +} - if o.LdapSettings.LastNameAttribute == nil { - o.LdapSettings.LastNameAttribute = new(string) - *o.LdapSettings.LastNameAttribute = LDAP_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE - } +type SamlSettings struct { + // Basic + Enable *bool + EnableSyncWithLdap *bool - if o.LdapSettings.EmailAttribute == nil { - o.LdapSettings.EmailAttribute = new(string) - *o.LdapSettings.EmailAttribute = LDAP_SETTINGS_DEFAULT_EMAIL_ATTRIBUTE - } + Verify *bool + Encrypt *bool - if o.LdapSettings.UsernameAttribute == nil { - o.LdapSettings.UsernameAttribute = new(string) - *o.LdapSettings.UsernameAttribute = LDAP_SETTINGS_DEFAULT_USERNAME_ATTRIBUTE - } + IdpUrl *string + IdpDescriptorUrl *string + AssertionConsumerServiceURL *string - if o.LdapSettings.NicknameAttribute == nil { - o.LdapSettings.NicknameAttribute = new(string) - *o.LdapSettings.NicknameAttribute = LDAP_SETTINGS_DEFAULT_NICKNAME_ATTRIBUTE - } + IdpCertificateFile *string + PublicCertificateFile *string + PrivateKeyFile *string - if o.LdapSettings.IdAttribute == nil { - o.LdapSettings.IdAttribute = new(string) - *o.LdapSettings.IdAttribute = LDAP_SETTINGS_DEFAULT_ID_ATTRIBUTE - } + // User Mapping + FirstNameAttribute *string + LastNameAttribute *string + EmailAttribute *string + UsernameAttribute *string + NicknameAttribute *string + LocaleAttribute *string + PositionAttribute *string - if o.LdapSettings.PositionAttribute == nil { - o.LdapSettings.PositionAttribute = new(string) - *o.LdapSettings.PositionAttribute = LDAP_SETTINGS_DEFAULT_POSITION_ATTRIBUTE - } + LoginButtonText *string - if o.LdapSettings.SyncIntervalMinutes == nil { - o.LdapSettings.SyncIntervalMinutes = new(int) - *o.LdapSettings.SyncIntervalMinutes = 60 - } + LoginButtonColor *string + LoginButtonBorderColor *string + LoginButtonTextColor *string +} - if o.LdapSettings.SkipCertificateVerification == nil { - o.LdapSettings.SkipCertificateVerification = new(bool) - *o.LdapSettings.SkipCertificateVerification = false +func (s *SamlSettings) SetDefaults() { + if s.Enable == nil { + s.Enable = NewBool(false) } - if o.LdapSettings.QueryTimeout == nil { - o.LdapSettings.QueryTimeout = new(int) - *o.LdapSettings.QueryTimeout = 60 + if s.EnableSyncWithLdap == nil { + s.EnableSyncWithLdap = NewBool(false) } - if o.LdapSettings.MaxPageSize == nil { - o.LdapSettings.MaxPageSize = new(int) - *o.LdapSettings.MaxPageSize = 0 + if s.Verify == nil { + s.Verify = NewBool(true) } - if o.LdapSettings.LoginFieldName == nil { - o.LdapSettings.LoginFieldName = new(string) - *o.LdapSettings.LoginFieldName = LDAP_SETTINGS_DEFAULT_LOGIN_FIELD_NAME + if s.Encrypt == nil { + s.Encrypt = NewBool(true) } - if o.ServiceSettings.SessionLengthWebInDays == nil { - o.ServiceSettings.SessionLengthWebInDays = new(int) - *o.ServiceSettings.SessionLengthWebInDays = 30 + if s.IdpUrl == nil { + s.IdpUrl = NewString("") } - if o.ServiceSettings.SessionLengthMobileInDays == nil { - o.ServiceSettings.SessionLengthMobileInDays = new(int) - *o.ServiceSettings.SessionLengthMobileInDays = 30 + if s.IdpDescriptorUrl == nil { + s.IdpDescriptorUrl = NewString("") } - if o.ServiceSettings.SessionLengthSSOInDays == nil { - o.ServiceSettings.SessionLengthSSOInDays = new(int) - *o.ServiceSettings.SessionLengthSSOInDays = 30 + if s.IdpCertificateFile == nil { + s.IdpCertificateFile = NewString("") } - if o.ServiceSettings.SessionCacheInMinutes == nil { - o.ServiceSettings.SessionCacheInMinutes = new(int) - *o.ServiceSettings.SessionCacheInMinutes = 10 + if s.PublicCertificateFile == nil { + s.PublicCertificateFile = NewString("") } - if o.ServiceSettings.EnableCommands == nil { - o.ServiceSettings.EnableCommands = new(bool) - *o.ServiceSettings.EnableCommands = false + if s.PrivateKeyFile == nil { + s.PrivateKeyFile = NewString("") } - if o.ServiceSettings.EnableOnlyAdminIntegrations == nil { - o.ServiceSettings.EnableOnlyAdminIntegrations = new(bool) - *o.ServiceSettings.EnableOnlyAdminIntegrations = true + if s.AssertionConsumerServiceURL == nil { + s.AssertionConsumerServiceURL = NewString("") } - if o.ServiceSettings.WebsocketPort == nil { - o.ServiceSettings.WebsocketPort = new(int) - *o.ServiceSettings.WebsocketPort = 80 + if s.LoginButtonText == nil || *s.LoginButtonText == "" { + s.LoginButtonText = NewString(USER_AUTH_SERVICE_SAML_TEXT) } - if o.ServiceSettings.WebsocketSecurePort == nil { - o.ServiceSettings.WebsocketSecurePort = new(int) - *o.ServiceSettings.WebsocketSecurePort = 443 + if s.FirstNameAttribute == nil { + s.FirstNameAttribute = NewString(SAML_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE) } - if o.ServiceSettings.AllowCorsFrom == nil { - o.ServiceSettings.AllowCorsFrom = new(string) - *o.ServiceSettings.AllowCorsFrom = SERVICE_SETTINGS_DEFAULT_ALLOW_CORS_FROM + if s.LastNameAttribute == nil { + s.LastNameAttribute = NewString(SAML_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE) } - if o.ServiceSettings.WebserverMode == nil { - o.ServiceSettings.WebserverMode = new(string) - *o.ServiceSettings.WebserverMode = "gzip" - } else if *o.ServiceSettings.WebserverMode == "regular" { - *o.ServiceSettings.WebserverMode = "gzip" + if s.EmailAttribute == nil { + s.EmailAttribute = NewString(SAML_SETTINGS_DEFAULT_EMAIL_ATTRIBUTE) } - if o.ServiceSettings.EnableCustomEmoji == nil { - o.ServiceSettings.EnableCustomEmoji = new(bool) - *o.ServiceSettings.EnableCustomEmoji = false + if s.UsernameAttribute == nil { + s.UsernameAttribute = NewString(SAML_SETTINGS_DEFAULT_USERNAME_ATTRIBUTE) } - if o.ServiceSettings.EnableEmojiPicker == nil { - o.ServiceSettings.EnableEmojiPicker = new(bool) - *o.ServiceSettings.EnableEmojiPicker = true + if s.NicknameAttribute == nil { + s.NicknameAttribute = NewString(SAML_SETTINGS_DEFAULT_NICKNAME_ATTRIBUTE) } - if o.ServiceSettings.RestrictCustomEmojiCreation == nil { - o.ServiceSettings.RestrictCustomEmojiCreation = new(string) - *o.ServiceSettings.RestrictCustomEmojiCreation = RESTRICT_EMOJI_CREATION_ALL + if s.PositionAttribute == nil { + s.PositionAttribute = NewString(SAML_SETTINGS_DEFAULT_POSITION_ATTRIBUTE) } - if o.ServiceSettings.RestrictPostDelete == nil { - o.ServiceSettings.RestrictPostDelete = new(string) - *o.ServiceSettings.RestrictPostDelete = PERMISSIONS_DELETE_POST_ALL + if s.LocaleAttribute == nil { + s.LocaleAttribute = NewString(SAML_SETTINGS_DEFAULT_LOCALE_ATTRIBUTE) } - if o.ServiceSettings.AllowEditPost == nil { - o.ServiceSettings.AllowEditPost = new(string) - *o.ServiceSettings.AllowEditPost = ALLOW_EDIT_POST_ALWAYS + if s.LoginButtonColor == nil { + s.LoginButtonColor = NewString("#34a28b") } - if o.ServiceSettings.PostEditTimeLimit == nil { - o.ServiceSettings.PostEditTimeLimit = new(int) - *o.ServiceSettings.PostEditTimeLimit = 300 + if s.LoginButtonBorderColor == nil { + s.LoginButtonBorderColor = NewString("#2389D7") } - if o.ClusterSettings.Enable == nil { - o.ClusterSettings.Enable = new(bool) - *o.ClusterSettings.Enable = false + if s.LoginButtonTextColor == nil { + s.LoginButtonTextColor = NewString("#ffffff") } +} - if o.ClusterSettings.ClusterName == nil { - o.ClusterSettings.ClusterName = new(string) - *o.ClusterSettings.ClusterName = "" - } +type NativeAppSettings struct { + AppDownloadLink *string + AndroidAppDownloadLink *string + IosAppDownloadLink *string +} - if o.ClusterSettings.OverrideHostname == nil { - o.ClusterSettings.OverrideHostname = new(string) - *o.ClusterSettings.OverrideHostname = "" +func (s *NativeAppSettings) SetDefaults() { + if s.AppDownloadLink == nil { + s.AppDownloadLink = NewString(NATIVEAPP_SETTINGS_DEFAULT_APP_DOWNLOAD_LINK) } - if o.ClusterSettings.UseIpAddress == nil { - o.ClusterSettings.UseIpAddress = new(bool) - *o.ClusterSettings.UseIpAddress = true + if s.AndroidAppDownloadLink == nil { + s.AndroidAppDownloadLink = NewString(NATIVEAPP_SETTINGS_DEFAULT_ANDROID_APP_DOWNLOAD_LINK) } - if o.ClusterSettings.UseExperimentalGossip == nil { - o.ClusterSettings.UseExperimentalGossip = new(bool) - *o.ClusterSettings.UseExperimentalGossip = false + if s.IosAppDownloadLink == nil { + s.IosAppDownloadLink = NewString(NATIVEAPP_SETTINGS_DEFAULT_IOS_APP_DOWNLOAD_LINK) } +} - if o.ClusterSettings.ReadOnlyConfig == nil { - o.ClusterSettings.ReadOnlyConfig = new(bool) - *o.ClusterSettings.ReadOnlyConfig = true - } +type WebrtcSettings struct { + Enable *bool + GatewayWebsocketUrl *string + GatewayAdminUrl *string + GatewayAdminSecret *string + StunURI *string + TurnURI *string + TurnUsername *string + TurnSharedKey *string +} - if o.ClusterSettings.GossipPort == nil { - o.ClusterSettings.GossipPort = new(int) - *o.ClusterSettings.GossipPort = 8074 +func (s *WebrtcSettings) SetDefaults() { + if s.Enable == nil { + s.Enable = NewBool(false) } - if o.ClusterSettings.StreamingPort == nil { - o.ClusterSettings.StreamingPort = new(int) - *o.ClusterSettings.StreamingPort = 8075 + if s.GatewayWebsocketUrl == nil { + s.GatewayWebsocketUrl = NewString("") } - if o.MetricsSettings.ListenAddress == nil { - o.MetricsSettings.ListenAddress = new(string) - *o.MetricsSettings.ListenAddress = ":8067" + if s.GatewayAdminUrl == nil { + s.GatewayAdminUrl = NewString("") } - if o.MetricsSettings.Enable == nil { - o.MetricsSettings.Enable = new(bool) - *o.MetricsSettings.Enable = false + if s.GatewayAdminSecret == nil { + s.GatewayAdminSecret = NewString("") } - if o.AnalyticsSettings.MaxUsersForStatistics == nil { - o.AnalyticsSettings.MaxUsersForStatistics = new(int) - *o.AnalyticsSettings.MaxUsersForStatistics = ANALYTICS_SETTINGS_DEFAULT_MAX_USERS_FOR_STATISTICS + if s.StunURI == nil { + s.StunURI = NewString(WEBRTC_SETTINGS_DEFAULT_STUN_URI) } - if o.ComplianceSettings.Enable == nil { - o.ComplianceSettings.Enable = new(bool) - *o.ComplianceSettings.Enable = false + if s.TurnURI == nil { + s.TurnURI = NewString(WEBRTC_SETTINGS_DEFAULT_TURN_URI) } - if o.ComplianceSettings.Directory == nil { - o.ComplianceSettings.Directory = new(string) - *o.ComplianceSettings.Directory = "./data/" + if s.TurnUsername == nil { + s.TurnUsername = NewString("") } - if o.ComplianceSettings.EnableDaily == nil { - o.ComplianceSettings.EnableDaily = new(bool) - *o.ComplianceSettings.EnableDaily = false + if s.TurnSharedKey == nil { + s.TurnSharedKey = NewString("") } +} + +type ElasticsearchSettings struct { + ConnectionUrl *string + Username *string + Password *string + EnableIndexing *bool + EnableSearching *bool + Sniff *bool + PostIndexReplicas *int + PostIndexShards *int + AggregatePostsAfterDays *int + PostsAggregatorJobStartTime *string + IndexPrefix *string + LiveIndexingBatchSize *int + BulkIndexingTimeWindowSeconds *int + RequestTimeoutSeconds *int +} - if o.LocalizationSettings.DefaultServerLocale == nil { - o.LocalizationSettings.DefaultServerLocale = new(string) - *o.LocalizationSettings.DefaultServerLocale = DEFAULT_LOCALE +func (s *ElasticsearchSettings) SetDefaults() { + if s.ConnectionUrl == nil { + s.ConnectionUrl = NewString(ELASTICSEARCH_SETTINGS_DEFAULT_CONNECTION_URL) } - if o.LocalizationSettings.DefaultClientLocale == nil { - o.LocalizationSettings.DefaultClientLocale = new(string) - *o.LocalizationSettings.DefaultClientLocale = DEFAULT_LOCALE + if s.Username == nil { + s.Username = NewString(ELASTICSEARCH_SETTINGS_DEFAULT_USERNAME) } - if o.LocalizationSettings.AvailableLocales == nil { - o.LocalizationSettings.AvailableLocales = new(string) - *o.LocalizationSettings.AvailableLocales = "" + if s.Password == nil { + s.Password = NewString(ELASTICSEARCH_SETTINGS_DEFAULT_PASSWORD) } - if o.LogSettings.EnableDiagnostics == nil { - o.LogSettings.EnableDiagnostics = new(bool) - *o.LogSettings.EnableDiagnostics = true + if s.EnableIndexing == nil { + s.EnableIndexing = NewBool(false) } - if o.SamlSettings.Enable == nil { - o.SamlSettings.Enable = new(bool) - *o.SamlSettings.Enable = false + if s.EnableSearching == nil { + s.EnableSearching = NewBool(false) } - if o.SamlSettings.Verify == nil { - o.SamlSettings.Verify = new(bool) - *o.SamlSettings.Verify = true + if s.Sniff == nil { + s.Sniff = NewBool(true) } - if o.SamlSettings.Encrypt == nil { - o.SamlSettings.Encrypt = new(bool) - *o.SamlSettings.Encrypt = true + if s.PostIndexReplicas == nil { + s.PostIndexReplicas = NewInt(ELASTICSEARCH_SETTINGS_DEFAULT_POST_INDEX_REPLICAS) } - if o.SamlSettings.IdpUrl == nil { - o.SamlSettings.IdpUrl = new(string) - *o.SamlSettings.IdpUrl = "" + if s.PostIndexShards == nil { + s.PostIndexShards = NewInt(ELASTICSEARCH_SETTINGS_DEFAULT_POST_INDEX_SHARDS) } - if o.SamlSettings.IdpDescriptorUrl == nil { - o.SamlSettings.IdpDescriptorUrl = new(string) - *o.SamlSettings.IdpDescriptorUrl = "" + if s.AggregatePostsAfterDays == nil { + s.AggregatePostsAfterDays = NewInt(ELASTICSEARCH_SETTINGS_DEFAULT_AGGREGATE_POSTS_AFTER_DAYS) } - if o.SamlSettings.IdpCertificateFile == nil { - o.SamlSettings.IdpCertificateFile = new(string) - *o.SamlSettings.IdpCertificateFile = "" + if s.PostsAggregatorJobStartTime == nil { + s.PostsAggregatorJobStartTime = NewString(ELASTICSEARCH_SETTINGS_DEFAULT_POSTS_AGGREGATOR_JOB_START_TIME) } - if o.SamlSettings.PublicCertificateFile == nil { - o.SamlSettings.PublicCertificateFile = new(string) - *o.SamlSettings.PublicCertificateFile = "" + if s.IndexPrefix == nil { + s.IndexPrefix = NewString(ELASTICSEARCH_SETTINGS_DEFAULT_INDEX_PREFIX) } - if o.SamlSettings.PrivateKeyFile == nil { - o.SamlSettings.PrivateKeyFile = new(string) - *o.SamlSettings.PrivateKeyFile = "" + if s.LiveIndexingBatchSize == nil { + s.LiveIndexingBatchSize = NewInt(ELASTICSEARCH_SETTINGS_DEFAULT_LIVE_INDEXING_BATCH_SIZE) } - if o.SamlSettings.AssertionConsumerServiceURL == nil { - o.SamlSettings.AssertionConsumerServiceURL = new(string) - *o.SamlSettings.AssertionConsumerServiceURL = "" + if s.BulkIndexingTimeWindowSeconds == nil { + s.BulkIndexingTimeWindowSeconds = NewInt(ELASTICSEARCH_SETTINGS_DEFAULT_BULK_INDEXING_TIME_WINDOW_SECONDS) } - if o.SamlSettings.LoginButtonText == nil || *o.SamlSettings.LoginButtonText == "" { - o.SamlSettings.LoginButtonText = new(string) - *o.SamlSettings.LoginButtonText = USER_AUTH_SERVICE_SAML_TEXT + if s.RequestTimeoutSeconds == nil { + s.RequestTimeoutSeconds = NewInt(ELASTICSEARCH_SETTINGS_DEFAULT_REQUEST_TIMEOUT_SECONDS) } +} + +type DataRetentionSettings struct { + EnableMessageDeletion *bool + EnableFileDeletion *bool + MessageRetentionDays *int + FileRetentionDays *int + DeletionJobStartTime *string +} - if o.SamlSettings.FirstNameAttribute == nil { - o.SamlSettings.FirstNameAttribute = new(string) - *o.SamlSettings.FirstNameAttribute = SAML_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE +func (s *DataRetentionSettings) SetDefaults() { + if s.EnableMessageDeletion == nil { + s.EnableMessageDeletion = NewBool(false) } - if o.SamlSettings.LastNameAttribute == nil { - o.SamlSettings.LastNameAttribute = new(string) - *o.SamlSettings.LastNameAttribute = SAML_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE + if s.EnableFileDeletion == nil { + s.EnableFileDeletion = NewBool(false) } - if o.SamlSettings.EmailAttribute == nil { - o.SamlSettings.EmailAttribute = new(string) - *o.SamlSettings.EmailAttribute = SAML_SETTINGS_DEFAULT_EMAIL_ATTRIBUTE + if s.MessageRetentionDays == nil { + s.MessageRetentionDays = NewInt(DATA_RETENTION_SETTINGS_DEFAULT_MESSAGE_RETENTION_DAYS) } - if o.SamlSettings.UsernameAttribute == nil { - o.SamlSettings.UsernameAttribute = new(string) - *o.SamlSettings.UsernameAttribute = SAML_SETTINGS_DEFAULT_USERNAME_ATTRIBUTE + if s.FileRetentionDays == nil { + s.FileRetentionDays = NewInt(DATA_RETENTION_SETTINGS_DEFAULT_FILE_RETENTION_DAYS) } - if o.SamlSettings.NicknameAttribute == nil { - o.SamlSettings.NicknameAttribute = new(string) - *o.SamlSettings.NicknameAttribute = SAML_SETTINGS_DEFAULT_NICKNAME_ATTRIBUTE + if s.DeletionJobStartTime == nil { + s.DeletionJobStartTime = NewString(DATA_RETENTION_SETTINGS_DEFAULT_DELETION_JOB_START_TIME) } +} + +type JobSettings struct { + RunJobs *bool + RunScheduler *bool +} - if o.SamlSettings.PositionAttribute == nil { - o.SamlSettings.PositionAttribute = new(string) - *o.SamlSettings.PositionAttribute = SAML_SETTINGS_DEFAULT_POSITION_ATTRIBUTE +func (s *JobSettings) SetDefaults() { + if s.RunJobs == nil { + s.RunJobs = NewBool(true) } - if o.SamlSettings.LocaleAttribute == nil { - o.SamlSettings.LocaleAttribute = new(string) - *o.SamlSettings.LocaleAttribute = SAML_SETTINGS_DEFAULT_LOCALE_ATTRIBUTE + if s.RunScheduler == nil { + s.RunScheduler = NewBool(true) } +} - if o.TeamSettings.TeammateNameDisplay == nil { - o.TeamSettings.TeammateNameDisplay = new(string) - *o.TeamSettings.TeammateNameDisplay = SHOW_USERNAME +type PluginState struct { + Enable bool +} - if *o.SamlSettings.Enable || *o.LdapSettings.Enable { - *o.TeamSettings.TeammateNameDisplay = SHOW_FULLNAME - } +type PluginSettings struct { + Enable *bool + EnableUploads *bool + Directory *string + ClientDirectory *string + Plugins map[string]interface{} + PluginStates map[string]*PluginState +} + +func (s *PluginSettings) SetDefaults() { + if s.Enable == nil { + s.Enable = NewBool(true) } - if o.NativeAppSettings.AppDownloadLink == nil { - o.NativeAppSettings.AppDownloadLink = new(string) - *o.NativeAppSettings.AppDownloadLink = NATIVEAPP_SETTINGS_DEFAULT_APP_DOWNLOAD_LINK + if s.EnableUploads == nil { + s.EnableUploads = NewBool(false) } - if o.NativeAppSettings.AndroidAppDownloadLink == nil { - o.NativeAppSettings.AndroidAppDownloadLink = new(string) - *o.NativeAppSettings.AndroidAppDownloadLink = NATIVEAPP_SETTINGS_DEFAULT_ANDROID_APP_DOWNLOAD_LINK + if s.Directory == nil { + s.Directory = NewString(PLUGIN_SETTINGS_DEFAULT_DIRECTORY) } - if o.NativeAppSettings.IosAppDownloadLink == nil { - o.NativeAppSettings.IosAppDownloadLink = new(string) - *o.NativeAppSettings.IosAppDownloadLink = NATIVEAPP_SETTINGS_DEFAULT_IOS_APP_DOWNLOAD_LINK + if *s.Directory == "" { + *s.Directory = PLUGIN_SETTINGS_DEFAULT_DIRECTORY } - if o.RateLimitSettings.Enable == nil { - o.RateLimitSettings.Enable = new(bool) - *o.RateLimitSettings.Enable = false + if s.ClientDirectory == nil { + s.ClientDirectory = NewString(PLUGIN_SETTINGS_DEFAULT_CLIENT_DIRECTORY) } - if o.ServiceSettings.GoroutineHealthThreshold == nil { - o.ServiceSettings.GoroutineHealthThreshold = new(int) - *o.ServiceSettings.GoroutineHealthThreshold = -1 + if *s.ClientDirectory == "" { + *s.ClientDirectory = PLUGIN_SETTINGS_DEFAULT_CLIENT_DIRECTORY } - if o.RateLimitSettings.MaxBurst == nil { - o.RateLimitSettings.MaxBurst = new(int) - *o.RateLimitSettings.MaxBurst = 100 + if s.Plugins == nil { + s.Plugins = make(map[string]interface{}) } - if o.ServiceSettings.ConnectionSecurity == nil { - o.ServiceSettings.ConnectionSecurity = new(string) - *o.ServiceSettings.ConnectionSecurity = "" + if s.PluginStates == nil { + s.PluginStates = make(map[string]*PluginState) } +} + +type MessageExportSettings struct { + EnableExport *bool + DailyRunTime *string + ExportFromTimestamp *int64 + BatchSize *int +} - if o.ServiceSettings.TLSKeyFile == nil { - o.ServiceSettings.TLSKeyFile = new(string) - *o.ServiceSettings.TLSKeyFile = SERVICE_SETTINGS_DEFAULT_TLS_KEY_FILE +func (s *MessageExportSettings) SetDefaults() { + if s.EnableExport == nil { + s.EnableExport = NewBool(false) } - if o.ServiceSettings.TLSCertFile == nil { - o.ServiceSettings.TLSCertFile = new(string) - *o.ServiceSettings.TLSCertFile = SERVICE_SETTINGS_DEFAULT_TLS_CERT_FILE + if s.DailyRunTime == nil { + s.DailyRunTime = NewString("01:00") } - if o.ServiceSettings.UseLetsEncrypt == nil { - o.ServiceSettings.UseLetsEncrypt = new(bool) - *o.ServiceSettings.UseLetsEncrypt = false + if s.ExportFromTimestamp == nil { + s.ExportFromTimestamp = NewInt64(0) } - if o.ServiceSettings.LetsEncryptCertificateCacheFile == nil { - o.ServiceSettings.LetsEncryptCertificateCacheFile = new(string) - *o.ServiceSettings.LetsEncryptCertificateCacheFile = "./config/letsencrypt.cache" + if s.EnableExport != nil && *s.EnableExport && *s.ExportFromTimestamp == int64(0) { + // when the feature is enabled via the System Console, use the current timestamp as the start time for future exports + s.ExportFromTimestamp = NewInt64(GetMillis()) + } else if s.EnableExport != nil && !*s.EnableExport { + // when the feature is disabled, reset the timestamp so that the timestamp will be set if the feature is re-enabled + s.ExportFromTimestamp = NewInt64(0) } - if o.ServiceSettings.ReadTimeout == nil { - o.ServiceSettings.ReadTimeout = new(int) - *o.ServiceSettings.ReadTimeout = SERVICE_SETTINGS_DEFAULT_READ_TIMEOUT + if s.BatchSize == nil { + s.BatchSize = NewInt(10000) } +} + +type ConfigFunc func() *Config + +type Config struct { + ServiceSettings ServiceSettings + TeamSettings TeamSettings + ClientRequirements ClientRequirements + SqlSettings SqlSettings + LogSettings LogSettings + PasswordSettings PasswordSettings + FileSettings FileSettings + EmailSettings EmailSettings + RateLimitSettings RateLimitSettings + PrivacySettings PrivacySettings + SupportSettings SupportSettings + AnnouncementSettings AnnouncementSettings + ThemeSettings ThemeSettings + GitLabSettings SSOSettings + GoogleSettings SSOSettings + Office365Settings SSOSettings + LdapSettings LdapSettings + ComplianceSettings ComplianceSettings + LocalizationSettings LocalizationSettings + SamlSettings SamlSettings + NativeAppSettings NativeAppSettings + ClusterSettings ClusterSettings + MetricsSettings MetricsSettings + AnalyticsSettings AnalyticsSettings + WebrtcSettings WebrtcSettings + ElasticsearchSettings ElasticsearchSettings + DataRetentionSettings DataRetentionSettings + MessageExportSettings MessageExportSettings + JobSettings JobSettings + PluginSettings PluginSettings +} - if o.ServiceSettings.WriteTimeout == nil { - o.ServiceSettings.WriteTimeout = new(int) - *o.ServiceSettings.WriteTimeout = SERVICE_SETTINGS_DEFAULT_WRITE_TIMEOUT +func (o *Config) Clone() *Config { + var ret Config + if err := json.Unmarshal([]byte(o.ToJson()), &ret); err != nil { + panic(err) } + return &ret +} - if o.ServiceSettings.Forward80To443 == nil { - o.ServiceSettings.Forward80To443 = new(bool) - *o.ServiceSettings.Forward80To443 = false +func (o *Config) ToJson() string { + b, err := json.Marshal(o) + if err != nil { + return "" + } else { + return string(b) } +} - if o.MetricsSettings.BlockProfileRate == nil { - o.MetricsSettings.BlockProfileRate = new(int) - *o.MetricsSettings.BlockProfileRate = 0 +func (o *Config) GetSSOService(service string) *SSOSettings { + switch service { + case SERVICE_GITLAB: + return &o.GitLabSettings + case SERVICE_GOOGLE: + return &o.GoogleSettings + case SERVICE_OFFICE365: + return &o.Office365Settings } - if o.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds == nil { - o.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds = new(int64) - *o.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds = 5000 + return nil +} + +func ConfigFromJson(data io.Reader) *Config { + decoder := json.NewDecoder(data) + var o Config + err := decoder.Decode(&o) + if err == nil { + return &o + } else { + return nil } +} + +func (o *Config) SetDefaults() { + o.LdapSettings.SetDefaults() + o.SamlSettings.SetDefaults() - if o.ServiceSettings.EnablePostSearch == nil { - o.ServiceSettings.EnablePostSearch = new(bool) - *o.ServiceSettings.EnablePostSearch = true + if o.TeamSettings.TeammateNameDisplay == nil { + o.TeamSettings.TeammateNameDisplay = NewString(SHOW_USERNAME) + + if *o.SamlSettings.Enable || *o.LdapSettings.Enable { + *o.TeamSettings.TeammateNameDisplay = SHOW_FULLNAME + } } - if o.ServiceSettings.EnableUserTypingMessages == nil { - o.ServiceSettings.EnableUserTypingMessages = new(bool) - *o.ServiceSettings.EnableUserTypingMessages = true + o.SqlSettings.SetDefaults() + o.FileSettings.SetDefaults() + o.EmailSettings.SetDefaults() + o.ServiceSettings.SetDefaults() + o.PasswordSettings.SetDefaults() + o.TeamSettings.SetDefaults() + o.MetricsSettings.SetDefaults() + o.SupportSettings.SetDefaults() + o.AnnouncementSettings.SetDefaults() + o.ThemeSettings.SetDefaults() + o.ClusterSettings.SetDefaults() + o.PluginSettings.SetDefaults() + o.AnalyticsSettings.SetDefaults() + o.ComplianceSettings.SetDefaults() + o.LocalizationSettings.SetDefaults() + o.ElasticsearchSettings.SetDefaults() + o.NativeAppSettings.SetDefaults() + o.DataRetentionSettings.SetDefaults() + o.RateLimitSettings.SetDefaults() + o.LogSettings.SetDefaults() + o.JobSettings.SetDefaults() + o.WebrtcSettings.SetDefaults() + o.MessageExportSettings.SetDefaults() +} + +func (o *Config) IsValid() *AppError { + if len(*o.ServiceSettings.SiteURL) == 0 && *o.EmailSettings.EnableEmailBatching { + return NewAppError("Config.IsValid", "model.config.is_valid.site_url_email_batching.app_error", nil, "", http.StatusBadRequest) } - if o.ServiceSettings.EnableChannelViewedMessages == nil { - o.ServiceSettings.EnableChannelViewedMessages = new(bool) - *o.ServiceSettings.EnableChannelViewedMessages = true + if *o.ClusterSettings.Enable && *o.EmailSettings.EnableEmailBatching { + return NewAppError("Config.IsValid", "model.config.is_valid.cluster_email_batching.app_error", nil, "", http.StatusBadRequest) } - if o.ServiceSettings.EnableUserStatuses == nil { - o.ServiceSettings.EnableUserStatuses = new(bool) - *o.ServiceSettings.EnableUserStatuses = true + if err := o.TeamSettings.isValid(); err != nil { + return err } - if o.ServiceSettings.ClusterLogTimeoutMilliseconds == nil { - o.ServiceSettings.ClusterLogTimeoutMilliseconds = new(int) - *o.ServiceSettings.ClusterLogTimeoutMilliseconds = 2000 + if err := o.SqlSettings.isValid(); err != nil { + return err } - if o.ElasticsearchSettings.ConnectionUrl == nil { - o.ElasticsearchSettings.ConnectionUrl = new(string) - *o.ElasticsearchSettings.ConnectionUrl = ELASTICSEARCH_SETTINGS_DEFAULT_CONNECTION_URL + if err := o.FileSettings.isValid(); err != nil { + return err } - if o.ElasticsearchSettings.Username == nil { - o.ElasticsearchSettings.Username = new(string) - *o.ElasticsearchSettings.Username = ELASTICSEARCH_SETTINGS_DEFAULT_USERNAME + if err := o.EmailSettings.isValid(); err != nil { + return err } - if o.ElasticsearchSettings.Password == nil { - o.ElasticsearchSettings.Password = new(string) - *o.ElasticsearchSettings.Password = ELASTICSEARCH_SETTINGS_DEFAULT_PASSWORD + if err := o.LdapSettings.isValid(); err != nil { + return err } - if o.ElasticsearchSettings.EnableIndexing == nil { - o.ElasticsearchSettings.EnableIndexing = new(bool) - *o.ElasticsearchSettings.EnableIndexing = false + if err := o.SamlSettings.isValid(); err != nil { + return err } - if o.ElasticsearchSettings.EnableSearching == nil { - o.ElasticsearchSettings.EnableSearching = new(bool) - *o.ElasticsearchSettings.EnableSearching = false + if *o.PasswordSettings.MinimumLength < PASSWORD_MINIMUM_LENGTH || *o.PasswordSettings.MinimumLength > PASSWORD_MAXIMUM_LENGTH { + return NewAppError("Config.IsValid", "model.config.is_valid.password_length.app_error", map[string]interface{}{"MinLength": PASSWORD_MINIMUM_LENGTH, "MaxLength": PASSWORD_MAXIMUM_LENGTH}, "", http.StatusBadRequest) } - if o.ElasticsearchSettings.Sniff == nil { - o.ElasticsearchSettings.Sniff = new(bool) - *o.ElasticsearchSettings.Sniff = true + if err := o.RateLimitSettings.isValid(); err != nil { + return err } - if o.ElasticsearchSettings.PostIndexReplicas == nil { - o.ElasticsearchSettings.PostIndexReplicas = new(int) - *o.ElasticsearchSettings.PostIndexReplicas = ELASTICSEARCH_SETTINGS_DEFAULT_POST_INDEX_REPLICAS + if err := o.WebrtcSettings.isValid(); err != nil { + return err } - if o.ElasticsearchSettings.PostIndexShards == nil { - o.ElasticsearchSettings.PostIndexShards = new(int) - *o.ElasticsearchSettings.PostIndexShards = ELASTICSEARCH_SETTINGS_DEFAULT_POST_INDEX_SHARDS + if err := o.ServiceSettings.isValid(); err != nil { + return err } - if o.DataRetentionSettings.Enable == nil { - o.DataRetentionSettings.Enable = new(bool) - *o.DataRetentionSettings.Enable = false + if err := o.ElasticsearchSettings.isValid(); err != nil { + return err } - if o.JobSettings.RunJobs == nil { - o.JobSettings.RunJobs = new(bool) - *o.JobSettings.RunJobs = true + if err := o.DataRetentionSettings.isValid(); err != nil { + return err } - if o.JobSettings.RunScheduler == nil { - o.JobSettings.RunScheduler = new(bool) - *o.JobSettings.RunScheduler = true + if err := o.LocalizationSettings.isValid(); err != nil { + return err } - if o.PluginSettings.Plugins == nil { - o.PluginSettings.Plugins = make(map[string]interface{}) + if err := o.MessageExportSettings.isValid(o.FileSettings); err != nil { + return err } - o.defaultWebrtcSettings() + return nil } -func (o *Config) IsValid() *AppError { - - if o.ServiceSettings.MaximumLoginAttempts <= 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.login_attempts.app_error", nil, "") +func (ts *TeamSettings) isValid() *AppError { + if *ts.MaxUsersPerTeam <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.max_users.app_error", nil, "", http.StatusBadRequest) } - if len(*o.ServiceSettings.SiteURL) != 0 { - if _, err := url.ParseRequestURI(*o.ServiceSettings.SiteURL); err != nil { - return NewLocAppError("Config.IsValid", "model.config.is_valid.site_url.app_error", nil, "") - } + if *ts.MaxChannelsPerTeam <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.max_channels.app_error", nil, "", http.StatusBadRequest) } - if len(o.ServiceSettings.ListenAddress) == 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.listen_address.app_error", nil, "") + if *ts.MaxNotificationsPerChannel <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.max_notify_per_channel.app_error", nil, "", http.StatusBadRequest) } - if *o.ClusterSettings.Enable && *o.EmailSettings.EnableEmailBatching { - return NewLocAppError("Config.IsValid", "model.config.is_valid.cluster_email_batching.app_error", nil, "") + if !(*ts.RestrictDirectMessage == DIRECT_MESSAGE_ANY || *ts.RestrictDirectMessage == DIRECT_MESSAGE_TEAM) { + return NewAppError("Config.IsValid", "model.config.is_valid.restrict_direct_message.app_error", nil, "", http.StatusBadRequest) } - if len(*o.ServiceSettings.SiteURL) == 0 && *o.EmailSettings.EnableEmailBatching { - return NewLocAppError("Config.IsValid", "model.config.is_valid.site_url_email_batching.app_error", nil, "") + if !(*ts.TeammateNameDisplay == SHOW_FULLNAME || *ts.TeammateNameDisplay == SHOW_NICKNAME_FULLNAME || *ts.TeammateNameDisplay == SHOW_USERNAME) { + return NewAppError("Config.IsValid", "model.config.is_valid.teammate_name_display.app_error", nil, "", http.StatusBadRequest) } - if o.TeamSettings.MaxUsersPerTeam <= 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.max_users.app_error", nil, "") + if len(ts.SiteName) > SITENAME_MAX_LENGTH { + return NewAppError("Config.IsValid", "model.config.is_valid.sitename_length.app_error", map[string]interface{}{"MaxLength": SITENAME_MAX_LENGTH}, "", http.StatusBadRequest) } - if *o.TeamSettings.MaxChannelsPerTeam <= 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.max_channels.app_error", nil, "") - } + return nil +} - if *o.TeamSettings.MaxNotificationsPerChannel <= 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.max_notify_per_channel.app_error", nil, "") +func (ss *SqlSettings) isValid() *AppError { + if len(ss.AtRestEncryptKey) < 32 { + return NewAppError("Config.IsValid", "model.config.is_valid.encrypt_sql.app_error", nil, "", http.StatusBadRequest) } - if !(*o.TeamSettings.RestrictDirectMessage == DIRECT_MESSAGE_ANY || *o.TeamSettings.RestrictDirectMessage == DIRECT_MESSAGE_TEAM) { - return NewLocAppError("Config.IsValid", "model.config.is_valid.restrict_direct_message.app_error", nil, "") + if !(*ss.DriverName == DATABASE_DRIVER_MYSQL || *ss.DriverName == DATABASE_DRIVER_POSTGRES) { + return NewAppError("Config.IsValid", "model.config.is_valid.sql_driver.app_error", nil, "", http.StatusBadRequest) } - if !(*o.TeamSettings.TeammateNameDisplay == SHOW_FULLNAME || *o.TeamSettings.TeammateNameDisplay == SHOW_NICKNAME_FULLNAME || *o.TeamSettings.TeammateNameDisplay == SHOW_USERNAME) { - return NewLocAppError("Config.IsValid", "model.config.is_valid.teammate_name_display.app_error", nil, "") + if *ss.MaxIdleConns <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.sql_idle.app_error", nil, "", http.StatusBadRequest) } - if len(o.SqlSettings.AtRestEncryptKey) < 32 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.encrypt_sql.app_error", nil, "") + if *ss.QueryTimeout <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.sql_query_timeout.app_error", nil, "", http.StatusBadRequest) } - if !(o.SqlSettings.DriverName == DATABASE_DRIVER_MYSQL || o.SqlSettings.DriverName == DATABASE_DRIVER_POSTGRES) { - return NewLocAppError("Config.IsValid", "model.config.is_valid.sql_driver.app_error", nil, "") + if len(*ss.DataSource) == 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.sql_data_src.app_error", nil, "", http.StatusBadRequest) } - if o.SqlSettings.MaxIdleConns <= 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.sql_idle.app_error", nil, "") + if *ss.MaxOpenConns <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.sql_max_conn.app_error", nil, "", http.StatusBadRequest) } - if *o.SqlSettings.QueryTimeout <= 0 { - return NewAppError("Config.IsValid", "model.config.is_valid.sql_query_timeout.app_error", nil, "", http.StatusBadRequest) - } + return nil +} - if len(o.SqlSettings.DataSource) == 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.sql_data_src.app_error", nil, "") +func (fs *FileSettings) isValid() *AppError { + if *fs.MaxFileSize <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.max_file_size.app_error", nil, "", http.StatusBadRequest) } - if o.SqlSettings.MaxOpenConns <= 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.sql_max_conn.app_error", nil, "") + if !(*fs.DriverName == IMAGE_DRIVER_LOCAL || *fs.DriverName == IMAGE_DRIVER_S3) { + return NewAppError("Config.IsValid", "model.config.is_valid.file_driver.app_error", nil, "", http.StatusBadRequest) } - if *o.FileSettings.MaxFileSize <= 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.max_file_size.app_error", nil, "") + if len(*fs.PublicLinkSalt) < 32 { + return NewAppError("Config.IsValid", "model.config.is_valid.file_salt.app_error", nil, "", http.StatusBadRequest) } - if !(o.FileSettings.DriverName == IMAGE_DRIVER_LOCAL || o.FileSettings.DriverName == IMAGE_DRIVER_S3) { - return NewLocAppError("Config.IsValid", "model.config.is_valid.file_driver.app_error", nil, "") - } + return nil +} - if len(*o.FileSettings.PublicLinkSalt) < 32 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.file_salt.app_error", nil, "") +func (es *EmailSettings) isValid() *AppError { + if !(es.ConnectionSecurity == CONN_SECURITY_NONE || es.ConnectionSecurity == CONN_SECURITY_TLS || es.ConnectionSecurity == CONN_SECURITY_STARTTLS || es.ConnectionSecurity == CONN_SECURITY_PLAIN) { + return NewAppError("Config.IsValid", "model.config.is_valid.email_security.app_error", nil, "", http.StatusBadRequest) } - if !(o.EmailSettings.ConnectionSecurity == CONN_SECURITY_NONE || o.EmailSettings.ConnectionSecurity == CONN_SECURITY_TLS || o.EmailSettings.ConnectionSecurity == CONN_SECURITY_STARTTLS || o.EmailSettings.ConnectionSecurity == CONN_SECURITY_PLAIN) { - return NewLocAppError("Config.IsValid", "model.config.is_valid.email_security.app_error", nil, "") + if len(es.InviteSalt) < 32 { + return NewAppError("Config.IsValid", "model.config.is_valid.email_salt.app_error", nil, "", http.StatusBadRequest) } - if len(o.EmailSettings.InviteSalt) < 32 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.email_salt.app_error", nil, "") + if *es.EmailBatchingBufferSize <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.email_batching_buffer_size.app_error", nil, "", http.StatusBadRequest) } - if *o.EmailSettings.EmailBatchingBufferSize <= 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.email_batching_buffer_size.app_error", nil, "") + if *es.EmailBatchingInterval < 30 { + return NewAppError("Config.IsValid", "model.config.is_valid.email_batching_interval.app_error", nil, "", http.StatusBadRequest) } - if *o.EmailSettings.EmailBatchingInterval < 30 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.email_batching_interval.app_error", nil, "") + if !(*es.EmailNotificationContentsType == EMAIL_NOTIFICATION_CONTENTS_FULL || *es.EmailNotificationContentsType == EMAIL_NOTIFICATION_CONTENTS_GENERIC) { + return NewAppError("Config.IsValid", "model.config.is_valid.email_notification_contents_type.app_error", nil, "", http.StatusBadRequest) } - if !(*o.EmailSettings.EmailNotificationContentsType == EMAIL_NOTIFICATION_CONTENTS_FULL || *o.EmailSettings.EmailNotificationContentsType == EMAIL_NOTIFICATION_CONTENTS_GENERIC) { - return NewLocAppError("Config.IsValid", "model.config.is_valid.email_notification_contents_type.app_error", nil, "") + return nil +} + +func (rls *RateLimitSettings) isValid() *AppError { + if *rls.MemoryStoreSize <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.rate_mem.app_error", nil, "", http.StatusBadRequest) } - if o.RateLimitSettings.MemoryStoreSize <= 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.rate_mem.app_error", nil, "") + if *rls.PerSec <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.rate_sec.app_error", nil, "", http.StatusBadRequest) } - if o.RateLimitSettings.PerSec <= 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.rate_sec.app_error", nil, "") + if *rls.MaxBurst <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.max_burst.app_error", nil, "", http.StatusBadRequest) } - if !(*o.LdapSettings.ConnectionSecurity == CONN_SECURITY_NONE || *o.LdapSettings.ConnectionSecurity == CONN_SECURITY_TLS || *o.LdapSettings.ConnectionSecurity == CONN_SECURITY_STARTTLS) { - return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_security.app_error", nil, "") + return nil +} + +func (ls *LdapSettings) isValid() *AppError { + if !(*ls.ConnectionSecurity == CONN_SECURITY_NONE || *ls.ConnectionSecurity == CONN_SECURITY_TLS || *ls.ConnectionSecurity == CONN_SECURITY_STARTTLS) { + return NewAppError("Config.IsValid", "model.config.is_valid.ldap_security.app_error", nil, "", http.StatusBadRequest) } - if *o.LdapSettings.SyncIntervalMinutes <= 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_sync_interval.app_error", nil, "") + if *ls.SyncIntervalMinutes <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.ldap_sync_interval.app_error", nil, "", http.StatusBadRequest) } - if *o.LdapSettings.MaxPageSize < 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_max_page_size.app_error", nil, "") + if *ls.MaxPageSize < 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.ldap_max_page_size.app_error", nil, "", http.StatusBadRequest) } - if *o.LdapSettings.Enable { - if *o.LdapSettings.LdapServer == "" { - return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_server", nil, "") + if *ls.Enable { + if *ls.LdapServer == "" { + return NewAppError("Config.IsValid", "model.config.is_valid.ldap_server", nil, "", http.StatusBadRequest) } - if *o.LdapSettings.BaseDN == "" { - return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_basedn", nil, "") + if *ls.BaseDN == "" { + return NewAppError("Config.IsValid", "model.config.is_valid.ldap_basedn", nil, "", http.StatusBadRequest) } - if *o.LdapSettings.EmailAttribute == "" { - return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_email", nil, "") + if *ls.EmailAttribute == "" { + return NewAppError("Config.IsValid", "model.config.is_valid.ldap_email", nil, "", http.StatusBadRequest) } - if *o.LdapSettings.UsernameAttribute == "" { - return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_username", nil, "") + if *ls.UsernameAttribute == "" { + return NewAppError("Config.IsValid", "model.config.is_valid.ldap_username", nil, "", http.StatusBadRequest) } - if *o.LdapSettings.IdAttribute == "" { - return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_id", nil, "") + if *ls.IdAttribute == "" { + return NewAppError("Config.IsValid", "model.config.is_valid.ldap_id", nil, "", http.StatusBadRequest) } } - if *o.SamlSettings.Enable { - if len(*o.SamlSettings.IdpUrl) == 0 || !IsValidHttpUrl(*o.SamlSettings.IdpUrl) { - return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_idp_url.app_error", nil, "") + return nil +} + +func (ss *SamlSettings) isValid() *AppError { + if *ss.Enable { + if len(*ss.IdpUrl) == 0 || !IsValidHttpUrl(*ss.IdpUrl) { + return NewAppError("Config.IsValid", "model.config.is_valid.saml_idp_url.app_error", nil, "", http.StatusBadRequest) } - if len(*o.SamlSettings.IdpDescriptorUrl) == 0 || !IsValidHttpUrl(*o.SamlSettings.IdpDescriptorUrl) { - return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_idp_descriptor_url.app_error", nil, "") + if len(*ss.IdpDescriptorUrl) == 0 || !IsValidHttpUrl(*ss.IdpDescriptorUrl) { + return NewAppError("Config.IsValid", "model.config.is_valid.saml_idp_descriptor_url.app_error", nil, "", http.StatusBadRequest) } - if len(*o.SamlSettings.IdpCertificateFile) == 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_idp_cert.app_error", nil, "") + if len(*ss.IdpCertificateFile) == 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.saml_idp_cert.app_error", nil, "", http.StatusBadRequest) } - if len(*o.SamlSettings.EmailAttribute) == 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_email_attribute.app_error", nil, "") + if len(*ss.EmailAttribute) == 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.saml_email_attribute.app_error", nil, "", http.StatusBadRequest) } - if len(*o.SamlSettings.UsernameAttribute) == 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_username_attribute.app_error", nil, "") + if len(*ss.UsernameAttribute) == 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.saml_username_attribute.app_error", nil, "", http.StatusBadRequest) } - if *o.SamlSettings.Verify { - if len(*o.SamlSettings.AssertionConsumerServiceURL) == 0 || !IsValidHttpUrl(*o.SamlSettings.AssertionConsumerServiceURL) { - return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_assertion_consumer_service_url.app_error", nil, "") + if *ss.Verify { + if len(*ss.AssertionConsumerServiceURL) == 0 || !IsValidHttpUrl(*ss.AssertionConsumerServiceURL) { + return NewAppError("Config.IsValid", "model.config.is_valid.saml_assertion_consumer_service_url.app_error", nil, "", http.StatusBadRequest) } } - if *o.SamlSettings.Encrypt { - if len(*o.SamlSettings.PrivateKeyFile) == 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_private_key.app_error", nil, "") + if *ss.Encrypt { + if len(*ss.PrivateKeyFile) == 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.saml_private_key.app_error", nil, "", http.StatusBadRequest) } - if len(*o.SamlSettings.PublicCertificateFile) == 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_public_cert.app_error", nil, "") + if len(*ss.PublicCertificateFile) == 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.saml_public_cert.app_error", nil, "", http.StatusBadRequest) } } - if len(*o.SamlSettings.EmailAttribute) == 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_email_attribute.app_error", nil, "") + if len(*ss.EmailAttribute) == 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.saml_email_attribute.app_error", nil, "", http.StatusBadRequest) } } - if *o.PasswordSettings.MinimumLength < PASSWORD_MINIMUM_LENGTH || *o.PasswordSettings.MinimumLength > PASSWORD_MAXIMUM_LENGTH { - return NewLocAppError("Config.IsValid", "model.config.is_valid.password_length.app_error", map[string]interface{}{"MinLength": PASSWORD_MINIMUM_LENGTH, "MaxLength": PASSWORD_MAXIMUM_LENGTH}, "") + return nil +} + +func (ws *WebrtcSettings) isValid() *AppError { + if *ws.Enable { + if len(*ws.GatewayWebsocketUrl) == 0 || !IsValidWebsocketUrl(*ws.GatewayWebsocketUrl) { + return NewAppError("Config.IsValid", "model.config.is_valid.webrtc_gateway_ws_url.app_error", nil, "", http.StatusBadRequest) + } else if len(*ws.GatewayAdminUrl) == 0 || !IsValidHttpUrl(*ws.GatewayAdminUrl) { + return NewAppError("Config.IsValid", "model.config.is_valid.webrtc_gateway_admin_url.app_error", nil, "", http.StatusBadRequest) + } else if len(*ws.GatewayAdminSecret) == 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.webrtc_gateway_admin_secret.app_error", nil, "", http.StatusBadRequest) + } else if len(*ws.StunURI) != 0 && !IsValidTurnOrStunServer(*ws.StunURI) { + return NewAppError("Config.IsValid", "model.config.is_valid.webrtc_stun_uri.app_error", nil, "", http.StatusBadRequest) + } else if len(*ws.TurnURI) != 0 { + if !IsValidTurnOrStunServer(*ws.TurnURI) { + return NewAppError("Config.IsValid", "model.config.is_valid.webrtc_turn_uri.app_error", nil, "", http.StatusBadRequest) + } + if len(*ws.TurnUsername) == 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.webrtc_turn_username.app_error", nil, "", http.StatusBadRequest) + } else if len(*ws.TurnSharedKey) == 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.webrtc_turn_shared_key.app_error", nil, "", http.StatusBadRequest) + } + } } - if len(o.TeamSettings.SiteName) > SITENAME_MAX_LENGTH { - return NewLocAppError("Config.IsValid", "model.config.is_valid.sitename_length.app_error", map[string]interface{}{"MaxLength": SITENAME_MAX_LENGTH}, "") + return nil +} + +func (ss *ServiceSettings) isValid() *AppError { + if !(*ss.ConnectionSecurity == CONN_SECURITY_NONE || *ss.ConnectionSecurity == CONN_SECURITY_TLS) { + return NewAppError("Config.IsValid", "model.config.is_valid.webserver_security.app_error", nil, "", http.StatusBadRequest) } - if *o.RateLimitSettings.MaxBurst <= 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.max_burst.app_error", nil, "") + if *ss.ReadTimeout <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.read_timeout.app_error", nil, "", http.StatusBadRequest) } - if err := o.isValidWebrtcSettings(); err != nil { - return err + if *ss.WriteTimeout <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.write_timeout.app_error", nil, "", http.StatusBadRequest) } - if !(*o.ServiceSettings.ConnectionSecurity == CONN_SECURITY_NONE || *o.ServiceSettings.ConnectionSecurity == CONN_SECURITY_TLS) { - return NewLocAppError("Config.IsValid", "model.config.is_valid.webserver_security.app_error", nil, "") + if *ss.TimeBetweenUserTypingUpdatesMilliseconds < 1000 { + return NewAppError("Config.IsValid", "model.config.is_valid.time_between_user_typing.app_error", nil, "", http.StatusBadRequest) } - if *o.ServiceSettings.ReadTimeout <= 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.read_timeout.app_error", nil, "") + if *ss.MaximumLoginAttempts <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.login_attempts.app_error", nil, "", http.StatusBadRequest) } - if *o.ServiceSettings.WriteTimeout <= 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.write_timeout.app_error", nil, "") + if len(*ss.SiteURL) != 0 { + if _, err := url.ParseRequestURI(*ss.SiteURL); err != nil { + return NewAppError("Config.IsValid", "model.config.is_valid.site_url.app_error", nil, "", http.StatusBadRequest) + } } - if *o.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds < 1000 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.time_between_user_typing.app_error", nil, "") + if len(*ss.ListenAddress) == 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.listen_address.app_error", nil, "", http.StatusBadRequest) } - if *o.ElasticsearchSettings.EnableIndexing { - if len(*o.ElasticsearchSettings.ConnectionUrl) == 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.elastic_search.connection_url.app_error", nil, "") + return nil +} + +func (ess *ElasticsearchSettings) isValid() *AppError { + if *ess.EnableIndexing { + if len(*ess.ConnectionUrl) == 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.elastic_search.connection_url.app_error", nil, "", http.StatusBadRequest) } } - if *o.ElasticsearchSettings.EnableSearching && !*o.ElasticsearchSettings.EnableIndexing { - return NewLocAppError("Config.IsValid", "model.config.is_valid.elastic_search.enable_searching.app_error", nil, "") + if *ess.EnableSearching && !*ess.EnableIndexing { + return NewAppError("Config.IsValid", "model.config.is_valid.elastic_search.enable_searching.app_error", nil, "", http.StatusBadRequest) + } + + if *ess.AggregatePostsAfterDays < 1 { + return NewAppError("Config.IsValid", "model.config.is_valid.elastic_search.aggregate_posts_after_days.app_error", nil, "", http.StatusBadRequest) + } + + if _, err := time.Parse("15:04", *ess.PostsAggregatorJobStartTime); err != nil { + return NewAppError("Config.IsValid", "model.config.is_valid.elastic_search.posts_aggregator_job_start_time.app_error", nil, err.Error(), http.StatusBadRequest) + } + + if *ess.LiveIndexingBatchSize < 1 { + return NewAppError("Config.IsValid", "model.config.is_valid.elastic_search.live_indexing_batch_size.app_error", nil, "", http.StatusBadRequest) } + if *ess.BulkIndexingTimeWindowSeconds < 1 { + return NewAppError("Config.IsValid", "model.config.is_valid.elastic_search.bulk_indexing_time_window_seconds.app_error", nil, "", http.StatusBadRequest) + } + + if *ess.RequestTimeoutSeconds < 1 { + return NewAppError("Config.IsValid", "model.config.is_valid.elastic_search.request_timeout_seconds.app_error", nil, "", http.StatusBadRequest) + } + + return nil +} + +func (drs *DataRetentionSettings) isValid() *AppError { + if *drs.MessageRetentionDays <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.data_retention.message_retention_days_too_low.app_error", nil, "", http.StatusBadRequest) + } + + if *drs.FileRetentionDays <= 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.data_retention.file_retention_days_too_low.app_error", nil, "", http.StatusBadRequest) + } + + if _, err := time.Parse("15:04", *drs.DeletionJobStartTime); err != nil { + return NewAppError("Config.IsValid", "model.config.is_valid.data_retention.deletion_job_start_time.app_error", nil, err.Error(), http.StatusBadRequest) + } + + return nil +} + +func (ls *LocalizationSettings) isValid() *AppError { + if len(*ls.AvailableLocales) > 0 { + if !strings.Contains(*ls.AvailableLocales, *ls.DefaultClientLocale) { + return NewAppError("Config.IsValid", "model.config.is_valid.localization.available_locales.app_error", nil, "", http.StatusBadRequest) + } + } + + return nil +} + +func (mes *MessageExportSettings) isValid(fs FileSettings) *AppError { + if mes.EnableExport == nil { + return NewAppError("Config.IsValid", "model.config.is_valid.message_export.enable.app_error", nil, "", http.StatusBadRequest) + } + if *mes.EnableExport { + if mes.ExportFromTimestamp == nil || *mes.ExportFromTimestamp < 0 || *mes.ExportFromTimestamp > GetMillis() { + return NewAppError("Config.IsValid", "model.config.is_valid.message_export.export_from.app_error", nil, "", http.StatusBadRequest) + } else if mes.DailyRunTime == nil { + return NewAppError("Config.IsValid", "model.config.is_valid.message_export.daily_runtime.app_error", nil, "", http.StatusBadRequest) + } else if _, err := time.Parse("15:04", *mes.DailyRunTime); err != nil { + return NewAppError("Config.IsValid", "model.config.is_valid.message_export.daily_runtime.app_error", nil, err.Error(), http.StatusBadRequest) + } else if mes.BatchSize == nil || *mes.BatchSize < 0 { + return NewAppError("Config.IsValid", "model.config.is_valid.message_export.batch_size.app_error", nil, "", http.StatusBadRequest) + } + } return nil } @@ -1725,7 +2153,7 @@ func (o *Config) Sanitize() { o.GitLabSettings.Secret = FAKE_SETTING } - o.SqlSettings.DataSource = FAKE_SETTING + *o.SqlSettings.DataSource = FAKE_SETTING o.SqlSettings.AtRestEncryptKey = FAKE_SETTING for i := range o.SqlSettings.DataSourceReplicas { @@ -1738,71 +2166,3 @@ func (o *Config) Sanitize() { *o.ElasticsearchSettings.Password = FAKE_SETTING } - -func (o *Config) defaultWebrtcSettings() { - if o.WebrtcSettings.Enable == nil { - o.WebrtcSettings.Enable = new(bool) - *o.WebrtcSettings.Enable = false - } - - if o.WebrtcSettings.GatewayWebsocketUrl == nil { - o.WebrtcSettings.GatewayWebsocketUrl = new(string) - *o.WebrtcSettings.GatewayWebsocketUrl = "" - } - - if o.WebrtcSettings.GatewayAdminUrl == nil { - o.WebrtcSettings.GatewayAdminUrl = new(string) - *o.WebrtcSettings.GatewayAdminUrl = "" - } - - if o.WebrtcSettings.GatewayAdminSecret == nil { - o.WebrtcSettings.GatewayAdminSecret = new(string) - *o.WebrtcSettings.GatewayAdminSecret = "" - } - - if o.WebrtcSettings.StunURI == nil { - o.WebrtcSettings.StunURI = new(string) - *o.WebrtcSettings.StunURI = WEBRTC_SETTINGS_DEFAULT_STUN_URI - } - - if o.WebrtcSettings.TurnURI == nil { - o.WebrtcSettings.TurnURI = new(string) - *o.WebrtcSettings.TurnURI = WEBRTC_SETTINGS_DEFAULT_TURN_URI - } - - if o.WebrtcSettings.TurnUsername == nil { - o.WebrtcSettings.TurnUsername = new(string) - *o.WebrtcSettings.TurnUsername = "" - } - - if o.WebrtcSettings.TurnSharedKey == nil { - o.WebrtcSettings.TurnSharedKey = new(string) - *o.WebrtcSettings.TurnSharedKey = "" - } -} - -func (o *Config) isValidWebrtcSettings() *AppError { - if *o.WebrtcSettings.Enable { - if len(*o.WebrtcSettings.GatewayWebsocketUrl) == 0 || !IsValidWebsocketUrl(*o.WebrtcSettings.GatewayWebsocketUrl) { - return NewLocAppError("Config.IsValid", "model.config.is_valid.webrtc_gateway_ws_url.app_error", nil, "") - } else if len(*o.WebrtcSettings.GatewayAdminUrl) == 0 || !IsValidHttpUrl(*o.WebrtcSettings.GatewayAdminUrl) { - return NewLocAppError("Config.IsValid", "model.config.is_valid.webrtc_gateway_admin_url.app_error", nil, "") - } else if len(*o.WebrtcSettings.GatewayAdminSecret) == 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.webrtc_gateway_admin_secret.app_error", nil, "") - } else if len(*o.WebrtcSettings.StunURI) != 0 && !IsValidTurnOrStunServer(*o.WebrtcSettings.StunURI) { - return NewLocAppError("Config.IsValid", "model.config.is_valid.webrtc_stun_uri.app_error", nil, "") - } else if len(*o.WebrtcSettings.TurnURI) != 0 { - if !IsValidTurnOrStunServer(*o.WebrtcSettings.TurnURI) { - return NewLocAppError("Config.IsValid", "model.config.is_valid.webrtc_turn_uri.app_error", nil, "") - } - if len(*o.WebrtcSettings.TurnUsername) == 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.webrtc_turn_username.app_error", nil, "") - } else if len(*o.WebrtcSettings.TurnSharedKey) == 0 { - return NewLocAppError("Config.IsValid", "model.config.is_valid.webrtc_turn_shared_key.app_error", nil, "") - } - - } - } - - return nil -} diff --git a/vendor/github.com/mattermost/platform/model/data_retention_policy.go b/vendor/github.com/mattermost/platform/model/data_retention_policy.go new file mode 100644 index 00000000..7284477e --- /dev/null +++ b/vendor/github.com/mattermost/platform/model/data_retention_policy.go @@ -0,0 +1,36 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "encoding/json" + "io" +) + +type DataRetentionPolicy struct { + MessageDeletionEnabled bool `json:"message_deletion_enabled"` + FileDeletionEnabled bool `json:"file_deletion_enabled"` + MessageRetentionCutoff int64 `json:"message_retention_cutoff"` + FileRetentionCutoff int64 `json:"file_retention_cutoff"` +} + +func (me *DataRetentionPolicy) ToJson() string { + b, err := json.Marshal(me) + if err != nil { + return "" + } else { + return string(b) + } +} + +func DataRetentionPolicyFromJson(data io.Reader) *DataRetentionPolicy { + decoder := json.NewDecoder(data) + var me DataRetentionPolicy + err := decoder.Decode(&me) + if err == nil { + return &me + } else { + return nil + } +} diff --git a/vendor/github.com/mattermost/platform/model/emoji.go b/vendor/github.com/mattermost/platform/model/emoji.go index 5ade868c..272616d9 100644 --- a/vendor/github.com/mattermost/platform/model/emoji.go +++ b/vendor/github.com/mattermost/platform/model/emoji.go @@ -6,6 +6,7 @@ package model import ( "encoding/json" "io" + "net/http" ) type Emoji struct { @@ -19,23 +20,23 @@ type Emoji struct { func (emoji *Emoji) IsValid() *AppError { if len(emoji.Id) != 26 { - return NewLocAppError("Emoji.IsValid", "model.emoji.id.app_error", nil, "") + return NewAppError("Emoji.IsValid", "model.emoji.id.app_error", nil, "", http.StatusBadRequest) } if emoji.CreateAt == 0 { - return NewLocAppError("Emoji.IsValid", "model.emoji.create_at.app_error", nil, "id="+emoji.Id) + return NewAppError("Emoji.IsValid", "model.emoji.create_at.app_error", nil, "id="+emoji.Id, http.StatusBadRequest) } if emoji.UpdateAt == 0 { - return NewLocAppError("Emoji.IsValid", "model.emoji.update_at.app_error", nil, "id="+emoji.Id) + return NewAppError("Emoji.IsValid", "model.emoji.update_at.app_error", nil, "id="+emoji.Id, http.StatusBadRequest) } if len(emoji.CreatorId) != 26 { - return NewLocAppError("Emoji.IsValid", "model.emoji.user_id.app_error", nil, "") + return NewAppError("Emoji.IsValid", "model.emoji.user_id.app_error", nil, "", http.StatusBadRequest) } if len(emoji.Name) == 0 || len(emoji.Name) > 64 || !IsValidAlphaNumHyphenUnderscore(emoji.Name, false) { - return NewLocAppError("Emoji.IsValid", "model.emoji.name.app_error", nil, "") + return NewAppError("Emoji.IsValid", "model.emoji.name.app_error", nil, "", http.StatusBadRequest) } return nil diff --git a/vendor/github.com/mattermost/platform/model/file_info.go b/vendor/github.com/mattermost/platform/model/file_info.go index 8b568412..0ee2c50d 100644 --- a/vendor/github.com/mattermost/platform/model/file_info.go +++ b/vendor/github.com/mattermost/platform/model/file_info.go @@ -10,6 +10,7 @@ import ( "image/gif" "io" "mime" + "net/http" "path/filepath" "strings" ) @@ -80,33 +81,36 @@ func (o *FileInfo) PreSave() { if o.CreateAt == 0 { o.CreateAt = GetMillis() + } + + if o.UpdateAt < o.CreateAt { o.UpdateAt = o.CreateAt } } func (o *FileInfo) IsValid() *AppError { if len(o.Id) != 26 { - return NewLocAppError("FileInfo.IsValid", "model.file_info.is_valid.id.app_error", nil, "") + return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.id.app_error", nil, "", http.StatusBadRequest) } if len(o.CreatorId) != 26 { - return NewLocAppError("FileInfo.IsValid", "model.file_info.is_valid.user_id.app_error", nil, "id="+o.Id) + return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.user_id.app_error", nil, "id="+o.Id, http.StatusBadRequest) } if len(o.PostId) != 0 && len(o.PostId) != 26 { - return NewLocAppError("FileInfo.IsValid", "model.file_info.is_valid.post_id.app_error", nil, "id="+o.Id) + return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.post_id.app_error", nil, "id="+o.Id, http.StatusBadRequest) } if o.CreateAt == 0 { - return NewLocAppError("FileInfo.IsValid", "model.file_info.is_valid.create_at.app_error", nil, "id="+o.Id) + return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.create_at.app_error", nil, "id="+o.Id, http.StatusBadRequest) } if o.UpdateAt == 0 { - return NewLocAppError("FileInfo.IsValid", "model.file_info.is_valid.update_at.app_error", nil, "id="+o.Id) + return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.update_at.app_error", nil, "id="+o.Id, http.StatusBadRequest) } if o.Path == "" { - return NewLocAppError("FileInfo.IsValid", "model.file_info.is_valid.path.app_error", nil, "id="+o.Id) + return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.path.app_error", nil, "id="+o.Id, http.StatusBadRequest) } return nil @@ -144,7 +148,7 @@ func GetInfoForBytes(name string, data []byte) (*FileInfo, *AppError) { if gifConfig, err := gif.DecodeAll(bytes.NewReader(data)); err != nil { // Still return the rest of the info even though it doesn't appear to be an actual gif info.HasPreviewImage = true - err = NewLocAppError("GetInfoForBytes", "model.file_info.get.gif.app_error", nil, "name="+name) + err = NewAppError("GetInfoForBytes", "model.file_info.get.gif.app_error", nil, "name="+name, http.StatusBadRequest) } else { info.HasPreviewImage = len(gifConfig.Image) == 1 } diff --git a/vendor/github.com/mattermost/platform/model/gitlab/gitlab.go b/vendor/github.com/mattermost/platform/model/gitlab/gitlab.go index 7f1447ed..7e0cb10a 100644 --- a/vendor/github.com/mattermost/platform/model/gitlab/gitlab.go +++ b/vendor/github.com/mattermost/platform/model/gitlab/gitlab.go @@ -5,11 +5,12 @@ package oauthgitlab import ( "encoding/json" - "github.com/mattermost/platform/einterfaces" - "github.com/mattermost/platform/model" "io" "strconv" "strings" + + "github.com/mattermost/mattermost-server/einterfaces" + "github.com/mattermost/mattermost-server/model" ) type GitLabProvider struct { @@ -45,7 +46,6 @@ func userFromGitLabUser(glu *GitLabUser) *model.User { } else { user.FirstName = glu.Name } - strings.TrimSpace(user.Email) user.Email = glu.Email userId := strconv.FormatInt(glu.Id, 10) user.AuthData = &userId diff --git a/vendor/github.com/mattermost/platform/model/incoming_webhook.go b/vendor/github.com/mattermost/platform/model/incoming_webhook.go index ce755f88..3e0488d2 100644 --- a/vendor/github.com/mattermost/platform/model/incoming_webhook.go +++ b/vendor/github.com/mattermost/platform/model/incoming_webhook.go @@ -25,6 +25,8 @@ type IncomingWebhook struct { TeamId string `json:"team_id"` DisplayName string `json:"display_name"` Description string `json:"description"` + Username string `json:"username"` + IconURL string `json:"icon_url"` } type IncomingWebhookRequest struct { @@ -112,6 +114,14 @@ func (o *IncomingWebhook) IsValid() *AppError { return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.description.app_error", nil, "", http.StatusBadRequest) } + if len(o.Username) > 64 { + return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.username.app_error", nil, "", http.StatusBadRequest) + } + + if len(o.IconURL) > 1024 { + return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.icon_url.app_error", nil, "", http.StatusBadRequest) + } + return nil } @@ -193,7 +203,7 @@ func decodeIncomingWebhookRequest(by []byte) (*IncomingWebhookRequest, error) { } } -func IncomingWebhookRequestFromJson(data io.Reader) *IncomingWebhookRequest { +func IncomingWebhookRequestFromJson(data io.Reader) (*IncomingWebhookRequest, *AppError) { buf := new(bytes.Buffer) buf.ReadFrom(data) by := buf.Bytes() @@ -204,12 +214,11 @@ func IncomingWebhookRequestFromJson(data io.Reader) *IncomingWebhookRequest { if err != nil { o, err = decodeIncomingWebhookRequest(escapeControlCharsFromPayload(by)) if err != nil { - return nil + return nil, NewAppError("IncomingWebhookRequestFromJson", "Unable to parse incoming data", nil, err.Error(), http.StatusBadRequest) } } - o.Text = ExpandAnnouncement(o.Text) - o.Attachments = ProcessSlackAttachments(o.Attachments) + o.Attachments = StringifySlackFieldValue(o.Attachments) - return o + return o, nil } diff --git a/vendor/github.com/mattermost/platform/model/job.go b/vendor/github.com/mattermost/platform/model/job.go index 004331a1..9a756602 100644 --- a/vendor/github.com/mattermost/platform/model/job.go +++ b/vendor/github.com/mattermost/platform/model/job.go @@ -7,11 +7,15 @@ import ( "encoding/json" "io" "net/http" + "time" ) const ( - JOB_TYPE_DATA_RETENTION = "data_retention" - JOB_TYPE_ELASTICSEARCH_POST_INDEXING = "elasticsearch_post_indexing" + JOB_TYPE_DATA_RETENTION = "data_retention" + JOB_TYPE_MESSAGE_EXPORT = "message_export" + JOB_TYPE_ELASTICSEARCH_POST_INDEXING = "elasticsearch_post_indexing" + JOB_TYPE_ELASTICSEARCH_POST_AGGREGATION = "elasticsearch_post_aggregation" + JOB_TYPE_LDAP_SYNC = "ldap_sync" JOB_STATUS_PENDING = "pending" JOB_STATUS_IN_PROGRESS = "in_progress" @@ -22,15 +26,15 @@ const ( ) type Job struct { - Id string `json:"id"` - Type string `json:"type"` - Priority int64 `json:"priority"` - CreateAt int64 `json:"create_at"` - StartAt int64 `json:"start_at"` - LastActivityAt int64 `json:"last_activity_at"` - Status string `json:"status"` - Progress int64 `json:"progress"` - Data map[string]interface{} `json:"data"` + Id string `json:"id"` + Type string `json:"type"` + Priority int64 `json:"priority"` + CreateAt int64 `json:"create_at"` + StartAt int64 `json:"start_at"` + LastActivityAt int64 `json:"last_activity_at"` + Status string `json:"status"` + Progress int64 `json:"progress"` + Data map[string]string `json:"data"` } func (j *Job) IsValid() *AppError { @@ -45,6 +49,9 @@ func (j *Job) IsValid() *AppError { switch j.Type { case JOB_TYPE_DATA_RETENTION: case JOB_TYPE_ELASTICSEARCH_POST_INDEXING: + case JOB_TYPE_ELASTICSEARCH_POST_AGGREGATION: + case JOB_TYPE_LDAP_SYNC: + case JOB_TYPE_MESSAGE_EXPORT: default: return NewAppError("Job.IsValid", "model.job.is_valid.type.app_error", nil, "id="+j.Id, http.StatusBadRequest) } @@ -112,6 +119,9 @@ type Worker interface { } type Scheduler interface { - Run() - Stop() + Name() string + JobType() string + Enabled(cfg *Config) bool + NextScheduleTime(cfg *Config, now time.Time, pendingJobs bool, lastSuccessfulJob *Job) *time.Time + ScheduleJob(cfg *Config, pendingJobs bool, lastSuccessfulJob *Job) (*Job, *AppError) } diff --git a/vendor/github.com/mattermost/platform/model/license.go b/vendor/github.com/mattermost/platform/model/license.go index ea108972..a81f882c 100644 --- a/vendor/github.com/mattermost/platform/model/license.go +++ b/vendor/github.com/mattermost/platform/model/license.go @@ -6,6 +6,7 @@ package model import ( "encoding/json" "io" + "net/http" ) const ( @@ -51,7 +52,10 @@ type Features struct { PasswordRequirements *bool `json:"password_requirements"` Elasticsearch *bool `json:"elastic_search"` Announcement *bool `json:"announcement"` + ThemeManagement *bool `json:"theme_management"` EmailNotificationContents *bool `json:"email_notification_contents"` + DataRetention *bool `json:"data_retention"` + MessageExport *bool `json:"message_export"` // after we enabled more features for webrtc we'll need to control them with this FutureFeatures *bool `json:"future_features"` @@ -72,106 +76,96 @@ func (f *Features) ToMap() map[string]interface{} { "password": *f.PasswordRequirements, "elastic_search": *f.Elasticsearch, "email_notification_contents": *f.EmailNotificationContents, + "data_retention": *f.DataRetention, + "message_export": *f.MessageExport, "future": *f.FutureFeatures, } } func (f *Features) SetDefaults() { if f.FutureFeatures == nil { - f.FutureFeatures = new(bool) - *f.FutureFeatures = true + f.FutureFeatures = NewBool(true) } if f.Users == nil { - f.Users = new(int) - *f.Users = 0 + f.Users = NewInt(0) } if f.LDAP == nil { - f.LDAP = new(bool) - *f.LDAP = *f.FutureFeatures + f.LDAP = NewBool(*f.FutureFeatures) } if f.MFA == nil { - f.MFA = new(bool) - *f.MFA = *f.FutureFeatures + f.MFA = NewBool(*f.FutureFeatures) } if f.GoogleOAuth == nil { - f.GoogleOAuth = new(bool) - *f.GoogleOAuth = *f.FutureFeatures + f.GoogleOAuth = NewBool(*f.FutureFeatures) } if f.Office365OAuth == nil { - f.Office365OAuth = new(bool) - *f.Office365OAuth = *f.FutureFeatures + f.Office365OAuth = NewBool(*f.FutureFeatures) } if f.Compliance == nil { - f.Compliance = new(bool) - *f.Compliance = *f.FutureFeatures + f.Compliance = NewBool(*f.FutureFeatures) } if f.Cluster == nil { - f.Cluster = new(bool) - *f.Cluster = *f.FutureFeatures + f.Cluster = NewBool(*f.FutureFeatures) } if f.Metrics == nil { - f.Metrics = new(bool) - *f.Metrics = *f.FutureFeatures + f.Metrics = NewBool(*f.FutureFeatures) } if f.CustomBrand == nil { - f.CustomBrand = new(bool) - *f.CustomBrand = *f.FutureFeatures + f.CustomBrand = NewBool(*f.FutureFeatures) } if f.MHPNS == nil { - f.MHPNS = new(bool) - *f.MHPNS = *f.FutureFeatures + f.MHPNS = NewBool(*f.FutureFeatures) } if f.SAML == nil { - f.SAML = new(bool) - *f.SAML = *f.FutureFeatures + f.SAML = NewBool(*f.FutureFeatures) } if f.PasswordRequirements == nil { - f.PasswordRequirements = new(bool) - *f.PasswordRequirements = *f.FutureFeatures + f.PasswordRequirements = NewBool(*f.FutureFeatures) } if f.Elasticsearch == nil { - f.Elasticsearch = new(bool) - *f.Elasticsearch = *f.FutureFeatures + f.Elasticsearch = NewBool(*f.FutureFeatures) } if f.Announcement == nil { - f.Announcement = new(bool) - *f.Announcement = true + f.Announcement = NewBool(true) + } + + if f.ThemeManagement == nil { + f.ThemeManagement = NewBool(true) } if f.EmailNotificationContents == nil { - f.EmailNotificationContents = new(bool) - *f.EmailNotificationContents = *f.FutureFeatures + f.EmailNotificationContents = NewBool(*f.FutureFeatures) + } + + if f.DataRetention == nil { + f.DataRetention = NewBool(*f.FutureFeatures) + } + + if f.MessageExport == nil { + f.MessageExport = NewBool(*f.FutureFeatures) } } func (l *License) IsExpired() bool { - now := GetMillis() - if l.ExpiresAt < now { - return true - } - return false + return l.ExpiresAt < GetMillis() } func (l *License) IsStarted() bool { - now := GetMillis() - if l.StartsAt < now { - return true - } - return false + return l.StartsAt < GetMillis() } func (l *License) ToJson() string { @@ -196,15 +190,15 @@ func LicenseFromJson(data io.Reader) *License { func (lr *LicenseRecord) IsValid() *AppError { if len(lr.Id) != 26 { - return NewLocAppError("LicenseRecord.IsValid", "model.license_record.is_valid.id.app_error", nil, "") + return NewAppError("LicenseRecord.IsValid", "model.license_record.is_valid.id.app_error", nil, "", http.StatusBadRequest) } if lr.CreateAt == 0 { - return NewLocAppError("LicenseRecord.IsValid", "model.license_record.is_valid.create_at.app_error", nil, "") + return NewAppError("LicenseRecord.IsValid", "model.license_record.is_valid.create_at.app_error", nil, "", http.StatusBadRequest) } if len(lr.Bytes) == 0 || len(lr.Bytes) > 10000 { - return NewLocAppError("LicenseRecord.IsValid", "model.license_record.is_valid.create_at.app_error", nil, "") + return NewAppError("LicenseRecord.IsValid", "model.license_record.is_valid.create_at.app_error", nil, "", http.StatusBadRequest) } return nil diff --git a/vendor/github.com/mattermost/platform/model/manifest.go b/vendor/github.com/mattermost/platform/model/manifest.go new file mode 100644 index 00000000..03d78f84 --- /dev/null +++ b/vendor/github.com/mattermost/platform/model/manifest.go @@ -0,0 +1,246 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "encoding/json" + "io" + "io/ioutil" + "os" + "path/filepath" + + "gopkg.in/yaml.v2" +) + +const ( + PLUGIN_CONFIG_TYPE_TEXT = "text" + PLUGIN_CONFIG_TYPE_BOOL = "bool" + PLUGIN_CONFIG_TYPE_RADIO = "radio" + PLUGIN_CONFIG_TYPE_DROPDOWN = "dropdown" + PLUGIN_CONFIG_TYPE_GENERATED = "generated" + PLUGIN_CONFIG_TYPE_USERNAME = "username" +) + +type PluginOption struct { + // The display name for the option. + DisplayName string `json:"display_name" yaml:"display_name"` + + // The string value for the option. + Value string `json:"value" yaml:"value"` +} + +type PluginSetting struct { + // The key that the setting will be assigned to in the configuration file. + Key string `json:"key" yaml:"key"` + + // The display name for the setting. + DisplayName string `json:"display_name" yaml:"display_name"` + + // The type of the setting. + // + // "bool" will result in a boolean true or false setting. + // + // "dropdown" will result in a string setting that allows the user to select from a list of + // pre-defined options. + // + // "generated" will result in a string setting that is set to a random, cryptographically secure + // string. + // + // "radio" will result in a string setting that allows the user to select from a short selection + // of pre-defined options. + // + // "text" will result in a string setting that can be typed in manually. + // + // "username" will result in a text setting that will autocomplete to a username. + Type string `json:"type" yaml:"type"` + + // The help text to display to the user. + HelpText string `json:"help_text" yaml:"help_text"` + + // The help text to display alongside the "Regenerate" button for settings of the "generated" type. + RegenerateHelpText string `json:"regenerate_help_text,omitempty" yaml:"regenerate_help_text,omitempty"` + + // The placeholder to display for "text", "generated" and "username" types when blank. + Placeholder string `json:"placeholder" yaml:"placeholder"` + + // The default value of the setting. + Default interface{} `json:"default" yaml:"default"` + + // For "radio" or "dropdown" settings, this is the list of pre-defined options that the user can choose + // from. + Options []*PluginOption `json:"options,omitempty" yaml:"options,omitempty"` +} + +type PluginSettingsSchema struct { + // Optional text to display above the settings. + Header string `json:"header" yaml:"header"` + + // Optional text to display below the settings. + Footer string `json:"footer" yaml:"footer"` + + // A list of setting definitions. + Settings []*PluginSetting `json:"settings" yaml:"settings"` +} + +// The plugin manifest defines the metadata required to load and present your plugin. The manifest +// file should be named plugin.json or plugin.yaml and placed in the top of your +// plugin bundle. +// +// Example plugin.yaml: +// +// id: com.mycompany.myplugin +// name: My Plugin +// description: This is my plugin. It does stuff. +// backend: +// executable: myplugin +// settings_schema: +// settings: +// - key: enable_extra_thing +// type: bool +// display_name: Enable Extra Thing +// help_text: When true, an extra thing will be enabled! +// default: false +type Manifest struct { + // The id is a globally unique identifier that represents your plugin. Ids are limited + // to 190 characters. Reverse-DNS notation using a name you control is a good option. + // For example, "com.mycompany.myplugin". + Id string `json:"id" yaml:"id"` + + // The name to be displayed for the plugin. + Name string `json:"name,omitempty" yaml:"name,omitempty"` + + // A description of what your plugin is and does. + Description string `json:"description,omitempty" yaml:"description,omitempty"` + + // A version number for your plugin. Semantic versioning is recommended: http://semver.org + Version string `json:"version" yaml:"version"` + + // If your plugin extends the server, you'll need define backend. + Backend *ManifestBackend `json:"backend,omitempty" yaml:"backend,omitempty"` + + // If your plugin extends the web app, you'll need to define webapp. + Webapp *ManifestWebapp `json:"webapp,omitempty" yaml:"webapp,omitempty"` + + // To allow administrators to configure your plugin via the Mattermost system console, you can + // provide your settings schema. + SettingsSchema *PluginSettingsSchema `json:"settings_schema,omitempty" yaml:"settings_schema,omitempty"` +} + +type ManifestBackend struct { + // The path to your executable binary. This should be relative to the root of your bundle and the + // location of the manifest file. + // + // On Windows, this file must have a ".exe" extension. + Executable string `json:"executable" yaml:"executable"` +} + +type ManifestWebapp struct { + // The path to your webapp bundle. This should be relative to the root of your bundle and the + // location of the manifest file. + BundlePath string `json:"bundle_path" yaml:"bundle_path"` +} + +func (m *Manifest) ToJson() string { + b, err := json.Marshal(m) + if err != nil { + return "" + } else { + return string(b) + } +} + +func ManifestListToJson(m []*Manifest) string { + b, err := json.Marshal(m) + if err != nil { + return "" + } else { + return string(b) + } +} + +func ManifestFromJson(data io.Reader) *Manifest { + decoder := json.NewDecoder(data) + var m Manifest + err := decoder.Decode(&m) + if err == nil { + return &m + } else { + return nil + } +} + +func ManifestListFromJson(data io.Reader) []*Manifest { + decoder := json.NewDecoder(data) + var manifests []*Manifest + err := decoder.Decode(&manifests) + if err == nil { + return manifests + } else { + return nil + } +} + +func (m *Manifest) HasClient() bool { + return m.Webapp != nil +} + +func (m *Manifest) ClientManifest() *Manifest { + cm := new(Manifest) + *cm = *m + cm.Name = "" + cm.Description = "" + cm.Backend = nil + return cm +} + +// FindManifest will find and parse the manifest in a given directory. +// +// In all cases other than a does-not-exist error, path is set to the path of the manifest file that was +// found. +// +// Manifests are JSON or YAML files named plugin.json, plugin.yaml, or plugin.yml. +func FindManifest(dir string) (manifest *Manifest, path string, err error) { + for _, name := range []string{"plugin.yml", "plugin.yaml"} { + path = filepath.Join(dir, name) + f, ferr := os.Open(path) + if ferr != nil { + if !os.IsNotExist(ferr) { + err = ferr + return + } + continue + } + b, ioerr := ioutil.ReadAll(f) + f.Close() + if ioerr != nil { + err = ioerr + return + } + var parsed Manifest + err = yaml.Unmarshal(b, &parsed) + if err != nil { + return + } + manifest = &parsed + return + } + + path = filepath.Join(dir, "plugin.json") + f, ferr := os.Open(path) + if ferr != nil { + if os.IsNotExist(ferr) { + path = "" + } + err = ferr + return + } + defer f.Close() + var parsed Manifest + err = json.NewDecoder(f).Decode(&parsed) + if err != nil { + return + } + manifest = &parsed + return +} diff --git a/vendor/github.com/mattermost/platform/model/message_export.go b/vendor/github.com/mattermost/platform/model/message_export.go new file mode 100644 index 00000000..b59b114d --- /dev/null +++ b/vendor/github.com/mattermost/platform/model/message_export.go @@ -0,0 +1,18 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +type MessageExport struct { + ChannelId *string + ChannelDisplayName *string + + UserId *string + UserEmail *string + + PostId *string + PostCreateAt *int64 + PostMessage *string + PostType *string + PostFileIds StringArray +} diff --git a/vendor/github.com/mattermost/platform/model/outgoing_webhook.go b/vendor/github.com/mattermost/platform/model/outgoing_webhook.go index 59408c24..477a277d 100644 --- a/vendor/github.com/mattermost/platform/model/outgoing_webhook.go +++ b/vendor/github.com/mattermost/platform/model/outgoing_webhook.go @@ -45,6 +45,17 @@ type OutgoingWebhookPayload struct { FileIds string `json:"file_ids"` } +type OutgoingWebhookResponse struct { + Text *string `json:"text"` + Username string `json:"username"` + IconURL string `json:"icon_url"` + Props StringInterface `json:"props"` + Type string `json:"type"` + ResponseType string `json:"response_type"` +} + +const OUTGOING_HOOK_RESPONSE_TYPE_COMMENT = "comment" + func (o *OutgoingWebhookPayload) ToJSON() string { b, err := json.Marshal(o) if err != nil { @@ -112,6 +123,26 @@ func OutgoingWebhookListFromJson(data io.Reader) []*OutgoingWebhook { } } +func (o *OutgoingWebhookResponse) ToJson() string { + b, err := json.Marshal(o) + if err != nil { + return "" + } else { + return string(b) + } +} + +func OutgoingWebhookResponseFromJson(data io.Reader) *OutgoingWebhookResponse { + decoder := json.NewDecoder(data) + var o OutgoingWebhookResponse + err := decoder.Decode(&o) + if err == nil { + return &o + } else { + return nil + } +} + func (o *OutgoingWebhook) IsValid() *AppError { if len(o.Id) != 26 { diff --git a/vendor/github.com/mattermost/platform/model/plugin_key_value.go b/vendor/github.com/mattermost/platform/model/plugin_key_value.go new file mode 100644 index 00000000..b7a7731c --- /dev/null +++ b/vendor/github.com/mattermost/platform/model/plugin_key_value.go @@ -0,0 +1,32 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "net/http" + "unicode/utf8" +) + +const ( + KEY_VALUE_PLUGIN_ID_MAX_RUNES = 190 + KEY_VALUE_KEY_MAX_RUNES = 50 +) + +type PluginKeyValue struct { + PluginId string `json:"plugin_id"` + Key string `json:"key" db:"PKey"` + Value []byte `json:"value" db:"PValue"` +} + +func (kv *PluginKeyValue) IsValid() *AppError { + if len(kv.PluginId) == 0 || utf8.RuneCountInString(kv.PluginId) > KEY_VALUE_PLUGIN_ID_MAX_RUNES { + return NewAppError("PluginKeyValue.IsValid", "model.plugin_key_value.is_valid.plugin_id.app_error", map[string]interface{}{"Max": KEY_VALUE_KEY_MAX_RUNES, "Min": 0}, "key="+kv.Key, http.StatusBadRequest) + } + + if len(kv.Key) == 0 || utf8.RuneCountInString(kv.Key) > KEY_VALUE_KEY_MAX_RUNES { + return NewAppError("PluginKeyValue.IsValid", "model.plugin_key_value.is_valid.key.app_error", map[string]interface{}{"Max": KEY_VALUE_KEY_MAX_RUNES, "Min": 0}, "key="+kv.Key, http.StatusBadRequest) + } + + return nil +} diff --git a/vendor/github.com/mattermost/platform/model/plugins_response.go b/vendor/github.com/mattermost/platform/model/plugins_response.go new file mode 100644 index 00000000..74c89af2 --- /dev/null +++ b/vendor/github.com/mattermost/platform/model/plugins_response.go @@ -0,0 +1,39 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "encoding/json" + "io" +) + +type PluginInfo struct { + Manifest + Prepackaged bool `json:"prepackaged"` +} + +type PluginsResponse struct { + Active []*PluginInfo `json:"active"` + Inactive []*PluginInfo `json:"inactive"` +} + +func (m *PluginsResponse) ToJson() string { + b, err := json.Marshal(m) + if err != nil { + return "" + } else { + return string(b) + } +} + +func PluginsResponseFromJson(data io.Reader) *PluginsResponse { + decoder := json.NewDecoder(data) + var m PluginsResponse + err := decoder.Decode(&m) + if err == nil { + return &m + } else { + return nil + } +} diff --git a/vendor/github.com/mattermost/platform/model/post.go b/vendor/github.com/mattermost/platform/model/post.go index 55e6f591..6b282fbf 100644 --- a/vendor/github.com/mattermost/platform/model/post.go +++ b/vendor/github.com/mattermost/platform/model/post.go @@ -6,6 +6,9 @@ package model import ( "encoding/json" "io" + "net/http" + "regexp" + "strings" "unicode/utf8" ) @@ -17,9 +20,13 @@ const ( POST_JOIN_LEAVE = "system_join_leave" // Deprecated, use POST_JOIN_CHANNEL or POST_LEAVE_CHANNEL instead POST_JOIN_CHANNEL = "system_join_channel" POST_LEAVE_CHANNEL = "system_leave_channel" + POST_JOIN_TEAM = "system_join_team" + POST_LEAVE_TEAM = "system_leave_team" POST_ADD_REMOVE = "system_add_remove" // Deprecated, use POST_ADD_TO_CHANNEL or POST_REMOVE_FROM_CHANNEL instead POST_ADD_TO_CHANNEL = "system_add_to_channel" POST_REMOVE_FROM_CHANNEL = "system_remove_from_channel" + POST_ADD_TO_TEAM = "system_add_to_team" + POST_REMOVE_FROM_TEAM = "system_remove_from_team" POST_HEADER_CHANGE = "system_header_change" POST_DISPLAYNAME_CHANGE = "system_displayname_change" POST_PURPOSE_CHANGE = "system_purpose_change" @@ -30,6 +37,9 @@ const ( POST_HASHTAGS_MAX_RUNES = 1000 POST_MESSAGE_MAX_RUNES = 4000 POST_PROPS_MAX_RUNES = 8000 + POST_PROPS_MAX_USER_RUNES = POST_PROPS_MAX_RUNES - 400 // Leave some room for system / pre-save modifications + POST_CUSTOM_TYPE_PREFIX = "custom_" + PROPS_ADD_CHANNEL_MEMBER = "add_channel_member" ) type Post struct { @@ -68,8 +78,31 @@ type PostForIndexing struct { ParentCreateAt *int64 `json:"parent_create_at"` } +type PostAction struct { + Id string `json:"id"` + Name string `json:"name"` + Integration *PostActionIntegration `json:"integration,omitempty"` +} + +type PostActionIntegration struct { + URL string `json:"url,omitempty"` + Context StringInterface `json:"context,omitempty"` +} + +type PostActionIntegrationRequest struct { + UserId string `json:"user_id"` + Context StringInterface `json:"context,omitempty"` +} + +type PostActionIntegrationResponse struct { + Update *Post `json:"update"` + EphemeralText string `json:"ephemeral_text"` +} + func (o *Post) ToJson() string { - b, err := json.Marshal(o) + copy := *o + copy.StripActionIntegrations() + b, err := json.Marshal(©) if err != nil { return "" } else { @@ -95,73 +128,100 @@ func (o *Post) Etag() string { func (o *Post) IsValid() *AppError { if len(o.Id) != 26 { - return NewLocAppError("Post.IsValid", "model.post.is_valid.id.app_error", nil, "") + return NewAppError("Post.IsValid", "model.post.is_valid.id.app_error", nil, "", http.StatusBadRequest) } if o.CreateAt == 0 { - return NewLocAppError("Post.IsValid", "model.post.is_valid.create_at.app_error", nil, "id="+o.Id) + return NewAppError("Post.IsValid", "model.post.is_valid.create_at.app_error", nil, "id="+o.Id, http.StatusBadRequest) } if o.UpdateAt == 0 { - return NewLocAppError("Post.IsValid", "model.post.is_valid.update_at.app_error", nil, "id="+o.Id) + return NewAppError("Post.IsValid", "model.post.is_valid.update_at.app_error", nil, "id="+o.Id, http.StatusBadRequest) } if len(o.UserId) != 26 { - return NewLocAppError("Post.IsValid", "model.post.is_valid.user_id.app_error", nil, "") + return NewAppError("Post.IsValid", "model.post.is_valid.user_id.app_error", nil, "", http.StatusBadRequest) } if len(o.ChannelId) != 26 { - return NewLocAppError("Post.IsValid", "model.post.is_valid.channel_id.app_error", nil, "") + return NewAppError("Post.IsValid", "model.post.is_valid.channel_id.app_error", nil, "", http.StatusBadRequest) } if !(len(o.RootId) == 26 || len(o.RootId) == 0) { - return NewLocAppError("Post.IsValid", "model.post.is_valid.root_id.app_error", nil, "") + return NewAppError("Post.IsValid", "model.post.is_valid.root_id.app_error", nil, "", http.StatusBadRequest) } if !(len(o.ParentId) == 26 || len(o.ParentId) == 0) { - return NewLocAppError("Post.IsValid", "model.post.is_valid.parent_id.app_error", nil, "") + return NewAppError("Post.IsValid", "model.post.is_valid.parent_id.app_error", nil, "", http.StatusBadRequest) } if len(o.ParentId) == 26 && len(o.RootId) == 0 { - return NewLocAppError("Post.IsValid", "model.post.is_valid.root_parent.app_error", nil, "") + return NewAppError("Post.IsValid", "model.post.is_valid.root_parent.app_error", nil, "", http.StatusBadRequest) } if !(len(o.OriginalId) == 26 || len(o.OriginalId) == 0) { - return NewLocAppError("Post.IsValid", "model.post.is_valid.original_id.app_error", nil, "") + return NewAppError("Post.IsValid", "model.post.is_valid.original_id.app_error", nil, "", http.StatusBadRequest) } if utf8.RuneCountInString(o.Message) > POST_MESSAGE_MAX_RUNES { - return NewLocAppError("Post.IsValid", "model.post.is_valid.msg.app_error", nil, "id="+o.Id) + return NewAppError("Post.IsValid", "model.post.is_valid.msg.app_error", nil, "id="+o.Id, http.StatusBadRequest) } if utf8.RuneCountInString(o.Hashtags) > POST_HASHTAGS_MAX_RUNES { - return NewLocAppError("Post.IsValid", "model.post.is_valid.hashtags.app_error", nil, "id="+o.Id) + return NewAppError("Post.IsValid", "model.post.is_valid.hashtags.app_error", nil, "id="+o.Id, http.StatusBadRequest) } - // should be removed once more message types are supported - if !(o.Type == POST_DEFAULT || o.Type == POST_JOIN_LEAVE || o.Type == POST_ADD_REMOVE || - o.Type == POST_JOIN_CHANNEL || o.Type == POST_LEAVE_CHANNEL || - o.Type == POST_REMOVE_FROM_CHANNEL || o.Type == POST_ADD_TO_CHANNEL || - o.Type == POST_SLACK_ATTACHMENT || o.Type == POST_HEADER_CHANGE || o.Type == POST_PURPOSE_CHANGE || - o.Type == POST_DISPLAYNAME_CHANGE || o.Type == POST_CHANNEL_DELETED) { - return NewLocAppError("Post.IsValid", "model.post.is_valid.type.app_error", nil, "id="+o.Type) + switch o.Type { + case + POST_DEFAULT, + POST_JOIN_LEAVE, + POST_ADD_REMOVE, + POST_JOIN_CHANNEL, + POST_LEAVE_CHANNEL, + POST_JOIN_TEAM, + POST_LEAVE_TEAM, + POST_ADD_TO_CHANNEL, + POST_REMOVE_FROM_CHANNEL, + POST_ADD_TO_TEAM, + POST_REMOVE_FROM_TEAM, + POST_SLACK_ATTACHMENT, + POST_HEADER_CHANGE, + POST_PURPOSE_CHANGE, + POST_DISPLAYNAME_CHANGE, + POST_CHANNEL_DELETED: + default: + if !strings.HasPrefix(o.Type, POST_CUSTOM_TYPE_PREFIX) { + return NewAppError("Post.IsValid", "model.post.is_valid.type.app_error", nil, "id="+o.Type, http.StatusBadRequest) + } } if utf8.RuneCountInString(ArrayToJson(o.Filenames)) > POST_FILENAMES_MAX_RUNES { - return NewLocAppError("Post.IsValid", "model.post.is_valid.filenames.app_error", nil, "id="+o.Id) + return NewAppError("Post.IsValid", "model.post.is_valid.filenames.app_error", nil, "id="+o.Id, http.StatusBadRequest) } if utf8.RuneCountInString(ArrayToJson(o.FileIds)) > POST_FILEIDS_MAX_RUNES { - return NewLocAppError("Post.IsValid", "model.post.is_valid.file_ids.app_error", nil, "id="+o.Id) + return NewAppError("Post.IsValid", "model.post.is_valid.file_ids.app_error", nil, "id="+o.Id, http.StatusBadRequest) } if utf8.RuneCountInString(StringInterfaceToJson(o.Props)) > POST_PROPS_MAX_RUNES { - return NewLocAppError("Post.IsValid", "model.post.is_valid.props.app_error", nil, "id="+o.Id) + return NewAppError("Post.IsValid", "model.post.is_valid.props.app_error", nil, "id="+o.Id, http.StatusBadRequest) } return nil } +func (o *Post) SanitizeProps() { + membersToSanitize := []string{ + PROPS_ADD_CHANNEL_MEMBER, + } + + for _, member := range membersToSanitize { + if _, ok := o.Props[member]; ok { + delete(o.Props, member) + } + } +} + func (o *Post) PreSave() { if o.Id == "" { o.Id = NewId() @@ -174,7 +234,10 @@ func (o *Post) PreSave() { } o.UpdateAt = o.CreateAt + o.PreCommit() +} +func (o *Post) PreCommit() { if o.Props == nil { o.Props = make(map[string]interface{}) } @@ -186,6 +249,8 @@ func (o *Post) PreSave() { if o.FileIds == nil { o.FileIds = []string{} } + + o.GenerateActionIds() } func (o *Post) MakeNonNil() { @@ -246,3 +311,84 @@ func PostPatchFromJson(data io.Reader) *PostPatch { return &post } + +var channelMentionRegexp = regexp.MustCompile(`\B~[a-zA-Z0-9\-_]+`) + +func (o *Post) ChannelMentions() (names []string) { + if strings.Contains(o.Message, "~") { + alreadyMentioned := make(map[string]bool) + for _, match := range channelMentionRegexp.FindAllString(o.Message, -1) { + name := match[1:] + if !alreadyMentioned[name] { + names = append(names, name) + alreadyMentioned[name] = true + } + } + } + return +} + +func (r *PostActionIntegrationRequest) ToJson() string { + b, err := json.Marshal(r) + if err != nil { + return "" + } else { + return string(b) + } +} + +func (o *Post) Attachments() []*SlackAttachment { + if attachments, ok := o.Props["attachments"].([]*SlackAttachment); ok { + return attachments + } + var ret []*SlackAttachment + if attachments, ok := o.Props["attachments"].([]interface{}); ok { + for _, attachment := range attachments { + if enc, err := json.Marshal(attachment); err == nil { + var decoded SlackAttachment + if json.Unmarshal(enc, &decoded) == nil { + ret = append(ret, &decoded) + } + } + } + } + return ret +} + +func (o *Post) StripActionIntegrations() { + attachments := o.Attachments() + if o.Props["attachments"] != nil { + o.Props["attachments"] = attachments + } + for _, attachment := range attachments { + for _, action := range attachment.Actions { + action.Integration = nil + } + } +} + +func (o *Post) GetAction(id string) *PostAction { + for _, attachment := range o.Attachments() { + for _, action := range attachment.Actions { + if action.Id == id { + return action + } + } + } + return nil +} + +func (o *Post) GenerateActionIds() { + if o.Props["attachments"] != nil { + o.Props["attachments"] = o.Attachments() + } + if attachments, ok := o.Props["attachments"].([]*SlackAttachment); ok { + for _, attachment := range attachments { + for _, action := range attachment.Actions { + if action.Id == "" { + action.Id = NewId() + } + } + } + } +} diff --git a/vendor/github.com/mattermost/platform/model/post_list.go b/vendor/github.com/mattermost/platform/model/post_list.go index 63f6d682..018f7d14 100644 --- a/vendor/github.com/mattermost/platform/model/post_list.go +++ b/vendor/github.com/mattermost/platform/model/post_list.go @@ -6,6 +6,7 @@ package model import ( "encoding/json" "io" + "sort" ) type PostList struct { @@ -20,8 +21,20 @@ func NewPostList() *PostList { } } +func (o *PostList) StripActionIntegrations() { + posts := o.Posts + o.Posts = make(map[string]*Post) + for id, post := range posts { + pcopy := *post + pcopy.StripActionIntegrations() + o.Posts[id] = &pcopy + } +} + func (o *PostList) ToJson() string { - b, err := json.Marshal(o) + copy := *o + copy.StripActionIntegrations() + b, err := json.Marshal(©) if err != nil { return "" } else { @@ -70,6 +83,12 @@ func (o *PostList) Extend(other *PostList) { } } +func (o *PostList) SortByCreateAt() { + sort.Slice(o.Order, func(i, j int) bool { + return o.Posts[o.Order[i]].CreateAt > o.Posts[o.Order[j]].CreateAt + }) +} + func (o *PostList) Etag() string { id := "0" diff --git a/vendor/github.com/mattermost/platform/model/preference.go b/vendor/github.com/mattermost/platform/model/preference.go index 6bbe7326..5d462de8 100644 --- a/vendor/github.com/mattermost/platform/model/preference.go +++ b/vendor/github.com/mattermost/platform/model/preference.go @@ -6,6 +6,7 @@ package model import ( "encoding/json" "io" + "net/http" "regexp" "strings" "unicode/utf8" @@ -67,25 +68,25 @@ func PreferenceFromJson(data io.Reader) *Preference { func (o *Preference) IsValid() *AppError { if len(o.UserId) != 26 { - return NewLocAppError("Preference.IsValid", "model.preference.is_valid.id.app_error", nil, "user_id="+o.UserId) + return NewAppError("Preference.IsValid", "model.preference.is_valid.id.app_error", nil, "user_id="+o.UserId, http.StatusBadRequest) } if len(o.Category) == 0 || len(o.Category) > 32 { - return NewLocAppError("Preference.IsValid", "model.preference.is_valid.category.app_error", nil, "category="+o.Category) + return NewAppError("Preference.IsValid", "model.preference.is_valid.category.app_error", nil, "category="+o.Category, http.StatusBadRequest) } if len(o.Name) > 32 { - return NewLocAppError("Preference.IsValid", "model.preference.is_valid.name.app_error", nil, "name="+o.Name) + return NewAppError("Preference.IsValid", "model.preference.is_valid.name.app_error", nil, "name="+o.Name, http.StatusBadRequest) } if utf8.RuneCountInString(o.Value) > 2000 { - return NewLocAppError("Preference.IsValid", "model.preference.is_valid.value.app_error", nil, "value="+o.Value) + return NewAppError("Preference.IsValid", "model.preference.is_valid.value.app_error", nil, "value="+o.Value, http.StatusBadRequest) } if o.Category == PREFERENCE_CATEGORY_THEME { var unused map[string]string if err := json.NewDecoder(strings.NewReader(o.Value)).Decode(&unused); err != nil { - return NewLocAppError("Preference.IsValid", "model.preference.is_valid.theme.app_error", nil, "value="+o.Value) + return NewAppError("Preference.IsValid", "model.preference.is_valid.theme.app_error", nil, "value="+o.Value, http.StatusBadRequest) } } diff --git a/vendor/github.com/mattermost/platform/model/push_notification.go b/vendor/github.com/mattermost/platform/model/push_notification.go index 654d1d9a..69719e74 100644 --- a/vendor/github.com/mattermost/platform/model/push_notification.go +++ b/vendor/github.com/mattermost/platform/model/push_notification.go @@ -18,7 +18,9 @@ const ( PUSH_TYPE_MESSAGE = "message" PUSH_TYPE_CLEAR = "clear" - CATEGORY_DM = "DIRECT_MESSAGE" + // The category is set to handle a set of interactive Actions + // with the push notifications + CATEGORY_CAN_REPLY = "CAN_REPLY" MHPNS = "https://push.mattermost.com" ) @@ -34,6 +36,8 @@ type PushNotification struct { ContentAvailable int `json:"cont_ava"` TeamId string `json:"team_id"` ChannelId string `json:"channel_id"` + PostId string `json:"post_id"` + RootId string `json:"root_id"` ChannelName string `json:"channel_name"` Type string `json:"type"` SenderId string `json:"sender_id"` diff --git a/vendor/github.com/mattermost/platform/model/reaction.go b/vendor/github.com/mattermost/platform/model/reaction.go index 3d334c21..4b72dd44 100644 --- a/vendor/github.com/mattermost/platform/model/reaction.go +++ b/vendor/github.com/mattermost/platform/model/reaction.go @@ -6,6 +6,7 @@ package model import ( "encoding/json" "io" + "net/http" "regexp" ) @@ -54,21 +55,21 @@ func ReactionsFromJson(data io.Reader) []*Reaction { func (o *Reaction) IsValid() *AppError { if len(o.UserId) != 26 { - return NewLocAppError("Reaction.IsValid", "model.reaction.is_valid.user_id.app_error", nil, "user_id="+o.UserId) + return NewAppError("Reaction.IsValid", "model.reaction.is_valid.user_id.app_error", nil, "user_id="+o.UserId, http.StatusBadRequest) } if len(o.PostId) != 26 { - return NewLocAppError("Reaction.IsValid", "model.reaction.is_valid.post_id.app_error", nil, "post_id="+o.PostId) + return NewAppError("Reaction.IsValid", "model.reaction.is_valid.post_id.app_error", nil, "post_id="+o.PostId, http.StatusBadRequest) } validName := regexp.MustCompile(`^[a-zA-Z0-9\-\+_]+$`) if len(o.EmojiName) == 0 || len(o.EmojiName) > 64 || !validName.MatchString(o.EmojiName) { - return NewLocAppError("Reaction.IsValid", "model.reaction.is_valid.emoji_name.app_error", nil, "emoji_name="+o.EmojiName) + return NewAppError("Reaction.IsValid", "model.reaction.is_valid.emoji_name.app_error", nil, "emoji_name="+o.EmojiName, http.StatusBadRequest) } if o.CreateAt == 0 { - return NewLocAppError("Reaction.IsValid", "model.reaction.is_valid.create_at.app_error", nil, "") + return NewAppError("Reaction.IsValid", "model.reaction.is_valid.create_at.app_error", nil, "", http.StatusBadRequest) } return nil diff --git a/vendor/github.com/mattermost/platform/model/search_params.go b/vendor/github.com/mattermost/platform/model/search_params.go index 070ac6d2..2feea8da 100644 --- a/vendor/github.com/mattermost/platform/model/search_params.go +++ b/vendor/github.com/mattermost/platform/model/search_params.go @@ -31,16 +31,6 @@ func (o *SearchParams) ToJson() string { var searchFlags = [...]string{"from", "channel", "in"} -func splitWordsNoQuotes(text string) []string { - words := []string{} - - for _, word := range strings.Fields(text) { - words = append(words, word) - } - - return words -} - func splitWords(text string) []string { words := []string{} @@ -55,14 +45,14 @@ func splitWords(text string) []string { foundQuote = false location = i + 1 } else { - words = append(words, splitWordsNoQuotes(text[location:i])...) + words = append(words, strings.Fields(text[location:i])...) foundQuote = true location = i } } } - words = append(words, splitWordsNoQuotes(text[location:])...) + words = append(words, strings.Fields(text[location:])...) return words } diff --git a/vendor/github.com/mattermost/platform/model/session.go b/vendor/github.com/mattermost/platform/model/session.go index 960c18cb..704af067 100644 --- a/vendor/github.com/mattermost/platform/model/session.go +++ b/vendor/github.com/mattermost/platform/model/session.go @@ -37,6 +37,11 @@ type Session struct { TeamMembers []*TeamMember `json:"team_members" db:"-"` } +func (me *Session) DeepCopy() *Session { + copy := *me + return © +} + func (me *Session) ToJson() string { b, err := json.Marshal(me) if err != nil { diff --git a/vendor/github.com/mattermost/platform/model/slack_attachment.go b/vendor/github.com/mattermost/platform/model/slack_attachment.go index 85583821..197d3f0f 100644 --- a/vendor/github.com/mattermost/platform/model/slack_attachment.go +++ b/vendor/github.com/mattermost/platform/model/slack_attachment.go @@ -5,7 +5,6 @@ package model import ( "fmt" - "strings" ) type SlackAttachment struct { @@ -25,6 +24,7 @@ type SlackAttachment struct { Footer string `json:"footer"` FooterIcon string `json:"footer_icon"` Timestamp interface{} `json:"ts"` // This is either a string or an int64 + Actions []*PostAction `json:"actions,omitempty"` } type SlackAttachmentField struct { @@ -33,23 +33,7 @@ type SlackAttachmentField struct { Short bool `json:"short"` } -// To mention @channel via a webhook in Slack, the message should contain -// <!channel>, as explained at the bottom of this article: -// https://get.slack.help/hc/en-us/articles/202009646-Making-announcements -func ExpandAnnouncement(text string) string { - c1 := "<!channel>" - c2 := "@channel" - if strings.Contains(text, c1) { - return strings.Replace(text, c1, c2, -1) - } - return text -} - -// Expand announcements in incoming webhooks from Slack. Those announcements -// can be found in the text attribute, or in the pretext, text, title and value -// attributes of the attachment structure. The Slack attachment structure is -// documented here: https://api.slack.com/docs/attachments -func ProcessSlackAttachments(a []*SlackAttachment) []*SlackAttachment { +func StringifySlackFieldValue(a []*SlackAttachment) []*SlackAttachment { var nonNilAttachments []*SlackAttachment for _, attachment := range a { if attachment == nil { @@ -57,10 +41,6 @@ func ProcessSlackAttachments(a []*SlackAttachment) []*SlackAttachment { } nonNilAttachments = append(nonNilAttachments, attachment) - attachment.Pretext = ExpandAnnouncement(attachment.Pretext) - attachment.Text = ExpandAnnouncement(attachment.Text) - attachment.Title = ExpandAnnouncement(attachment.Title) - var nonNilFields []*SlackAttachmentField for _, field := range attachment.Fields { if field == nil { @@ -70,7 +50,7 @@ func ProcessSlackAttachments(a []*SlackAttachment) []*SlackAttachment { if field.Value != nil { // Ensure the value is set to a string if it is set - field.Value = ExpandAnnouncement(fmt.Sprintf("%v", field.Value)) + field.Value = fmt.Sprintf("%v", field.Value) } } attachment.Fields = nonNilFields diff --git a/vendor/github.com/mattermost/platform/model/status.go b/vendor/github.com/mattermost/platform/model/status.go index d838eea0..6da6161e 100644 --- a/vendor/github.com/mattermost/platform/model/status.go +++ b/vendor/github.com/mattermost/platform/model/status.go @@ -11,6 +11,7 @@ import ( const ( STATUS_OFFLINE = "offline" STATUS_AWAY = "away" + STATUS_DND = "dnd" STATUS_ONLINE = "online" STATUS_CACHE_SIZE = SESSION_CACHE_SIZE STATUS_CHANNEL_TIMEOUT = 20000 // 20 seconds diff --git a/vendor/github.com/mattermost/platform/model/team_member.go b/vendor/github.com/mattermost/platform/model/team_member.go index 3a0befa3..6c70b75e 100644 --- a/vendor/github.com/mattermost/platform/model/team_member.go +++ b/vendor/github.com/mattermost/platform/model/team_member.go @@ -6,6 +6,7 @@ package model import ( "encoding/json" "io" + "net/http" "strings" ) @@ -103,11 +104,11 @@ func TeamsUnreadFromJson(data io.Reader) []*TeamUnread { func (o *TeamMember) IsValid() *AppError { if len(o.TeamId) != 26 { - return NewLocAppError("TeamMember.IsValid", "model.team_member.is_valid.team_id.app_error", nil, "") + return NewAppError("TeamMember.IsValid", "model.team_member.is_valid.team_id.app_error", nil, "", http.StatusBadRequest) } if len(o.UserId) != 26 { - return NewLocAppError("TeamMember.IsValid", "model.team_member.is_valid.user_id.app_error", nil, "") + return NewAppError("TeamMember.IsValid", "model.team_member.is_valid.user_id.app_error", nil, "", http.StatusBadRequest) } return nil diff --git a/vendor/github.com/mattermost/platform/model/user.go b/vendor/github.com/mattermost/platform/model/user.go index ab4b21e2..7e767fd5 100644 --- a/vendor/github.com/mattermost/platform/model/user.go +++ b/vendor/github.com/mattermost/platform/model/user.go @@ -88,6 +88,12 @@ type UserPatch struct { Locale *string `json:"locale"` } +type UserAuth struct { + Password string `json:"password,omitempty"` + AuthData *string `json:"auth_data,omitempty"` + AuthService string `json:"auth_service,omitempty"` +} + // IsValid validates the user and returns an error if it isn't configured // correctly. func (u *User) IsValid() *AppError { @@ -228,16 +234,13 @@ func (u *User) SetDefaultNotifications() { u.NotifyProps = make(map[string]string) u.NotifyProps["email"] = "true" u.NotifyProps["push"] = USER_NOTIFY_MENTION - u.NotifyProps["desktop"] = USER_NOTIFY_ALL + u.NotifyProps["desktop"] = USER_NOTIFY_MENTION u.NotifyProps["desktop_sound"] = "true" u.NotifyProps["mention_keys"] = u.Username + ",@" + u.Username u.NotifyProps["channel"] = "true" - - if u.FirstName == "" { - u.NotifyProps["first_name"] = "false" - } else { - u.NotifyProps["first_name"] = "true" - } + u.NotifyProps["push_status"] = STATUS_AWAY + u.NotifyProps["comments"] = "never" + u.NotifyProps["first_name"] = "false" } func (user *User) UpdateMentionKeysFromUsername(oldUsername string) { @@ -312,6 +315,15 @@ func (u *UserPatch) ToJson() string { } } +func (u *UserAuth) ToJson() string { + b, err := json.Marshal(u) + if err != nil { + return "" + } else { + return string(b) + } +} + // Generate a valid strong etag so the browser can cache the results func (u *User) Etag(showFullName, showEmail bool) string { return Etag(u.Id, u.UpdateAt, showFullName, showEmail) @@ -320,8 +332,7 @@ func (u *User) Etag(showFullName, showEmail bool) string { // Remove any private data from the user object func (u *User) Sanitize(options map[string]bool) { u.Password = "" - u.AuthData = new(string) - *u.AuthData = "" + u.AuthData = NewString("") u.MfaSecret = "" if len(options) != 0 && !options["email"] { @@ -341,12 +352,10 @@ func (u *User) Sanitize(options map[string]bool) { func (u *User) ClearNonProfileFields() { u.Password = "" - u.AuthData = new(string) - *u.AuthData = "" + u.AuthData = NewString("") u.MfaSecret = "" u.EmailVerified = false u.AllowMarketing = false - u.Props = StringMap{} u.NotifyProps = StringMap{} u.LastPasswordUpdate = 0 u.FailedAttempts = 0 @@ -437,7 +446,7 @@ func IsValidUserRoles(userRoles string) bool { } func isValidRole(roleId string) bool { - _, ok := BuiltInRoles[roleId] + _, ok := DefaultRoles[roleId] return ok } @@ -500,6 +509,17 @@ func UserPatchFromJson(data io.Reader) *UserPatch { } } +func UserAuthFromJson(data io.Reader) *UserAuth { + decoder := json.NewDecoder(data) + var user UserAuth + err := decoder.Decode(&user) + if err == nil { + return &user + } else { + return nil + } +} + func UserMapToJson(u map[string]*User) string { b, err := json.Marshal(u) if err != nil { diff --git a/vendor/github.com/mattermost/platform/model/user_access_token.go b/vendor/github.com/mattermost/platform/model/user_access_token.go index 090780fd..e189ec23 100644 --- a/vendor/github.com/mattermost/platform/model/user_access_token.go +++ b/vendor/github.com/mattermost/platform/model/user_access_token.go @@ -14,6 +14,7 @@ type UserAccessToken struct { Token string `json:"token,omitempty"` UserId string `json:"user_id"` Description string `json:"description"` + IsActive bool `json:"is_active"` } func (t *UserAccessToken) IsValid() *AppError { @@ -38,6 +39,7 @@ func (t *UserAccessToken) IsValid() *AppError { func (t *UserAccessToken) PreSave() { t.Id = NewId() + t.IsActive = true } func (t *UserAccessToken) ToJson() string { diff --git a/vendor/github.com/mattermost/platform/model/utils.go b/vendor/github.com/mattermost/platform/model/utils.go index 090644ec..e84d44f7 100644 --- a/vendor/github.com/mattermost/platform/model/utils.go +++ b/vendor/github.com/mattermost/platform/model/utils.go @@ -12,12 +12,14 @@ import ( "io" "io/ioutil" "net" + "net/http" "net/mail" "net/url" "regexp" "strconv" "strings" "time" + "unicode" goi18n "github.com/nicksnyder/go-i18n/i18n" "github.com/pborman/uuid" @@ -90,7 +92,7 @@ func AppErrorFromJson(data io.Reader) *AppError { if err == nil { return &er } else { - return NewLocAppError("AppErrorFromJson", "model.utils.decode_json.app_error", nil, "body: "+str) + return NewAppError("AppErrorFromJson", "model.utils.decode_json.app_error", nil, "body: "+str, http.StatusInternalServerError) } } @@ -106,18 +108,6 @@ func NewAppError(where string, id string, params map[string]interface{}, details return ap } -func NewLocAppError(where string, id string, params map[string]interface{}, details string) *AppError { - ap := &AppError{} - ap.Id = id - ap.params = params - ap.Message = id - ap.Where = where - ap.DetailedError = details - ap.StatusCode = 500 - ap.IsOAuth = false - return ap -} - var encoding = base32.NewEncoding("ybndrfg8ejkmcpqxot1uwisza345h769") // NewId is a globally unique identifier. It is a [A-Z0-9] string 26 @@ -283,11 +273,7 @@ func GetServerIpAddress() string { } func IsLower(s string) bool { - if strings.ToLower(s) == s { - return true - } - - return false + return strings.ToLower(s) == s } func IsValidEmail(email string) bool { @@ -492,3 +478,17 @@ func IsValidNumberString(value string) bool { return true } + +func IsValidId(value string) bool { + if len(value) != 26 { + return false + } + + for _, r := range value { + if !unicode.IsLetter(r) && !unicode.IsNumber(r) { + return false + } + } + + return true +} diff --git a/vendor/github.com/mattermost/platform/model/version.go b/vendor/github.com/mattermost/platform/model/version.go index b08af46b..430924ee 100644 --- a/vendor/github.com/mattermost/platform/model/version.go +++ b/vendor/github.com/mattermost/platform/model/version.go @@ -13,6 +13,11 @@ import ( // It should be maitained in chronological order with most current // release at the front of the list. var versions = []string{ + "4.6.0", + "4.5.0", + "4.4.0", + "4.3.0", + "4.2.0", "4.1.0", "4.0.0", "3.10.0", diff --git a/vendor/github.com/mattermost/platform/model/websocket_client.go b/vendor/github.com/mattermost/platform/model/websocket_client.go index 2fa405f3..e5c44dde 100644 --- a/vendor/github.com/mattermost/platform/model/websocket_client.go +++ b/vendor/github.com/mattermost/platform/model/websocket_client.go @@ -5,6 +5,8 @@ package model import ( "encoding/json" + "net/http" + "github.com/gorilla/websocket" ) @@ -29,7 +31,7 @@ type WebSocketClient struct { func NewWebSocketClient(url, authToken string) (*WebSocketClient, *AppError) { conn, _, err := websocket.DefaultDialer.Dial(url+API_URL_SUFFIX_V3+"/users/websocket", nil) if err != nil { - return nil, NewLocAppError("NewWebSocketClient", "model.websocket_client.connect_fail.app_error", nil, err.Error()) + return nil, NewAppError("NewWebSocketClient", "model.websocket_client.connect_fail.app_error", nil, err.Error(), http.StatusInternalServerError) } client := &WebSocketClient{ @@ -54,7 +56,7 @@ func NewWebSocketClient(url, authToken string) (*WebSocketClient, *AppError) { func NewWebSocketClient4(url, authToken string) (*WebSocketClient, *AppError) { conn, _, err := websocket.DefaultDialer.Dial(url+API_URL_SUFFIX+"/websocket", nil) if err != nil { - return nil, NewLocAppError("NewWebSocketClient4", "model.websocket_client.connect_fail.app_error", nil, err.Error()) + return nil, NewAppError("NewWebSocketClient4", "model.websocket_client.connect_fail.app_error", nil, err.Error(), http.StatusInternalServerError) } client := &WebSocketClient{ @@ -78,7 +80,7 @@ func (wsc *WebSocketClient) Connect() *AppError { var err error wsc.Conn, _, err = websocket.DefaultDialer.Dial(wsc.ConnectUrl, nil) if err != nil { - return NewLocAppError("Connect", "model.websocket_client.connect_fail.app_error", nil, err.Error()) + return NewAppError("Connect", "model.websocket_client.connect_fail.app_error", nil, err.Error(), http.StatusInternalServerError) } wsc.EventChannel = make(chan *WebSocketEvent, 100) @@ -106,7 +108,7 @@ func (wsc *WebSocketClient) Listen() { var err error if _, rawMsg, err = wsc.Conn.ReadMessage(); err != nil { if !websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseNoStatusReceived) { - wsc.ListenError = NewLocAppError("NewWebSocketClient", "model.websocket_client.connect_fail.app_error", nil, err.Error()) + wsc.ListenError = NewAppError("NewWebSocketClient", "model.websocket_client.connect_fail.app_error", nil, err.Error(), http.StatusInternalServerError) } return diff --git a/vendor/github.com/mattermost/platform/model/websocket_message.go b/vendor/github.com/mattermost/platform/model/websocket_message.go index 6b8c0342..bf2535dc 100644 --- a/vendor/github.com/mattermost/platform/model/websocket_message.go +++ b/vendor/github.com/mattermost/platform/model/websocket_message.go @@ -24,6 +24,7 @@ const ( WEBSOCKET_EVENT_UPDATE_TEAM = "update_team" WEBSOCKET_EVENT_USER_ADDED = "user_added" WEBSOCKET_EVENT_USER_UPDATED = "user_updated" + WEBSOCKET_EVENT_USER_ROLE_UPDATED = "user_role_updated" WEBSOCKET_EVENT_MEMBERROLE_UPDATED = "memberrole_updated" WEBSOCKET_EVENT_USER_REMOVED = "user_removed" WEBSOCKET_EVENT_PREFERENCE_CHANGED = "preference_changed" @@ -39,6 +40,8 @@ const ( WEBSOCKET_EVENT_RESPONSE = "response" WEBSOCKET_EVENT_EMOJI_ADDED = "emoji_added" WEBSOCKET_EVENT_CHANNEL_VIEWED = "channel_viewed" + WEBSOCKET_EVENT_PLUGIN_ACTIVATED = "plugin_activated" // EXPERIMENTAL - SUBJECT TO CHANGE + WEBSOCKET_EVENT_PLUGIN_DEACTIVATED = "plugin_deactivated" // EXPERIMENTAL - SUBJECT TO CHANGE ) type WebSocketMessage interface { |