5
0
mirror of https://github.com/cwinfo/matterbridge.git synced 2024-11-30 05:01:36 +00:00
matterbridge/vendor/github.com/mattermost/mattermost-server/v6/model/config.go
2021-10-16 23:23:24 +02:00

3916 lines
136 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package model
import (
"crypto/tls"
"encoding/json"
"io"
"math"
"net"
"net/http"
"net/url"
"os"
"reflect"
"regexp"
"strconv"
"strings"
"time"
"github.com/mattermost/ldap"
"github.com/mattermost/mattermost-server/v6/shared/filestore"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
)
const (
ConnSecurityNone = ""
ConnSecurityPlain = "PLAIN"
ConnSecurityTLS = "TLS"
ConnSecurityStarttls = "STARTTLS"
ImageDriverLocal = "local"
ImageDriverS3 = "amazons3"
DatabaseDriverMysql = "mysql"
DatabaseDriverPostgres = "postgres"
SearchengineElasticsearch = "elasticsearch"
MinioAccessKey = "minioaccesskey"
MinioSecretKey = "miniosecretkey"
MinioBucket = "mattermost-test"
PasswordMaximumLength = 64
PasswordMinimumLength = 5
ServiceGitlab = "gitlab"
ServiceGoogle = "google"
ServiceOffice365 = "office365"
ServiceOpenid = "openid"
GenericNoChannelNotification = "generic_no_channel"
GenericNotification = "generic"
GenericNotificationServer = "https://push-test.mattermost.com"
MmSupportAdvisorAddress = "support-advisor@mattermost.com"
FullNotification = "full"
IdLoadedNotification = "id_loaded"
DirectMessageAny = "any"
DirectMessageTeam = "team"
ShowUsername = "username"
ShowNicknameFullName = "nickname_full_name"
ShowFullName = "full_name"
PermissionsAll = "all"
PermissionsChannelAdmin = "channel_admin"
PermissionsTeamAdmin = "team_admin"
PermissionsSystemAdmin = "system_admin"
FakeSetting = "********************************"
RestrictEmojiCreationAll = "all"
RestrictEmojiCreationAdmin = "admin"
RestrictEmojiCreationSystemAdmin = "system_admin"
PermissionsDeletePostAll = "all"
PermissionsDeletePostTeamAdmin = "team_admin"
PermissionsDeletePostSystemAdmin = "system_admin"
GroupUnreadChannelsDisabled = "disabled"
GroupUnreadChannelsDefaultOn = "default_on"
GroupUnreadChannelsDefaultOff = "default_off"
CollapsedThreadsDisabled = "disabled"
CollapsedThreadsDefaultOn = "default_on"
CollapsedThreadsDefaultOff = "default_off"
EmailBatchingBufferSize = 256
EmailBatchingInterval = 30
EmailNotificationContentsFull = "full"
EmailNotificationContentsGeneric = "generic"
SitenameMaxLength = 30
ServiceSettingsDefaultSiteURL = "http://localhost:8065"
ServiceSettingsDefaultTLSCertFile = ""
ServiceSettingsDefaultTLSKeyFile = ""
ServiceSettingsDefaultReadTimeout = 300
ServiceSettingsDefaultWriteTimeout = 300
ServiceSettingsDefaultIdleTimeout = 60
ServiceSettingsDefaultMaxLoginAttempts = 10
ServiceSettingsDefaultAllowCorsFrom = ""
ServiceSettingsDefaultListenAndAddress = ":8065"
ServiceSettingsDefaultGfycatAPIKey = "2_KtH_W5"
ServiceSettingsDefaultGfycatAPISecret = "3wLVZPiswc3DnaiaFoLkDvB4X0IV6CpMkj4tf2inJRsBY6-FnkT08zGmppWFgeof"
TeamSettingsDefaultSiteName = "Mattermost"
TeamSettingsDefaultMaxUsersPerTeam = 50
TeamSettingsDefaultCustomBrandText = ""
TeamSettingsDefaultCustomDescriptionText = ""
TeamSettingsDefaultUserStatusAwayTimeout = 300
SqlSettingsDefaultDataSource = "postgres://mmuser:mostest@localhost/mattermost_test?sslmode=disable&connect_timeout=10"
FileSettingsDefaultDirectory = "./data/"
ImportSettingsDefaultDirectory = "./import"
ImportSettingsDefaultRetentionDays = 30
ExportSettingsDefaultDirectory = "./export"
ExportSettingsDefaultRetentionDays = 30
EmailSettingsDefaultFeedbackOrganization = ""
SupportSettingsDefaultTermsOfServiceLink = "https://mattermost.com/terms-of-service/"
SupportSettingsDefaultPrivacyPolicyLink = "https://mattermost.com/privacy-policy/"
SupportSettingsDefaultAboutLink = "https://about.mattermost.com/default-about/"
SupportSettingsDefaultHelpLink = "https://about.mattermost.com/default-help/"
SupportSettingsDefaultReportAProblemLink = "https://about.mattermost.com/default-report-a-problem/"
SupportSettingsDefaultSupportEmail = ""
SupportSettingsDefaultReAcceptancePeriod = 365
LdapSettingsDefaultFirstNameAttribute = ""
LdapSettingsDefaultLastNameAttribute = ""
LdapSettingsDefaultEmailAttribute = ""
LdapSettingsDefaultUsernameAttribute = ""
LdapSettingsDefaultNicknameAttribute = ""
LdapSettingsDefaultIdAttribute = ""
LdapSettingsDefaultPositionAttribute = ""
LdapSettingsDefaultLoginFieldName = ""
LdapSettingsDefaultGroupDisplayNameAttribute = ""
LdapSettingsDefaultGroupIdAttribute = ""
LdapSettingsDefaultPictureAttribute = ""
SamlSettingsDefaultIdAttribute = ""
SamlSettingsDefaultGuestAttribute = ""
SamlSettingsDefaultAdminAttribute = ""
SamlSettingsDefaultFirstNameAttribute = ""
SamlSettingsDefaultLastNameAttribute = ""
SamlSettingsDefaultEmailAttribute = ""
SamlSettingsDefaultUsernameAttribute = ""
SamlSettingsDefaultNicknameAttribute = ""
SamlSettingsDefaultLocaleAttribute = ""
SamlSettingsDefaultPositionAttribute = ""
SamlSettingsSignatureAlgorithmSha1 = "RSAwithSHA1"
SamlSettingsSignatureAlgorithmSha256 = "RSAwithSHA256"
SamlSettingsSignatureAlgorithmSha512 = "RSAwithSHA512"
SamlSettingsDefaultSignatureAlgorithm = SamlSettingsSignatureAlgorithmSha1
SamlSettingsCanonicalAlgorithmC14n = "Canonical1.0"
SamlSettingsCanonicalAlgorithmC14n11 = "Canonical1.1"
SamlSettingsDefaultCanonicalAlgorithm = SamlSettingsCanonicalAlgorithmC14n
NativeappSettingsDefaultAppDownloadLink = "https://mattermost.com/download/#mattermostApps"
NativeappSettingsDefaultAndroidAppDownloadLink = "https://about.mattermost.com/mattermost-android-app/"
NativeappSettingsDefaultIosAppDownloadLink = "https://about.mattermost.com/mattermost-ios-app/"
ExperimentalSettingsDefaultLinkMetadataTimeoutMilliseconds = 5000
AnalyticsSettingsDefaultMaxUsersForStatistics = 2500
AnnouncementSettingsDefaultBannerColor = "#f2a93b"
AnnouncementSettingsDefaultBannerTextColor = "#333333"
AnnouncementSettingsDefaultNoticesJsonURL = "https://notices.mattermost.com/"
AnnouncementSettingsDefaultNoticesFetchFrequencySeconds = 3600
TeamSettingsDefaultTeamText = "default"
ElasticsearchSettingsDefaultConnectionURL = "http://localhost:9200"
ElasticsearchSettingsDefaultUsername = "elastic"
ElasticsearchSettingsDefaultPassword = "changeme"
ElasticsearchSettingsDefaultPostIndexReplicas = 1
ElasticsearchSettingsDefaultPostIndexShards = 1
ElasticsearchSettingsDefaultChannelIndexReplicas = 1
ElasticsearchSettingsDefaultChannelIndexShards = 1
ElasticsearchSettingsDefaultUserIndexReplicas = 1
ElasticsearchSettingsDefaultUserIndexShards = 1
ElasticsearchSettingsDefaultAggregatePostsAfterDays = 365
ElasticsearchSettingsDefaultPostsAggregatorJobStartTime = "03:00"
ElasticsearchSettingsDefaultIndexPrefix = ""
ElasticsearchSettingsDefaultLiveIndexingBatchSize = 1
ElasticsearchSettingsDefaultBulkIndexingTimeWindowSeconds = 3600
ElasticsearchSettingsDefaultRequestTimeoutSeconds = 30
BleveSettingsDefaultIndexDir = ""
BleveSettingsDefaultBulkIndexingTimeWindowSeconds = 3600
DataRetentionSettingsDefaultMessageRetentionDays = 365
DataRetentionSettingsDefaultFileRetentionDays = 365
DataRetentionSettingsDefaultDeletionJobStartTime = "02:00"
DataRetentionSettingsDefaultBatchSize = 3000
PluginSettingsDefaultDirectory = "./plugins"
PluginSettingsDefaultClientDirectory = "./client/plugins"
PluginSettingsDefaultEnableMarketplace = true
PluginSettingsDefaultMarketplaceURL = "https://api.integrations.mattermost.com"
PluginSettingsOldMarketplaceURL = "https://marketplace.integrations.mattermost.com"
ComplianceExportTypeCsv = "csv"
ComplianceExportTypeActiance = "actiance"
ComplianceExportTypeGlobalrelay = "globalrelay"
ComplianceExportTypeGlobalrelayZip = "globalrelay-zip"
GlobalrelayCustomerTypeA9 = "A9"
GlobalrelayCustomerTypeA10 = "A10"
ClientSideCertCheckPrimaryAuth = "primary"
ClientSideCertCheckSecondaryAuth = "secondary"
ImageProxyTypeLocal = "local"
ImageProxyTypeAtmosCamo = "atmos/camo"
GoogleSettingsDefaultScope = "profile email"
GoogleSettingsDefaultAuthEndpoint = "https://accounts.google.com/o/oauth2/v2/auth"
GoogleSettingsDefaultTokenEndpoint = "https://www.googleapis.com/oauth2/v4/token"
GoogleSettingsDefaultUserAPIEndpoint = "https://people.googleapis.com/v1/people/me?personFields=names,emailAddresses,nicknames,metadata"
Office365SettingsDefaultScope = "User.Read"
Office365SettingsDefaultAuthEndpoint = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
Office365SettingsDefaultTokenEndpoint = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
Office365SettingsDefaultUserAPIEndpoint = "https://graph.microsoft.com/v1.0/me"
CloudSettingsDefaultCwsURL = "https://customers.mattermost.com"
CloudSettingsDefaultCwsAPIURL = "https://portal.internal.prod.cloud.mattermost.com"
OpenidSettingsDefaultScope = "profile openid email"
LocalModeSocketPath = "/var/tmp/mattermost_local.socket"
)
func GetDefaultAppCustomURLSchemes() []string {
return []string{"mmauth://", "mmauthbeta://"}
}
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 `access:"environment_web_server,authentication_saml,write_restrictable"`
WebsocketURL *string `access:"write_restrictable,cloud_restrictable"`
LicenseFileLocation *string `access:"write_restrictable,cloud_restrictable"` // telemetry: none
ListenAddress *string `access:"environment_web_server,write_restrictable,cloud_restrictable"` // telemetry: none
ConnectionSecurity *string `access:"environment_web_server,write_restrictable,cloud_restrictable"`
TLSCertFile *string `access:"environment_web_server,write_restrictable,cloud_restrictable"`
TLSKeyFile *string `access:"environment_web_server,write_restrictable,cloud_restrictable"`
TLSMinVer *string `access:"write_restrictable,cloud_restrictable"` // telemetry: none
TLSStrictTransport *bool `access:"write_restrictable,cloud_restrictable"`
TLSStrictTransportMaxAge *int64 `access:"write_restrictable,cloud_restrictable"` // telemetry: none
TLSOverwriteCiphers []string `access:"write_restrictable,cloud_restrictable"` // telemetry: none
UseLetsEncrypt *bool `access:"environment_web_server,write_restrictable,cloud_restrictable"`
LetsEncryptCertificateCacheFile *string `access:"environment_web_server,write_restrictable,cloud_restrictable"` // telemetry: none
Forward80To443 *bool `access:"environment_web_server,write_restrictable,cloud_restrictable"`
TrustedProxyIPHeader []string `access:"write_restrictable,cloud_restrictable"` // telemetry: none
ReadTimeout *int `access:"environment_web_server,write_restrictable,cloud_restrictable"`
WriteTimeout *int `access:"environment_web_server,write_restrictable,cloud_restrictable"`
IdleTimeout *int `access:"write_restrictable,cloud_restrictable"`
MaximumLoginAttempts *int `access:"authentication_password,write_restrictable,cloud_restrictable"`
GoroutineHealthThreshold *int `access:"write_restrictable,cloud_restrictable"` // telemetry: none
EnableOAuthServiceProvider *bool `access:"integrations_integration_management"`
EnableIncomingWebhooks *bool `access:"integrations_integration_management"`
EnableOutgoingWebhooks *bool `access:"integrations_integration_management"`
EnableCommands *bool `access:"integrations_integration_management"`
EnablePostUsernameOverride *bool `access:"integrations_integration_management"`
EnablePostIconOverride *bool `access:"integrations_integration_management"`
GoogleDeveloperKey *string `access:"site_posts,write_restrictable,cloud_restrictable"`
EnableLinkPreviews *bool `access:"site_posts"`
EnablePermalinkPreviews *bool `access:"site_posts"`
RestrictLinkPreviews *string `access:"site_posts"`
EnableTesting *bool `access:"environment_developer,write_restrictable,cloud_restrictable"`
EnableDeveloper *bool `access:"environment_developer,write_restrictable,cloud_restrictable"`
EnableOpenTracing *bool `access:"write_restrictable,cloud_restrictable"`
EnableSecurityFixAlert *bool `access:"environment_smtp,write_restrictable,cloud_restrictable"`
EnableInsecureOutgoingConnections *bool `access:"environment_web_server,write_restrictable,cloud_restrictable"`
AllowedUntrustedInternalConnections *string `access:"environment_web_server,write_restrictable,cloud_restrictable"`
EnableMultifactorAuthentication *bool `access:"authentication_mfa"`
EnforceMultifactorAuthentication *bool `access:"authentication_mfa"`
EnableUserAccessTokens *bool `access:"integrations_integration_management"`
AllowCorsFrom *string `access:"integrations_cors,write_restrictable,cloud_restrictable"`
CorsExposedHeaders *string `access:"integrations_cors,write_restrictable,cloud_restrictable"`
CorsAllowCredentials *bool `access:"integrations_cors,write_restrictable,cloud_restrictable"`
CorsDebug *bool `access:"integrations_cors,write_restrictable,cloud_restrictable"`
AllowCookiesForSubdomains *bool `access:"write_restrictable,cloud_restrictable"`
ExtendSessionLengthWithActivity *bool `access:"environment_session_lengths,write_restrictable,cloud_restrictable"`
SessionLengthWebInDays *int `access:"environment_session_lengths,write_restrictable,cloud_restrictable"`
SessionLengthMobileInDays *int `access:"environment_session_lengths,write_restrictable,cloud_restrictable"`
SessionLengthSSOInDays *int `access:"environment_session_lengths,write_restrictable,cloud_restrictable"`
SessionCacheInMinutes *int `access:"environment_session_lengths,write_restrictable,cloud_restrictable"`
SessionIdleTimeoutInMinutes *int `access:"environment_session_lengths,write_restrictable,cloud_restrictable"`
WebsocketSecurePort *int `access:"write_restrictable,cloud_restrictable"` // telemetry: none
WebsocketPort *int `access:"write_restrictable,cloud_restrictable"` // telemetry: none
WebserverMode *string `access:"environment_web_server,write_restrictable,cloud_restrictable"`
EnableGifPicker *bool `access:"integrations_gif"`
GfycatAPIKey *string `access:"integrations_gif"`
GfycatAPISecret *string `access:"integrations_gif"`
EnableCustomEmoji *bool `access:"site_emoji"`
EnableEmojiPicker *bool `access:"site_emoji"`
PostEditTimeLimit *int `access:"user_management_permissions"`
TimeBetweenUserTypingUpdatesMilliseconds *int64 `access:"experimental_features,write_restrictable,cloud_restrictable"`
EnablePostSearch *bool `access:"write_restrictable,cloud_restrictable"`
EnableFileSearch *bool `access:"write_restrictable"`
MinimumHashtagLength *int `access:"environment_database,write_restrictable,cloud_restrictable"`
EnableUserTypingMessages *bool `access:"experimental_features,write_restrictable,cloud_restrictable"`
EnableChannelViewedMessages *bool `access:"experimental_features,write_restrictable,cloud_restrictable"`
EnableUserStatuses *bool `access:"write_restrictable,cloud_restrictable"`
ExperimentalEnableAuthenticationTransfer *bool `access:"experimental_features,write_restrictable,cloud_restrictable"`
ClusterLogTimeoutMilliseconds *int `access:"write_restrictable,cloud_restrictable"`
EnablePreviewFeatures *bool `access:"experimental_features"`
EnableTutorial *bool `access:"experimental_features"`
EnableOnboardingFlow *bool `access:"experimental_features"`
ExperimentalEnableDefaultChannelLeaveJoinMessages *bool `access:"experimental_features"`
ExperimentalGroupUnreadChannels *string `access:"experimental_features"`
EnableAPITeamDeletion *bool
EnableAPIUserDeletion *bool
ExperimentalEnableHardenedMode *bool `access:"experimental_features"`
ExperimentalStrictCSRFEnforcement *bool `access:"experimental_features,write_restrictable,cloud_restrictable"`
EnableEmailInvitations *bool `access:"authentication_signup"`
DisableBotsWhenOwnerIsDeactivated *bool `access:"integrations_bot_accounts,write_restrictable,cloud_restrictable"`
EnableBotAccountCreation *bool `access:"integrations_bot_accounts"`
EnableSVGs *bool `access:"site_posts"`
EnableLatex *bool `access:"site_posts"`
EnableAPIChannelDeletion *bool
EnableLocalMode *bool
LocalModeSocketLocation *string // telemetry: none
EnableAWSMetering *bool // telemetry: none
SplitKey *string `access:"experimental_feature_flags,write_restrictable"` // telemetry: none
FeatureFlagSyncIntervalSeconds *int `access:"experimental_feature_flags,write_restrictable"` // telemetry: none
DebugSplit *bool `access:"experimental_feature_flags,write_restrictable"` // telemetry: none
ThreadAutoFollow *bool `access:"experimental_features"`
CollapsedThreads *string `access:"experimental_features"`
ManagedResourcePaths *string `access:"environment_web_server,write_restrictable,cloud_restrictable"`
EnableReliableWebSockets *bool `access:"experimental_features"` // telemetry: none
}
func (s *ServiceSettings) SetDefaults(isUpdate bool) {
if s.EnableEmailInvitations == nil {
// If the site URL is also not present then assume this is a clean install
if s.SiteURL == nil {
s.EnableEmailInvitations = NewBool(false)
} else {
s.EnableEmailInvitations = NewBool(true)
}
}
if s.SiteURL == nil {
if s.EnableDeveloper != nil && *s.EnableDeveloper {
s.SiteURL = NewString(ServiceSettingsDefaultSiteURL)
} else {
s.SiteURL = NewString("")
}
}
if s.WebsocketURL == nil {
s.WebsocketURL = NewString("")
}
if s.LicenseFileLocation == nil {
s.LicenseFileLocation = NewString("")
}
if s.ListenAddress == nil {
s.ListenAddress = NewString(ServiceSettingsDefaultListenAndAddress)
}
if s.EnableLinkPreviews == nil {
s.EnableLinkPreviews = NewBool(true)
}
if s.EnablePermalinkPreviews == nil {
s.EnablePermalinkPreviews = NewBool(true)
}
if s.RestrictLinkPreviews == nil {
s.RestrictLinkPreviews = NewString("")
}
if s.EnableTesting == nil {
s.EnableTesting = NewBool(false)
}
if s.EnableDeveloper == nil {
s.EnableDeveloper = NewBool(false)
}
if s.EnableOpenTracing == nil {
s.EnableOpenTracing = NewBool(false)
}
if s.EnableSecurityFixAlert == nil {
s.EnableSecurityFixAlert = NewBool(true)
}
if s.EnableInsecureOutgoingConnections == nil {
s.EnableInsecureOutgoingConnections = NewBool(false)
}
if s.AllowedUntrustedInternalConnections == nil {
s.AllowedUntrustedInternalConnections = NewString("")
}
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.GoogleDeveloperKey == nil {
s.GoogleDeveloperKey = NewString("")
}
if s.EnableOAuthServiceProvider == nil {
s.EnableOAuthServiceProvider = NewBool(false)
}
if s.EnableIncomingWebhooks == nil {
s.EnableIncomingWebhooks = NewBool(true)
}
if s.EnableOutgoingWebhooks == nil {
s.EnableOutgoingWebhooks = NewBool(true)
}
if s.ConnectionSecurity == nil {
s.ConnectionSecurity = NewString("")
}
if s.TLSKeyFile == nil {
s.TLSKeyFile = NewString(ServiceSettingsDefaultTLSKeyFile)
}
if s.TLSCertFile == nil {
s.TLSCertFile = NewString(ServiceSettingsDefaultTLSCertFile)
}
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)
}
if s.LetsEncryptCertificateCacheFile == nil {
s.LetsEncryptCertificateCacheFile = NewString("./config/letsencrypt.cache")
}
if s.ReadTimeout == nil {
s.ReadTimeout = NewInt(ServiceSettingsDefaultReadTimeout)
}
if s.WriteTimeout == nil {
s.WriteTimeout = NewInt(ServiceSettingsDefaultWriteTimeout)
}
if s.IdleTimeout == nil {
s.IdleTimeout = NewInt(ServiceSettingsDefaultIdleTimeout)
}
if s.MaximumLoginAttempts == nil {
s.MaximumLoginAttempts = NewInt(ServiceSettingsDefaultMaxLoginAttempts)
}
if s.Forward80To443 == nil {
s.Forward80To443 = NewBool(false)
}
if isUpdate {
// When updating an existing configuration, ensure that defaults are set.
if s.TrustedProxyIPHeader == nil {
s.TrustedProxyIPHeader = []string{HeaderForwarded, HeaderRealIP}
}
} else {
// When generating a blank configuration, leave the list empty.
s.TrustedProxyIPHeader = []string{}
}
if s.TimeBetweenUserTypingUpdatesMilliseconds == nil {
s.TimeBetweenUserTypingUpdatesMilliseconds = NewInt64(5000)
}
if s.EnablePostSearch == nil {
s.EnablePostSearch = NewBool(true)
}
if s.EnableFileSearch == nil {
s.EnableFileSearch = NewBool(true)
}
if s.MinimumHashtagLength == nil {
s.MinimumHashtagLength = NewInt(3)
}
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.EnableTutorial == nil {
s.EnableTutorial = NewBool(true)
}
if s.EnableOnboardingFlow == nil {
s.EnableOnboardingFlow = NewBool(true)
}
// Must be manually enabled for existing installations.
if s.ExtendSessionLengthWithActivity == nil {
s.ExtendSessionLengthWithActivity = NewBool(!isUpdate)
}
if s.SessionLengthWebInDays == nil {
if isUpdate {
s.SessionLengthWebInDays = NewInt(180)
} else {
s.SessionLengthWebInDays = NewInt(30)
}
}
if s.SessionLengthMobileInDays == nil {
if isUpdate {
s.SessionLengthMobileInDays = NewInt(180)
} else {
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(43200)
}
if s.EnableCommands == nil {
s.EnableCommands = NewBool(true)
}
if s.EnablePostUsernameOverride == nil {
s.EnablePostUsernameOverride = NewBool(false)
}
if s.EnablePostIconOverride == nil {
s.EnablePostIconOverride = NewBool(false)
}
if s.WebsocketPort == nil {
s.WebsocketPort = NewInt(80)
}
if s.WebsocketSecurePort == nil {
s.WebsocketSecurePort = NewInt(443)
}
if s.AllowCorsFrom == nil {
s.AllowCorsFrom = NewString(ServiceSettingsDefaultAllowCorsFrom)
}
if s.CorsExposedHeaders == nil {
s.CorsExposedHeaders = NewString("")
}
if s.CorsAllowCredentials == nil {
s.CorsAllowCredentials = NewBool(false)
}
if s.CorsDebug == nil {
s.CorsDebug = NewBool(false)
}
if s.AllowCookiesForSubdomains == nil {
s.AllowCookiesForSubdomains = NewBool(false)
}
if s.WebserverMode == nil {
s.WebserverMode = NewString("gzip")
} else if *s.WebserverMode == "regular" {
*s.WebserverMode = "gzip"
}
if s.EnableCustomEmoji == nil {
s.EnableCustomEmoji = NewBool(true)
}
if s.EnableEmojiPicker == nil {
s.EnableEmojiPicker = NewBool(true)
}
if s.EnableGifPicker == nil {
s.EnableGifPicker = NewBool(true)
}
if s.GfycatAPIKey == nil || *s.GfycatAPIKey == "" {
s.GfycatAPIKey = NewString(ServiceSettingsDefaultGfycatAPIKey)
}
if s.GfycatAPISecret == nil || *s.GfycatAPISecret == "" {
s.GfycatAPISecret = NewString(ServiceSettingsDefaultGfycatAPISecret)
}
if s.ExperimentalEnableAuthenticationTransfer == nil {
s.ExperimentalEnableAuthenticationTransfer = NewBool(true)
}
if s.PostEditTimeLimit == nil {
s.PostEditTimeLimit = NewInt(-1)
}
if s.EnablePreviewFeatures == nil {
s.EnablePreviewFeatures = NewBool(true)
}
if s.ExperimentalEnableDefaultChannelLeaveJoinMessages == nil {
s.ExperimentalEnableDefaultChannelLeaveJoinMessages = NewBool(true)
}
if s.ExperimentalGroupUnreadChannels == nil {
s.ExperimentalGroupUnreadChannels = NewString(GroupUnreadChannelsDisabled)
} else if *s.ExperimentalGroupUnreadChannels == "0" {
s.ExperimentalGroupUnreadChannels = NewString(GroupUnreadChannelsDisabled)
} else if *s.ExperimentalGroupUnreadChannels == "1" {
s.ExperimentalGroupUnreadChannels = NewString(GroupUnreadChannelsDefaultOn)
}
if s.EnableAPITeamDeletion == nil {
s.EnableAPITeamDeletion = NewBool(false)
}
if s.EnableAPIUserDeletion == nil {
s.EnableAPIUserDeletion = NewBool(false)
}
if s.EnableAPIChannelDeletion == nil {
s.EnableAPIChannelDeletion = NewBool(false)
}
if s.ExperimentalEnableHardenedMode == nil {
s.ExperimentalEnableHardenedMode = NewBool(false)
}
if s.ExperimentalStrictCSRFEnforcement == nil {
s.ExperimentalStrictCSRFEnforcement = NewBool(false)
}
if s.DisableBotsWhenOwnerIsDeactivated == nil {
s.DisableBotsWhenOwnerIsDeactivated = NewBool(true)
}
if s.EnableBotAccountCreation == nil {
s.EnableBotAccountCreation = NewBool(false)
}
if s.EnableSVGs == nil {
if isUpdate {
s.EnableSVGs = NewBool(true)
} else {
s.EnableSVGs = NewBool(false)
}
}
if s.EnableLatex == nil {
if isUpdate {
s.EnableLatex = NewBool(true)
} else {
s.EnableLatex = NewBool(false)
}
}
if s.EnableLocalMode == nil {
s.EnableLocalMode = NewBool(false)
}
if s.LocalModeSocketLocation == nil {
s.LocalModeSocketLocation = NewString(LocalModeSocketPath)
}
if s.EnableAWSMetering == nil {
s.EnableAWSMetering = NewBool(false)
}
if s.SplitKey == nil {
s.SplitKey = NewString("")
}
if s.FeatureFlagSyncIntervalSeconds == nil {
s.FeatureFlagSyncIntervalSeconds = NewInt(30)
}
if s.DebugSplit == nil {
s.DebugSplit = NewBool(false)
}
if s.ThreadAutoFollow == nil {
s.ThreadAutoFollow = NewBool(true)
}
if s.CollapsedThreads == nil {
s.CollapsedThreads = NewString(CollapsedThreadsDisabled)
}
if s.ManagedResourcePaths == nil {
s.ManagedResourcePaths = NewString("")
}
if s.EnableReliableWebSockets == nil {
s.EnableReliableWebSockets = NewBool(true)
}
}
type ClusterSettings struct {
Enable *bool `access:"environment_high_availability,write_restrictable"`
ClusterName *string `access:"environment_high_availability,write_restrictable,cloud_restrictable"` // telemetry: none
OverrideHostname *string `access:"environment_high_availability,write_restrictable,cloud_restrictable"` // telemetry: none
NetworkInterface *string `access:"environment_high_availability,write_restrictable,cloud_restrictable"`
BindAddress *string `access:"environment_high_availability,write_restrictable,cloud_restrictable"`
AdvertiseAddress *string `access:"environment_high_availability,write_restrictable,cloud_restrictable"`
UseIPAddress *bool `access:"environment_high_availability,write_restrictable,cloud_restrictable"`
EnableGossipCompression *bool `access:"environment_high_availability,write_restrictable,cloud_restrictable"`
EnableExperimentalGossipEncryption *bool `access:"environment_high_availability,write_restrictable,cloud_restrictable"`
ReadOnlyConfig *bool `access:"environment_high_availability,write_restrictable,cloud_restrictable"`
GossipPort *int `access:"environment_high_availability,write_restrictable,cloud_restrictable"` // telemetry: none
StreamingPort *int `access:"environment_high_availability,write_restrictable,cloud_restrictable"` // telemetry: none
MaxIdleConns *int `access:"environment_high_availability,write_restrictable,cloud_restrictable"` // telemetry: none
MaxIdleConnsPerHost *int `access:"environment_high_availability,write_restrictable,cloud_restrictable"` // telemetry: none
IdleConnTimeoutMilliseconds *int `access:"environment_high_availability,write_restrictable,cloud_restrictable"` // telemetry: none
}
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.NetworkInterface == nil {
s.NetworkInterface = NewString("")
}
if s.BindAddress == nil {
s.BindAddress = NewString("")
}
if s.AdvertiseAddress == nil {
s.AdvertiseAddress = NewString("")
}
if s.UseIPAddress == nil {
s.UseIPAddress = NewBool(true)
}
if s.EnableExperimentalGossipEncryption == nil {
s.EnableExperimentalGossipEncryption = NewBool(false)
}
if s.EnableGossipCompression == nil {
s.EnableGossipCompression = NewBool(true)
}
if s.ReadOnlyConfig == nil {
s.ReadOnlyConfig = NewBool(true)
}
if s.GossipPort == nil {
s.GossipPort = NewInt(8074)
}
if s.StreamingPort == nil {
s.StreamingPort = NewInt(8075)
}
if s.MaxIdleConns == nil {
s.MaxIdleConns = NewInt(100)
}
if s.MaxIdleConnsPerHost == nil {
s.MaxIdleConnsPerHost = NewInt(128)
}
if s.IdleConnTimeoutMilliseconds == nil {
s.IdleConnTimeoutMilliseconds = NewInt(90000)
}
}
type MetricsSettings struct {
Enable *bool `access:"environment_performance_monitoring,write_restrictable,cloud_restrictable"`
BlockProfileRate *int `access:"environment_performance_monitoring,write_restrictable,cloud_restrictable"`
ListenAddress *string `access:"environment_performance_monitoring,write_restrictable,cloud_restrictable"` // telemetry: none
}
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 ExperimentalSettings struct {
ClientSideCertEnable *bool `access:"experimental_features,cloud_restrictable"`
ClientSideCertCheck *string `access:"experimental_features,cloud_restrictable"`
EnableClickToReply *bool `access:"experimental_features,write_restrictable,cloud_restrictable"`
LinkMetadataTimeoutMilliseconds *int64 `access:"experimental_features,write_restrictable,cloud_restrictable"`
RestrictSystemAdmin *bool `access:"experimental_features,write_restrictable"`
UseNewSAMLLibrary *bool `access:"experimental_features,cloud_restrictable"`
CloudUserLimit *int64 `access:"experimental_features,write_restrictable"`
CloudBilling *bool `access:"experimental_features,write_restrictable"`
EnableSharedChannels *bool `access:"experimental_features"`
EnableRemoteClusterService *bool `access:"experimental_features"`
}
func (s *ExperimentalSettings) SetDefaults() {
if s.ClientSideCertEnable == nil {
s.ClientSideCertEnable = NewBool(false)
}
if s.ClientSideCertCheck == nil {
s.ClientSideCertCheck = NewString(ClientSideCertCheckSecondaryAuth)
}
if s.EnableClickToReply == nil {
s.EnableClickToReply = NewBool(false)
}
if s.LinkMetadataTimeoutMilliseconds == nil {
s.LinkMetadataTimeoutMilliseconds = NewInt64(ExperimentalSettingsDefaultLinkMetadataTimeoutMilliseconds)
}
if s.RestrictSystemAdmin == nil {
s.RestrictSystemAdmin = NewBool(false)
}
if s.CloudUserLimit == nil {
// User limit 0 is treated as no limit
s.CloudUserLimit = NewInt64(0)
}
if s.CloudBilling == nil {
s.CloudBilling = NewBool(false)
}
if s.UseNewSAMLLibrary == nil {
s.UseNewSAMLLibrary = NewBool(false)
}
if s.EnableSharedChannels == nil {
s.EnableSharedChannels = NewBool(false)
}
if s.EnableRemoteClusterService == nil {
s.EnableRemoteClusterService = NewBool(false)
}
}
type AnalyticsSettings struct {
MaxUsersForStatistics *int `access:"write_restrictable,cloud_restrictable"`
}
func (s *AnalyticsSettings) SetDefaults() {
if s.MaxUsersForStatistics == nil {
s.MaxUsersForStatistics = NewInt(AnalyticsSettingsDefaultMaxUsersForStatistics)
}
}
type SSOSettings struct {
Enable *bool `access:"authentication_openid"`
Secret *string `access:"authentication_openid"` // telemetry: none
Id *string `access:"authentication_openid"` // telemetry: none
Scope *string `access:"authentication_openid"` // telemetry: none
AuthEndpoint *string `access:"authentication_openid"` // telemetry: none
TokenEndpoint *string `access:"authentication_openid"` // telemetry: none
UserAPIEndpoint *string `access:"authentication_openid"` // telemetry: none
DiscoveryEndpoint *string `access:"authentication_openid"` // telemetry: none
ButtonText *string `access:"authentication_openid"` // telemetry: none
ButtonColor *string `access:"authentication_openid"` // telemetry: none
}
func (s *SSOSettings) setDefaults(scope, authEndpoint, tokenEndpoint, userAPIEndpoint, buttonColor string) {
if s.Enable == nil {
s.Enable = NewBool(false)
}
if s.Secret == nil {
s.Secret = NewString("")
}
if s.Id == nil {
s.Id = NewString("")
}
if s.Scope == nil {
s.Scope = NewString(scope)
}
if s.DiscoveryEndpoint == nil {
s.DiscoveryEndpoint = NewString("")
}
if s.AuthEndpoint == nil {
s.AuthEndpoint = NewString(authEndpoint)
}
if s.TokenEndpoint == nil {
s.TokenEndpoint = NewString(tokenEndpoint)
}
if s.UserAPIEndpoint == nil {
s.UserAPIEndpoint = NewString(userAPIEndpoint)
}
if s.ButtonText == nil {
s.ButtonText = NewString("")
}
if s.ButtonColor == nil {
s.ButtonColor = NewString(buttonColor)
}
}
type Office365Settings struct {
Enable *bool `access:"authentication_openid"`
Secret *string `access:"authentication_openid"` // telemetry: none
Id *string `access:"authentication_openid"` // telemetry: none
Scope *string `access:"authentication_openid"`
AuthEndpoint *string `access:"authentication_openid"` // telemetry: none
TokenEndpoint *string `access:"authentication_openid"` // telemetry: none
UserAPIEndpoint *string `access:"authentication_openid"` // telemetry: none
DiscoveryEndpoint *string `access:"authentication_openid"` // telemetry: none
DirectoryId *string `access:"authentication_openid"` // telemetry: none
}
func (s *Office365Settings) setDefaults() {
if s.Enable == nil {
s.Enable = NewBool(false)
}
if s.Id == nil {
s.Id = NewString("")
}
if s.Secret == nil {
s.Secret = NewString("")
}
if s.Scope == nil {
s.Scope = NewString(Office365SettingsDefaultScope)
}
if s.DiscoveryEndpoint == nil {
s.DiscoveryEndpoint = NewString("")
}
if s.AuthEndpoint == nil {
s.AuthEndpoint = NewString(Office365SettingsDefaultAuthEndpoint)
}
if s.TokenEndpoint == nil {
s.TokenEndpoint = NewString(Office365SettingsDefaultTokenEndpoint)
}
if s.UserAPIEndpoint == nil {
s.UserAPIEndpoint = NewString(Office365SettingsDefaultUserAPIEndpoint)
}
if s.DirectoryId == nil {
s.DirectoryId = NewString("")
}
}
func (s *Office365Settings) SSOSettings() *SSOSettings {
ssoSettings := SSOSettings{}
ssoSettings.Enable = s.Enable
ssoSettings.Secret = s.Secret
ssoSettings.Id = s.Id
ssoSettings.Scope = s.Scope
ssoSettings.DiscoveryEndpoint = s.DiscoveryEndpoint
ssoSettings.AuthEndpoint = s.AuthEndpoint
ssoSettings.TokenEndpoint = s.TokenEndpoint
ssoSettings.UserAPIEndpoint = s.UserAPIEndpoint
return &ssoSettings
}
type ReplicaLagSettings struct {
DataSource *string `access:"environment,write_restrictable,cloud_restrictable"` // telemetry: none
QueryAbsoluteLag *string `access:"environment,write_restrictable,cloud_restrictable"` // telemetry: none
QueryTimeLag *string `access:"environment,write_restrictable,cloud_restrictable"` // telemetry: none
}
type SqlSettings struct {
DriverName *string `access:"environment_database,write_restrictable,cloud_restrictable"`
DataSource *string `access:"environment_database,write_restrictable,cloud_restrictable"` // telemetry: none
DataSourceReplicas []string `access:"environment_database,write_restrictable,cloud_restrictable"`
DataSourceSearchReplicas []string `access:"environment_database,write_restrictable,cloud_restrictable"`
MaxIdleConns *int `access:"environment_database,write_restrictable,cloud_restrictable"`
ConnMaxLifetimeMilliseconds *int `access:"environment_database,write_restrictable,cloud_restrictable"`
ConnMaxIdleTimeMilliseconds *int `access:"environment_database,write_restrictable,cloud_restrictable"`
MaxOpenConns *int `access:"environment_database,write_restrictable,cloud_restrictable"`
Trace *bool `access:"environment_database,write_restrictable,cloud_restrictable"`
AtRestEncryptKey *string `access:"environment_database,write_restrictable,cloud_restrictable"` // telemetry: none
QueryTimeout *int `access:"environment_database,write_restrictable,cloud_restrictable"`
DisableDatabaseSearch *bool `access:"environment_database,write_restrictable,cloud_restrictable"`
ReplicaLagSettings []*ReplicaLagSettings `access:"environment_database,write_restrictable,cloud_restrictable"` // telemetry: none
}
func (s *SqlSettings) SetDefaults(isUpdate bool) {
if s.DriverName == nil {
s.DriverName = NewString(DatabaseDriverPostgres)
}
if s.DataSource == nil {
s.DataSource = NewString(SqlSettingsDefaultDataSource)
}
if s.DataSourceReplicas == nil {
s.DataSourceReplicas = []string{}
}
if s.DataSourceSearchReplicas == nil {
s.DataSourceSearchReplicas = []string{}
}
if isUpdate {
// When updating an existing configuration, ensure an encryption key has been specified.
if s.AtRestEncryptKey == nil || *s.AtRestEncryptKey == "" {
s.AtRestEncryptKey = NewString(NewRandomString(32))
}
} else {
// When generating a blank configuration, leave this key empty to be generated on server start.
s.AtRestEncryptKey = NewString("")
}
if s.MaxIdleConns == nil {
s.MaxIdleConns = NewInt(20)
}
if s.MaxOpenConns == nil {
s.MaxOpenConns = NewInt(300)
}
if s.ConnMaxLifetimeMilliseconds == nil {
s.ConnMaxLifetimeMilliseconds = NewInt(3600000)
}
if s.ConnMaxIdleTimeMilliseconds == nil {
s.ConnMaxIdleTimeMilliseconds = NewInt(300000)
}
if s.Trace == nil {
s.Trace = NewBool(false)
}
if s.QueryTimeout == nil {
s.QueryTimeout = NewInt(30)
}
if s.DisableDatabaseSearch == nil {
s.DisableDatabaseSearch = NewBool(false)
}
if s.ReplicaLagSettings == nil {
s.ReplicaLagSettings = []*ReplicaLagSettings{}
}
}
type LogSettings struct {
EnableConsole *bool `access:"environment_logging,write_restrictable,cloud_restrictable"`
ConsoleLevel *string `access:"environment_logging,write_restrictable,cloud_restrictable"`
ConsoleJson *bool `access:"environment_logging,write_restrictable,cloud_restrictable"`
EnableColor *bool `access:"environment_logging,write_restrictable,cloud_restrictable"` // telemetry: none
EnableFile *bool `access:"environment_logging,write_restrictable,cloud_restrictable"`
FileLevel *string `access:"environment_logging,write_restrictable,cloud_restrictable"`
FileJson *bool `access:"environment_logging,write_restrictable,cloud_restrictable"`
FileLocation *string `access:"environment_logging,write_restrictable,cloud_restrictable"`
EnableWebhookDebugging *bool `access:"environment_logging,write_restrictable,cloud_restrictable"`
EnableDiagnostics *bool `access:"environment_logging,write_restrictable,cloud_restrictable"` // telemetry: none
EnableSentry *bool `access:"environment_logging,write_restrictable,cloud_restrictable"` // telemetry: none
AdvancedLoggingConfig *string `access:"environment_logging,write_restrictable,cloud_restrictable"`
}
func NewLogSettings() *LogSettings {
settings := &LogSettings{}
settings.SetDefaults()
return settings
}
func (s *LogSettings) SetDefaults() {
if s.EnableConsole == nil {
s.EnableConsole = NewBool(true)
}
if s.ConsoleLevel == nil {
s.ConsoleLevel = NewString("DEBUG")
}
if s.EnableColor == nil {
s.EnableColor = NewBool(false)
}
if s.EnableFile == nil {
s.EnableFile = NewBool(true)
}
if s.FileLevel == nil {
s.FileLevel = NewString("INFO")
}
if s.FileLocation == nil {
s.FileLocation = NewString("")
}
if s.EnableWebhookDebugging == nil {
s.EnableWebhookDebugging = NewBool(true)
}
if s.EnableDiagnostics == nil {
s.EnableDiagnostics = NewBool(true)
}
if s.EnableSentry == nil {
s.EnableSentry = NewBool(*s.EnableDiagnostics)
}
if s.ConsoleJson == nil {
s.ConsoleJson = NewBool(true)
}
if s.FileJson == nil {
s.FileJson = NewBool(true)
}
if s.AdvancedLoggingConfig == nil {
s.AdvancedLoggingConfig = NewString("")
}
}
type ExperimentalAuditSettings struct {
FileEnabled *bool `access:"experimental_features,write_restrictable,cloud_restrictable"`
FileName *string `access:"experimental_features,write_restrictable,cloud_restrictable"` // telemetry: none
FileMaxSizeMB *int `access:"experimental_features,write_restrictable,cloud_restrictable"`
FileMaxAgeDays *int `access:"experimental_features,write_restrictable,cloud_restrictable"`
FileMaxBackups *int `access:"experimental_features,write_restrictable,cloud_restrictable"`
FileCompress *bool `access:"experimental_features,write_restrictable,cloud_restrictable"`
FileMaxQueueSize *int `access:"experimental_features,write_restrictable,cloud_restrictable"`
AdvancedLoggingConfig *string `access:"experimental_features,write_restrictable,cloud_restrictable"`
}
func (s *ExperimentalAuditSettings) SetDefaults() {
if s.FileEnabled == nil {
s.FileEnabled = NewBool(false)
}
if s.FileName == nil {
s.FileName = NewString("")
}
if s.FileMaxSizeMB == nil {
s.FileMaxSizeMB = NewInt(100)
}
if s.FileMaxAgeDays == nil {
s.FileMaxAgeDays = NewInt(0) // no limit on age
}
if s.FileMaxBackups == nil { // no limit on number of backups
s.FileMaxBackups = NewInt(0)
}
if s.FileCompress == nil {
s.FileCompress = NewBool(false)
}
if s.FileMaxQueueSize == nil {
s.FileMaxQueueSize = NewInt(1000)
}
if s.AdvancedLoggingConfig == nil {
s.AdvancedLoggingConfig = NewString("")
}
}
type NotificationLogSettings struct {
EnableConsole *bool `access:"write_restrictable,cloud_restrictable"`
ConsoleLevel *string `access:"write_restrictable,cloud_restrictable"`
ConsoleJson *bool `access:"write_restrictable,cloud_restrictable"`
EnableColor *bool `access:"write_restrictable,cloud_restrictable"` // telemetry: none
EnableFile *bool `access:"write_restrictable,cloud_restrictable"`
FileLevel *string `access:"write_restrictable,cloud_restrictable"`
FileJson *bool `access:"write_restrictable,cloud_restrictable"`
FileLocation *string `access:"write_restrictable,cloud_restrictable"`
AdvancedLoggingConfig *string `access:"write_restrictable,cloud_restrictable"`
}
func (s *NotificationLogSettings) SetDefaults() {
if s.EnableConsole == nil {
s.EnableConsole = NewBool(true)
}
if s.ConsoleLevel == nil {
s.ConsoleLevel = NewString("DEBUG")
}
if s.EnableFile == nil {
s.EnableFile = NewBool(true)
}
if s.FileLevel == nil {
s.FileLevel = NewString("INFO")
}
if s.FileLocation == nil {
s.FileLocation = NewString("")
}
if s.ConsoleJson == nil {
s.ConsoleJson = NewBool(true)
}
if s.EnableColor == nil {
s.EnableColor = NewBool(false)
}
if s.FileJson == nil {
s.FileJson = NewBool(true)
}
if s.AdvancedLoggingConfig == nil {
s.AdvancedLoggingConfig = NewString("")
}
}
type PasswordSettings struct {
MinimumLength *int `access:"authentication_password"`
Lowercase *bool `access:"authentication_password"`
Number *bool `access:"authentication_password"`
Uppercase *bool `access:"authentication_password"`
Symbol *bool `access:"authentication_password"`
}
func (s *PasswordSettings) SetDefaults() {
if s.MinimumLength == nil {
s.MinimumLength = NewInt(10)
}
if s.Lowercase == nil {
s.Lowercase = NewBool(true)
}
if s.Number == nil {
s.Number = NewBool(true)
}
if s.Uppercase == nil {
s.Uppercase = NewBool(true)
}
if s.Symbol == nil {
s.Symbol = NewBool(true)
}
}
type FileSettings struct {
EnableFileAttachments *bool `access:"site_file_sharing_and_downloads,cloud_restrictable"`
EnableMobileUpload *bool `access:"site_file_sharing_and_downloads,cloud_restrictable"`
EnableMobileDownload *bool `access:"site_file_sharing_and_downloads,cloud_restrictable"`
MaxFileSize *int64 `access:"environment_file_storage,cloud_restrictable"`
MaxImageResolution *int64 `access:"environment_file_storage,cloud_restrictable"`
DriverName *string `access:"environment_file_storage,write_restrictable,cloud_restrictable"`
Directory *string `access:"environment_file_storage,write_restrictable,cloud_restrictable"`
EnablePublicLink *bool `access:"site_public_links,cloud_restrictable"`
ExtractContent *bool `access:"environment_file_storage,write_restrictable"`
ArchiveRecursion *bool `access:"environment_file_storage,write_restrictable"`
PublicLinkSalt *string `access:"site_public_links,cloud_restrictable"` // telemetry: none
InitialFont *string `access:"environment_file_storage,cloud_restrictable"` // telemetry: none
AmazonS3AccessKeyId *string `access:"environment_file_storage,write_restrictable,cloud_restrictable"` // telemetry: none
AmazonS3SecretAccessKey *string `access:"environment_file_storage,write_restrictable,cloud_restrictable"` // telemetry: none
AmazonS3Bucket *string `access:"environment_file_storage,write_restrictable,cloud_restrictable"` // telemetry: none
AmazonS3PathPrefix *string `access:"environment_file_storage,write_restrictable,cloud_restrictable"` // telemetry: none
AmazonS3Region *string `access:"environment_file_storage,write_restrictable,cloud_restrictable"` // telemetry: none
AmazonS3Endpoint *string `access:"environment_file_storage,write_restrictable,cloud_restrictable"` // telemetry: none
AmazonS3SSL *bool `access:"environment_file_storage,write_restrictable,cloud_restrictable"`
AmazonS3SignV2 *bool `access:"environment_file_storage,write_restrictable,cloud_restrictable"`
AmazonS3SSE *bool `access:"environment_file_storage,write_restrictable,cloud_restrictable"`
AmazonS3Trace *bool `access:"environment_file_storage,write_restrictable,cloud_restrictable"`
}
func (s *FileSettings) SetDefaults(isUpdate bool) {
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(100 * 1024 * 1024) // 100MB (IEC)
}
if s.MaxImageResolution == nil {
s.MaxImageResolution = NewInt64(7680 * 4320) // 8K, ~33MPX
}
if s.DriverName == nil {
s.DriverName = NewString(ImageDriverLocal)
}
if s.Directory == nil || *s.Directory == "" {
s.Directory = NewString(FileSettingsDefaultDirectory)
}
if s.EnablePublicLink == nil {
s.EnablePublicLink = NewBool(false)
}
if s.ExtractContent == nil {
s.ExtractContent = NewBool(true)
}
if s.ArchiveRecursion == nil {
s.ArchiveRecursion = NewBool(false)
}
if isUpdate {
// When updating an existing configuration, ensure link salt has been specified.
if s.PublicLinkSalt == nil || *s.PublicLinkSalt == "" {
s.PublicLinkSalt = NewString(NewRandomString(32))
}
} else {
// When generating a blank configuration, leave link salt empty to be generated on server start.
s.PublicLinkSalt = NewString("")
}
if s.InitialFont == nil {
// Defaults to "nunito-bold.ttf"
s.InitialFont = NewString("nunito-bold.ttf")
}
if s.AmazonS3AccessKeyId == nil {
s.AmazonS3AccessKeyId = NewString("")
}
if s.AmazonS3SecretAccessKey == nil {
s.AmazonS3SecretAccessKey = NewString("")
}
if s.AmazonS3Bucket == nil {
s.AmazonS3Bucket = NewString("")
}
if s.AmazonS3PathPrefix == nil {
s.AmazonS3PathPrefix = NewString("")
}
if s.AmazonS3Region == nil {
s.AmazonS3Region = NewString("")
}
if s.AmazonS3Endpoint == nil || *s.AmazonS3Endpoint == "" {
// Defaults to "s3.amazonaws.com"
s.AmazonS3Endpoint = NewString("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)
}
}
func (s *FileSettings) ToFileBackendSettings(enableComplianceFeature bool) filestore.FileBackendSettings {
if *s.DriverName == ImageDriverLocal {
return filestore.FileBackendSettings{
DriverName: *s.DriverName,
Directory: *s.Directory,
}
}
return filestore.FileBackendSettings{
DriverName: *s.DriverName,
AmazonS3AccessKeyId: *s.AmazonS3AccessKeyId,
AmazonS3SecretAccessKey: *s.AmazonS3SecretAccessKey,
AmazonS3Bucket: *s.AmazonS3Bucket,
AmazonS3PathPrefix: *s.AmazonS3PathPrefix,
AmazonS3Region: *s.AmazonS3Region,
AmazonS3Endpoint: *s.AmazonS3Endpoint,
AmazonS3SSL: s.AmazonS3SSL == nil || *s.AmazonS3SSL,
AmazonS3SignV2: s.AmazonS3SignV2 != nil && *s.AmazonS3SignV2,
AmazonS3SSE: s.AmazonS3SSE != nil && *s.AmazonS3SSE && enableComplianceFeature,
AmazonS3Trace: s.AmazonS3Trace != nil && *s.AmazonS3Trace,
}
}
type EmailSettings struct {
EnableSignUpWithEmail *bool `access:"authentication_email"`
EnableSignInWithEmail *bool `access:"authentication_email"`
EnableSignInWithUsername *bool `access:"authentication_email"`
SendEmailNotifications *bool `access:"site_notifications"`
UseChannelInEmailNotifications *bool `access:"experimental_features"`
RequireEmailVerification *bool `access:"authentication_email"`
FeedbackName *string `access:"site_notifications"`
FeedbackEmail *string `access:"site_notifications,cloud_restrictable"`
ReplyToAddress *string `access:"site_notifications,cloud_restrictable"`
FeedbackOrganization *string `access:"site_notifications"`
EnableSMTPAuth *bool `access:"environment_smtp,write_restrictable,cloud_restrictable"`
SMTPUsername *string `access:"environment_smtp,write_restrictable,cloud_restrictable"` // telemetry: none
SMTPPassword *string `access:"environment_smtp,write_restrictable,cloud_restrictable"` // telemetry: none
SMTPServer *string `access:"environment_smtp,write_restrictable,cloud_restrictable"` // telemetry: none
SMTPPort *string `access:"environment_smtp,write_restrictable,cloud_restrictable"` // telemetry: none
SMTPServerTimeout *int `access:"cloud_restrictable"`
ConnectionSecurity *string `access:"environment_smtp,write_restrictable,cloud_restrictable"`
SendPushNotifications *bool `access:"environment_push_notification_server"`
PushNotificationServer *string `access:"environment_push_notification_server"` // telemetry: none
PushNotificationContents *string `access:"site_notifications"`
PushNotificationBuffer *int // telemetry: none
EnableEmailBatching *bool `access:"site_notifications"`
EmailBatchingBufferSize *int `access:"experimental_features"`
EmailBatchingInterval *int `access:"experimental_features"`
EnablePreviewModeBanner *bool `access:"site_notifications"`
SkipServerCertificateVerification *bool `access:"environment_smtp,write_restrictable,cloud_restrictable"`
EmailNotificationContentsType *string `access:"site_notifications"`
LoginButtonColor *string `access:"experimental_features"`
LoginButtonBorderColor *string `access:"experimental_features"`
LoginButtonTextColor *string `access:"experimental_features"`
}
func (s *EmailSettings) SetDefaults(isUpdate bool) {
if s.EnableSignUpWithEmail == nil {
s.EnableSignUpWithEmail = NewBool(true)
}
if s.EnableSignInWithEmail == nil {
s.EnableSignInWithEmail = NewBool(*s.EnableSignUpWithEmail)
}
if s.EnableSignInWithUsername == nil {
s.EnableSignInWithUsername = NewBool(true)
}
if s.SendEmailNotifications == nil {
s.SendEmailNotifications = NewBool(true)
}
if s.UseChannelInEmailNotifications == nil {
s.UseChannelInEmailNotifications = NewBool(false)
}
if s.RequireEmailVerification == nil {
s.RequireEmailVerification = NewBool(false)
}
if s.FeedbackName == nil {
s.FeedbackName = NewString("")
}
if s.FeedbackEmail == nil {
s.FeedbackEmail = NewString("test@example.com")
}
if s.ReplyToAddress == nil {
s.ReplyToAddress = NewString("test@example.com")
}
if s.FeedbackOrganization == nil {
s.FeedbackOrganization = NewString(EmailSettingsDefaultFeedbackOrganization)
}
if s.EnableSMTPAuth == nil {
if s.ConnectionSecurity == nil || *s.ConnectionSecurity == ConnSecurityNone {
s.EnableSMTPAuth = NewBool(false)
} else {
s.EnableSMTPAuth = NewBool(true)
}
}
if s.SMTPUsername == nil {
s.SMTPUsername = NewString("")
}
if s.SMTPPassword == nil {
s.SMTPPassword = NewString("")
}
if s.SMTPServer == nil || *s.SMTPServer == "" {
s.SMTPServer = NewString("localhost")
}
if s.SMTPPort == nil || *s.SMTPPort == "" {
s.SMTPPort = NewString("10025")
}
if s.SMTPServerTimeout == nil || *s.SMTPServerTimeout == 0 {
s.SMTPServerTimeout = NewInt(10)
}
if s.ConnectionSecurity == nil || *s.ConnectionSecurity == ConnSecurityPlain {
s.ConnectionSecurity = NewString(ConnSecurityNone)
}
if s.SendPushNotifications == nil {
s.SendPushNotifications = NewBool(!isUpdate)
}
if s.PushNotificationServer == nil {
if isUpdate {
s.PushNotificationServer = NewString("")
} else {
s.PushNotificationServer = NewString(GenericNotificationServer)
}
}
if s.PushNotificationContents == nil {
s.PushNotificationContents = NewString(FullNotification)
}
if s.PushNotificationBuffer == nil {
s.PushNotificationBuffer = NewInt(1000)
}
if s.EnableEmailBatching == nil {
s.EnableEmailBatching = NewBool(false)
}
if s.EmailBatchingBufferSize == nil {
s.EmailBatchingBufferSize = NewInt(EmailBatchingBufferSize)
}
if s.EmailBatchingInterval == nil {
s.EmailBatchingInterval = NewInt(EmailBatchingInterval)
}
if s.EnablePreviewModeBanner == nil {
s.EnablePreviewModeBanner = NewBool(true)
}
if s.EnableSMTPAuth == nil {
if *s.ConnectionSecurity == ConnSecurityNone {
s.EnableSMTPAuth = NewBool(false)
} else {
s.EnableSMTPAuth = NewBool(true)
}
}
if *s.ConnectionSecurity == ConnSecurityPlain {
*s.ConnectionSecurity = ConnSecurityNone
}
if s.SkipServerCertificateVerification == nil {
s.SkipServerCertificateVerification = NewBool(false)
}
if s.EmailNotificationContentsType == nil {
s.EmailNotificationContentsType = NewString(EmailNotificationContentsFull)
}
if s.LoginButtonColor == nil {
s.LoginButtonColor = NewString("#0000")
}
if s.LoginButtonBorderColor == nil {
s.LoginButtonBorderColor = NewString("#2389D7")
}
if s.LoginButtonTextColor == nil {
s.LoginButtonTextColor = NewString("#2389D7")
}
}
type RateLimitSettings struct {
Enable *bool `access:"environment_rate_limiting,write_restrictable,cloud_restrictable"`
PerSec *int `access:"environment_rate_limiting,write_restrictable,cloud_restrictable"`
MaxBurst *int `access:"environment_rate_limiting,write_restrictable,cloud_restrictable"`
MemoryStoreSize *int `access:"environment_rate_limiting,write_restrictable,cloud_restrictable"`
VaryByRemoteAddr *bool `access:"environment_rate_limiting,write_restrictable,cloud_restrictable"`
VaryByUser *bool `access:"environment_rate_limiting,write_restrictable,cloud_restrictable"`
VaryByHeader string `access:"environment_rate_limiting,write_restrictable,cloud_restrictable"`
}
func (s *RateLimitSettings) SetDefaults() {
if s.Enable == nil {
s.Enable = NewBool(false)
}
if s.PerSec == nil {
s.PerSec = NewInt(10)
}
if s.MaxBurst == nil {
s.MaxBurst = NewInt(100)
}
if s.MemoryStoreSize == nil {
s.MemoryStoreSize = NewInt(10000)
}
if s.VaryByRemoteAddr == nil {
s.VaryByRemoteAddr = NewBool(true)
}
if s.VaryByUser == nil {
s.VaryByUser = NewBool(false)
}
}
type PrivacySettings struct {
ShowEmailAddress *bool `access:"site_users_and_teams"`
ShowFullName *bool `access:"site_users_and_teams"`
}
func (s *PrivacySettings) setDefaults() {
if s.ShowEmailAddress == nil {
s.ShowEmailAddress = NewBool(true)
}
if s.ShowFullName == nil {
s.ShowFullName = NewBool(true)
}
}
type SupportSettings struct {
TermsOfServiceLink *string `access:"site_customization,write_restrictable,cloud_restrictable"`
PrivacyPolicyLink *string `access:"site_customization,write_restrictable,cloud_restrictable"`
AboutLink *string `access:"site_customization,write_restrictable,cloud_restrictable"`
HelpLink *string `access:"site_customization,write_restrictable,cloud_restrictable"`
ReportAProblemLink *string `access:"site_customization,write_restrictable,cloud_restrictable"`
SupportEmail *string `access:"site_customization"`
CustomTermsOfServiceEnabled *bool `access:"compliance_custom_terms_of_service"`
CustomTermsOfServiceReAcceptancePeriod *int `access:"compliance_custom_terms_of_service"`
EnableAskCommunityLink *bool `access:"site_customization"`
}
func (s *SupportSettings) SetDefaults() {
if !isSafeLink(s.TermsOfServiceLink) {
*s.TermsOfServiceLink = SupportSettingsDefaultTermsOfServiceLink
}
if s.TermsOfServiceLink == nil {
s.TermsOfServiceLink = NewString(SupportSettingsDefaultTermsOfServiceLink)
}
if !isSafeLink(s.PrivacyPolicyLink) {
*s.PrivacyPolicyLink = ""
}
if s.PrivacyPolicyLink == nil {
s.PrivacyPolicyLink = NewString(SupportSettingsDefaultPrivacyPolicyLink)
}
if !isSafeLink(s.AboutLink) {
*s.AboutLink = ""
}
if s.AboutLink == nil {
s.AboutLink = NewString(SupportSettingsDefaultAboutLink)
}
if !isSafeLink(s.HelpLink) {
*s.HelpLink = ""
}
if s.HelpLink == nil {
s.HelpLink = NewString(SupportSettingsDefaultHelpLink)
}
if !isSafeLink(s.ReportAProblemLink) {
*s.ReportAProblemLink = ""
}
if s.ReportAProblemLink == nil {
s.ReportAProblemLink = NewString(SupportSettingsDefaultReportAProblemLink)
}
if s.SupportEmail == nil {
s.SupportEmail = NewString(SupportSettingsDefaultSupportEmail)
}
if s.CustomTermsOfServiceEnabled == nil {
s.CustomTermsOfServiceEnabled = NewBool(false)
}
if s.CustomTermsOfServiceReAcceptancePeriod == nil {
s.CustomTermsOfServiceReAcceptancePeriod = NewInt(SupportSettingsDefaultReAcceptancePeriod)
}
if s.EnableAskCommunityLink == nil {
s.EnableAskCommunityLink = NewBool(true)
}
}
type AnnouncementSettings struct {
EnableBanner *bool `access:"site_announcement_banner"`
BannerText *string `access:"site_announcement_banner"` // telemetry: none
BannerColor *string `access:"site_announcement_banner"`
BannerTextColor *string `access:"site_announcement_banner"`
AllowBannerDismissal *bool `access:"site_announcement_banner"`
AdminNoticesEnabled *bool `access:"site_notices"`
UserNoticesEnabled *bool `access:"site_notices"`
NoticesURL *string `access:"site_notices,write_restrictable"` // telemetry: none
NoticesFetchFrequency *int `access:"site_notices,write_restrictable"` // telemetry: none
NoticesSkipCache *bool `access:"site_notices,write_restrictable"` // telemetry: none
}
func (s *AnnouncementSettings) SetDefaults() {
if s.EnableBanner == nil {
s.EnableBanner = NewBool(false)
}
if s.BannerText == nil {
s.BannerText = NewString("")
}
if s.BannerColor == nil {
s.BannerColor = NewString(AnnouncementSettingsDefaultBannerColor)
}
if s.BannerTextColor == nil {
s.BannerTextColor = NewString(AnnouncementSettingsDefaultBannerTextColor)
}
if s.AllowBannerDismissal == nil {
s.AllowBannerDismissal = NewBool(true)
}
if s.AdminNoticesEnabled == nil {
s.AdminNoticesEnabled = NewBool(true)
}
if s.UserNoticesEnabled == nil {
s.UserNoticesEnabled = NewBool(true)
}
if s.NoticesURL == nil {
s.NoticesURL = NewString(AnnouncementSettingsDefaultNoticesJsonURL)
}
if s.NoticesSkipCache == nil {
s.NoticesSkipCache = NewBool(false)
}
if s.NoticesFetchFrequency == nil {
s.NoticesFetchFrequency = NewInt(AnnouncementSettingsDefaultNoticesFetchFrequencySeconds)
}
}
type ThemeSettings struct {
EnableThemeSelection *bool `access:"experimental_features"`
DefaultTheme *string `access:"experimental_features"`
AllowCustomThemes *bool `access:"experimental_features"`
AllowedThemes []string
}
func (s *ThemeSettings) SetDefaults() {
if s.EnableThemeSelection == nil {
s.EnableThemeSelection = NewBool(true)
}
if s.DefaultTheme == nil {
s.DefaultTheme = NewString(TeamSettingsDefaultTeamText)
}
if s.AllowCustomThemes == nil {
s.AllowCustomThemes = NewBool(true)
}
if s.AllowedThemes == nil {
s.AllowedThemes = []string{}
}
}
type TeamSettings struct {
SiteName *string `access:"site_customization"`
MaxUsersPerTeam *int `access:"site_users_and_teams"`
EnableUserCreation *bool `access:"authentication_signup"`
EnableOpenServer *bool `access:"authentication_signup"`
EnableUserDeactivation *bool `access:"experimental_features"`
RestrictCreationToDomains *string `access:"authentication_signup"` // telemetry: none
EnableCustomUserStatuses *bool `access:"site_users_and_teams"`
EnableCustomBrand *bool `access:"site_customization"`
CustomBrandText *string `access:"site_customization"`
CustomDescriptionText *string `access:"site_customization"`
RestrictDirectMessage *string `access:"site_users_and_teams"`
UserStatusAwayTimeout *int64 `access:"experimental_features"`
MaxChannelsPerTeam *int64 `access:"site_users_and_teams"`
MaxNotificationsPerChannel *int64 `access:"environment_push_notification_server"`
EnableConfirmNotificationsToChannel *bool `access:"site_notifications"`
TeammateNameDisplay *string `access:"site_users_and_teams"`
ExperimentalViewArchivedChannels *bool `access:"experimental_features,site_users_and_teams"`
ExperimentalEnableAutomaticReplies *bool `access:"experimental_features"`
LockTeammateNameDisplay *bool `access:"site_users_and_teams"`
ExperimentalPrimaryTeam *string `access:"experimental_features"`
ExperimentalDefaultChannels []string `access:"experimental_features"`
}
func (s *TeamSettings) SetDefaults() {
if s.SiteName == nil || *s.SiteName == "" {
s.SiteName = NewString(TeamSettingsDefaultSiteName)
}
if s.MaxUsersPerTeam == nil {
s.MaxUsersPerTeam = NewInt(TeamSettingsDefaultMaxUsersPerTeam)
}
if s.EnableUserCreation == nil {
s.EnableUserCreation = NewBool(true)
}
if s.EnableOpenServer == nil {
s.EnableOpenServer = NewBool(false)
}
if s.RestrictCreationToDomains == nil {
s.RestrictCreationToDomains = NewString("")
}
if s.EnableCustomUserStatuses == nil {
s.EnableCustomUserStatuses = NewBool(true)
}
if s.EnableCustomBrand == nil {
s.EnableCustomBrand = NewBool(false)
}
if s.EnableUserDeactivation == nil {
s.EnableUserDeactivation = NewBool(false)
}
if s.CustomBrandText == nil {
s.CustomBrandText = NewString(TeamSettingsDefaultCustomBrandText)
}
if s.CustomDescriptionText == nil {
s.CustomDescriptionText = NewString(TeamSettingsDefaultCustomDescriptionText)
}
if s.RestrictDirectMessage == nil {
s.RestrictDirectMessage = NewString(DirectMessageAny)
}
if s.UserStatusAwayTimeout == nil {
s.UserStatusAwayTimeout = NewInt64(TeamSettingsDefaultUserStatusAwayTimeout)
}
if s.MaxChannelsPerTeam == nil {
s.MaxChannelsPerTeam = NewInt64(2000)
}
if s.MaxNotificationsPerChannel == nil {
s.MaxNotificationsPerChannel = NewInt64(1000)
}
if s.EnableConfirmNotificationsToChannel == nil {
s.EnableConfirmNotificationsToChannel = NewBool(true)
}
if s.ExperimentalEnableAutomaticReplies == nil {
s.ExperimentalEnableAutomaticReplies = NewBool(false)
}
if s.ExperimentalPrimaryTeam == nil {
s.ExperimentalPrimaryTeam = NewString("")
}
if s.ExperimentalDefaultChannels == nil {
s.ExperimentalDefaultChannels = []string{}
}
if s.EnableUserCreation == nil {
s.EnableUserCreation = NewBool(true)
}
if s.ExperimentalViewArchivedChannels == nil {
s.ExperimentalViewArchivedChannels = NewBool(true)
}
if s.LockTeammateNameDisplay == nil {
s.LockTeammateNameDisplay = NewBool(false)
}
}
type ClientRequirements struct {
AndroidLatestVersion string `access:"write_restrictable,cloud_restrictable"`
AndroidMinVersion string `access:"write_restrictable,cloud_restrictable"`
DesktopLatestVersion string `access:"write_restrictable,cloud_restrictable"`
DesktopMinVersion string `access:"write_restrictable,cloud_restrictable"`
IosLatestVersion string `access:"write_restrictable,cloud_restrictable"`
IosMinVersion string `access:"write_restrictable,cloud_restrictable"`
}
type LdapSettings struct {
// Basic
Enable *bool `access:"authentication_ldap"`
EnableSync *bool `access:"authentication_ldap"`
LdapServer *string `access:"authentication_ldap"` // telemetry: none
LdapPort *int `access:"authentication_ldap"` // telemetry: none
ConnectionSecurity *string `access:"authentication_ldap"`
BaseDN *string `access:"authentication_ldap"` // telemetry: none
BindUsername *string `access:"authentication_ldap"` // telemetry: none
BindPassword *string `access:"authentication_ldap"` // telemetry: none
// Filtering
UserFilter *string `access:"authentication_ldap"` // telemetry: none
GroupFilter *string `access:"authentication_ldap"`
GuestFilter *string `access:"authentication_ldap"`
EnableAdminFilter *bool
AdminFilter *string
// Group Mapping
GroupDisplayNameAttribute *string `access:"authentication_ldap"`
GroupIdAttribute *string `access:"authentication_ldap"`
// User Mapping
FirstNameAttribute *string `access:"authentication_ldap"`
LastNameAttribute *string `access:"authentication_ldap"`
EmailAttribute *string `access:"authentication_ldap"`
UsernameAttribute *string `access:"authentication_ldap"`
NicknameAttribute *string `access:"authentication_ldap"`
IdAttribute *string `access:"authentication_ldap"`
PositionAttribute *string `access:"authentication_ldap"`
LoginIdAttribute *string `access:"authentication_ldap"`
PictureAttribute *string `access:"authentication_ldap"`
// Synchronization
SyncIntervalMinutes *int `access:"authentication_ldap"`
// Advanced
SkipCertificateVerification *bool `access:"authentication_ldap"`
PublicCertificateFile *string `access:"authentication_ldap"`
PrivateKeyFile *string `access:"authentication_ldap"`
QueryTimeout *int `access:"authentication_ldap"`
MaxPageSize *int `access:"authentication_ldap"`
// Customization
LoginFieldName *string `access:"authentication_ldap"`
LoginButtonColor *string `access:"experimental_features"`
LoginButtonBorderColor *string `access:"experimental_features"`
LoginButtonTextColor *string `access:"experimental_features"`
Trace *bool `access:"authentication_ldap"` // telemetry: none
}
func (s *LdapSettings) SetDefaults() {
if s.Enable == nil {
s.Enable = NewBool(false)
}
// When unset should default to LDAP Enabled
if s.EnableSync == nil {
s.EnableSync = NewBool(*s.Enable)
}
if s.EnableAdminFilter == nil {
s.EnableAdminFilter = NewBool(false)
}
if s.LdapServer == nil {
s.LdapServer = NewString("")
}
if s.LdapPort == nil {
s.LdapPort = NewInt(389)
}
if s.ConnectionSecurity == nil {
s.ConnectionSecurity = NewString("")
}
if s.PublicCertificateFile == nil {
s.PublicCertificateFile = NewString("")
}
if s.PrivateKeyFile == nil {
s.PrivateKeyFile = NewString("")
}
if s.BaseDN == nil {
s.BaseDN = NewString("")
}
if s.BindUsername == nil {
s.BindUsername = NewString("")
}
if s.BindPassword == nil {
s.BindPassword = NewString("")
}
if s.UserFilter == nil {
s.UserFilter = NewString("")
}
if s.GuestFilter == nil {
s.GuestFilter = NewString("")
}
if s.AdminFilter == nil {
s.AdminFilter = NewString("")
}
if s.GroupFilter == nil {
s.GroupFilter = NewString("")
}
if s.GroupDisplayNameAttribute == nil {
s.GroupDisplayNameAttribute = NewString(LdapSettingsDefaultGroupDisplayNameAttribute)
}
if s.GroupIdAttribute == nil {
s.GroupIdAttribute = NewString(LdapSettingsDefaultGroupIdAttribute)
}
if s.FirstNameAttribute == nil {
s.FirstNameAttribute = NewString(LdapSettingsDefaultFirstNameAttribute)
}
if s.LastNameAttribute == nil {
s.LastNameAttribute = NewString(LdapSettingsDefaultLastNameAttribute)
}
if s.EmailAttribute == nil {
s.EmailAttribute = NewString(LdapSettingsDefaultEmailAttribute)
}
if s.UsernameAttribute == nil {
s.UsernameAttribute = NewString(LdapSettingsDefaultUsernameAttribute)
}
if s.NicknameAttribute == nil {
s.NicknameAttribute = NewString(LdapSettingsDefaultNicknameAttribute)
}
if s.IdAttribute == nil {
s.IdAttribute = NewString(LdapSettingsDefaultIdAttribute)
}
if s.PositionAttribute == nil {
s.PositionAttribute = NewString(LdapSettingsDefaultPositionAttribute)
}
if s.PictureAttribute == nil {
s.PictureAttribute = NewString(LdapSettingsDefaultPictureAttribute)
}
// For those upgrading to the version when LoginIdAttribute was added
// they need IdAttribute == LoginIdAttribute not to break
if s.LoginIdAttribute == nil {
s.LoginIdAttribute = s.IdAttribute
}
if s.SyncIntervalMinutes == nil {
s.SyncIntervalMinutes = NewInt(60)
}
if s.SkipCertificateVerification == nil {
s.SkipCertificateVerification = NewBool(false)
}
if s.QueryTimeout == nil {
s.QueryTimeout = NewInt(60)
}
if s.MaxPageSize == nil {
s.MaxPageSize = NewInt(0)
}
if s.LoginFieldName == nil {
s.LoginFieldName = NewString(LdapSettingsDefaultLoginFieldName)
}
if s.LoginButtonColor == nil {
s.LoginButtonColor = NewString("#0000")
}
if s.LoginButtonBorderColor == nil {
s.LoginButtonBorderColor = NewString("#2389D7")
}
if s.LoginButtonTextColor == nil {
s.LoginButtonTextColor = NewString("#2389D7")
}
if s.Trace == nil {
s.Trace = NewBool(false)
}
}
type ComplianceSettings struct {
Enable *bool `access:"compliance_compliance_monitoring"`
Directory *string `access:"compliance_compliance_monitoring"` // telemetry: none
EnableDaily *bool `access:"compliance_compliance_monitoring"`
BatchSize *int `access:"compliance_compliance_monitoring"` // telemetry: none
}
func (s *ComplianceSettings) SetDefaults() {
if s.Enable == nil {
s.Enable = NewBool(false)
}
if s.Directory == nil {
s.Directory = NewString("./data/")
}
if s.EnableDaily == nil {
s.EnableDaily = NewBool(false)
}
if s.BatchSize == nil {
s.BatchSize = NewInt(30000)
}
}
type LocalizationSettings struct {
DefaultServerLocale *string `access:"site_localization"`
DefaultClientLocale *string `access:"site_localization"`
AvailableLocales *string `access:"site_localization"`
}
func (s *LocalizationSettings) SetDefaults() {
if s.DefaultServerLocale == nil {
s.DefaultServerLocale = NewString(DefaultLocale)
}
if s.DefaultClientLocale == nil {
s.DefaultClientLocale = NewString(DefaultLocale)
}
if s.AvailableLocales == nil {
s.AvailableLocales = NewString("")
}
}
type SamlSettings struct {
// Basic
Enable *bool `access:"authentication_saml"`
EnableSyncWithLdap *bool `access:"authentication_saml"`
EnableSyncWithLdapIncludeAuth *bool `access:"authentication_saml"`
IgnoreGuestsLdapSync *bool `access:"authentication_saml"`
Verify *bool `access:"authentication_saml"`
Encrypt *bool `access:"authentication_saml"`
SignRequest *bool `access:"authentication_saml"`
IdpURL *string `access:"authentication_saml"` // telemetry: none
IdpDescriptorURL *string `access:"authentication_saml"` // telemetry: none
IdpMetadataURL *string `access:"authentication_saml"` // telemetry: none
ServiceProviderIdentifier *string `access:"authentication_saml"` // telemetry: none
AssertionConsumerServiceURL *string `access:"authentication_saml"` // telemetry: none
SignatureAlgorithm *string `access:"authentication_saml"`
CanonicalAlgorithm *string `access:"authentication_saml"`
ScopingIDPProviderId *string `access:"authentication_saml"`
ScopingIDPName *string `access:"authentication_saml"`
IdpCertificateFile *string `access:"authentication_saml"` // telemetry: none
PublicCertificateFile *string `access:"authentication_saml"` // telemetry: none
PrivateKeyFile *string `access:"authentication_saml"` // telemetry: none
// User Mapping
IdAttribute *string `access:"authentication_saml"`
GuestAttribute *string `access:"authentication_saml"`
EnableAdminAttribute *bool
AdminAttribute *string
FirstNameAttribute *string `access:"authentication_saml"`
LastNameAttribute *string `access:"authentication_saml"`
EmailAttribute *string `access:"authentication_saml"`
UsernameAttribute *string `access:"authentication_saml"`
NicknameAttribute *string `access:"authentication_saml"`
LocaleAttribute *string `access:"authentication_saml"`
PositionAttribute *string `access:"authentication_saml"`
LoginButtonText *string `access:"authentication_saml"`
LoginButtonColor *string `access:"experimental_features"`
LoginButtonBorderColor *string `access:"experimental_features"`
LoginButtonTextColor *string `access:"experimental_features"`
}
func (s *SamlSettings) SetDefaults() {
if s.Enable == nil {
s.Enable = NewBool(false)
}
if s.EnableSyncWithLdap == nil {
s.EnableSyncWithLdap = NewBool(false)
}
if s.EnableSyncWithLdapIncludeAuth == nil {
s.EnableSyncWithLdapIncludeAuth = NewBool(false)
}
if s.IgnoreGuestsLdapSync == nil {
s.IgnoreGuestsLdapSync = NewBool(false)
}
if s.EnableAdminAttribute == nil {
s.EnableAdminAttribute = NewBool(false)
}
if s.Verify == nil {
s.Verify = NewBool(true)
}
if s.Encrypt == nil {
s.Encrypt = NewBool(true)
}
if s.SignRequest == nil {
s.SignRequest = NewBool(false)
}
if s.SignatureAlgorithm == nil {
s.SignatureAlgorithm = NewString(SamlSettingsDefaultSignatureAlgorithm)
}
if s.CanonicalAlgorithm == nil {
s.CanonicalAlgorithm = NewString(SamlSettingsDefaultCanonicalAlgorithm)
}
if s.IdpURL == nil {
s.IdpURL = NewString("")
}
if s.IdpDescriptorURL == nil {
s.IdpDescriptorURL = NewString("")
}
if s.ServiceProviderIdentifier == nil {
if s.IdpDescriptorURL != nil {
s.ServiceProviderIdentifier = NewString(*s.IdpDescriptorURL)
} else {
s.ServiceProviderIdentifier = NewString("")
}
}
if s.IdpMetadataURL == nil {
s.IdpMetadataURL = NewString("")
}
if s.IdpCertificateFile == nil {
s.IdpCertificateFile = NewString("")
}
if s.PublicCertificateFile == nil {
s.PublicCertificateFile = NewString("")
}
if s.PrivateKeyFile == nil {
s.PrivateKeyFile = NewString("")
}
if s.AssertionConsumerServiceURL == nil {
s.AssertionConsumerServiceURL = NewString("")
}
if s.ScopingIDPProviderId == nil {
s.ScopingIDPProviderId = NewString("")
}
if s.ScopingIDPName == nil {
s.ScopingIDPName = NewString("")
}
if s.LoginButtonText == nil || *s.LoginButtonText == "" {
s.LoginButtonText = NewString(UserAuthServiceSamlText)
}
if s.IdAttribute == nil {
s.IdAttribute = NewString(SamlSettingsDefaultIdAttribute)
}
if s.GuestAttribute == nil {
s.GuestAttribute = NewString(SamlSettingsDefaultGuestAttribute)
}
if s.AdminAttribute == nil {
s.AdminAttribute = NewString(SamlSettingsDefaultAdminAttribute)
}
if s.FirstNameAttribute == nil {
s.FirstNameAttribute = NewString(SamlSettingsDefaultFirstNameAttribute)
}
if s.LastNameAttribute == nil {
s.LastNameAttribute = NewString(SamlSettingsDefaultLastNameAttribute)
}
if s.EmailAttribute == nil {
s.EmailAttribute = NewString(SamlSettingsDefaultEmailAttribute)
}
if s.UsernameAttribute == nil {
s.UsernameAttribute = NewString(SamlSettingsDefaultUsernameAttribute)
}
if s.NicknameAttribute == nil {
s.NicknameAttribute = NewString(SamlSettingsDefaultNicknameAttribute)
}
if s.PositionAttribute == nil {
s.PositionAttribute = NewString(SamlSettingsDefaultPositionAttribute)
}
if s.LocaleAttribute == nil {
s.LocaleAttribute = NewString(SamlSettingsDefaultLocaleAttribute)
}
if s.LoginButtonColor == nil {
s.LoginButtonColor = NewString("#34a28b")
}
if s.LoginButtonBorderColor == nil {
s.LoginButtonBorderColor = NewString("#2389D7")
}
if s.LoginButtonTextColor == nil {
s.LoginButtonTextColor = NewString("#ffffff")
}
}
type NativeAppSettings struct {
AppCustomURLSchemes []string `access:"site_customization,write_restrictable,cloud_restrictable"` // telemetry: none
AppDownloadLink *string `access:"site_customization,write_restrictable,cloud_restrictable"`
AndroidAppDownloadLink *string `access:"site_customization,write_restrictable,cloud_restrictable"`
IosAppDownloadLink *string `access:"site_customization,write_restrictable,cloud_restrictable"`
}
func (s *NativeAppSettings) SetDefaults() {
if s.AppDownloadLink == nil {
s.AppDownloadLink = NewString(NativeappSettingsDefaultAppDownloadLink)
}
if s.AndroidAppDownloadLink == nil {
s.AndroidAppDownloadLink = NewString(NativeappSettingsDefaultAndroidAppDownloadLink)
}
if s.IosAppDownloadLink == nil {
s.IosAppDownloadLink = NewString(NativeappSettingsDefaultIosAppDownloadLink)
}
if s.AppCustomURLSchemes == nil {
s.AppCustomURLSchemes = GetDefaultAppCustomURLSchemes()
}
}
type ElasticsearchSettings struct {
ConnectionURL *string `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
Username *string `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
Password *string `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
EnableIndexing *bool `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
EnableSearching *bool `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
EnableAutocomplete *bool `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
Sniff *bool `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
PostIndexReplicas *int `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
PostIndexShards *int `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
ChannelIndexReplicas *int `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
ChannelIndexShards *int `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
UserIndexReplicas *int `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
UserIndexShards *int `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
AggregatePostsAfterDays *int `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"` // telemetry: none
PostsAggregatorJobStartTime *string `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"` // telemetry: none
IndexPrefix *string `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
LiveIndexingBatchSize *int `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
BulkIndexingTimeWindowSeconds *int `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
RequestTimeoutSeconds *int `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
SkipTLSVerification *bool `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
Trace *string `access:"environment_elasticsearch,write_restrictable,cloud_restrictable"`
}
func (s *ElasticsearchSettings) SetDefaults() {
if s.ConnectionURL == nil {
s.ConnectionURL = NewString(ElasticsearchSettingsDefaultConnectionURL)
}
if s.Username == nil {
s.Username = NewString(ElasticsearchSettingsDefaultUsername)
}
if s.Password == nil {
s.Password = NewString(ElasticsearchSettingsDefaultPassword)
}
if s.EnableIndexing == nil {
s.EnableIndexing = NewBool(false)
}
if s.EnableSearching == nil {
s.EnableSearching = NewBool(false)
}
if s.EnableAutocomplete == nil {
s.EnableAutocomplete = NewBool(false)
}
if s.Sniff == nil {
s.Sniff = NewBool(true)
}
if s.PostIndexReplicas == nil {
s.PostIndexReplicas = NewInt(ElasticsearchSettingsDefaultPostIndexReplicas)
}
if s.PostIndexShards == nil {
s.PostIndexShards = NewInt(ElasticsearchSettingsDefaultPostIndexShards)
}
if s.ChannelIndexReplicas == nil {
s.ChannelIndexReplicas = NewInt(ElasticsearchSettingsDefaultChannelIndexReplicas)
}
if s.ChannelIndexShards == nil {
s.ChannelIndexShards = NewInt(ElasticsearchSettingsDefaultChannelIndexShards)
}
if s.UserIndexReplicas == nil {
s.UserIndexReplicas = NewInt(ElasticsearchSettingsDefaultUserIndexReplicas)
}
if s.UserIndexShards == nil {
s.UserIndexShards = NewInt(ElasticsearchSettingsDefaultUserIndexShards)
}
if s.AggregatePostsAfterDays == nil {
s.AggregatePostsAfterDays = NewInt(ElasticsearchSettingsDefaultAggregatePostsAfterDays)
}
if s.PostsAggregatorJobStartTime == nil {
s.PostsAggregatorJobStartTime = NewString(ElasticsearchSettingsDefaultPostsAggregatorJobStartTime)
}
if s.IndexPrefix == nil {
s.IndexPrefix = NewString(ElasticsearchSettingsDefaultIndexPrefix)
}
if s.LiveIndexingBatchSize == nil {
s.LiveIndexingBatchSize = NewInt(ElasticsearchSettingsDefaultLiveIndexingBatchSize)
}
if s.BulkIndexingTimeWindowSeconds == nil {
s.BulkIndexingTimeWindowSeconds = NewInt(ElasticsearchSettingsDefaultBulkIndexingTimeWindowSeconds)
}
if s.RequestTimeoutSeconds == nil {
s.RequestTimeoutSeconds = NewInt(ElasticsearchSettingsDefaultRequestTimeoutSeconds)
}
if s.SkipTLSVerification == nil {
s.SkipTLSVerification = NewBool(false)
}
if s.Trace == nil {
s.Trace = NewString("")
}
}
type BleveSettings struct {
IndexDir *string `access:"experimental_bleve"` // telemetry: none
EnableIndexing *bool `access:"experimental_bleve"`
EnableSearching *bool `access:"experimental_bleve"`
EnableAutocomplete *bool `access:"experimental_bleve"`
BulkIndexingTimeWindowSeconds *int `access:"experimental_bleve"`
}
func (bs *BleveSettings) SetDefaults() {
if bs.IndexDir == nil {
bs.IndexDir = NewString(BleveSettingsDefaultIndexDir)
}
if bs.EnableIndexing == nil {
bs.EnableIndexing = NewBool(false)
}
if bs.EnableSearching == nil {
bs.EnableSearching = NewBool(false)
}
if bs.EnableAutocomplete == nil {
bs.EnableAutocomplete = NewBool(false)
}
if bs.BulkIndexingTimeWindowSeconds == nil {
bs.BulkIndexingTimeWindowSeconds = NewInt(BleveSettingsDefaultBulkIndexingTimeWindowSeconds)
}
}
type DataRetentionSettings struct {
EnableMessageDeletion *bool `access:"compliance_data_retention_policy"`
EnableFileDeletion *bool `access:"compliance_data_retention_policy"`
MessageRetentionDays *int `access:"compliance_data_retention_policy"`
FileRetentionDays *int `access:"compliance_data_retention_policy"`
DeletionJobStartTime *string `access:"compliance_data_retention_policy"`
BatchSize *int `access:"compliance_data_retention_policy"`
}
func (s *DataRetentionSettings) SetDefaults() {
if s.EnableMessageDeletion == nil {
s.EnableMessageDeletion = NewBool(false)
}
if s.EnableFileDeletion == nil {
s.EnableFileDeletion = NewBool(false)
}
if s.MessageRetentionDays == nil {
s.MessageRetentionDays = NewInt(DataRetentionSettingsDefaultMessageRetentionDays)
}
if s.FileRetentionDays == nil {
s.FileRetentionDays = NewInt(DataRetentionSettingsDefaultFileRetentionDays)
}
if s.DeletionJobStartTime == nil {
s.DeletionJobStartTime = NewString(DataRetentionSettingsDefaultDeletionJobStartTime)
}
if s.BatchSize == nil {
s.BatchSize = NewInt(DataRetentionSettingsDefaultBatchSize)
}
}
type JobSettings struct {
RunJobs *bool `access:"write_restrictable,cloud_restrictable"`
RunScheduler *bool `access:"write_restrictable,cloud_restrictable"`
}
func (s *JobSettings) SetDefaults() {
if s.RunJobs == nil {
s.RunJobs = NewBool(true)
}
if s.RunScheduler == nil {
s.RunScheduler = NewBool(true)
}
}
type CloudSettings struct {
CWSURL *string `access:"write_restrictable"`
CWSAPIURL *string `access:"write_restrictable"`
}
func (s *CloudSettings) SetDefaults() {
if s.CWSURL == nil {
s.CWSURL = NewString(CloudSettingsDefaultCwsURL)
}
if s.CWSAPIURL == nil {
s.CWSAPIURL = NewString(CloudSettingsDefaultCwsAPIURL)
}
}
type PluginState struct {
Enable bool
}
type PluginSettings struct {
Enable *bool `access:"plugins,write_restrictable"`
EnableUploads *bool `access:"plugins,write_restrictable,cloud_restrictable"`
AllowInsecureDownloadURL *bool `access:"plugins,write_restrictable,cloud_restrictable"`
EnableHealthCheck *bool `access:"plugins,write_restrictable,cloud_restrictable"`
Directory *string `access:"plugins,write_restrictable,cloud_restrictable"` // telemetry: none
ClientDirectory *string `access:"plugins,write_restrictable,cloud_restrictable"` // telemetry: none
Plugins map[string]map[string]interface{} `access:"plugins"` // telemetry: none
PluginStates map[string]*PluginState `access:"plugins"` // telemetry: none
EnableMarketplace *bool `access:"plugins,write_restrictable,cloud_restrictable"`
EnableRemoteMarketplace *bool `access:"plugins,write_restrictable,cloud_restrictable"`
AutomaticPrepackagedPlugins *bool `access:"plugins,write_restrictable,cloud_restrictable"`
RequirePluginSignature *bool `access:"plugins,write_restrictable,cloud_restrictable"`
MarketplaceURL *string `access:"plugins,write_restrictable,cloud_restrictable"`
SignaturePublicKeyFiles []string `access:"plugins,write_restrictable,cloud_restrictable"`
ChimeraOAuthProxyURL *string `access:"plugins,write_restrictable,cloud_restrictable"`
}
func (s *PluginSettings) SetDefaults(ls LogSettings) {
if s.Enable == nil {
s.Enable = NewBool(true)
}
if s.EnableUploads == nil {
s.EnableUploads = NewBool(false)
}
if s.AllowInsecureDownloadURL == nil {
s.AllowInsecureDownloadURL = NewBool(false)
}
if s.EnableHealthCheck == nil {
s.EnableHealthCheck = NewBool(true)
}
if s.Directory == nil || *s.Directory == "" {
s.Directory = NewString(PluginSettingsDefaultDirectory)
}
if s.ClientDirectory == nil || *s.ClientDirectory == "" {
s.ClientDirectory = NewString(PluginSettingsDefaultClientDirectory)
}
if s.Plugins == nil {
s.Plugins = make(map[string]map[string]interface{})
}
if s.PluginStates == nil {
s.PluginStates = make(map[string]*PluginState)
}
if s.PluginStates["com.mattermost.nps"] == nil {
// Enable the NPS plugin by default if diagnostics are enabled
s.PluginStates["com.mattermost.nps"] = &PluginState{Enable: ls.EnableDiagnostics == nil || *ls.EnableDiagnostics}
}
if s.PluginStates["playbooks"] == nil {
// Enable the playbooks plugin by default
s.PluginStates["playbooks"] = &PluginState{Enable: true}
}
if s.PluginStates["com.mattermost.plugin-channel-export"] == nil && BuildEnterpriseReady == "true" {
// Enable the channel export plugin by default
s.PluginStates["com.mattermost.plugin-channel-export"] = &PluginState{Enable: true}
}
if s.PluginStates["focalboard"] == nil {
// Enable the focalboard plugin by default
s.PluginStates["focalboard"] = &PluginState{Enable: true}
}
if s.EnableMarketplace == nil {
s.EnableMarketplace = NewBool(PluginSettingsDefaultEnableMarketplace)
}
if s.EnableRemoteMarketplace == nil {
s.EnableRemoteMarketplace = NewBool(true)
}
if s.AutomaticPrepackagedPlugins == nil {
s.AutomaticPrepackagedPlugins = NewBool(true)
}
if s.MarketplaceURL == nil || *s.MarketplaceURL == "" || *s.MarketplaceURL == PluginSettingsOldMarketplaceURL {
s.MarketplaceURL = NewString(PluginSettingsDefaultMarketplaceURL)
}
if s.RequirePluginSignature == nil {
s.RequirePluginSignature = NewBool(false)
}
if s.SignaturePublicKeyFiles == nil {
s.SignaturePublicKeyFiles = []string{}
}
if s.ChimeraOAuthProxyURL == nil {
s.ChimeraOAuthProxyURL = NewString("")
}
}
type GlobalRelayMessageExportSettings struct {
CustomerType *string `access:"compliance_compliance_export"` // must be either A9 or A10, dictates SMTP server url
SMTPUsername *string `access:"compliance_compliance_export"`
SMTPPassword *string `access:"compliance_compliance_export"`
EmailAddress *string `access:"compliance_compliance_export"` // the address to send messages to
SMTPServerTimeout *int `access:"compliance_compliance_export"`
}
func (s *GlobalRelayMessageExportSettings) SetDefaults() {
if s.CustomerType == nil {
s.CustomerType = NewString(GlobalrelayCustomerTypeA9)
}
if s.SMTPUsername == nil {
s.SMTPUsername = NewString("")
}
if s.SMTPPassword == nil {
s.SMTPPassword = NewString("")
}
if s.EmailAddress == nil {
s.EmailAddress = NewString("")
}
if s.SMTPServerTimeout == nil || *s.SMTPServerTimeout == 0 {
s.SMTPServerTimeout = NewInt(1800)
}
}
type MessageExportSettings struct {
EnableExport *bool `access:"compliance_compliance_export"`
ExportFormat *string `access:"compliance_compliance_export"`
DailyRunTime *string `access:"compliance_compliance_export"`
ExportFromTimestamp *int64 `access:"compliance_compliance_export"`
BatchSize *int `access:"compliance_compliance_export"`
DownloadExportResults *bool `access:"compliance_compliance_export"`
// formatter-specific settings - these are only expected to be non-nil if ExportFormat is set to the associated format
GlobalRelaySettings *GlobalRelayMessageExportSettings `access:"compliance_compliance_export"`
}
func (s *MessageExportSettings) SetDefaults() {
if s.EnableExport == nil {
s.EnableExport = NewBool(false)
}
if s.DownloadExportResults == nil {
s.DownloadExportResults = NewBool(false)
}
if s.ExportFormat == nil {
s.ExportFormat = NewString(ComplianceExportTypeActiance)
}
if s.DailyRunTime == nil {
s.DailyRunTime = NewString("01:00")
}
if s.ExportFromTimestamp == nil {
s.ExportFromTimestamp = NewInt64(0)
}
if s.BatchSize == nil {
s.BatchSize = NewInt(10000)
}
if s.GlobalRelaySettings == nil {
s.GlobalRelaySettings = &GlobalRelayMessageExportSettings{}
}
s.GlobalRelaySettings.SetDefaults()
}
type DisplaySettings struct {
CustomURLSchemes []string `access:"site_customization"`
ExperimentalTimezone *bool `access:"experimental_features"`
}
func (s *DisplaySettings) SetDefaults() {
if s.CustomURLSchemes == nil {
customURLSchemes := []string{}
s.CustomURLSchemes = customURLSchemes
}
if s.ExperimentalTimezone == nil {
s.ExperimentalTimezone = NewBool(true)
}
}
type GuestAccountsSettings struct {
Enable *bool `access:"authentication_guest_access"`
AllowEmailAccounts *bool `access:"authentication_guest_access"`
EnforceMultifactorAuthentication *bool `access:"authentication_guest_access"`
RestrictCreationToDomains *string `access:"authentication_guest_access"`
}
func (s *GuestAccountsSettings) SetDefaults() {
if s.Enable == nil {
s.Enable = NewBool(false)
}
if s.AllowEmailAccounts == nil {
s.AllowEmailAccounts = NewBool(true)
}
if s.EnforceMultifactorAuthentication == nil {
s.EnforceMultifactorAuthentication = NewBool(false)
}
if s.RestrictCreationToDomains == nil {
s.RestrictCreationToDomains = NewString("")
}
}
type ImageProxySettings struct {
Enable *bool `access:"environment_image_proxy"`
ImageProxyType *string `access:"environment_image_proxy"`
RemoteImageProxyURL *string `access:"environment_image_proxy"`
RemoteImageProxyOptions *string `access:"environment_image_proxy"`
}
func (s *ImageProxySettings) SetDefaults() {
if s.Enable == nil {
s.Enable = NewBool(false)
}
if s.ImageProxyType == nil {
s.ImageProxyType = NewString(ImageProxyTypeLocal)
}
if s.RemoteImageProxyURL == nil {
s.RemoteImageProxyURL = NewString("")
}
if s.RemoteImageProxyOptions == nil {
s.RemoteImageProxyOptions = NewString("")
}
}
// ImportSettings defines configuration settings for file imports.
type ImportSettings struct {
// The directory where to store the imported files.
Directory *string
// The number of days to retain the imported files before deleting them.
RetentionDays *int
}
func (s *ImportSettings) isValid() *AppError {
if *s.Directory == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.import.directory.app_error", nil, "", http.StatusBadRequest)
}
if *s.RetentionDays <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.import.retention_days_too_low.app_error", nil, "", http.StatusBadRequest)
}
return nil
}
// SetDefaults applies the default settings to the struct.
func (s *ImportSettings) SetDefaults() {
if s.Directory == nil || *s.Directory == "" {
s.Directory = NewString(ImportSettingsDefaultDirectory)
}
if s.RetentionDays == nil {
s.RetentionDays = NewInt(ImportSettingsDefaultRetentionDays)
}
}
// ExportSettings defines configuration settings for file exports.
type ExportSettings struct {
// The directory where to store the exported files.
Directory *string // telemetry: none
// The number of days to retain the exported files before deleting them.
RetentionDays *int
}
func (s *ExportSettings) isValid() *AppError {
if *s.Directory == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.export.directory.app_error", nil, "", http.StatusBadRequest)
}
if *s.RetentionDays <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.export.retention_days_too_low.app_error", nil, "", http.StatusBadRequest)
}
return nil
}
// SetDefaults applies the default settings to the struct.
func (s *ExportSettings) SetDefaults() {
if s.Directory == nil || *s.Directory == "" {
s.Directory = NewString(ExportSettingsDefaultDirectory)
}
if s.RetentionDays == nil {
s.RetentionDays = NewInt(ExportSettingsDefaultRetentionDays)
}
}
type ConfigFunc func() *Config
const ConfigAccessTagType = "access"
const ConfigAccessTagWriteRestrictable = "write_restrictable"
const ConfigAccessTagCloudRestrictable = "cloud_restrictable"
// Allows read access if any PermissionSysconsoleRead* is allowed
const ConfigAccessTagAnySysConsoleRead = "*_read"
// Config fields support the 'access' tag with the following values corresponding to the suffix of the associated
// PermissionSysconsole* permission Id: 'about', 'reporting', 'user_management_users',
// 'user_management_groups', 'user_management_teams', 'user_management_channels',
// 'user_management_permissions', 'environment_web_server', 'environment_database', 'environment_elasticsearch',
// 'environment_file_storage', 'environment_image_proxy', 'environment_smtp', 'environment_push_notification_server',
// 'environment_high_availability', 'environment_rate_limiting', 'environment_logging', 'environment_session_lengths',
// 'environment_performance_monitoring', 'environment_developer', 'site', 'authentication', 'plugins',
// 'integrations', 'compliance', 'plugins', and 'experimental'. They grant read and/or write access to the config field
// to roles without PermissionManageSystem.
//
// The 'access' tag '*_read' checks for any Sysconsole read permission and grants access if any read permission is allowed.
//
// By default config values can be written with PermissionManageSystem, but if ExperimentalSettings.RestrictSystemAdmin is true
// and the access tag contains the value 'write_restrictable', then even PermissionManageSystem, does not grant write access.
//
// PermissionManageSystem always grants read access.
//
// Config values with the access tag 'cloud_restrictable' mean that are marked to be filtered when it's used in a cloud licensed
// environment with ExperimentalSettings.RestrictedSystemAdmin set to true.
//
// Example:
// type HairSettings struct {
// // Colour is writeable with either PermissionSysconsoleWriteReporting or PermissionSysconsoleWriteUserManagementGroups.
// // It is readable by PermissionSysconsoleReadReporting and PermissionSysconsoleReadUserManagementGroups permissions.
// // PermissionManageSystem grants read and write access.
// Colour string `access:"reporting,user_management_groups"`
//
// // Length is only readable and writable via PermissionManageSystem.
// Length string
//
// // Product is only writeable by PermissionManageSystem if ExperimentalSettings.RestrictSystemAdmin is false.
// // PermissionManageSystem can always read the value.
// Product bool `access:write_restrictable`
// }
type Config struct {
ServiceSettings ServiceSettings
TeamSettings TeamSettings
ClientRequirements ClientRequirements
SqlSettings SqlSettings
LogSettings LogSettings
ExperimentalAuditSettings ExperimentalAuditSettings
NotificationLogSettings NotificationLogSettings
PasswordSettings PasswordSettings
FileSettings FileSettings
EmailSettings EmailSettings
RateLimitSettings RateLimitSettings
PrivacySettings PrivacySettings
SupportSettings SupportSettings
AnnouncementSettings AnnouncementSettings
ThemeSettings ThemeSettings
GitLabSettings SSOSettings
GoogleSettings SSOSettings
Office365Settings Office365Settings
OpenIdSettings SSOSettings
LdapSettings LdapSettings
ComplianceSettings ComplianceSettings
LocalizationSettings LocalizationSettings
SamlSettings SamlSettings
NativeAppSettings NativeAppSettings
ClusterSettings ClusterSettings
MetricsSettings MetricsSettings
ExperimentalSettings ExperimentalSettings
AnalyticsSettings AnalyticsSettings
ElasticsearchSettings ElasticsearchSettings
BleveSettings BleveSettings
DataRetentionSettings DataRetentionSettings
MessageExportSettings MessageExportSettings
JobSettings JobSettings // telemetry: none
PluginSettings PluginSettings
DisplaySettings DisplaySettings
GuestAccountsSettings GuestAccountsSettings
ImageProxySettings ImageProxySettings
CloudSettings CloudSettings // telemetry: none
FeatureFlags *FeatureFlags `access:"*_read" json:",omitempty"`
ImportSettings ImportSettings // telemetry: none
ExportSettings ExportSettings
}
func (o *Config) Clone() *Config {
buf, err := json.Marshal(o)
if err != nil {
panic(err)
}
var ret Config
err = json.Unmarshal(buf, &ret)
if err != nil {
panic(err)
}
return &ret
}
func (o *Config) ToJSONFiltered(tagType, tagValue string) ([]byte, error) {
filteredConfigMap := structToMapFilteredByTag(*o, tagType, tagValue)
for key, value := range filteredConfigMap {
v, ok := value.(map[string]interface{})
if ok && len(v) == 0 {
delete(filteredConfigMap, key)
}
}
return json.Marshal(filteredConfigMap)
}
func (o *Config) GetSSOService(service string) *SSOSettings {
switch service {
case ServiceGitlab:
return &o.GitLabSettings
case ServiceGoogle:
return &o.GoogleSettings
case ServiceOffice365:
return o.Office365Settings.SSOSettings()
case ServiceOpenid:
return &o.OpenIdSettings
}
return nil
}
func ConfigFromJSON(data io.Reader) *Config {
var o *Config
json.NewDecoder(data).Decode(&o)
return o
}
// isUpdate detects a pre-existing config based on whether SiteURL has been changed
func (o *Config) isUpdate() bool {
return o.ServiceSettings.SiteURL != nil
}
func (o *Config) SetDefaults() {
isUpdate := o.isUpdate()
o.LdapSettings.SetDefaults()
o.SamlSettings.SetDefaults()
if o.TeamSettings.TeammateNameDisplay == nil {
o.TeamSettings.TeammateNameDisplay = NewString(ShowUsername)
if *o.SamlSettings.Enable || *o.LdapSettings.Enable {
*o.TeamSettings.TeammateNameDisplay = ShowFullName
}
}
o.SqlSettings.SetDefaults(isUpdate)
o.FileSettings.SetDefaults(isUpdate)
o.EmailSettings.SetDefaults(isUpdate)
o.PrivacySettings.setDefaults()
o.Office365Settings.setDefaults()
o.Office365Settings.setDefaults()
o.GitLabSettings.setDefaults("", "", "", "", "")
o.GoogleSettings.setDefaults(GoogleSettingsDefaultScope, GoogleSettingsDefaultAuthEndpoint, GoogleSettingsDefaultTokenEndpoint, GoogleSettingsDefaultUserAPIEndpoint, "")
o.OpenIdSettings.setDefaults(OpenidSettingsDefaultScope, "", "", "", "#145DBF")
o.ServiceSettings.SetDefaults(isUpdate)
o.PasswordSettings.SetDefaults()
o.TeamSettings.SetDefaults()
o.MetricsSettings.SetDefaults()
o.ExperimentalSettings.SetDefaults()
o.SupportSettings.SetDefaults()
o.AnnouncementSettings.SetDefaults()
o.ThemeSettings.SetDefaults()
o.ClusterSettings.SetDefaults()
o.PluginSettings.SetDefaults(o.LogSettings)
o.AnalyticsSettings.SetDefaults()
o.ComplianceSettings.SetDefaults()
o.LocalizationSettings.SetDefaults()
o.ElasticsearchSettings.SetDefaults()
o.BleveSettings.SetDefaults()
o.NativeAppSettings.SetDefaults()
o.DataRetentionSettings.SetDefaults()
o.RateLimitSettings.SetDefaults()
o.LogSettings.SetDefaults()
o.ExperimentalAuditSettings.SetDefaults()
o.NotificationLogSettings.SetDefaults()
o.JobSettings.SetDefaults()
o.MessageExportSettings.SetDefaults()
o.DisplaySettings.SetDefaults()
o.GuestAccountsSettings.SetDefaults()
o.ImageProxySettings.SetDefaults()
o.CloudSettings.SetDefaults()
if o.FeatureFlags == nil {
o.FeatureFlags = &FeatureFlags{}
o.FeatureFlags.SetDefaults()
}
o.ImportSettings.SetDefaults()
o.ExportSettings.SetDefaults()
}
func (o *Config) IsValid() *AppError {
if *o.ServiceSettings.SiteURL == "" && *o.EmailSettings.EnableEmailBatching {
return NewAppError("Config.IsValid", "model.config.is_valid.site_url_email_batching.app_error", nil, "", http.StatusBadRequest)
}
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.SiteURL == "" && *o.ServiceSettings.AllowCookiesForSubdomains {
return NewAppError("Config.IsValid", "model.config.is_valid.allow_cookies_for_subdomains.app_error", nil, "", http.StatusBadRequest)
}
if err := o.TeamSettings.isValid(); err != nil {
return err
}
if err := o.SqlSettings.isValid(); err != nil {
return err
}
if err := o.FileSettings.isValid(); err != nil {
return err
}
if err := o.EmailSettings.isValid(); err != nil {
return err
}
if err := o.LdapSettings.isValid(); err != nil {
return err
}
if err := o.SamlSettings.isValid(); err != nil {
return err
}
if *o.PasswordSettings.MinimumLength < PasswordMinimumLength || *o.PasswordSettings.MinimumLength > PasswordMaximumLength {
return NewAppError("Config.IsValid", "model.config.is_valid.password_length.app_error", map[string]interface{}{"MinLength": PasswordMinimumLength, "MaxLength": PasswordMaximumLength}, "", http.StatusBadRequest)
}
if err := o.RateLimitSettings.isValid(); err != nil {
return err
}
if err := o.ServiceSettings.isValid(); err != nil {
return err
}
if err := o.ElasticsearchSettings.isValid(); err != nil {
return err
}
if err := o.BleveSettings.isValid(); err != nil {
return err
}
if err := o.DataRetentionSettings.isValid(); err != nil {
return err
}
if err := o.LocalizationSettings.isValid(); err != nil {
return err
}
if err := o.MessageExportSettings.isValid(); err != nil {
return err
}
if err := o.DisplaySettings.isValid(); err != nil {
return err
}
if err := o.ImageProxySettings.isValid(); err != nil {
return err
}
if err := o.ImportSettings.isValid(); err != nil {
return err
}
return nil
}
func (s *TeamSettings) isValid() *AppError {
if *s.MaxUsersPerTeam <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.max_users.app_error", nil, "", http.StatusBadRequest)
}
if *s.MaxChannelsPerTeam <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.max_channels.app_error", nil, "", http.StatusBadRequest)
}
if *s.MaxNotificationsPerChannel <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.max_notify_per_channel.app_error", nil, "", http.StatusBadRequest)
}
if !(*s.RestrictDirectMessage == DirectMessageAny || *s.RestrictDirectMessage == DirectMessageTeam) {
return NewAppError("Config.IsValid", "model.config.is_valid.restrict_direct_message.app_error", nil, "", http.StatusBadRequest)
}
if !(*s.TeammateNameDisplay == ShowFullName || *s.TeammateNameDisplay == ShowNicknameFullName || *s.TeammateNameDisplay == ShowUsername) {
return NewAppError("Config.IsValid", "model.config.is_valid.teammate_name_display.app_error", nil, "", http.StatusBadRequest)
}
if len(*s.SiteName) > SitenameMaxLength {
return NewAppError("Config.IsValid", "model.config.is_valid.sitename_length.app_error", map[string]interface{}{"MaxLength": SitenameMaxLength}, "", http.StatusBadRequest)
}
return nil
}
func (s *SqlSettings) isValid() *AppError {
if *s.AtRestEncryptKey != "" && len(*s.AtRestEncryptKey) < 32 {
return NewAppError("Config.IsValid", "model.config.is_valid.encrypt_sql.app_error", nil, "", http.StatusBadRequest)
}
if !(*s.DriverName == DatabaseDriverMysql || *s.DriverName == DatabaseDriverPostgres) {
return NewAppError("Config.IsValid", "model.config.is_valid.sql_driver.app_error", nil, "", http.StatusBadRequest)
}
if *s.MaxIdleConns <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.sql_idle.app_error", nil, "", http.StatusBadRequest)
}
if *s.ConnMaxLifetimeMilliseconds < 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.sql_conn_max_lifetime_milliseconds.app_error", nil, "", http.StatusBadRequest)
}
if *s.ConnMaxIdleTimeMilliseconds < 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.sql_conn_max_idle_time_milliseconds.app_error", nil, "", http.StatusBadRequest)
}
if *s.QueryTimeout <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.sql_query_timeout.app_error", nil, "", http.StatusBadRequest)
}
if *s.DataSource == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.sql_data_src.app_error", nil, "", http.StatusBadRequest)
}
if *s.MaxOpenConns <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.sql_max_conn.app_error", nil, "", http.StatusBadRequest)
}
return nil
}
func (s *FileSettings) isValid() *AppError {
if *s.MaxFileSize <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.max_file_size.app_error", nil, "", http.StatusBadRequest)
}
if !(*s.DriverName == ImageDriverLocal || *s.DriverName == ImageDriverS3) {
return NewAppError("Config.IsValid", "model.config.is_valid.file_driver.app_error", nil, "", http.StatusBadRequest)
}
if *s.PublicLinkSalt != "" && len(*s.PublicLinkSalt) < 32 {
return NewAppError("Config.IsValid", "model.config.is_valid.file_salt.app_error", nil, "", http.StatusBadRequest)
}
if *s.Directory == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.directory.app_error", nil, "", http.StatusBadRequest)
}
return nil
}
func (s *EmailSettings) isValid() *AppError {
if !(*s.ConnectionSecurity == ConnSecurityNone || *s.ConnectionSecurity == ConnSecurityTLS || *s.ConnectionSecurity == ConnSecurityStarttls || *s.ConnectionSecurity == ConnSecurityPlain) {
return NewAppError("Config.IsValid", "model.config.is_valid.email_security.app_error", nil, "", http.StatusBadRequest)
}
if *s.EmailBatchingBufferSize <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.email_batching_buffer_size.app_error", nil, "", http.StatusBadRequest)
}
if *s.EmailBatchingInterval < 30 {
return NewAppError("Config.IsValid", "model.config.is_valid.email_batching_interval.app_error", nil, "", http.StatusBadRequest)
}
if !(*s.EmailNotificationContentsType == EmailNotificationContentsFull || *s.EmailNotificationContentsType == EmailNotificationContentsGeneric) {
return NewAppError("Config.IsValid", "model.config.is_valid.email_notification_contents_type.app_error", nil, "", http.StatusBadRequest)
}
return nil
}
func (s *RateLimitSettings) isValid() *AppError {
if *s.MemoryStoreSize <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.rate_mem.app_error", nil, "", http.StatusBadRequest)
}
if *s.PerSec <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.rate_sec.app_error", nil, "", http.StatusBadRequest)
}
if *s.MaxBurst <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.max_burst.app_error", nil, "", http.StatusBadRequest)
}
return nil
}
func (s *LdapSettings) isValid() *AppError {
if !(*s.ConnectionSecurity == ConnSecurityNone || *s.ConnectionSecurity == ConnSecurityTLS || *s.ConnectionSecurity == ConnSecurityStarttls) {
return NewAppError("Config.IsValid", "model.config.is_valid.ldap_security.app_error", nil, "", http.StatusBadRequest)
}
if *s.SyncIntervalMinutes <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.ldap_sync_interval.app_error", nil, "", http.StatusBadRequest)
}
if *s.MaxPageSize < 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.ldap_max_page_size.app_error", nil, "", http.StatusBadRequest)
}
if *s.Enable {
if *s.LdapServer == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.ldap_server", nil, "", http.StatusBadRequest)
}
if *s.BaseDN == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.ldap_basedn", nil, "", http.StatusBadRequest)
}
if *s.EmailAttribute == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.ldap_email", nil, "", http.StatusBadRequest)
}
if *s.UsernameAttribute == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.ldap_username", nil, "", http.StatusBadRequest)
}
if *s.IdAttribute == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.ldap_id", nil, "", http.StatusBadRequest)
}
if *s.LoginIdAttribute == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.ldap_login_id", nil, "", http.StatusBadRequest)
}
if *s.UserFilter != "" {
if _, err := ldap.CompileFilter(*s.UserFilter); err != nil {
return NewAppError("ValidateFilter", "ent.ldap.validate_filter.app_error", nil, err.Error(), http.StatusBadRequest)
}
}
if *s.GuestFilter != "" {
if _, err := ldap.CompileFilter(*s.GuestFilter); err != nil {
return NewAppError("LdapSettings.isValid", "ent.ldap.validate_guest_filter.app_error", nil, err.Error(), http.StatusBadRequest)
}
}
if *s.AdminFilter != "" {
if _, err := ldap.CompileFilter(*s.AdminFilter); err != nil {
return NewAppError("LdapSettings.isValid", "ent.ldap.validate_admin_filter.app_error", nil, err.Error(), http.StatusBadRequest)
}
}
}
return nil
}
func (s *SamlSettings) isValid() *AppError {
if *s.Enable {
if *s.IdpURL == "" || !IsValidHTTPURL(*s.IdpURL) {
return NewAppError("Config.IsValid", "model.config.is_valid.saml_idp_url.app_error", nil, "", http.StatusBadRequest)
}
if *s.IdpDescriptorURL == "" || !IsValidHTTPURL(*s.IdpDescriptorURL) {
return NewAppError("Config.IsValid", "model.config.is_valid.saml_idp_descriptor_url.app_error", nil, "", http.StatusBadRequest)
}
if *s.IdpCertificateFile == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.saml_idp_cert.app_error", nil, "", http.StatusBadRequest)
}
if *s.EmailAttribute == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.saml_email_attribute.app_error", nil, "", http.StatusBadRequest)
}
if *s.UsernameAttribute == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.saml_username_attribute.app_error", nil, "", http.StatusBadRequest)
}
if *s.ServiceProviderIdentifier == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.saml_spidentifier_attribute.app_error", nil, "", http.StatusBadRequest)
}
if *s.Verify {
if *s.AssertionConsumerServiceURL == "" || !IsValidHTTPURL(*s.AssertionConsumerServiceURL) {
return NewAppError("Config.IsValid", "model.config.is_valid.saml_assertion_consumer_service_url.app_error", nil, "", http.StatusBadRequest)
}
}
if *s.Encrypt {
if *s.PrivateKeyFile == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.saml_private_key.app_error", nil, "", http.StatusBadRequest)
}
if *s.PublicCertificateFile == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.saml_public_cert.app_error", nil, "", http.StatusBadRequest)
}
}
if *s.EmailAttribute == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.saml_email_attribute.app_error", nil, "", http.StatusBadRequest)
}
if !(*s.SignatureAlgorithm == SamlSettingsSignatureAlgorithmSha1 || *s.SignatureAlgorithm == SamlSettingsSignatureAlgorithmSha256 || *s.SignatureAlgorithm == SamlSettingsSignatureAlgorithmSha512) {
return NewAppError("Config.IsValid", "model.config.is_valid.saml_signature_algorithm.app_error", nil, "", http.StatusBadRequest)
}
if !(*s.CanonicalAlgorithm == SamlSettingsCanonicalAlgorithmC14n || *s.CanonicalAlgorithm == SamlSettingsCanonicalAlgorithmC14n11) {
return NewAppError("Config.IsValid", "model.config.is_valid.saml_canonical_algorithm.app_error", nil, "", http.StatusBadRequest)
}
if *s.GuestAttribute != "" {
if !(strings.Contains(*s.GuestAttribute, "=")) {
return NewAppError("Config.IsValid", "model.config.is_valid.saml_guest_attribute.app_error", nil, "", http.StatusBadRequest)
}
if len(strings.Split(*s.GuestAttribute, "=")) != 2 {
return NewAppError("Config.IsValid", "model.config.is_valid.saml_guest_attribute.app_error", nil, "", http.StatusBadRequest)
}
}
if *s.AdminAttribute != "" {
if !(strings.Contains(*s.AdminAttribute, "=")) {
return NewAppError("Config.IsValid", "model.config.is_valid.saml_admin_attribute.app_error", nil, "", http.StatusBadRequest)
}
if len(strings.Split(*s.AdminAttribute, "=")) != 2 {
return NewAppError("Config.IsValid", "model.config.is_valid.saml_admin_attribute.app_error", nil, "", http.StatusBadRequest)
}
}
}
return nil
}
func (s *ServiceSettings) isValid() *AppError {
if !(*s.ConnectionSecurity == ConnSecurityNone || *s.ConnectionSecurity == ConnSecurityTLS) {
return NewAppError("Config.IsValid", "model.config.is_valid.webserver_security.app_error", nil, "", http.StatusBadRequest)
}
if *s.ConnectionSecurity == ConnSecurityTLS && !*s.UseLetsEncrypt {
appErr := NewAppError("Config.IsValid", "model.config.is_valid.tls_cert_file_missing.app_error", nil, "", http.StatusBadRequest)
if *s.TLSCertFile == "" {
return appErr
} else if _, err := os.Stat(*s.TLSCertFile); os.IsNotExist(err) {
return appErr
}
appErr = NewAppError("Config.IsValid", "model.config.is_valid.tls_key_file_missing.app_error", nil, "", http.StatusBadRequest)
if *s.TLSKeyFile == "" {
return appErr
} else if _, err := os.Stat(*s.TLSKeyFile); os.IsNotExist(err) {
return appErr
}
}
if len(s.TLSOverwriteCiphers) > 0 {
for _, cipher := range s.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 *s.ReadTimeout <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.read_timeout.app_error", nil, "", http.StatusBadRequest)
}
if *s.WriteTimeout <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.write_timeout.app_error", nil, "", http.StatusBadRequest)
}
if *s.TimeBetweenUserTypingUpdatesMilliseconds < 1000 {
return NewAppError("Config.IsValid", "model.config.is_valid.time_between_user_typing.app_error", nil, "", http.StatusBadRequest)
}
if *s.MaximumLoginAttempts <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.login_attempts.app_error", nil, "", http.StatusBadRequest)
}
if *s.SiteURL != "" {
if _, err := url.ParseRequestURI(*s.SiteURL); err != nil {
return NewAppError("Config.IsValid", "model.config.is_valid.site_url.app_error", nil, "", http.StatusBadRequest)
}
}
if *s.WebsocketURL != "" {
if _, err := url.ParseRequestURI(*s.WebsocketURL); err != nil {
return NewAppError("Config.IsValid", "model.config.is_valid.websocket_url.app_error", nil, "", http.StatusBadRequest)
}
}
host, port, _ := net.SplitHostPort(*s.ListenAddress)
var isValidHost bool
if host == "" {
isValidHost = true
} else {
isValidHost = (net.ParseIP(host) != nil) || isDomainName(host)
}
portInt, err := strconv.Atoi(port)
if err != nil || !isValidHost || portInt < 0 || portInt > math.MaxUint16 {
return NewAppError("Config.IsValid", "model.config.is_valid.listen_address.app_error", nil, "", http.StatusBadRequest)
}
if *s.ExperimentalGroupUnreadChannels != GroupUnreadChannelsDisabled &&
*s.ExperimentalGroupUnreadChannels != GroupUnreadChannelsDefaultOn &&
*s.ExperimentalGroupUnreadChannels != GroupUnreadChannelsDefaultOff {
return NewAppError("Config.IsValid", "model.config.is_valid.group_unread_channels.app_error", nil, "", http.StatusBadRequest)
}
if *s.CollapsedThreads != CollapsedThreadsDisabled && !*s.ThreadAutoFollow {
return NewAppError("Config.IsValid", "model.config.is_valid.collapsed_threads.autofollow.app_error", nil, "", http.StatusBadRequest)
}
if *s.CollapsedThreads != CollapsedThreadsDisabled &&
*s.CollapsedThreads != CollapsedThreadsDefaultOn &&
*s.CollapsedThreads != CollapsedThreadsDefaultOff {
return NewAppError("Config.IsValid", "model.config.is_valid.collapsed_threads.app_error", nil, "", http.StatusBadRequest)
}
return nil
}
func (s *ElasticsearchSettings) isValid() *AppError {
if *s.EnableIndexing {
if *s.ConnectionURL == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.elastic_search.connection_url.app_error", nil, "", http.StatusBadRequest)
}
}
if *s.EnableSearching && !*s.EnableIndexing {
return NewAppError("Config.IsValid", "model.config.is_valid.elastic_search.enable_searching.app_error", nil, "", http.StatusBadRequest)
}
if *s.EnableAutocomplete && !*s.EnableIndexing {
return NewAppError("Config.IsValid", "model.config.is_valid.elastic_search.enable_autocomplete.app_error", nil, "", http.StatusBadRequest)
}
if *s.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", *s.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 *s.LiveIndexingBatchSize < 1 {
return NewAppError("Config.IsValid", "model.config.is_valid.elastic_search.live_indexing_batch_size.app_error", nil, "", http.StatusBadRequest)
}
if *s.BulkIndexingTimeWindowSeconds < 1 {
return NewAppError("Config.IsValid", "model.config.is_valid.elastic_search.bulk_indexing_time_window_seconds.app_error", nil, "", http.StatusBadRequest)
}
if *s.RequestTimeoutSeconds < 1 {
return NewAppError("Config.IsValid", "model.config.is_valid.elastic_search.request_timeout_seconds.app_error", nil, "", http.StatusBadRequest)
}
return nil
}
func (bs *BleveSettings) isValid() *AppError {
if *bs.EnableIndexing {
if *bs.IndexDir == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.bleve_search.filename.app_error", nil, "", http.StatusBadRequest)
}
} else {
if *bs.EnableSearching {
return NewAppError("Config.IsValid", "model.config.is_valid.bleve_search.enable_searching.app_error", nil, "", http.StatusBadRequest)
}
if *bs.EnableAutocomplete {
return NewAppError("Config.IsValid", "model.config.is_valid.bleve_search.enable_autocomplete.app_error", nil, "", http.StatusBadRequest)
}
}
if *bs.BulkIndexingTimeWindowSeconds < 1 {
return NewAppError("Config.IsValid", "model.config.is_valid.bleve_search.bulk_indexing_time_window_seconds.app_error", nil, "", http.StatusBadRequest)
}
return nil
}
func (s *DataRetentionSettings) isValid() *AppError {
if *s.MessageRetentionDays <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.data_retention.message_retention_days_too_low.app_error", nil, "", http.StatusBadRequest)
}
if *s.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", *s.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 (s *LocalizationSettings) isValid() *AppError {
if *s.AvailableLocales != "" {
if !strings.Contains(*s.AvailableLocales, *s.DefaultClientLocale) {
return NewAppError("Config.IsValid", "model.config.is_valid.localization.available_locales.app_error", nil, "", http.StatusBadRequest)
}
}
return nil
}
func (s *MessageExportSettings) isValid() *AppError {
if s.EnableExport == nil {
return NewAppError("Config.IsValid", "model.config.is_valid.message_export.enable.app_error", nil, "", http.StatusBadRequest)
}
if *s.EnableExport {
if s.ExportFromTimestamp == nil || *s.ExportFromTimestamp < 0 || *s.ExportFromTimestamp > GetMillis() {
return NewAppError("Config.IsValid", "model.config.is_valid.message_export.export_from.app_error", nil, "", http.StatusBadRequest)
} else if s.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", *s.DailyRunTime); err != nil {
return NewAppError("Config.IsValid", "model.config.is_valid.message_export.daily_runtime.app_error", nil, err.Error(), http.StatusBadRequest)
} else if s.BatchSize == nil || *s.BatchSize < 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.message_export.batch_size.app_error", nil, "", http.StatusBadRequest)
} else if s.ExportFormat == nil || (*s.ExportFormat != ComplianceExportTypeActiance && *s.ExportFormat != ComplianceExportTypeGlobalrelay && *s.ExportFormat != ComplianceExportTypeCsv) {
return NewAppError("Config.IsValid", "model.config.is_valid.message_export.export_type.app_error", nil, "", http.StatusBadRequest)
}
if *s.ExportFormat == ComplianceExportTypeGlobalrelay {
if s.GlobalRelaySettings == nil {
return NewAppError("Config.IsValid", "model.config.is_valid.message_export.global_relay.config_missing.app_error", nil, "", http.StatusBadRequest)
} else if s.GlobalRelaySettings.CustomerType == nil || (*s.GlobalRelaySettings.CustomerType != GlobalrelayCustomerTypeA9 && *s.GlobalRelaySettings.CustomerType != GlobalrelayCustomerTypeA10) {
return NewAppError("Config.IsValid", "model.config.is_valid.message_export.global_relay.customer_type.app_error", nil, "", http.StatusBadRequest)
} else if s.GlobalRelaySettings.EmailAddress == nil || !strings.Contains(*s.GlobalRelaySettings.EmailAddress, "@") {
// validating email addresses is hard - just make sure it contains an '@' sign
// see https://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address
return NewAppError("Config.IsValid", "model.config.is_valid.message_export.global_relay.email_address.app_error", nil, "", http.StatusBadRequest)
} else if s.GlobalRelaySettings.SMTPUsername == nil || *s.GlobalRelaySettings.SMTPUsername == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.message_export.global_relay.smtp_username.app_error", nil, "", http.StatusBadRequest)
} else if s.GlobalRelaySettings.SMTPPassword == nil || *s.GlobalRelaySettings.SMTPPassword == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.message_export.global_relay.smtp_password.app_error", nil, "", http.StatusBadRequest)
}
}
}
return nil
}
func (s *DisplaySettings) isValid() *AppError {
if len(s.CustomURLSchemes) != 0 {
validProtocolPattern := regexp.MustCompile(`(?i)^\s*[A-Za-z][A-Za-z0-9.+-]*\s*$`)
for _, scheme := range s.CustomURLSchemes {
if !validProtocolPattern.MatchString(scheme) {
return NewAppError(
"Config.IsValid",
"model.config.is_valid.display.custom_url_schemes.app_error",
map[string]interface{}{"Scheme": scheme},
"",
http.StatusBadRequest,
)
}
}
}
return nil
}
func (s *ImageProxySettings) isValid() *AppError {
if *s.Enable {
switch *s.ImageProxyType {
case ImageProxyTypeLocal:
// No other settings to validate
case ImageProxyTypeAtmosCamo:
if *s.RemoteImageProxyURL == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.atmos_camo_image_proxy_url.app_error", nil, "", http.StatusBadRequest)
}
if *s.RemoteImageProxyOptions == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.atmos_camo_image_proxy_options.app_error", nil, "", http.StatusBadRequest)
}
default:
return NewAppError("Config.IsValid", "model.config.is_valid.image_proxy_type.app_error", nil, "", http.StatusBadRequest)
}
}
return nil
}
func (o *Config) GetSanitizeOptions() map[string]bool {
options := map[string]bool{}
options["fullname"] = *o.PrivacySettings.ShowFullName
options["email"] = *o.PrivacySettings.ShowEmailAddress
return options
}
func (o *Config) Sanitize() {
if o.LdapSettings.BindPassword != nil && *o.LdapSettings.BindPassword != "" {
*o.LdapSettings.BindPassword = FakeSetting
}
*o.FileSettings.PublicLinkSalt = FakeSetting
if *o.FileSettings.AmazonS3SecretAccessKey != "" {
*o.FileSettings.AmazonS3SecretAccessKey = FakeSetting
}
if o.EmailSettings.SMTPPassword != nil && *o.EmailSettings.SMTPPassword != "" {
*o.EmailSettings.SMTPPassword = FakeSetting
}
if *o.GitLabSettings.Secret != "" {
*o.GitLabSettings.Secret = FakeSetting
}
if o.GoogleSettings.Secret != nil && *o.GoogleSettings.Secret != "" {
*o.GoogleSettings.Secret = FakeSetting
}
if o.Office365Settings.Secret != nil && *o.Office365Settings.Secret != "" {
*o.Office365Settings.Secret = FakeSetting
}
if o.OpenIdSettings.Secret != nil && *o.OpenIdSettings.Secret != "" {
*o.OpenIdSettings.Secret = FakeSetting
}
*o.SqlSettings.DataSource = FakeSetting
*o.SqlSettings.AtRestEncryptKey = FakeSetting
*o.ElasticsearchSettings.Password = FakeSetting
for i := range o.SqlSettings.DataSourceReplicas {
o.SqlSettings.DataSourceReplicas[i] = FakeSetting
}
for i := range o.SqlSettings.DataSourceSearchReplicas {
o.SqlSettings.DataSourceSearchReplicas[i] = FakeSetting
}
if o.MessageExportSettings.GlobalRelaySettings.SMTPPassword != nil && *o.MessageExportSettings.GlobalRelaySettings.SMTPPassword != "" {
*o.MessageExportSettings.GlobalRelaySettings.SMTPPassword = FakeSetting
}
if o.ServiceSettings.GfycatAPISecret != nil && *o.ServiceSettings.GfycatAPISecret != "" {
*o.ServiceSettings.GfycatAPISecret = FakeSetting
}
*o.ServiceSettings.SplitKey = FakeSetting
}
// structToMapFilteredByTag converts a struct into a map removing those fields that has the tag passed
// as argument
func structToMapFilteredByTag(t interface{}, typeOfTag, filterTag string) map[string]interface{} {
defer func() {
if r := recover(); r != nil {
mlog.Warn("Panicked in structToMapFilteredByTag. This should never happen.", mlog.Any("recover", r))
}
}()
val := reflect.ValueOf(t)
elemField := reflect.TypeOf(t)
if val.Kind() != reflect.Struct {
return nil
}
out := map[string]interface{}{}
for i := 0; i < val.NumField(); i++ {
field := val.Field(i)
structField := elemField.Field(i)
tagPermissions := strings.Split(structField.Tag.Get(typeOfTag), ",")
if isTagPresent(filterTag, tagPermissions) {
continue
}
var value interface{}
switch field.Kind() {
case reflect.Struct:
value = structToMapFilteredByTag(field.Interface(), typeOfTag, filterTag)
case reflect.Ptr:
indirectType := field.Elem()
if indirectType.Kind() == reflect.Struct {
value = structToMapFilteredByTag(indirectType.Interface(), typeOfTag, filterTag)
} else if indirectType.Kind() != reflect.Invalid {
value = indirectType.Interface()
}
default:
value = field.Interface()
}
out[val.Type().Field(i).Name] = value
}
return out
}
func isTagPresent(tag string, tags []string) bool {
for _, val := range tags {
tagValue := strings.TrimSpace(val)
if tagValue != "" && tagValue == tag {
return true
}
}
return false
}
// Copied from https://golang.org/src/net/dnsclient.go#L119
func isDomainName(s string) bool {
// See RFC 1035, RFC 3696.
// Presentation format has dots before every label except the first, and the
// terminal empty label is optional here because we assume fully-qualified
// (absolute) input. We must therefore reserve space for the first and last
// labels' length octets in wire format, where they are necessary and the
// maximum total length is 255.
// So our _effective_ maximum is 253, but 254 is not rejected if the last
// character is a dot.
l := len(s)
if l == 0 || l > 254 || l == 254 && s[l-1] != '.' {
return false
}
last := byte('.')
ok := false // Ok once we've seen a letter.
partlen := 0
for i := 0; i < len(s); i++ {
c := s[i]
switch {
default:
return false
case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_':
ok = true
partlen++
case '0' <= c && c <= '9':
// fine
partlen++
case c == '-':
// Byte before dash cannot be dot.
if last == '.' {
return false
}
partlen++
case c == '.':
// Byte before dot cannot be dot, dash.
if last == '.' || last == '-' {
return false
}
if partlen > 63 || partlen == 0 {
return false
}
partlen = 0
}
last = c
}
if last == '-' || partlen > 63 {
return false
}
return ok
}
func isSafeLink(link *string) bool {
if link != nil {
if IsValidHTTPURL(*link) {
return true
} else if strings.HasPrefix(*link, "/") {
return true
} else {
return false
}
}
return true
}