summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/mattermost/mattermost-server/v6/model/config.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/mattermost/mattermost-server/v6/model/config.go')
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v6/model/config.go3915
1 files changed, 3915 insertions, 0 deletions
diff --git a/vendor/github.com/mattermost/mattermost-server/v6/model/config.go b/vendor/github.com/mattermost/mattermost-server/v6/model/config.go
new file mode 100644
index 00000000..39cdb893
--- /dev/null
+++ b/vendor/github.com/mattermost/mattermost-server/v6/model/config.go
@@ -0,0 +1,3915 @@
+// 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
+}