Update dependencies for 5.6 (#24)

This commit is contained in:
Hanzei 2018-12-17 08:28:01 +01:00 committed by GitHub
parent 76ba0b57a7
commit 415e8b5f72
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 3499 additions and 1746 deletions

View file

@ -429,6 +429,41 @@ Go package for fast and reliable abstraction of browser user agent strings.
---
## blang/semver
This product contains 'semver' by Benedikt Lang.
Semantic Versioning (semver) library written in golang
* HOMEPAGE:
* https://github.com/blang/semver
* LICENSE: MIT
The MIT License
Copyright (c) 2014 Benedikt Lang <github at benediktlang.de>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---
## dgryski/dgoogauth
This product contains 'dgoogauth' by Damian Gryski.
@ -2947,6 +2982,41 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
---
## sirupsen/logrus
This product contains 'logrus' by Simon Eskildsen.
Structured, pluggable logging for Go.
* HOMEPAGE:
* https://github.com/sirupsen/logrus
* LICENSE: MIT
The MIT License (MIT)
Copyright (c) 2014 Simon Eskildsen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---
## spf13/cobra
This product contains 'cobra' by Steve Francia.

View file

@ -29,6 +29,9 @@ const (
CHANNEL_HEADER_MAX_RUNES = 1024
CHANNEL_PURPOSE_MAX_RUNES = 250
CHANNEL_CACHE_SIZE = 25000
CHANNEL_SORT_BY_USERNAME = "username"
CHANNEL_SORT_BY_STATUS = "status"
)
type Channel struct {

View file

@ -11,12 +11,16 @@ import (
)
const (
CHANNEL_NOTIFY_DEFAULT = "default"
CHANNEL_NOTIFY_ALL = "all"
CHANNEL_NOTIFY_MENTION = "mention"
CHANNEL_NOTIFY_NONE = "none"
CHANNEL_MARK_UNREAD_ALL = "all"
CHANNEL_MARK_UNREAD_MENTION = "mention"
CHANNEL_NOTIFY_DEFAULT = "default"
CHANNEL_NOTIFY_ALL = "all"
CHANNEL_NOTIFY_MENTION = "mention"
CHANNEL_NOTIFY_NONE = "none"
CHANNEL_MARK_UNREAD_ALL = "all"
CHANNEL_MARK_UNREAD_MENTION = "mention"
IGNORE_CHANNEL_MENTIONS_DEFAULT = "default"
IGNORE_CHANNEL_MENTIONS_OFF = "off"
IGNORE_CHANNEL_MENTIONS_ON = "on"
IGNORE_CHANNEL_MENTIONS_NOTIFY_PROP = "ignore_channel_mentions"
)
type ChannelUnread struct {
@ -116,6 +120,12 @@ func (o *ChannelMember) IsValid() *AppError {
}
}
if ignoreChannelMentions, ok := o.NotifyProps[IGNORE_CHANNEL_MENTIONS_NOTIFY_PROP]; ok {
if len(ignoreChannelMentions) > 40 || !IsIgnoreChannelMentionsValid(ignoreChannelMentions) {
return NewAppError("ChannelMember.IsValid", "model.channel_member.is_valid.ignore_channel_mentions_value.app_error", nil, "ignore_channel_mentions="+ignoreChannelMentions, http.StatusBadRequest)
}
}
return nil
}
@ -146,11 +156,16 @@ func IsSendEmailValid(sendEmail string) bool {
return sendEmail == CHANNEL_NOTIFY_DEFAULT || sendEmail == "true" || sendEmail == "false"
}
func IsIgnoreChannelMentionsValid(ignoreChannelMentions string) bool {
return ignoreChannelMentions == IGNORE_CHANNEL_MENTIONS_ON || ignoreChannelMentions == IGNORE_CHANNEL_MENTIONS_OFF || ignoreChannelMentions == IGNORE_CHANNEL_MENTIONS_DEFAULT
}
func GetDefaultChannelNotifyProps() StringMap {
return StringMap{
DESKTOP_NOTIFY_PROP: CHANNEL_NOTIFY_DEFAULT,
MARK_UNREAD_NOTIFY_PROP: CHANNEL_MARK_UNREAD_ALL,
PUSH_NOTIFY_PROP: CHANNEL_NOTIFY_DEFAULT,
EMAIL_NOTIFY_PROP: CHANNEL_NOTIFY_DEFAULT,
DESKTOP_NOTIFY_PROP: CHANNEL_NOTIFY_DEFAULT,
MARK_UNREAD_NOTIFY_PROP: CHANNEL_MARK_UNREAD_ALL,
PUSH_NOTIFY_PROP: CHANNEL_NOTIFY_DEFAULT,
EMAIL_NOTIFY_PROP: CHANNEL_NOTIFY_DEFAULT,
IGNORE_CHANNEL_MENTIONS_NOTIFY_PROP: IGNORE_CHANNEL_MENTIONS_DEFAULT,
}
}

File diff suppressed because it is too large Load diff

View file

@ -16,6 +16,7 @@ type CommandArgs struct {
TeamId string `json:"team_id"`
RootId string `json:"root_id"`
ParentId string `json:"parent_id"`
TriggerId string `json:"trigger_id,omitempty"`
Command string `json:"command"`
SiteURL string `json:"-"`
T goi18n.TranslateFunc `json:"-"`

View file

@ -18,14 +18,16 @@ const (
)
type CommandResponse struct {
ResponseType string `json:"response_type"`
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"`
ResponseType string `json:"response_type"`
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"`
TriggerId string `json:"trigger_id"`
Attachments []*SlackAttachment `json:"attachments"`
ExtraResponses []*CommandResponse `json:"extra_responses"`
}
func (o *CommandResponse) ToJson() string {
@ -63,5 +65,11 @@ func CommandResponseFromJson(data io.Reader) (*CommandResponse, error) {
o.Attachments = StringifySlackFieldValue(o.Attachments)
if o.ExtraResponses != nil {
for _, resp := range o.ExtraResponses {
resp.Attachments = StringifySlackFieldValue(resp.Attachments)
}
}
return &o, nil
}

View file

@ -4,12 +4,14 @@
package model
import (
"crypto/tls"
"encoding/json"
"io"
"math"
"net"
"net/http"
"net/url"
"os"
"regexp"
"strconv"
"strings"
@ -110,6 +112,7 @@ const (
SUPPORT_SETTINGS_DEFAULT_HELP_LINK = "https://about.mattermost.com/default-help/"
SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK = "https://about.mattermost.com/default-report-a-problem/"
SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL = "feedback@mattermost.com"
SUPPORT_SETTINGS_DEFAULT_RE_ACCEPTANCE_PERIOD = 365
LDAP_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE = ""
LDAP_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE = ""
@ -133,9 +136,6 @@ const (
NATIVEAPP_SETTINGS_DEFAULT_ANDROID_APP_DOWNLOAD_LINK = "https://about.mattermost.com/mattermost-android-app/"
NATIVEAPP_SETTINGS_DEFAULT_IOS_APP_DOWNLOAD_LINK = "https://about.mattermost.com/mattermost-ios-app/"
WEBRTC_SETTINGS_DEFAULT_STUN_URI = ""
WEBRTC_SETTINGS_DEFAULT_TURN_URI = ""
ANALYTICS_SETTINGS_DEFAULT_MAX_USERS_FOR_STATISTICS = 2500
ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_COLOR = "#f2a93b"
@ -174,6 +174,31 @@ const (
CLIENT_SIDE_CERT_CHECK_SECONDARY_AUTH = "secondary"
)
var ServerTLSSupportedCiphers = map[string]uint16{
"TLS_RSA_WITH_RC4_128_SHA": tls.TLS_RSA_WITH_RC4_128_SHA,
"TLS_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
"TLS_RSA_WITH_AES_128_CBC_SHA": tls.TLS_RSA_WITH_AES_128_CBC_SHA,
"TLS_RSA_WITH_AES_256_CBC_SHA": tls.TLS_RSA_WITH_AES_256_CBC_SHA,
"TLS_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
"TLS_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
"TLS_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
"TLS_ECDHE_RSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
}
type ServiceSettings struct {
SiteURL *string
WebsocketURL *string
@ -182,6 +207,10 @@ type ServiceSettings struct {
ConnectionSecurity *string
TLSCertFile *string
TLSKeyFile *string
TLSMinVer *string
TLSStrictTransport *bool
TLSStrictTransportMaxAge *int64
TLSOverwriteCiphers []string
UseLetsEncrypt *bool
LetsEncryptCertificateCacheFile *string
Forward80To443 *bool
@ -194,7 +223,7 @@ type ServiceSettings struct {
EnableIncomingWebhooks bool
EnableOutgoingWebhooks bool
EnableCommands *bool
EnableOnlyAdminIntegrations *bool
DEPRECATED_DO_NOT_USE_EnableOnlyAdminIntegrations *bool `json:"EnableOnlyAdminIntegrations"` // This field is deprecated and must not be used.
EnablePostUsernameOverride bool
EnablePostIconOverride bool
EnableLinkPreviews *bool
@ -224,9 +253,9 @@ type ServiceSettings struct {
EnableGifPicker *bool
GfycatApiKey *string
GfycatApiSecret *string
RestrictCustomEmojiCreation *string
RestrictPostDelete *string
AllowEditPost *string
DEPRECATED_DO_NOT_USE_RestrictCustomEmojiCreation *string `json:"RestrictCustomEmojiCreation"` // This field is deprecated and must not be used.
DEPRECATED_DO_NOT_USE_RestrictPostDelete *string `json:"RestrictPostDelete"` // This field is deprecated and must not be used.
DEPRECATED_DO_NOT_USE_AllowEditPost *string `json:"AllowEditPost"` // This field is deprecated and must not be used.
PostEditTimeLimit *int
TimeBetweenUserTypingUpdatesMilliseconds *int64
EnablePostSearch *bool
@ -246,7 +275,6 @@ type ServiceSettings struct {
ImageProxyOptions *string
EnableAPITeamDeletion *bool
ExperimentalEnableHardenedMode *bool
ExperimentalLimitClientConfig *bool
EnableEmailInvitations *bool
}
@ -324,6 +352,22 @@ func (s *ServiceSettings) SetDefaults() {
s.TLSCertFile = NewString(SERVICE_SETTINGS_DEFAULT_TLS_CERT_FILE)
}
if s.TLSMinVer == nil {
s.TLSMinVer = NewString("1.2")
}
if s.TLSStrictTransport == nil {
s.TLSStrictTransport = NewBool(false)
}
if s.TLSStrictTransportMaxAge == nil {
s.TLSStrictTransportMaxAge = NewInt64(63072000)
}
if s.TLSOverwriteCiphers == nil {
s.TLSOverwriteCiphers = []string{}
}
if s.UseLetsEncrypt == nil {
s.UseLetsEncrypt = NewBool(false)
}
@ -404,8 +448,8 @@ func (s *ServiceSettings) SetDefaults() {
s.EnableCommands = NewBool(false)
}
if s.EnableOnlyAdminIntegrations == nil {
s.EnableOnlyAdminIntegrations = NewBool(true)
if s.DEPRECATED_DO_NOT_USE_EnableOnlyAdminIntegrations == nil {
s.DEPRECATED_DO_NOT_USE_EnableOnlyAdminIntegrations = NewBool(true)
}
if s.WebsocketPort == nil {
@ -462,16 +506,16 @@ func (s *ServiceSettings) SetDefaults() {
s.GfycatApiSecret = NewString(SERVICE_SETTINGS_DEFAULT_GFYCAT_API_SECRET)
}
if s.RestrictCustomEmojiCreation == nil {
s.RestrictCustomEmojiCreation = NewString(RESTRICT_EMOJI_CREATION_ALL)
if s.DEPRECATED_DO_NOT_USE_RestrictCustomEmojiCreation == nil {
s.DEPRECATED_DO_NOT_USE_RestrictCustomEmojiCreation = NewString(RESTRICT_EMOJI_CREATION_ALL)
}
if s.RestrictPostDelete == nil {
s.RestrictPostDelete = NewString(PERMISSIONS_DELETE_POST_ALL)
if s.DEPRECATED_DO_NOT_USE_RestrictPostDelete == nil {
s.DEPRECATED_DO_NOT_USE_RestrictPostDelete = NewString(PERMISSIONS_DELETE_POST_ALL)
}
if s.AllowEditPost == nil {
s.AllowEditPost = NewString(ALLOW_EDIT_POST_ALWAYS)
if s.DEPRECATED_DO_NOT_USE_AllowEditPost == nil {
s.DEPRECATED_DO_NOT_USE_AllowEditPost = NewString(ALLOW_EDIT_POST_ALWAYS)
}
if s.ExperimentalEnableAuthenticationTransfer == nil {
@ -522,10 +566,6 @@ func (s *ServiceSettings) SetDefaults() {
if s.ExperimentalEnableHardenedMode == nil {
s.ExperimentalEnableHardenedMode = NewBool(false)
}
if s.ExperimentalLimitClientConfig == nil {
s.ExperimentalLimitClientConfig = NewBool(false)
}
}
type ClusterSettings struct {
@ -611,6 +651,7 @@ func (s *MetricsSettings) SetDefaults() {
type ExperimentalSettings struct {
ClientSideCertEnable *bool
ClientSideCertCheck *string
EnablePostMetadata *bool
}
func (s *ExperimentalSettings) SetDefaults() {
@ -621,6 +662,10 @@ func (s *ExperimentalSettings) SetDefaults() {
if s.ClientSideCertCheck == nil {
s.ClientSideCertCheck = NewString(CLIENT_SIDE_CERT_CHECK_SECONDARY_AUTH)
}
if s.EnablePostMetadata == nil {
s.EnablePostMetadata = NewBool(false)
}
}
type AnalyticsSettings struct {
@ -644,17 +689,16 @@ type SSOSettings struct {
}
type SqlSettings struct {
DriverName *string
DataSource *string
DataSourceReplicas []string
DataSourceSearchReplicas []string
MaxIdleConns *int
ConnMaxLifetimeMilliseconds *int
MaxOpenConns *int
Trace bool
AtRestEncryptKey string
QueryTimeout *int
EnablePublicChannelsMaterialization *bool
DriverName *string
DataSource *string
DataSourceReplicas []string
DataSourceSearchReplicas []string
MaxIdleConns *int
ConnMaxLifetimeMilliseconds *int
MaxOpenConns *int
Trace bool
AtRestEncryptKey string
QueryTimeout *int
}
func (s *SqlSettings) SetDefaults() {
@ -685,10 +729,6 @@ func (s *SqlSettings) SetDefaults() {
if s.QueryTimeout == nil {
s.QueryTimeout = NewInt(30)
}
if s.EnablePublicChannelsMaterialization == nil {
s.EnablePublicChannelsMaterialization = NewBool(true)
}
}
type LogSettings struct {
@ -996,13 +1036,14 @@ type PrivacySettings struct {
}
type SupportSettings struct {
TermsOfServiceLink *string
PrivacyPolicyLink *string
AboutLink *string
HelpLink *string
ReportAProblemLink *string
SupportEmail *string
CustomTermsOfServiceEnabled *bool
TermsOfServiceLink *string
PrivacyPolicyLink *string
AboutLink *string
HelpLink *string
ReportAProblemLink *string
SupportEmail *string
CustomTermsOfServiceEnabled *bool
CustomTermsOfServiceReAcceptancePeriod *int
}
func (s *SupportSettings) SetDefaults() {
@ -1053,6 +1094,10 @@ func (s *SupportSettings) SetDefaults() {
if s.CustomTermsOfServiceEnabled == nil {
s.CustomTermsOfServiceEnabled = NewBool(false)
}
if s.CustomTermsOfServiceReAcceptancePeriod == nil {
s.CustomTermsOfServiceReAcceptancePeriod = NewInt(SUPPORT_SETTINGS_DEFAULT_RE_ACCEPTANCE_PERIOD)
}
}
type AnnouncementSettings struct {
@ -1111,37 +1156,37 @@ func (s *ThemeSettings) SetDefaults() {
}
type TeamSettings struct {
SiteName string
MaxUsersPerTeam *int
EnableTeamCreation *bool
EnableUserCreation *bool
EnableOpenServer *bool
EnableUserDeactivation *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
ExperimentalViewArchivedChannels *bool
ExperimentalEnableAutomaticReplies *bool
ExperimentalHideTownSquareinLHS *bool
ExperimentalTownSquareIsReadOnly *bool
ExperimentalPrimaryTeam *string
ExperimentalDefaultChannels []string
SiteName string
MaxUsersPerTeam *int
DEPRECATED_DO_NOT_USE_EnableTeamCreation *bool `json:"EnableTeamCreation"` // This field is deprecated and must not be used.
EnableUserCreation *bool
EnableOpenServer *bool
EnableUserDeactivation *bool
RestrictCreationToDomains string
EnableCustomBrand *bool
CustomBrandText *string
CustomDescriptionText *string
RestrictDirectMessage *string
DEPRECATED_DO_NOT_USE_RestrictTeamInvite *string `json:"RestrictTeamInvite"` // This field is deprecated and must not be used.
DEPRECATED_DO_NOT_USE_RestrictPublicChannelManagement *string `json:"RestrictPublicChannelManagement"` // This field is deprecated and must not be used.
DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManagement *string `json:"RestrictPrivateChannelManagement"` // This field is deprecated and must not be used.
DEPRECATED_DO_NOT_USE_RestrictPublicChannelCreation *string `json:"RestrictPublicChannelCreation"` // This field is deprecated and must not be used.
DEPRECATED_DO_NOT_USE_RestrictPrivateChannelCreation *string `json:"RestrictPrivateChannelCreation"` // This field is deprecated and must not be used.
DEPRECATED_DO_NOT_USE_RestrictPublicChannelDeletion *string `json:"RestrictPublicChannelDeletion"` // This field is deprecated and must not be used.
DEPRECATED_DO_NOT_USE_RestrictPrivateChannelDeletion *string `json:"RestrictPrivateChannelDeletion"` // This field is deprecated and must not be used.
DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManageMembers *string `json:"RestrictPrivateChannelManageMembers"` // This field is deprecated and must not be used.
EnableXToLeaveChannelsFromLHS *bool
UserStatusAwayTimeout *int64
MaxChannelsPerTeam *int64
MaxNotificationsPerChannel *int64
EnableConfirmNotificationsToChannel *bool
TeammateNameDisplay *string
ExperimentalViewArchivedChannels *bool
ExperimentalEnableAutomaticReplies *bool
ExperimentalHideTownSquareinLHS *bool
ExperimentalTownSquareIsReadOnly *bool
ExperimentalPrimaryTeam *string
ExperimentalDefaultChannels []string
}
func (s *TeamSettings) SetDefaults() {
@ -1173,49 +1218,49 @@ func (s *TeamSettings) SetDefaults() {
s.RestrictDirectMessage = NewString(DIRECT_MESSAGE_ANY)
}
if s.RestrictTeamInvite == nil {
s.RestrictTeamInvite = NewString(PERMISSIONS_ALL)
if s.DEPRECATED_DO_NOT_USE_RestrictTeamInvite == nil {
s.DEPRECATED_DO_NOT_USE_RestrictTeamInvite = NewString(PERMISSIONS_ALL)
}
if s.RestrictPublicChannelManagement == nil {
s.RestrictPublicChannelManagement = NewString(PERMISSIONS_ALL)
if s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelManagement == nil {
s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelManagement = NewString(PERMISSIONS_ALL)
}
if s.RestrictPrivateChannelManagement == nil {
s.RestrictPrivateChannelManagement = NewString(PERMISSIONS_ALL)
if s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManagement == nil {
s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManagement = NewString(PERMISSIONS_ALL)
}
if s.RestrictPublicChannelCreation == nil {
s.RestrictPublicChannelCreation = new(string)
if s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelCreation == nil {
s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelCreation = new(string)
// If this setting does not exist, assume migration from <3.6, so use management setting as default.
if *s.RestrictPublicChannelManagement == PERMISSIONS_CHANNEL_ADMIN {
*s.RestrictPublicChannelCreation = PERMISSIONS_TEAM_ADMIN
if *s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelManagement == PERMISSIONS_CHANNEL_ADMIN {
*s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelCreation = PERMISSIONS_TEAM_ADMIN
} else {
*s.RestrictPublicChannelCreation = *s.RestrictPublicChannelManagement
*s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelCreation = *s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelManagement
}
}
if s.RestrictPrivateChannelCreation == nil {
if s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelCreation == nil {
// If this setting does not exist, assume migration from <3.6, so use management setting as default.
if *s.RestrictPrivateChannelManagement == PERMISSIONS_CHANNEL_ADMIN {
s.RestrictPrivateChannelCreation = NewString(PERMISSIONS_TEAM_ADMIN)
if *s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManagement == PERMISSIONS_CHANNEL_ADMIN {
s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelCreation = NewString(PERMISSIONS_TEAM_ADMIN)
} else {
s.RestrictPrivateChannelCreation = NewString(*s.RestrictPrivateChannelManagement)
s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelCreation = NewString(*s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManagement)
}
}
if s.RestrictPublicChannelDeletion == nil {
if s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelDeletion == nil {
// If this setting does not exist, assume migration from <3.6, so use management setting as default.
s.RestrictPublicChannelDeletion = NewString(*s.RestrictPublicChannelManagement)
s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelDeletion = NewString(*s.DEPRECATED_DO_NOT_USE_RestrictPublicChannelManagement)
}
if s.RestrictPrivateChannelDeletion == nil {
if s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelDeletion == nil {
// If this setting does not exist, assume migration from <3.6, so use management setting as default.
s.RestrictPrivateChannelDeletion = NewString(*s.RestrictPrivateChannelManagement)
s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelDeletion = NewString(*s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManagement)
}
if s.RestrictPrivateChannelManageMembers == nil {
s.RestrictPrivateChannelManageMembers = NewString(PERMISSIONS_ALL)
if s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManageMembers == nil {
s.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManageMembers = NewString(PERMISSIONS_ALL)
}
if s.EnableXToLeaveChannelsFromLHS == nil {
@ -1258,8 +1303,8 @@ func (s *TeamSettings) SetDefaults() {
s.ExperimentalDefaultChannels = []string{}
}
if s.EnableTeamCreation == nil {
s.EnableTeamCreation = NewBool(true)
if s.DEPRECATED_DO_NOT_USE_EnableTeamCreation == nil {
s.DEPRECATED_DO_NOT_USE_EnableTeamCreation = NewBool(true)
}
if s.EnableUserCreation == nil {
@ -1624,51 +1669,6 @@ func (s *NativeAppSettings) SetDefaults() {
}
}
type WebrtcSettings struct {
Enable *bool
GatewayWebsocketUrl *string
GatewayAdminUrl *string
GatewayAdminSecret *string
StunURI *string
TurnURI *string
TurnUsername *string
TurnSharedKey *string
}
func (s *WebrtcSettings) SetDefaults() {
if s.Enable == nil {
s.Enable = NewBool(false)
}
if s.GatewayWebsocketUrl == nil {
s.GatewayWebsocketUrl = NewString("")
}
if s.GatewayAdminUrl == nil {
s.GatewayAdminUrl = NewString("")
}
if s.GatewayAdminSecret == nil {
s.GatewayAdminSecret = NewString("")
}
if s.StunURI == nil {
s.StunURI = NewString(WEBRTC_SETTINGS_DEFAULT_STUN_URI)
}
if s.TurnURI == nil {
s.TurnURI = NewString(WEBRTC_SETTINGS_DEFAULT_TURN_URI)
}
if s.TurnUsername == nil {
s.TurnUsername = NewString("")
}
if s.TurnSharedKey == nil {
s.TurnSharedKey = NewString("")
}
}
type ElasticsearchSettings struct {
ConnectionUrl *string
Username *string
@ -1886,14 +1886,6 @@ func (s *MessageExportSettings) SetDefaults() {
s.ExportFromTimestamp = NewInt64(0)
}
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 s.BatchSize == nil {
s.BatchSize = NewInt(10000)
}
@ -1959,7 +1951,6 @@ type Config struct {
MetricsSettings MetricsSettings
ExperimentalSettings ExperimentalSettings
AnalyticsSettings AnalyticsSettings
WebrtcSettings WebrtcSettings
ElasticsearchSettings ElasticsearchSettings
DataRetentionSettings DataRetentionSettings
MessageExportSettings MessageExportSettings
@ -2035,7 +2026,6 @@ func (o *Config) SetDefaults() {
o.RateLimitSettings.SetDefaults()
o.LogSettings.SetDefaults()
o.JobSettings.SetDefaults()
o.WebrtcSettings.SetDefaults()
o.MessageExportSettings.SetDefaults()
o.TimezoneSettings.SetDefaults()
o.DisplaySettings.SetDefaults()
@ -2087,10 +2077,6 @@ func (o *Config) IsValid() *AppError {
return err
}
if err := o.WebrtcSettings.isValid(); err != nil {
return err
}
if err := o.ServiceSettings.isValid(); err != nil {
return err
}
@ -2322,36 +2308,37 @@ func (ss *SamlSettings) isValid() *AppError {
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)
}
}
}
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 *ss.ConnectionSecurity == CONN_SECURITY_TLS && *ss.UseLetsEncrypt == false {
appErr := NewAppError("Config.IsValid", "model.config.is_valid.tls_cert_file.app_error", nil, "", http.StatusBadRequest)
if *ss.TLSCertFile == "" {
return appErr
} else if _, err := os.Stat(*ss.TLSCertFile); os.IsNotExist(err) {
return appErr
}
appErr = NewAppError("Config.IsValid", "model.config.is_valid.tls_key_file.app_error", nil, "", http.StatusBadRequest)
if *ss.TLSKeyFile == "" {
return appErr
} else if _, err := os.Stat(*ss.TLSKeyFile); os.IsNotExist(err) {
return appErr
}
}
if len(ss.TLSOverwriteCiphers) > 0 {
for _, cipher := range ss.TLSOverwriteCiphers {
if _, ok := ServerTLSSupportedCiphers[cipher]; !ok {
return NewAppError("Config.IsValid", "model.config.is_valid.tls_overwrite_cipher.app_error", map[string]interface{}{"name": cipher}, "", http.StatusBadRequest)
}
}
}
if *ss.ReadTimeout <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.read_timeout.app_error", nil, "", http.StatusBadRequest)
}

View file

@ -7,6 +7,7 @@ import (
"encoding/json"
"io"
"net/http"
"regexp"
)
const (
@ -14,6 +15,8 @@ const (
EMOJI_SORT_BY_NAME = "name"
)
var EMOJI_PATTERN = regexp.MustCompile(`:[a-zA-Z0-9_-]+:`)
type Emoji struct {
Id string `json:"id"`
CreateAt int64 `json:"create_at"`

View file

@ -85,7 +85,7 @@ func (o *FileInfo) IsValid() *AppError {
return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.id.app_error", nil, "", http.StatusBadRequest)
}
if len(o.CreatorId) != 26 {
if len(o.CreatorId) != 26 && o.CreatorId != "nouser" {
return NewAppError("FileInfo.IsValid", "model.file_info.is_valid.user_id.app_error", nil, "id="+o.Id, http.StatusBadRequest)
}

View file

@ -0,0 +1,294 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"crypto"
"crypto/ecdsa"
"crypto/rand"
"encoding/asn1"
"encoding/base64"
"encoding/json"
"io"
"math/big"
"net/http"
"strconv"
"strings"
)
const (
POST_ACTION_TYPE_BUTTON = "button"
POST_ACTION_TYPE_SELECT = "select"
INTERACTIVE_DIALOG_TRIGGER_TIMEOUT_MILLISECONDS = 3000
)
type DoPostActionRequest struct {
SelectedOption string `json:"selected_option"`
}
type PostAction struct {
Id string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
DataSource string `json:"data_source"`
Options []*PostActionOptions `json:"options"`
Integration *PostActionIntegration `json:"integration,omitempty"`
}
type PostActionOptions struct {
Text string `json:"text"`
Value string `json:"value"`
}
type PostActionIntegration struct {
URL string `json:"url,omitempty"`
Context map[string]interface{} `json:"context,omitempty"`
}
type PostActionIntegrationRequest struct {
UserId string `json:"user_id"`
ChannelId string `json:"channel_id"`
TeamId string `json:"team_id"`
PostId string `json:"post_id"`
TriggerId string `json:"trigger_id"`
Type string `json:"type"`
DataSource string `json:"data_source"`
Context map[string]interface{} `json:"context,omitempty"`
}
type PostActionIntegrationResponse struct {
Update *Post `json:"update"`
EphemeralText string `json:"ephemeral_text"`
}
type PostActionAPIResponse struct {
Status string `json:"status"` // needed to maintain backwards compatibility
TriggerId string `json:"trigger_id"`
}
type Dialog struct {
CallbackId string `json:"callback_id"`
Title string `json:"title"`
IconURL string `json:"icon_url"`
Elements []DialogElement `json:"elements"`
SubmitLabel string `json:"submit_label"`
NotifyOnCancel bool `json:"notify_on_cancel"`
State string `json:"state"`
}
type DialogElement struct {
DisplayName string `json:"display_name"`
Name string `json:"name"`
Type string `json:"type"`
SubType string `json:"subtype"`
Default string `json:"default"`
Placeholder string `json:"placeholder"`
HelpText string `json:"help_text"`
Optional bool `json:"optional"`
MinLength int `json:"min_length"`
MaxLength int `json:"max_length"`
DataSource string `json:"data_source"`
Options []*PostActionOptions `json:"options"`
}
type OpenDialogRequest struct {
TriggerId string `json:"trigger_id"`
URL string `json:"url"`
Dialog Dialog `json:"dialog"`
}
type SubmitDialogRequest struct {
Type string `json:"type"`
URL string `json:"url,omitempty"`
CallbackId string `json:"callback_id"`
State string `json:"state"`
UserId string `json:"user_id"`
ChannelId string `json:"channel_id"`
TeamId string `json:"team_id"`
Submission map[string]interface{} `json:"submission"`
Cancelled bool `json:"cancelled"`
}
type SubmitDialogResponse struct {
Errors map[string]string `json:"errors,omitempty"`
}
func GenerateTriggerId(userId string, s crypto.Signer) (string, string, *AppError) {
clientTriggerId := NewId()
triggerData := strings.Join([]string{clientTriggerId, userId, strconv.FormatInt(GetMillis(), 10)}, ":") + ":"
h := crypto.SHA256
sum := h.New()
sum.Write([]byte(triggerData))
signature, err := s.Sign(rand.Reader, sum.Sum(nil), h)
if err != nil {
return "", "", NewAppError("GenerateTriggerId", "interactive_message.generate_trigger_id.signing_failed", nil, err.Error(), http.StatusInternalServerError)
}
base64Sig := base64.StdEncoding.EncodeToString(signature)
triggerId := base64.StdEncoding.EncodeToString([]byte(triggerData + base64Sig))
return clientTriggerId, triggerId, nil
}
func (r *PostActionIntegrationRequest) GenerateTriggerId(s crypto.Signer) (string, string, *AppError) {
clientTriggerId, triggerId, err := GenerateTriggerId(r.UserId, s)
if err != nil {
return "", "", err
}
r.TriggerId = triggerId
return clientTriggerId, triggerId, nil
}
func DecodeAndVerifyTriggerId(triggerId string, s *ecdsa.PrivateKey) (string, string, *AppError) {
triggerIdBytes, err := base64.StdEncoding.DecodeString(triggerId)
if err != nil {
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.base64_decode_failed", nil, err.Error(), http.StatusBadRequest)
}
split := strings.Split(string(triggerIdBytes), ":")
if len(split) != 4 {
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.missing_data", nil, "", http.StatusBadRequest)
}
clientTriggerId := split[0]
userId := split[1]
timestampStr := split[2]
timestamp, _ := strconv.ParseInt(timestampStr, 10, 64)
now := GetMillis()
if now-timestamp > INTERACTIVE_DIALOG_TRIGGER_TIMEOUT_MILLISECONDS {
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.expired", map[string]interface{}{"Seconds": INTERACTIVE_DIALOG_TRIGGER_TIMEOUT_MILLISECONDS / 1000}, "", http.StatusBadRequest)
}
signature, err := base64.StdEncoding.DecodeString(split[3])
if err != nil {
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.base64_decode_failed_signature", nil, err.Error(), http.StatusBadRequest)
}
var esig struct {
R, S *big.Int
}
if _, err := asn1.Unmarshal([]byte(signature), &esig); err != nil {
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.signature_decode_failed", nil, err.Error(), http.StatusBadRequest)
}
triggerData := strings.Join([]string{clientTriggerId, userId, timestampStr}, ":") + ":"
h := crypto.SHA256
sum := h.New()
sum.Write([]byte(triggerData))
if !ecdsa.Verify(&s.PublicKey, sum.Sum(nil), esig.R, esig.S) {
return "", "", NewAppError("DecodeAndVerifyTriggerId", "interactive_message.decode_trigger_id.verify_signature_failed", nil, "", http.StatusBadRequest)
}
return clientTriggerId, userId, nil
}
func (r *OpenDialogRequest) DecodeAndVerifyTriggerId(s *ecdsa.PrivateKey) (string, string, *AppError) {
return DecodeAndVerifyTriggerId(r.TriggerId, s)
}
func (r *PostActionIntegrationRequest) ToJson() []byte {
b, _ := json.Marshal(r)
return b
}
func PostActionIntegrationRequestFromJson(data io.Reader) *PostActionIntegrationRequest {
var o *PostActionIntegrationRequest
err := json.NewDecoder(data).Decode(&o)
if err != nil {
return nil
}
return o
}
func (r *PostActionIntegrationResponse) ToJson() []byte {
b, _ := json.Marshal(r)
return b
}
func PostActionIntegrationResponseFromJson(data io.Reader) *PostActionIntegrationResponse {
var o *PostActionIntegrationResponse
err := json.NewDecoder(data).Decode(&o)
if err != nil {
return nil
}
return o
}
func SubmitDialogRequestFromJson(data io.Reader) *SubmitDialogRequest {
var o *SubmitDialogRequest
err := json.NewDecoder(data).Decode(&o)
if err != nil {
return nil
}
return o
}
func (r *SubmitDialogRequest) ToJson() []byte {
b, _ := json.Marshal(r)
return b
}
func SubmitDialogResponseFromJson(data io.Reader) *SubmitDialogResponse {
var o *SubmitDialogResponse
err := json.NewDecoder(data).Decode(&o)
if err != nil {
return nil
}
return o
}
func (r *SubmitDialogResponse) ToJson() []byte {
b, _ := json.Marshal(r)
return b
}
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()
}
}
}
}
}
func DoPostActionRequestFromJson(data io.Reader) *DoPostActionRequest {
var o *DoPostActionRequest
json.NewDecoder(data).Decode(&o)
return o
}

View file

@ -17,6 +17,7 @@ const (
JOB_TYPE_ELASTICSEARCH_POST_AGGREGATION = "elasticsearch_post_aggregation"
JOB_TYPE_LDAP_SYNC = "ldap_sync"
JOB_TYPE_MIGRATIONS = "migrations"
JOB_TYPE_PLUGINS = "plugins"
JOB_STATUS_PENDING = "pending"
JOB_STATUS_IN_PROGRESS = "in_progress"

View file

@ -21,12 +21,14 @@ type LicenseRecord struct {
}
type License struct {
Id string `json:"id"`
IssuedAt int64 `json:"issued_at"`
StartsAt int64 `json:"starts_at"`
ExpiresAt int64 `json:"expires_at"`
Customer *Customer `json:"customer"`
Features *Features `json:"features"`
Id string `json:"id"`
IssuedAt int64 `json:"issued_at"`
StartsAt int64 `json:"starts_at"`
ExpiresAt int64 `json:"expires_at"`
Customer *Customer `json:"customer"`
Features *Features `json:"features"`
SkuName string `json:"sku_name"`
SkuShortName string `json:"sku_short_name"`
}
type Customer struct {
@ -57,7 +59,7 @@ type Features struct {
CustomPermissionsSchemes *bool `json:"custom_permissions_schemes"`
CustomTermsOfService *bool `json:"custom_terms_of_service"`
// after we enabled more features for webrtc we'll need to control them with this
// after we enabled more features we'll need to control them with this
FutureFeatures *bool `json:"future_features"`
}

View file

@ -5,6 +5,7 @@ package model
import (
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
@ -12,6 +13,7 @@ import (
"path/filepath"
"strings"
"github.com/blang/semver"
"gopkg.in/yaml.v2"
)
@ -45,6 +47,8 @@ type PluginSetting struct {
//
// "text" will result in a string setting that can be typed in manually.
//
// "longtext" will result in a multi line string 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"`
@ -109,6 +113,11 @@ type Manifest struct {
// A version number for your plugin. Semantic versioning is recommended: http://semver.org
Version string `json:"version" yaml:"version"`
// The minimum Mattermost server version required for your plugin.
//
// Minimum server version: 5.6
MinServerVersion string `json:"min_server_version,omitempty" yaml:"min_server_version,omitempty"`
// Server defines the server-side portion of your plugin.
Server *ManifestServer `json:"server,omitempty" yaml:"server,omitempty"`
@ -240,6 +249,18 @@ func (m *Manifest) HasWebapp() bool {
return m.Webapp != nil
}
func (m *Manifest) MeetMinServerVersion(serverVersion string) (bool, error) {
minServerVersion, err := semver.Parse(m.MinServerVersion)
if err != nil {
return false, errors.New("failed to parse MinServerVersion")
}
sv := semver.MustParse(serverVersion)
if sv.LT(minServerVersion) {
return false, nil
}
return true, nil
}
// 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
@ -252,25 +273,23 @@ func FindManifest(dir string) (manifest *Manifest, path string, err error) {
f, ferr := os.Open(path)
if ferr != nil {
if !os.IsNotExist(ferr) {
err = ferr
return
return nil, "", ferr
}
continue
}
b, ioerr := ioutil.ReadAll(f)
f.Close()
if ioerr != nil {
err = ioerr
return
return nil, path, ioerr
}
var parsed Manifest
err = yaml.Unmarshal(b, &parsed)
if err != nil {
return
return nil, path, err
}
manifest = &parsed
manifest.Id = strings.ToLower(manifest.Id)
return
return manifest, path, nil
}
path = filepath.Join(dir, "plugin.json")
@ -279,16 +298,15 @@ func FindManifest(dir string) (manifest *Manifest, path string, err error) {
if os.IsNotExist(ferr) {
path = ""
}
err = ferr
return
return nil, path, ferr
}
defer f.Close()
var parsed Manifest
err = json.NewDecoder(f).Decode(&parsed)
if err != nil {
return
return nil, path, err
}
manifest = &parsed
manifest.Id = strings.ToLower(manifest.Id)
return
return manifest, path, nil
}

View file

@ -17,6 +17,7 @@ type PluginKeyValue struct {
PluginId string `json:"plugin_id"`
Key string `json:"key" db:"PKey"`
Value []byte `json:"value" db:"PValue"`
ExpireAt int64 `json:"expire_at"`
}
func (kv *PluginKeyValue) IsValid() *AppError {

View file

@ -50,8 +50,6 @@ const (
PROPS_ADD_CHANNEL_MEMBER = "add_channel_member"
POST_PROPS_ADDED_USER_ID = "addedUserId"
POST_PROPS_DELETE_BY = "deleteBy"
POST_ACTION_TYPE_BUTTON = "button"
POST_ACTION_TYPE_SELECT = "select"
)
type Post struct {
@ -81,6 +79,9 @@ type Post struct {
FileIds StringArray `json:"file_ids,omitempty"`
PendingPostId string `json:"pending_post_id" db:"-"`
HasReactions bool `json:"has_reactions,omitempty"`
// Transient data populated before sending a post to the client
Metadata *PostMetadata `json:"metadata,omitempty" db:"-"`
}
type PostEphemeral struct {
@ -132,48 +133,16 @@ type PostForIndexing struct {
ParentCreateAt *int64 `json:"parent_create_at"`
}
type DoPostActionRequest struct {
SelectedOption string `json:"selected_option"`
}
type PostAction struct {
Id string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
DataSource string `json:"data_source"`
Options []*PostActionOptions `json:"options"`
Integration *PostActionIntegration `json:"integration,omitempty"`
}
type PostActionOptions struct {
Text string `json:"text"`
Value string `json:"value"`
}
type PostActionIntegration struct {
URL string `json:"url,omitempty"`
Context StringInterface `json:"context,omitempty"`
}
type PostActionIntegrationRequest struct {
UserId string `json:"user_id"`
ChannelId string `json:"channel_id"`
TeamId string `json:"team_id"`
PostId string `json:"post_id"`
Type string `json:"type"`
DataSource string `json:"data_source"`
Context StringInterface `json:"context,omitempty"`
}
type PostActionIntegrationResponse struct {
Update *Post `json:"update"`
EphemeralText string `json:"ephemeral_text"`
// Clone shallowly copies the post.
func (o *Post) Clone() *Post {
copy := *o
return &copy
}
func (o *Post) ToJson() string {
copy := *o
copy := o.Clone()
copy.StripActionIntegrations()
b, _ := json.Marshal(&copy)
b, _ := json.Marshal(copy)
return string(b)
}
@ -407,34 +376,6 @@ func (o *Post) ChannelMentions() []string {
return ChannelMentions(o.Message)
}
func (r *PostActionIntegrationRequest) ToJson() string {
b, _ := json.Marshal(r)
return string(b)
}
func PostActionIntegrationRequesteFromJson(data io.Reader) *PostActionIntegrationRequest {
var o *PostActionIntegrationRequest
err := json.NewDecoder(data).Decode(&o)
if err != nil {
return nil
}
return o
}
func (r *PostActionIntegrationResponse) ToJson() string {
b, _ := json.Marshal(r)
return string(b)
}
func PostActionIntegrationResponseFromJson(data io.Reader) *PostActionIntegrationResponse {
var o *PostActionIntegrationResponse
err := json.NewDecoder(data).Decode(&o)
if err != nil {
return nil
}
return o
}
func (o *Post) Attachments() []*SlackAttachment {
if attachments, ok := o.Props["attachments"].([]*SlackAttachment); ok {
return attachments
@ -453,44 +394,6 @@ func (o *Post) Attachments() []*SlackAttachment {
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()
}
}
}
}
}
var markdownDestinationEscaper = strings.NewReplacer(
`\`, `\\`,
`<`, `\<`,
@ -502,12 +405,12 @@ var markdownDestinationEscaper = strings.NewReplacer(
// WithRewrittenImageURLs returns a new shallow copy of the post where the message has been
// rewritten via RewriteImageURLs.
func (o *Post) WithRewrittenImageURLs(f func(string) string) *Post {
copy := *o
copy := o.Clone()
copy.Message = RewriteImageURLs(o.Message, f)
if copy.MessageSource == "" && copy.Message != o.Message {
copy.MessageSource = o.Message
}
return &copy
return copy
}
func (o *PostEphemeral) ToUnsanitizedJson() string {
@ -515,12 +418,6 @@ func (o *PostEphemeral) ToUnsanitizedJson() string {
return string(b)
}
func DoPostActionRequestFromJson(data io.Reader) *DoPostActionRequest {
var o *DoPostActionRequest
json.NewDecoder(data).Decode(&o)
return o
}
// RewriteImageURLs takes a message and returns a copy that has all of the image URLs replaced
// according to the function f. For each image URL, f will be invoked, and the resulting markdown
// will contain the URL returned by that invocation instead.

View file

@ -0,0 +1,22 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
const (
POST_EMBED_IMAGE PostEmbedType = "image"
POST_EMBED_MESSAGE_ATTACHMENT PostEmbedType = "message_attachment"
POST_EMBED_OPENGRAPH PostEmbedType = "opengraph"
)
type PostEmbedType string
type PostEmbed struct {
Type PostEmbedType `json:"type"`
// The URL of the embedded content. Used for image and OpenGraph embeds.
URL string `json:"url,omitempty"`
// Any additional data for the embedded content. Only used for OpenGraph embeds.
Data interface{} `json:"data,omitempty"`
}

View file

@ -0,0 +1,30 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
type PostMetadata struct {
// Embeds holds information required to render content embedded in the post. This includes the OpenGraph metadata
// for links in the post.
Embeds []*PostEmbed `json:"embeds,omitempty"`
// Emojis holds all custom emojis used in the post or used in reaction to the post.
Emojis []*Emoji `json:"emojis,omitempty"`
// Files holds information about the file attachments on the post.
Files []*FileInfo `json:"files,omitempty"`
// Images holds the dimensions of all external images in the post as a map of the image URL to its diemsnions.
// This includes image embeds (when the message contains a plaintext link to an image), Markdown images, images
// contained in the OpenGraph metadata, and images contained in message attachments. It does not contain
// the dimensions of any file attachments as those are stored in FileInfos.
Images map[string]*PostImage `json:"images,omitempty"`
// Reactions holds reactions made to the post.
Reactions []*Reaction `json:"reactions,omitempty"`
}
type PostImage struct {
Width int `json:"width"`
Height int `json:"height"`
}

View file

@ -42,6 +42,11 @@ const (
PREFERENCE_EMAIL_INTERVAL_NO_BATCHING_SECONDS = "30" // the "immediate" setting is actually 30s
PREFERENCE_EMAIL_INTERVAL_BATCHING_SECONDS = "900" // fifteen minutes is 900 seconds
PREFERENCE_EMAIL_INTERVAL_IMMEDIATELY = "immediately"
PREFERENCE_EMAIL_INTERVAL_FIFTEEN = "fifteen"
PREFERENCE_EMAIL_INTERVAL_FIFTEEN_AS_SECONDS = "900"
PREFERENCE_EMAIL_INTERVAL_HOUR = "hour"
PREFERENCE_EMAIL_INTERVAL_HOUR_AS_SECONDS = "3600"
)
type Preference struct {

View file

@ -10,7 +10,7 @@ import (
const (
USER_AUTH_SERVICE_SAML = "saml"
USER_AUTH_SERVICE_SAML_TEXT = "With SAML"
USER_AUTH_SERVICE_SAML_TEXT = "SAML"
)
type SamlAuthRequest struct {

View file

@ -64,7 +64,9 @@ func StringifySlackFieldValue(a []*SlackAttachment) []*SlackAttachment {
// This method only parses and processes the attachments,
// all else should be set in the post which is passed
func ParseSlackAttachment(post *Post, attachments []*SlackAttachment) {
post.Type = POST_SLACK_ATTACHMENT
if post.Type == "" {
post.Type = POST_SLACK_ATTACHMENT
}
for _, attachment := range attachments {
attachment.Text = ParseSlackLinksToMarkdown(attachment.Text)

View file

@ -11,7 +11,6 @@ import (
"unicode/utf8"
)
// we only ever need the latest version of terms of service
const TERMS_OF_SERVICE_CACHE_SIZE = 1
type TermsOfService struct {
@ -58,7 +57,7 @@ func InvalidTermsOfServiceError(fieldName string, termsOfServiceId string) *AppE
if termsOfServiceId != "" {
details = "terms_of_service_id=" + termsOfServiceId
}
return NewAppError("TermsOfServiceStore.IsValid", id, map[string]interface{}{"MaxLength": POST_MESSAGE_MAX_RUNES_V2}, details, http.StatusBadRequest)
return NewAppError("TermsOfService.IsValid", id, map[string]interface{}{"MaxLength": POST_MESSAGE_MAX_RUNES_V2}, details, http.StatusBadRequest)
}
func (t *TermsOfService) PreSave() {

View file

@ -48,33 +48,32 @@ const (
)
type User struct {
Id string `json:"id"`
CreateAt int64 `json:"create_at,omitempty"`
UpdateAt int64 `json:"update_at,omitempty"`
DeleteAt int64 `json:"delete_at"`
Username string `json:"username"`
Password string `json:"password,omitempty"`
AuthData *string `json:"auth_data,omitempty"`
AuthService string `json:"auth_service"`
Email string `json:"email"`
EmailVerified bool `json:"email_verified,omitempty"`
Nickname string `json:"nickname"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Position string `json:"position"`
Roles string `json:"roles"`
AllowMarketing bool `json:"allow_marketing,omitempty"`
Props StringMap `json:"props,omitempty"`
NotifyProps StringMap `json:"notify_props,omitempty"`
LastPasswordUpdate int64 `json:"last_password_update,omitempty"`
LastPictureUpdate int64 `json:"last_picture_update,omitempty"`
FailedAttempts int `json:"failed_attempts,omitempty"`
Locale string `json:"locale"`
Timezone StringMap `json:"timezone"`
MfaActive bool `json:"mfa_active,omitempty"`
MfaSecret string `json:"mfa_secret,omitempty"`
LastActivityAt int64 `db:"-" json:"last_activity_at,omitempty"`
AcceptedTermsOfServiceId string `json:"accepted_terms_of_service_id,omitempty"` // TODO remove this field when new TOS user action table is created
Id string `json:"id"`
CreateAt int64 `json:"create_at,omitempty"`
UpdateAt int64 `json:"update_at,omitempty"`
DeleteAt int64 `json:"delete_at"`
Username string `json:"username"`
Password string `json:"password,omitempty"`
AuthData *string `json:"auth_data,omitempty"`
AuthService string `json:"auth_service"`
Email string `json:"email"`
EmailVerified bool `json:"email_verified,omitempty"`
Nickname string `json:"nickname"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Position string `json:"position"`
Roles string `json:"roles"`
AllowMarketing bool `json:"allow_marketing,omitempty"`
Props StringMap `json:"props,omitempty"`
NotifyProps StringMap `json:"notify_props,omitempty"`
LastPasswordUpdate int64 `json:"last_password_update,omitempty"`
LastPictureUpdate int64 `json:"last_picture_update,omitempty"`
FailedAttempts int `json:"failed_attempts,omitempty"`
Locale string `json:"locale"`
Timezone StringMap `json:"timezone"`
MfaActive bool `json:"mfa_active,omitempty"`
MfaSecret string `json:"mfa_secret,omitempty"`
LastActivityAt int64 `db:"-" json:"last_activity_at,omitempty"`
}
type UserPatch struct {
@ -499,11 +498,7 @@ func (u *User) IsSAMLUser() bool {
}
func (u *User) GetPreferredTimezone() string {
if u.Timezone["useAutomaticTimezone"] == "true" {
return u.Timezone["automaticTimezone"]
}
return u.Timezone["manualTimezone"]
return GetPreferredTimezone(u.Timezone)
}
// UserFromJson will decode the input and return a User
@ -639,3 +634,9 @@ func IsValidCommentsNotifyLevel(notifyLevel string) bool {
notifyLevel == COMMENTS_NOTIFY_ROOT ||
notifyLevel == COMMENTS_NOTIFY_NEVER
}
func IsValidEmailBatchingInterval(emailInterval string) bool {
return emailInterval == PREFERENCE_EMAIL_INTERVAL_IMMEDIATELY ||
emailInterval == PREFERENCE_EMAIL_INTERVAL_FIFTEEN ||
emailInterval == PREFERENCE_EMAIL_INTERVAL_HOUR
}

View file

@ -8,6 +8,10 @@ import (
"io"
)
const USER_SEARCH_MAX_LIMIT = 1000
const USER_SEARCH_DEFAULT_LIMIT = 100
// UserSearch captures the parameters provided by a client for initiating a user search.
type UserSearch struct {
Term string `json:"term"`
TeamId string `json:"team_id"`
@ -16,17 +20,38 @@ type UserSearch struct {
NotInChannelId string `json:"not_in_channel_id"`
AllowInactive bool `json:"allow_inactive"`
WithoutTeam bool `json:"without_team"`
Limit int `json:"limit"`
}
// ToJson convert a User to a json string
func (u *UserSearch) ToJson() string {
func (u *UserSearch) ToJson() []byte {
b, _ := json.Marshal(u)
return string(b)
return b
}
// UserSearchFromJson will decode the input and return a User
func UserSearchFromJson(data io.Reader) *UserSearch {
var us *UserSearch
json.NewDecoder(data).Decode(&us)
if us.Limit == 0 {
us.Limit = USER_SEARCH_DEFAULT_LIMIT
}
return us
}
// UserSearchOptions captures internal parameters derived from the user's permissions and a
// UserSearch request.
type UserSearchOptions struct {
// IsAdmin tracks whether or not the search is being conducted by an administrator.
IsAdmin bool
// AllowEmails allows search to examine the emails of users.
AllowEmails bool
// AllowFullNames allows search to examine the full names of users, vs. just usernames and nicknames.
AllowFullNames bool
// AllowInactive configures whether or not to return inactive users in the search results.
AllowInactive bool
// Limit limits the total number of results returned.
Limit int
}

View file

@ -0,0 +1,61 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"encoding/json"
"fmt"
"io"
"net/http"
)
type UserTermsOfService struct {
UserId string `json:"user_id"`
TermsOfServiceId string `json:"terms_of_service_id"`
CreateAt int64 `json:"create_at"`
}
func (ut *UserTermsOfService) IsValid() *AppError {
if len(ut.UserId) != 26 {
return InvalidUserTermsOfServiceError("user_id", ut.UserId)
}
if len(ut.TermsOfServiceId) != 26 {
return InvalidUserTermsOfServiceError("terms_of_service_id", ut.UserId)
}
if ut.CreateAt == 0 {
return InvalidUserTermsOfServiceError("create_at", ut.UserId)
}
return nil
}
func (ut *UserTermsOfService) ToJson() string {
b, _ := json.Marshal(ut)
return string(b)
}
func (ut *UserTermsOfService) PreSave() {
if ut.UserId == "" {
ut.UserId = NewId()
}
ut.CreateAt = GetMillis()
}
func UserTermsOfServiceFromJson(data io.Reader) *UserTermsOfService {
var userTermsOfService *UserTermsOfService
json.NewDecoder(data).Decode(&userTermsOfService)
return userTermsOfService
}
func InvalidUserTermsOfServiceError(fieldName string, userTermsOfServiceId string) *AppError {
id := fmt.Sprintf("model.user_terms_of_service.is_valid.%s.app_error", fieldName)
details := ""
if userTermsOfServiceId != "" {
details = "user_terms_of_service_user_id=" + userTermsOfServiceId
}
return NewAppError("UserTermsOfService.IsValid", id, nil, details, http.StatusBadRequest)
}

View file

@ -564,3 +564,26 @@ func IsDomainName(s string) bool {
return ok
}
func RemoveDuplicateStrings(in []string) []string {
out := []string{}
seen := make(map[string]bool, len(in))
for _, item := range in {
if !seen[item] {
out = append(out, item)
seen[item] = true
}
}
return out
}
func GetPreferredTimezone(timezone StringMap) string {
if timezone["useAutomaticTimezone"] == "true" {
return timezone["automaticTimezone"]
}
return timezone["manualTimezone"]
}

View file

@ -13,6 +13,8 @@ import (
// It should be maintained in chronological order with most current
// release at the front of the list.
var versions = []string{
"5.6.0",
"5.5.0",
"5.4.0",
"5.3.0",
"5.2.0",

View file

@ -1,39 +0,0 @@
// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"encoding/json"
"io"
)
type WebrtcInfoResponse struct {
Token string `json:"token"`
GatewayUrl string `json:"gateway_url"`
StunUri string `json:"stun_uri,omitempty"`
TurnUri string `json:"turn_uri,omitempty"`
TurnPassword string `json:"turn_password,omitempty"`
TurnUsername string `json:"turn_username,omitempty"`
}
type GatewayResponse struct {
Status string `json:"janus"`
}
func GatewayResponseFromJson(data io.Reader) *GatewayResponse {
var o *GatewayResponse
json.NewDecoder(data).Decode(&o)
return o
}
func (o *WebrtcInfoResponse) ToJson() string {
b, _ := json.Marshal(o)
return string(b)
}
func WebrtcInfoResponseFromJson(data io.Reader) *WebrtcInfoResponse {
var o *WebrtcInfoResponse
json.NewDecoder(data).Decode(&o)
return o
}

View file

@ -37,7 +37,6 @@ const (
WEBSOCKET_EVENT_EPHEMERAL_MESSAGE = "ephemeral_message"
WEBSOCKET_EVENT_STATUS_CHANGE = "status_change"
WEBSOCKET_EVENT_HELLO = "hello"
WEBSOCKET_EVENT_WEBRTC = "webrtc"
WEBSOCKET_AUTHENTICATION_CHALLENGE = "authentication_challenge"
WEBSOCKET_EVENT_REACTION_ADDED = "reaction_added"
WEBSOCKET_EVENT_REACTION_REMOVED = "reaction_removed"
@ -50,6 +49,7 @@ const (
WEBSOCKET_EVENT_ROLE_UPDATED = "role_updated"
WEBSOCKET_EVENT_LICENSE_CHANGED = "license_changed"
WEBSOCKET_EVENT_CONFIG_CHANGED = "config_changed"
WEBSOCKET_EVENT_OPEN_DIALOG = "open_dialog"
)
type WebSocketMessage interface {