[MM-14400] Programmatically generate default.json (#10551)
* create/update config.json using go generate * added default config generator added config-reset to Jenkins and make package, updated defaults to consider 'isNew' flag * corrections after code review * fixed Config.isValid to handle empty encryption keys * fixed Config.isValid to handle empty encryption keys * fixed Config.isValid to handle empty encryption keys * isUpdate now only checks for nil * Addressed review comments, added unit testing for default config generator * err shadowing * license * provide output file for config generator via ENV variable, since go generate doesn't support arguments and we need two output paths (config-reset and package) * cleanup * proper defaults for PushNotificationServer and SendPushNotifications * corrected generating defaults for TrustedProxyIPHeader to be consistent with default.json in master * Check for empty SiteURL as well as nil * corrected SiteURL settings and checking * crazy typos fixed * corrected tests to newly expected values * relaxed the checks * fixed formatting
Этот коммит содержится в:
коммит произвёл
Jesse Hallam
родитель
978ee13262
Коммит
6a42ad2af5
2
Makefile
2
Makefile
@@ -535,7 +535,7 @@ config-ldap: ## Configures LDAP.
|
|||||||
config-reset: ## Resets the config/config.json file to the default.
|
config-reset: ## Resets the config/config.json file to the default.
|
||||||
@echo Resetting configuration to default
|
@echo Resetting configuration to default
|
||||||
rm -f config/config.json
|
rm -f config/config.json
|
||||||
cp config/default.json config/config.json
|
OUTPUT_CONFIG=$(PWD)/config/config.json go generate ./config
|
||||||
|
|
||||||
clean: stop-docker ## Clean up everything except persistant server data.
|
clean: stop-docker ## Clean up everything except persistant server data.
|
||||||
@echo Cleaning
|
@echo Cleaning
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ podTemplate(label: 'jenkins-slave',
|
|||||||
sh 'apt-get update && apt-get install zip -y'
|
sh 'apt-get update && apt-get install zip -y'
|
||||||
|
|
||||||
// Modify config to run on jenkins
|
// Modify config to run on jenkins
|
||||||
sh 'mv /go/src/github.com/mattermost/mattermost-server/config/default.json /go/src/github.com/mattermost/mattermost-server/config/config.json'
|
sh 'cd /go/src/github.com/mattermost/mattermost-server && make config-reset'
|
||||||
sh 'cd /go/src/github.com/mattermost/mattermost-server && sed -i \'s/dockerhost/localhost/g\' config/config.json'
|
sh 'cd /go/src/github.com/mattermost/mattermost-server && sed -i \'s/dockerhost/localhost/g\' config/config.json'
|
||||||
sh 'cd /go/src/github.com/mattermost/mattermost-server && sed -i \'s/2500/10025/g\' config/config.json'
|
sh 'cd /go/src/github.com/mattermost/mattermost-server && sed -i \'s/2500/10025/g\' config/config.json'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ pipeline {
|
|||||||
ansiColor('xterm') {
|
ansiColor('xterm') {
|
||||||
sh """
|
sh """
|
||||||
cd /go/src/github.com/mattermost/mattermost-server
|
cd /go/src/github.com/mattermost/mattermost-server
|
||||||
mv config/default.json config/config.json || echo ""
|
make config-reset
|
||||||
make check-style BUILD_NUMBER='${BRANCH_NAME}-${BUILD_NUMBER}'
|
make check-style BUILD_NUMBER='${BRANCH_NAME}-${BUILD_NUMBER}'
|
||||||
make build BUILD_NUMBER='${BRANCH_NAME}-${BUILD_NUMBER}'
|
make build BUILD_NUMBER='${BRANCH_NAME}-${BUILD_NUMBER}'
|
||||||
make package BUILD_NUMBER='${BRANCH_NAME}-${BUILD_NUMBER}'
|
make package BUILD_NUMBER='${BRANCH_NAME}-${BUILD_NUMBER}'
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ package:
|
|||||||
@# Resource directories
|
@# Resource directories
|
||||||
mkdir -p $(DIST_PATH)/config
|
mkdir -p $(DIST_PATH)/config
|
||||||
cp -L config/README.md $(DIST_PATH)/config
|
cp -L config/README.md $(DIST_PATH)/config
|
||||||
cp -L config/config.json $(DIST_PATH)/config
|
OUTPUT_CONFIG=$(PWD)/$(DIST_PATH)/config/config.json go generate ./config
|
||||||
cp -RL fonts $(DIST_PATH)
|
cp -RL fonts $(DIST_PATH)
|
||||||
cp -RL templates $(DIST_PATH)
|
cp -RL templates $(DIST_PATH)
|
||||||
cp -RL i18n $(DIST_PATH)
|
cp -RL i18n $(DIST_PATH)
|
||||||
|
|||||||
22
config/config_generator/generator/generator.go
Обычный файл
22
config/config_generator/generator/generator.go
Обычный файл
@@ -0,0 +1,22 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
package generator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost-server/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GenerateDefaultConfig(outputFile *os.File) error {
|
||||||
|
defaultCfg := &model.Config{}
|
||||||
|
defaultCfg.SetDefaults()
|
||||||
|
if data, err := json.MarshalIndent(defaultCfg, "", " "); err != nil {
|
||||||
|
return err
|
||||||
|
} else if _, err := outputFile.Write(data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
34
config/config_generator/main.go
Обычный файл
34
config/config_generator/main.go
Обычный файл
@@ -0,0 +1,34 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost-server/config/config_generator/generator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
outputFile := os.Getenv("OUTPUT_CONFIG")
|
||||||
|
if outputFile == "" {
|
||||||
|
fmt.Println("Output file name is missing. Please set OUTPUT_CONFIG env variable to absolute path")
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(outputFile); !os.IsNotExist(err) {
|
||||||
|
_, _ = fmt.Fprintf(os.Stderr, "File %s already exists. Not overwriting!\n", outputFile)
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
if file, err := os.Create(outputFile); err == nil {
|
||||||
|
err = generator.GenerateDefaultConfig(file)
|
||||||
|
_ = file.Close()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -101,7 +101,7 @@ func TestDatabaseStoreNew(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer ds.Close()
|
defer ds.Close()
|
||||||
|
|
||||||
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *ds.Get().ServiceSettings.SiteURL)
|
assert.Equal(t, "", *ds.Get().ServiceSettings.SiteURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("existing config, initialization required", func(t *testing.T) {
|
t.Run("existing config, initialization required", func(t *testing.T) {
|
||||||
@@ -221,7 +221,7 @@ func TestDatabaseStoreSet(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, oldCfg, retCfg)
|
assert.Equal(t, oldCfg, retCfg)
|
||||||
|
|
||||||
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *ds.Get().ServiceSettings.SiteURL)
|
assert.Equal(t, "", *ds.Get().ServiceSettings.SiteURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("desanitization required", func(t *testing.T) {
|
t.Run("desanitization required", func(t *testing.T) {
|
||||||
@@ -260,7 +260,7 @@ func TestDatabaseStoreSet(t *testing.T) {
|
|||||||
assert.EqualError(t, err, "new configuration is invalid: Config.IsValid: model.config.is_valid.site_url.app_error, ")
|
assert.EqualError(t, err, "new configuration is invalid: Config.IsValid: model.config.is_valid.site_url.app_error, ")
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *ds.Get().ServiceSettings.SiteURL)
|
assert.Equal(t, "", *ds.Get().ServiceSettings.SiteURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("duplicate ignored", func(t *testing.T) {
|
t.Run("duplicate ignored", func(t *testing.T) {
|
||||||
@@ -345,7 +345,7 @@ func TestDatabaseStoreSet(t *testing.T) {
|
|||||||
assert.True(t, strings.HasPrefix(err.Error(), "failed to persist: failed to write to database"))
|
assert.True(t, strings.HasPrefix(err.Error(), "failed to persist: failed to write to database"))
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *ds.Get().ServiceSettings.SiteURL)
|
assert.Equal(t, "", *ds.Get().ServiceSettings.SiteURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("listeners notified", func(t *testing.T) {
|
t.Run("listeners notified", func(t *testing.T) {
|
||||||
|
|||||||
6
config/default.go
Обычный файл
6
config/default.go
Обычный файл
@@ -0,0 +1,6 @@
|
|||||||
|
//go:generate go run config_generator/main.go
|
||||||
|
|
||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
package config
|
||||||
@@ -1,442 +0,0 @@
|
|||||||
{
|
|
||||||
"ServiceSettings": {
|
|
||||||
"SiteURL": "",
|
|
||||||
"WebsocketURL": "",
|
|
||||||
"LicenseFileLocation": "",
|
|
||||||
"ListenAddress": ":8065",
|
|
||||||
"ConnectionSecurity": "",
|
|
||||||
"TLSCertFile": "",
|
|
||||||
"TLSKeyFile": "",
|
|
||||||
"TLSMinVer": "1.2",
|
|
||||||
"TLSStrictTransport": false,
|
|
||||||
"TLSStrictTransportMaxAge": 63072000,
|
|
||||||
"TLSOverwriteCiphers": [],
|
|
||||||
"UseLetsEncrypt": false,
|
|
||||||
"LetsEncryptCertificateCacheFile": "./config/letsencrypt.cache",
|
|
||||||
"Forward80To443": false,
|
|
||||||
"TrustedProxyIPHeader": [],
|
|
||||||
"ReadTimeout": 300,
|
|
||||||
"WriteTimeout": 300,
|
|
||||||
"MaximumLoginAttempts": 10,
|
|
||||||
"GoroutineHealthThreshold": -1,
|
|
||||||
"GoogleDeveloperKey": "",
|
|
||||||
"EnableOAuthServiceProvider": false,
|
|
||||||
"EnableIncomingWebhooks": true,
|
|
||||||
"EnableOutgoingWebhooks": true,
|
|
||||||
"EnableCommands": true,
|
|
||||||
"EnableOnlyAdminIntegrations": true,
|
|
||||||
"EnablePostUsernameOverride": false,
|
|
||||||
"EnablePostIconOverride": false,
|
|
||||||
"EnableAPIv3": false,
|
|
||||||
"EnableLinkPreviews": false,
|
|
||||||
"EnableTesting": false,
|
|
||||||
"EnableDeveloper": false,
|
|
||||||
"EnableSecurityFixAlert": true,
|
|
||||||
"EnableInsecureOutgoingConnections": false,
|
|
||||||
"AllowedUntrustedInternalConnections": "",
|
|
||||||
"EnableMultifactorAuthentication": false,
|
|
||||||
"EnforceMultifactorAuthentication": false,
|
|
||||||
"EnableUserAccessTokens": false,
|
|
||||||
"AllowCorsFrom": "",
|
|
||||||
"CorsExposedHeaders": "",
|
|
||||||
"CorsAllowCredentials": false,
|
|
||||||
"CorsDebug": false,
|
|
||||||
"AllowCookiesForSubdomains": false,
|
|
||||||
"SessionLengthWebInDays": 180,
|
|
||||||
"SessionLengthMobileInDays": 180,
|
|
||||||
"SessionLengthSSOInDays": 30,
|
|
||||||
"SessionCacheInMinutes": 10,
|
|
||||||
"SessionIdleTimeoutInMinutes": 43200,
|
|
||||||
"WebsocketSecurePort": 443,
|
|
||||||
"WebsocketPort": 80,
|
|
||||||
"WebserverMode": "gzip",
|
|
||||||
"EnableCustomEmoji": false,
|
|
||||||
"EnableEmojiPicker": true,
|
|
||||||
"EnableGifPicker": false,
|
|
||||||
"GfycatApiKey": "2_KtH_W5",
|
|
||||||
"GfycatApiSecret": "3wLVZPiswc3DnaiaFoLkDvB4X0IV6CpMkj4tf2inJRsBY6-FnkT08zGmppWFgeof",
|
|
||||||
"RestrictCustomEmojiCreation": "all",
|
|
||||||
"RestrictPostDelete": "all",
|
|
||||||
"AllowEditPost": "always",
|
|
||||||
"PostEditTimeLimit": -1,
|
|
||||||
"ExperimentalEnableAuthenticationTransfer": true,
|
|
||||||
"TimeBetweenUserTypingUpdatesMilliseconds": 5000,
|
|
||||||
"EnablePostSearch": true,
|
|
||||||
"MinimumHashtagLength": 3,
|
|
||||||
"EnableUserTypingMessages": true,
|
|
||||||
"EnableChannelViewedMessages": true,
|
|
||||||
"EnableUserStatuses": true,
|
|
||||||
"ClusterLogTimeoutMilliseconds": 2000,
|
|
||||||
"EnablePreviewFeatures": true,
|
|
||||||
"CloseUnusedDirectMessages": false,
|
|
||||||
"EnableTutorial": true,
|
|
||||||
"ExperimentalEnableDefaultChannelLeaveJoinMessages": true,
|
|
||||||
"ExperimentalGroupUnreadChannels": "disabled",
|
|
||||||
"ExperimentalChannelOrganization": false,
|
|
||||||
"EnableAPITeamDeletion": false,
|
|
||||||
"ExperimentalEnableHardenedMode": false,
|
|
||||||
"DisableLegacyMFA": true,
|
|
||||||
"EnableEmailInvitations": false,
|
|
||||||
"ExperimentalLdapGroupSync": false,
|
|
||||||
"ExperimentalStrictCSRFEnforcement": false,
|
|
||||||
"EnableBotAccountCreation": false,
|
|
||||||
"DisableBotsWhenOwnerIsDeactivated": true
|
|
||||||
},
|
|
||||||
"TeamSettings": {
|
|
||||||
"SiteName": "Mattermost",
|
|
||||||
"MaxUsersPerTeam": 50,
|
|
||||||
"EnableTeamCreation": true,
|
|
||||||
"EnableUserCreation": true,
|
|
||||||
"EnableOpenServer": false,
|
|
||||||
"EnableUserDeactivation": false,
|
|
||||||
"RestrictCreationToDomains": "",
|
|
||||||
"EnableCustomBrand": false,
|
|
||||||
"CustomBrandText": "",
|
|
||||||
"CustomDescriptionText": "",
|
|
||||||
"RestrictDirectMessage": "any",
|
|
||||||
"RestrictTeamInvite": "all",
|
|
||||||
"RestrictPublicChannelManagement": "all",
|
|
||||||
"RestrictPrivateChannelManagement": "all",
|
|
||||||
"RestrictPublicChannelCreation": "all",
|
|
||||||
"RestrictPrivateChannelCreation": "all",
|
|
||||||
"RestrictPublicChannelDeletion": "all",
|
|
||||||
"RestrictPrivateChannelDeletion": "all",
|
|
||||||
"RestrictPrivateChannelManageMembers": "all",
|
|
||||||
"EnableXToLeaveChannelsFromLHS": false,
|
|
||||||
"UserStatusAwayTimeout": 300,
|
|
||||||
"MaxChannelsPerTeam": 2000,
|
|
||||||
"MaxNotificationsPerChannel": 1000,
|
|
||||||
"EnableConfirmNotificationsToChannel": true,
|
|
||||||
"TeammateNameDisplay": "username",
|
|
||||||
"ExperimentalViewArchivedChannels": false,
|
|
||||||
"ExperimentalEnableAutomaticReplies": false,
|
|
||||||
"ExperimentalHideTownSquareinLHS": false,
|
|
||||||
"ExperimentalTownSquareIsReadOnly": false,
|
|
||||||
"ExperimentalPrimaryTeam": "",
|
|
||||||
"ExperimentalDefaultChannels": ""
|
|
||||||
},
|
|
||||||
"DisplaySettings": {
|
|
||||||
"CustomUrlSchemes": [],
|
|
||||||
"ExperimentalTimezone": false
|
|
||||||
},
|
|
||||||
"ClientRequirements": {
|
|
||||||
"AndroidLatestVersion": "",
|
|
||||||
"AndroidMinVersion": "",
|
|
||||||
"DesktopLatestVersion": "",
|
|
||||||
"DesktopMinVersion": "",
|
|
||||||
"IosLatestVersion": "",
|
|
||||||
"IosMinVersion": ""
|
|
||||||
},
|
|
||||||
"SqlSettings": {
|
|
||||||
"DriverName": "mysql",
|
|
||||||
"DataSource": "mmuser:mostest@tcp(dockerhost:3306)/mattermost_test?charset=utf8mb4,utf8&readTimeout=30s&writeTimeout=30s",
|
|
||||||
"DataSourceReplicas": [],
|
|
||||||
"DataSourceSearchReplicas": [],
|
|
||||||
"MaxIdleConns": 20,
|
|
||||||
"ConnMaxLifetimeMilliseconds": 3600000,
|
|
||||||
"MaxOpenConns": 300,
|
|
||||||
"Trace": false,
|
|
||||||
"AtRestEncryptKey": "",
|
|
||||||
"QueryTimeout": 30
|
|
||||||
},
|
|
||||||
"LogSettings": {
|
|
||||||
"EnableConsole": true,
|
|
||||||
"ConsoleLevel": "DEBUG",
|
|
||||||
"ConsoleJson": true,
|
|
||||||
"EnableFile": true,
|
|
||||||
"FileLevel": "INFO",
|
|
||||||
"FileJson": true,
|
|
||||||
"FileLocation": "",
|
|
||||||
"EnableWebhookDebugging": true,
|
|
||||||
"EnableDiagnostics": true
|
|
||||||
},
|
|
||||||
"NotificationLogSettings": {
|
|
||||||
"EnableConsole": true,
|
|
||||||
"ConsoleLevel": "DEBUG",
|
|
||||||
"ConsoleJson": true,
|
|
||||||
"EnableFile": true,
|
|
||||||
"FileLevel": "INFO",
|
|
||||||
"FileJson": true,
|
|
||||||
"FileLocation": ""
|
|
||||||
},
|
|
||||||
"PasswordSettings": {
|
|
||||||
"MinimumLength": 10,
|
|
||||||
"Lowercase": true,
|
|
||||||
"Number": true,
|
|
||||||
"Uppercase": true,
|
|
||||||
"Symbol": true
|
|
||||||
},
|
|
||||||
"FileSettings": {
|
|
||||||
"EnableFileAttachments": true,
|
|
||||||
"EnableMobileUpload": true,
|
|
||||||
"EnableMobileDownload": true,
|
|
||||||
"MaxFileSize": 52428800,
|
|
||||||
"DriverName": "local",
|
|
||||||
"Directory": "./data/",
|
|
||||||
"EnablePublicLink": false,
|
|
||||||
"PublicLinkSalt": "",
|
|
||||||
"InitialFont": "nunito-bold.ttf",
|
|
||||||
"AmazonS3AccessKeyId": "",
|
|
||||||
"AmazonS3SecretAccessKey": "",
|
|
||||||
"AmazonS3Bucket": "",
|
|
||||||
"AmazonS3Region": "",
|
|
||||||
"AmazonS3Endpoint": "s3.amazonaws.com",
|
|
||||||
"AmazonS3SSL": true,
|
|
||||||
"AmazonS3SignV2": false,
|
|
||||||
"AmazonS3SSE": false,
|
|
||||||
"AmazonS3Trace": false
|
|
||||||
},
|
|
||||||
"EmailSettings": {
|
|
||||||
"EnableSignUpWithEmail": true,
|
|
||||||
"EnableSignInWithEmail": true,
|
|
||||||
"EnableSignInWithUsername": true,
|
|
||||||
"SendEmailNotifications": true,
|
|
||||||
"UseChannelInEmailNotifications": false,
|
|
||||||
"RequireEmailVerification": false,
|
|
||||||
"FeedbackName": "",
|
|
||||||
"FeedbackEmail": "test@example.com",
|
|
||||||
"ReplyToAddress": "test@example.com",
|
|
||||||
"FeedbackOrganization": "",
|
|
||||||
"EnableSMTPAuth": false,
|
|
||||||
"SMTPUsername": "",
|
|
||||||
"SMTPPassword": "",
|
|
||||||
"SMTPServer": "dockerhost",
|
|
||||||
"SMTPPort": "2500",
|
|
||||||
"ConnectionSecurity": "",
|
|
||||||
"SendPushNotifications": true,
|
|
||||||
"PushNotificationServer": "https://push-test.mattermost.com",
|
|
||||||
"PushNotificationContents": "generic",
|
|
||||||
"EnableEmailBatching": false,
|
|
||||||
"EmailBatchingBufferSize": 256,
|
|
||||||
"EmailBatchingInterval": 30,
|
|
||||||
"EnablePreviewModeBanner": true,
|
|
||||||
"SkipServerCertificateVerification": false,
|
|
||||||
"EmailNotificationContentsType": "full",
|
|
||||||
"LoginButtonColor": "#0000",
|
|
||||||
"LoginButtonBorderColor": "#2389D7",
|
|
||||||
"LoginButtonTextColor": "#2389D7"
|
|
||||||
},
|
|
||||||
"RateLimitSettings": {
|
|
||||||
"Enable": false,
|
|
||||||
"PerSec": 10,
|
|
||||||
"MaxBurst": 100,
|
|
||||||
"MemoryStoreSize": 10000,
|
|
||||||
"VaryByRemoteAddr": true,
|
|
||||||
"VaryByUser": false,
|
|
||||||
"VaryByHeader": ""
|
|
||||||
},
|
|
||||||
"PrivacySettings": {
|
|
||||||
"ShowEmailAddress": true,
|
|
||||||
"ShowFullName": true
|
|
||||||
},
|
|
||||||
"SupportSettings": {
|
|
||||||
"TermsOfServiceLink": "https://about.mattermost.com/default-terms/",
|
|
||||||
"PrivacyPolicyLink": "https://about.mattermost.com/default-privacy-policy/",
|
|
||||||
"AboutLink": "https://about.mattermost.com/default-about/",
|
|
||||||
"HelpLink": "https://about.mattermost.com/default-help/",
|
|
||||||
"ReportAProblemLink": "https://about.mattermost.com/default-report-a-problem/",
|
|
||||||
"SupportEmail": "feedback@mattermost.com"
|
|
||||||
},
|
|
||||||
"AnnouncementSettings": {
|
|
||||||
"EnableBanner": false,
|
|
||||||
"BannerText": "",
|
|
||||||
"BannerColor": "#f2a93b",
|
|
||||||
"BannerTextColor": "#333333",
|
|
||||||
"AllowBannerDismissal": true
|
|
||||||
},
|
|
||||||
"ThemeSettings": {
|
|
||||||
"EnableThemeSelection": true,
|
|
||||||
"DefaultTheme": "default",
|
|
||||||
"AllowCustomThemes": true,
|
|
||||||
"AllowedThemes": []
|
|
||||||
},
|
|
||||||
"GitLabSettings": {
|
|
||||||
"Enable": false,
|
|
||||||
"Secret": "",
|
|
||||||
"Id": "",
|
|
||||||
"Scope": "",
|
|
||||||
"AuthEndpoint": "",
|
|
||||||
"TokenEndpoint": "",
|
|
||||||
"UserApiEndpoint": ""
|
|
||||||
},
|
|
||||||
"GoogleSettings": {
|
|
||||||
"Enable": false,
|
|
||||||
"Secret": "",
|
|
||||||
"Id": "",
|
|
||||||
"Scope": "profile email",
|
|
||||||
"AuthEndpoint": "https://accounts.google.com/o/oauth2/v2/auth",
|
|
||||||
"TokenEndpoint": "https://www.googleapis.com/oauth2/v4/token",
|
|
||||||
"UserApiEndpoint": "https://people.googleapis.com/v1/people/me?personFields=names,emailAddresses,nicknames,metadata"
|
|
||||||
},
|
|
||||||
"Office365Settings": {
|
|
||||||
"Enable": false,
|
|
||||||
"Secret": "",
|
|
||||||
"Id": "",
|
|
||||||
"Scope": "User.Read",
|
|
||||||
"AuthEndpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
||||||
"TokenEndpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
||||||
"UserApiEndpoint": "https://graph.microsoft.com/v1.0/me"
|
|
||||||
},
|
|
||||||
"LdapSettings": {
|
|
||||||
"Enable": false,
|
|
||||||
"EnableSync": false,
|
|
||||||
"LdapServer": "",
|
|
||||||
"LdapPort": 389,
|
|
||||||
"ConnectionSecurity": "",
|
|
||||||
"BaseDN": "",
|
|
||||||
"BindUsername": "",
|
|
||||||
"BindPassword": "",
|
|
||||||
"UserFilter": "",
|
|
||||||
"GroupFilter": "",
|
|
||||||
"GroupDisplayNameAttribute": "",
|
|
||||||
"GroupIdAttribute": "",
|
|
||||||
"FirstNameAttribute": "",
|
|
||||||
"LastNameAttribute": "",
|
|
||||||
"EmailAttribute": "",
|
|
||||||
"UsernameAttribute": "",
|
|
||||||
"NicknameAttribute": "",
|
|
||||||
"IdAttribute": "",
|
|
||||||
"PositionAttribute": "",
|
|
||||||
"LoginIdAttribute": "",
|
|
||||||
"SyncIntervalMinutes": 60,
|
|
||||||
"SkipCertificateVerification": false,
|
|
||||||
"QueryTimeout": 60,
|
|
||||||
"MaxPageSize": 0,
|
|
||||||
"LoginFieldName": "",
|
|
||||||
"LoginButtonColor": "",
|
|
||||||
"LoginButtonBorderColor": "",
|
|
||||||
"LoginButtonTextColor": ""
|
|
||||||
},
|
|
||||||
"ComplianceSettings": {
|
|
||||||
"Enable": false,
|
|
||||||
"Directory": "./data/",
|
|
||||||
"EnableDaily": false
|
|
||||||
},
|
|
||||||
"LocalizationSettings": {
|
|
||||||
"DefaultServerLocale": "en",
|
|
||||||
"DefaultClientLocale": "en",
|
|
||||||
"AvailableLocales": ""
|
|
||||||
},
|
|
||||||
"SamlSettings": {
|
|
||||||
"Enable": false,
|
|
||||||
"EnableSyncWithLdap": false,
|
|
||||||
"EnableSyncWithLdapIncludeAuth": false,
|
|
||||||
"Verify": true,
|
|
||||||
"Encrypt": true,
|
|
||||||
"IdpUrl": "",
|
|
||||||
"IdpDescriptorUrl": "",
|
|
||||||
"AssertionConsumerServiceURL": "",
|
|
||||||
"ScopingIDPProviderId": "",
|
|
||||||
"ScopingIDPName": "",
|
|
||||||
"IdpCertificateFile": "",
|
|
||||||
"PublicCertificateFile": "",
|
|
||||||
"PrivateKeyFile": "",
|
|
||||||
"IdAttribute": "",
|
|
||||||
"FirstNameAttribute": "",
|
|
||||||
"LastNameAttribute": "",
|
|
||||||
"EmailAttribute": "",
|
|
||||||
"UsernameAttribute": "",
|
|
||||||
"NicknameAttribute": "",
|
|
||||||
"LocaleAttribute": "",
|
|
||||||
"PositionAttribute": "",
|
|
||||||
"LoginButtonText": "SAML",
|
|
||||||
"LoginButtonColor": "",
|
|
||||||
"LoginButtonBorderColor": "",
|
|
||||||
"LoginButtonTextColor": ""
|
|
||||||
},
|
|
||||||
"NativeAppSettings": {
|
|
||||||
"AppDownloadLink": "https://about.mattermost.com/downloads/",
|
|
||||||
"AndroidAppDownloadLink": "https://about.mattermost.com/mattermost-android-app/",
|
|
||||||
"IosAppDownloadLink": "https://about.mattermost.com/mattermost-ios-app/"
|
|
||||||
},
|
|
||||||
"ClusterSettings": {
|
|
||||||
"Enable": false,
|
|
||||||
"ClusterName": "",
|
|
||||||
"OverrideHostname": "",
|
|
||||||
"UseIpAddress": true,
|
|
||||||
"UseExperimentalGossip": false,
|
|
||||||
"ReadOnlyConfig": true,
|
|
||||||
"GossipPort": 8074,
|
|
||||||
"StreamingPort": 8075,
|
|
||||||
"MaxIdleConns": 100,
|
|
||||||
"MaxIdleConnsPerHost": 128,
|
|
||||||
"IdleConnTimeoutMilliseconds": 90000
|
|
||||||
},
|
|
||||||
"MetricsSettings": {
|
|
||||||
"Enable": false,
|
|
||||||
"BlockProfileRate": 0,
|
|
||||||
"ListenAddress": ":8067"
|
|
||||||
},
|
|
||||||
"ExperimentalSettings": {
|
|
||||||
"ClientSideCertEnable": false,
|
|
||||||
"ClientSideCertCheck": "secondary",
|
|
||||||
"DisablePostMetadata": false,
|
|
||||||
"LinkMetadataTimeoutMilliseconds": 5000,
|
|
||||||
"RestrictSystemAdmin": false,
|
|
||||||
"EnableClickToReply": false
|
|
||||||
},
|
|
||||||
"AnalyticsSettings": {
|
|
||||||
"MaxUsersForStatistics": 2500
|
|
||||||
},
|
|
||||||
"ElasticsearchSettings": {
|
|
||||||
"ConnectionUrl": "http://dockerhost:9200",
|
|
||||||
"Username": "elastic",
|
|
||||||
"Password": "changeme",
|
|
||||||
"EnableIndexing": false,
|
|
||||||
"EnableSearching": false,
|
|
||||||
"EnableAutocomplete": false,
|
|
||||||
"Sniff": true,
|
|
||||||
"PostIndexReplicas": 1,
|
|
||||||
"PostIndexShards": 1,
|
|
||||||
"ChannelIndexReplicas": 1,
|
|
||||||
"ChannelIndexShards": 1,
|
|
||||||
"UserIndexReplicas": 1,
|
|
||||||
"UserIndexShards": 1,
|
|
||||||
"AggregatePostsAfterDays": 365,
|
|
||||||
"PostsAggregatorJobStartTime": "03:00",
|
|
||||||
"IndexPrefix": "",
|
|
||||||
"LiveIndexingBatchSize": 1,
|
|
||||||
"BulkIndexingTimeWindowSeconds": 3600,
|
|
||||||
"RequestTimeoutSeconds": 30,
|
|
||||||
"Trace": ""
|
|
||||||
},
|
|
||||||
"DataRetentionSettings": {
|
|
||||||
"EnableMessageDeletion": false,
|
|
||||||
"EnableFileDeletion": false,
|
|
||||||
"MessageRetentionDays": 365,
|
|
||||||
"FileRetentionDays": 365,
|
|
||||||
"DeletionJobStartTime": "02:00"
|
|
||||||
},
|
|
||||||
"MessageExportSettings": {
|
|
||||||
"EnableExport": false,
|
|
||||||
"DailyRunTime": "01:00",
|
|
||||||
"ExportFromTimestamp": 0,
|
|
||||||
"FileLocation": "export",
|
|
||||||
"BatchSize": 10000,
|
|
||||||
"GlobalRelaySettings": {
|
|
||||||
"CustomerType": "A9",
|
|
||||||
"SmtpUsername": "",
|
|
||||||
"SmtpPassword": "",
|
|
||||||
"EmailAddress": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"JobSettings": {
|
|
||||||
"RunJobs": true,
|
|
||||||
"RunScheduler": true
|
|
||||||
},
|
|
||||||
"PluginSettings": {
|
|
||||||
"Enable": true,
|
|
||||||
"EnableUploads": false,
|
|
||||||
"EnableHealthCheck": true,
|
|
||||||
"Directory": "./plugins",
|
|
||||||
"ClientDirectory": "./client/plugins",
|
|
||||||
"Plugins": {},
|
|
||||||
"PluginStates": {}
|
|
||||||
},
|
|
||||||
"ImageProxySettings": {
|
|
||||||
"Enable": false,
|
|
||||||
"ImageProxyType": "local",
|
|
||||||
"RemoteImageProxyURL": "",
|
|
||||||
"RemoteImageProxyOptions": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
42
config/default_test.go
Обычный файл
42
config/default_test.go
Обычный файл
@@ -0,0 +1,42 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost-server/model"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost-server/config/config_generator/generator"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDefaultsGenerator(t *testing.T) {
|
||||||
|
tmpFile, err := ioutil.TempFile("", "tempconfig")
|
||||||
|
defer os.Remove(tmpFile.Name())
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, generator.GenerateDefaultConfig(tmpFile))
|
||||||
|
_ = tmpFile.Close()
|
||||||
|
var config model.Config
|
||||||
|
|
||||||
|
b, err := ioutil.ReadFile(tmpFile.Name())
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, json.Unmarshal(b, &config))
|
||||||
|
require.True(t, *config.ServiceSettings.DisableLegacyMFA)
|
||||||
|
require.Equal(t, *config.SqlSettings.AtRestEncryptKey, "")
|
||||||
|
require.Equal(t, *config.FileSettings.PublicLinkSalt, "")
|
||||||
|
|
||||||
|
require.Equal(t, *config.Office365Settings.Scope, model.OFFICE365_SETTINGS_DEFAULT_SCOPE)
|
||||||
|
require.Equal(t, *config.Office365Settings.AuthEndpoint, model.OFFICE365_SETTINGS_DEFAULT_AUTH_ENDPOINT)
|
||||||
|
require.Equal(t, *config.Office365Settings.UserApiEndpoint, model.OFFICE365_SETTINGS_DEFAULT_USER_API_ENDPOINT)
|
||||||
|
require.Equal(t, *config.Office365Settings.TokenEndpoint, model.OFFICE365_SETTINGS_DEFAULT_TOKEN_ENDPOINT)
|
||||||
|
|
||||||
|
require.Equal(t, *config.GoogleSettings.Scope, model.GOOGLE_SETTINGS_DEFAULT_SCOPE)
|
||||||
|
require.Equal(t, *config.GoogleSettings.AuthEndpoint, model.GOOGLE_SETTINGS_DEFAULT_AUTH_ENDPOINT)
|
||||||
|
require.Equal(t, *config.GoogleSettings.UserApiEndpoint, model.GOOGLE_SETTINGS_DEFAULT_USER_API_ENDPOINT)
|
||||||
|
require.Equal(t, *config.GoogleSettings.TokenEndpoint, model.GOOGLE_SETTINGS_DEFAULT_TOKEN_ENDPOINT)
|
||||||
|
}
|
||||||
@@ -122,7 +122,7 @@ func TestFileStoreNew(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer fs.Close()
|
defer fs.Close()
|
||||||
|
|
||||||
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *fs.Get().ServiceSettings.SiteURL)
|
assert.Equal(t, "", *fs.Get().ServiceSettings.SiteURL)
|
||||||
assertFileNotEqualsConfig(t, testConfig, path)
|
assertFileNotEqualsConfig(t, testConfig, path)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -175,7 +175,7 @@ func TestFileStoreNew(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer fs.Close()
|
defer fs.Close()
|
||||||
|
|
||||||
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *fs.Get().ServiceSettings.SiteURL)
|
assert.Equal(t, "", *fs.Get().ServiceSettings.SiteURL)
|
||||||
assertFileNotEqualsConfig(t, testConfig, filepath.Join("config", path))
|
assertFileNotEqualsConfig(t, testConfig, filepath.Join("config", path))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -257,7 +257,7 @@ func TestFileStoreSet(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, oldCfg, retCfg)
|
assert.Equal(t, oldCfg, retCfg)
|
||||||
|
|
||||||
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *fs.Get().ServiceSettings.SiteURL)
|
assert.Equal(t, "", *fs.Get().ServiceSettings.SiteURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("desanitization required", func(t *testing.T) {
|
t.Run("desanitization required", func(t *testing.T) {
|
||||||
@@ -296,7 +296,7 @@ func TestFileStoreSet(t *testing.T) {
|
|||||||
assert.EqualError(t, err, "new configuration is invalid: Config.IsValid: model.config.is_valid.site_url.app_error, ")
|
assert.EqualError(t, err, "new configuration is invalid: Config.IsValid: model.config.is_valid.site_url.app_error, ")
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *fs.Get().ServiceSettings.SiteURL)
|
assert.Equal(t, "", *fs.Get().ServiceSettings.SiteURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("read-only", func(t *testing.T) {
|
t.Run("read-only", func(t *testing.T) {
|
||||||
@@ -314,7 +314,7 @@ func TestFileStoreSet(t *testing.T) {
|
|||||||
assert.Equal(t, config.ErrReadOnlyConfiguration, errors.Cause(err))
|
assert.Equal(t, config.ErrReadOnlyConfiguration, errors.Cause(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *fs.Get().ServiceSettings.SiteURL)
|
assert.Equal(t, "", *fs.Get().ServiceSettings.SiteURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("persist failed", func(t *testing.T) {
|
t.Run("persist failed", func(t *testing.T) {
|
||||||
@@ -335,7 +335,7 @@ func TestFileStoreSet(t *testing.T) {
|
|||||||
assert.True(t, strings.HasPrefix(err.Error(), "failed to persist: failed to write file"))
|
assert.True(t, strings.HasPrefix(err.Error(), "failed to persist: failed to write file"))
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *fs.Get().ServiceSettings.SiteURL)
|
assert.Equal(t, "", *fs.Get().ServiceSettings.SiteURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("listeners notified", func(t *testing.T) {
|
t.Run("listeners notified", func(t *testing.T) {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func TestMemoryStoreNew(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer ms.Close()
|
defer ms.Close()
|
||||||
|
|
||||||
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *ms.Get().ServiceSettings.SiteURL)
|
assert.Equal(t, "", *ms.Get().ServiceSettings.SiteURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("existing config, initialization required", func(t *testing.T) {
|
t.Run("existing config, initialization required", func(t *testing.T) {
|
||||||
@@ -134,7 +134,7 @@ func TestMemoryStoreSet(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, oldCfg, retCfg)
|
assert.Equal(t, oldCfg, retCfg)
|
||||||
|
|
||||||
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *ms.Get().ServiceSettings.SiteURL)
|
assert.Equal(t, "", *ms.Get().ServiceSettings.SiteURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("desanitization required", func(t *testing.T) {
|
t.Run("desanitization required", func(t *testing.T) {
|
||||||
@@ -171,7 +171,7 @@ func TestMemoryStoreSet(t *testing.T) {
|
|||||||
assert.EqualError(t, err, "new configuration is invalid: Config.IsValid: model.config.is_valid.site_url.app_error, ")
|
assert.EqualError(t, err, "new configuration is invalid: Config.IsValid: model.config.is_valid.site_url.app_error, ")
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *ms.Get().ServiceSettings.SiteURL)
|
assert.Equal(t, "", *ms.Get().ServiceSettings.SiteURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("read-only ignored", func(t *testing.T) {
|
t.Run("read-only ignored", func(t *testing.T) {
|
||||||
|
|||||||
100
model/config.go
100
model/config.go
@@ -46,6 +46,7 @@ const (
|
|||||||
|
|
||||||
GENERIC_NO_CHANNEL_NOTIFICATION = "generic_no_channel"
|
GENERIC_NO_CHANNEL_NOTIFICATION = "generic_no_channel"
|
||||||
GENERIC_NOTIFICATION = "generic"
|
GENERIC_NOTIFICATION = "generic"
|
||||||
|
GENERIC_NOTIFICATION_SERVER = "https://push-test.mattermost.com"
|
||||||
FULL_NOTIFICATION = "full"
|
FULL_NOTIFICATION = "full"
|
||||||
|
|
||||||
DIRECT_MESSAGE_ANY = "any"
|
DIRECT_MESSAGE_ANY = "any"
|
||||||
@@ -184,6 +185,16 @@ const (
|
|||||||
|
|
||||||
IMAGE_PROXY_TYPE_LOCAL = "local"
|
IMAGE_PROXY_TYPE_LOCAL = "local"
|
||||||
IMAGE_PROXY_TYPE_ATMOS_CAMO = "atmos/camo"
|
IMAGE_PROXY_TYPE_ATMOS_CAMO = "atmos/camo"
|
||||||
|
|
||||||
|
GOOGLE_SETTINGS_DEFAULT_SCOPE = "profile email"
|
||||||
|
GOOGLE_SETTINGS_DEFAULT_AUTH_ENDPOINT = "https://accounts.google.com/o/oauth2/v2/auth"
|
||||||
|
GOOGLE_SETTINGS_DEFAULT_TOKEN_ENDPOINT = "https://www.googleapis.com/oauth2/v4/token"
|
||||||
|
GOOGLE_SETTINGS_DEFAULT_USER_API_ENDPOINT = "https://people.googleapis.com/v1/people/me?personFields=names,emailAddresses,nicknames,metadata"
|
||||||
|
|
||||||
|
OFFICE365_SETTINGS_DEFAULT_SCOPE = "User.Read"
|
||||||
|
OFFICE365_SETTINGS_DEFAULT_AUTH_ENDPOINT = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
|
||||||
|
OFFICE365_SETTINGS_DEFAULT_TOKEN_ENDPOINT = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
|
||||||
|
OFFICE365_SETTINGS_DEFAULT_USER_API_ENDPOINT = "https://graph.microsoft.com/v1.0/me"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ServerTLSSupportedCiphers = map[string]uint16{
|
var ServerTLSSupportedCiphers = map[string]uint16{
|
||||||
@@ -297,7 +308,7 @@ type ServiceSettings struct {
|
|||||||
EnableBotAccountCreation *bool
|
EnableBotAccountCreation *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServiceSettings) SetDefaults() {
|
func (s *ServiceSettings) SetDefaults(isUpdate bool) {
|
||||||
if s.EnableEmailInvitations == nil {
|
if s.EnableEmailInvitations == nil {
|
||||||
// If the site URL is also not present then assume this is a clean install
|
// If the site URL is also not present then assume this is a clean install
|
||||||
if s.SiteURL == nil {
|
if s.SiteURL == nil {
|
||||||
@@ -308,7 +319,11 @@ func (s *ServiceSettings) SetDefaults() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if s.SiteURL == nil {
|
if s.SiteURL == nil {
|
||||||
s.SiteURL = NewString(SERVICE_SETTINGS_DEFAULT_SITE_URL)
|
if s.EnableDeveloper != nil && *s.EnableDeveloper {
|
||||||
|
s.SiteURL = NewString(SERVICE_SETTINGS_DEFAULT_SITE_URL)
|
||||||
|
} else {
|
||||||
|
s.SiteURL = NewString("")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.WebsocketURL == nil {
|
if s.WebsocketURL == nil {
|
||||||
@@ -435,8 +450,14 @@ func (s *ServiceSettings) SetDefaults() {
|
|||||||
s.Forward80To443 = NewBool(false)
|
s.Forward80To443 = NewBool(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.TrustedProxyIPHeader == nil {
|
if isUpdate {
|
||||||
s.TrustedProxyIPHeader = []string{HEADER_FORWARDED, HEADER_REAL_IP}
|
// When updating an existing configuration, ensure that defaults are set.
|
||||||
|
if s.TrustedProxyIPHeader == nil {
|
||||||
|
s.TrustedProxyIPHeader = []string{HEADER_FORWARDED, HEADER_REAL_IP}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// When generating a blank configuration, leave the list empty.
|
||||||
|
s.TrustedProxyIPHeader = []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.TimeBetweenUserTypingUpdatesMilliseconds == nil {
|
if s.TimeBetweenUserTypingUpdatesMilliseconds == nil {
|
||||||
@@ -627,7 +648,7 @@ func (s *ServiceSettings) SetDefaults() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if s.DisableLegacyMFA == nil {
|
if s.DisableLegacyMFA == nil {
|
||||||
s.DisableLegacyMFA = NewBool(false)
|
s.DisableLegacyMFA = NewBool(!isUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.ExperimentalLdapGroupSync == nil {
|
if s.ExperimentalLdapGroupSync == nil {
|
||||||
@@ -782,7 +803,7 @@ type SSOSettings struct {
|
|||||||
UserApiEndpoint *string
|
UserApiEndpoint *string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SSOSettings) setDefaults() {
|
func (s *SSOSettings) setDefaults(scope, authEndpoint, tokenEndpoint, userApiEndpoint string) {
|
||||||
if s.Enable == nil {
|
if s.Enable == nil {
|
||||||
s.Enable = NewBool(false)
|
s.Enable = NewBool(false)
|
||||||
}
|
}
|
||||||
@@ -796,19 +817,19 @@ func (s *SSOSettings) setDefaults() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if s.Scope == nil {
|
if s.Scope == nil {
|
||||||
s.Scope = NewString("")
|
s.Scope = NewString(scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.AuthEndpoint == nil {
|
if s.AuthEndpoint == nil {
|
||||||
s.AuthEndpoint = NewString("")
|
s.AuthEndpoint = NewString(authEndpoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.TokenEndpoint == nil {
|
if s.TokenEndpoint == nil {
|
||||||
s.TokenEndpoint = NewString("")
|
s.TokenEndpoint = NewString(tokenEndpoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.UserApiEndpoint == nil {
|
if s.UserApiEndpoint == nil {
|
||||||
s.UserApiEndpoint = NewString("")
|
s.UserApiEndpoint = NewString(userApiEndpoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -825,7 +846,7 @@ type SqlSettings struct {
|
|||||||
QueryTimeout *int `restricted:"true"`
|
QueryTimeout *int `restricted:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlSettings) SetDefaults() {
|
func (s *SqlSettings) SetDefaults(isUpdate bool) {
|
||||||
if s.DriverName == nil {
|
if s.DriverName == nil {
|
||||||
s.DriverName = NewString(DATABASE_DRIVER_MYSQL)
|
s.DriverName = NewString(DATABASE_DRIVER_MYSQL)
|
||||||
}
|
}
|
||||||
@@ -842,8 +863,14 @@ func (s *SqlSettings) SetDefaults() {
|
|||||||
s.DataSourceSearchReplicas = []string{}
|
s.DataSourceSearchReplicas = []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.AtRestEncryptKey == nil || len(*s.AtRestEncryptKey) == 0 {
|
if isUpdate {
|
||||||
s.AtRestEncryptKey = NewString(NewRandomString(32))
|
// When updating an existing configuration, ensure an encryption key has been specified.
|
||||||
|
if s.AtRestEncryptKey == nil || len(*s.AtRestEncryptKey) == 0 {
|
||||||
|
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 {
|
if s.MaxIdleConns == nil {
|
||||||
@@ -1008,7 +1035,7 @@ type FileSettings struct {
|
|||||||
AmazonS3Trace *bool `restricted:"true"`
|
AmazonS3Trace *bool `restricted:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *FileSettings) SetDefaults() {
|
func (s *FileSettings) SetDefaults(isUpdate bool) {
|
||||||
if s.EnableFileAttachments == nil {
|
if s.EnableFileAttachments == nil {
|
||||||
s.EnableFileAttachments = NewBool(true)
|
s.EnableFileAttachments = NewBool(true)
|
||||||
}
|
}
|
||||||
@@ -1037,8 +1064,14 @@ func (s *FileSettings) SetDefaults() {
|
|||||||
s.EnablePublicLink = NewBool(false)
|
s.EnablePublicLink = NewBool(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.PublicLinkSalt == nil || len(*s.PublicLinkSalt) == 0 {
|
if isUpdate {
|
||||||
s.PublicLinkSalt = NewString(NewRandomString(32))
|
// When updating an existing configuration, ensure link salt has been specified.
|
||||||
|
if s.PublicLinkSalt == nil || len(*s.PublicLinkSalt) == 0 {
|
||||||
|
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 {
|
if s.InitialFont == nil {
|
||||||
@@ -1116,7 +1149,7 @@ type EmailSettings struct {
|
|||||||
LoginButtonTextColor *string
|
LoginButtonTextColor *string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *EmailSettings) SetDefaults() {
|
func (s *EmailSettings) SetDefaults(isUpdate bool) {
|
||||||
if s.EnableSignUpWithEmail == nil {
|
if s.EnableSignUpWithEmail == nil {
|
||||||
s.EnableSignUpWithEmail = NewBool(true)
|
s.EnableSignUpWithEmail = NewBool(true)
|
||||||
}
|
}
|
||||||
@@ -1186,11 +1219,15 @@ func (s *EmailSettings) SetDefaults() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if s.SendPushNotifications == nil {
|
if s.SendPushNotifications == nil {
|
||||||
s.SendPushNotifications = NewBool(false)
|
s.SendPushNotifications = NewBool(!isUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.PushNotificationServer == nil {
|
if s.PushNotificationServer == nil {
|
||||||
s.PushNotificationServer = NewString("")
|
if isUpdate {
|
||||||
|
s.PushNotificationServer = NewString("")
|
||||||
|
} else {
|
||||||
|
s.PushNotificationServer = NewString(GENERIC_NOTIFICATION_SERVER)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.PushNotificationContents == nil {
|
if s.PushNotificationContents == nil {
|
||||||
@@ -2364,7 +2401,14 @@ func ConfigFromJson(data io.Reader) *Config {
|
|||||||
return 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() {
|
func (o *Config) SetDefaults() {
|
||||||
|
isUpdate := o.isUpdate()
|
||||||
|
|
||||||
o.LdapSettings.SetDefaults()
|
o.LdapSettings.SetDefaults()
|
||||||
o.SamlSettings.SetDefaults()
|
o.SamlSettings.SetDefaults()
|
||||||
|
|
||||||
@@ -2376,14 +2420,14 @@ func (o *Config) SetDefaults() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
o.SqlSettings.SetDefaults()
|
o.SqlSettings.SetDefaults(isUpdate)
|
||||||
o.FileSettings.SetDefaults()
|
o.FileSettings.SetDefaults(isUpdate)
|
||||||
o.EmailSettings.SetDefaults()
|
o.EmailSettings.SetDefaults(isUpdate)
|
||||||
o.PrivacySettings.setDefaults()
|
o.PrivacySettings.setDefaults()
|
||||||
o.Office365Settings.setDefaults()
|
o.Office365Settings.setDefaults(OFFICE365_SETTINGS_DEFAULT_SCOPE, OFFICE365_SETTINGS_DEFAULT_AUTH_ENDPOINT, OFFICE365_SETTINGS_DEFAULT_TOKEN_ENDPOINT, OFFICE365_SETTINGS_DEFAULT_USER_API_ENDPOINT)
|
||||||
o.GitLabSettings.setDefaults()
|
o.GitLabSettings.setDefaults("", "", "", "")
|
||||||
o.GoogleSettings.setDefaults()
|
o.GoogleSettings.setDefaults(GOOGLE_SETTINGS_DEFAULT_SCOPE, GOOGLE_SETTINGS_DEFAULT_AUTH_ENDPOINT, GOOGLE_SETTINGS_DEFAULT_TOKEN_ENDPOINT, GOOGLE_SETTINGS_DEFAULT_USER_API_ENDPOINT)
|
||||||
o.ServiceSettings.SetDefaults()
|
o.ServiceSettings.SetDefaults(isUpdate)
|
||||||
o.PasswordSettings.SetDefaults()
|
o.PasswordSettings.SetDefaults()
|
||||||
o.TeamSettings.SetDefaults()
|
o.TeamSettings.SetDefaults()
|
||||||
o.MetricsSettings.SetDefaults()
|
o.MetricsSettings.SetDefaults()
|
||||||
@@ -2517,7 +2561,7 @@ func (ts *TeamSettings) isValid() *AppError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ss *SqlSettings) isValid() *AppError {
|
func (ss *SqlSettings) isValid() *AppError {
|
||||||
if len(*ss.AtRestEncryptKey) < 32 {
|
if *ss.AtRestEncryptKey != "" && len(*ss.AtRestEncryptKey) < 32 {
|
||||||
return NewAppError("Config.IsValid", "model.config.is_valid.encrypt_sql.app_error", nil, "", http.StatusBadRequest)
|
return NewAppError("Config.IsValid", "model.config.is_valid.encrypt_sql.app_error", nil, "", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2557,7 +2601,7 @@ func (fs *FileSettings) isValid() *AppError {
|
|||||||
return NewAppError("Config.IsValid", "model.config.is_valid.file_driver.app_error", nil, "", http.StatusBadRequest)
|
return NewAppError("Config.IsValid", "model.config.is_valid.file_driver.app_error", nil, "", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(*fs.PublicLinkSalt) < 32 {
|
if *fs.PublicLinkSalt != "" && len(*fs.PublicLinkSalt) < 32 {
|
||||||
return NewAppError("Config.IsValid", "model.config.is_valid.file_salt.app_error", nil, "", http.StatusBadRequest)
|
return NewAppError("Config.IsValid", "model.config.is_valid.file_salt.app_error", nil, "", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -593,7 +593,7 @@ func TestListenAddressIsValidated(t *testing.T) {
|
|||||||
ss := &ServiceSettings{
|
ss := &ServiceSettings{
|
||||||
ListenAddress: NewString(key),
|
ListenAddress: NewString(key),
|
||||||
}
|
}
|
||||||
ss.SetDefaults()
|
ss.SetDefaults(true)
|
||||||
if expected {
|
if expected {
|
||||||
require.Nil(t, ss.isValid(), fmt.Sprintf("Got an error from '%v'.", key))
|
require.Nil(t, ss.isValid(), fmt.Sprintf("Got an error from '%v'.", key))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ func CheckMandatoryS3Fields(settings *model.FileSettings) *model.AppError {
|
|||||||
|
|
||||||
// if S3 endpoint is not set call the set defaults to set that
|
// if S3 endpoint is not set call the set defaults to set that
|
||||||
if settings.AmazonS3Endpoint == nil || len(*settings.AmazonS3Endpoint) == 0 {
|
if settings.AmazonS3Endpoint == nil || len(*settings.AmazonS3Endpoint) == 0 {
|
||||||
settings.SetDefaults()
|
settings.SetDefaults(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -141,16 +141,10 @@ func setupConfig(configDir string) error {
|
|||||||
return errors.Wrapf(err, "failed to create config directory %s", configDir)
|
return errors.Wrapf(err, "failed to create config directory %s", configDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultJson := path.Join(configDir, "default.json")
|
|
||||||
err = ioutil.WriteFile(defaultJson, []byte(config.ToJson()), 0644)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to write config to %s", defaultJson)
|
|
||||||
}
|
|
||||||
|
|
||||||
configJson := path.Join(configDir, "config.json")
|
configJson := path.Join(configDir, "config.json")
|
||||||
err = utils.CopyFile(defaultJson, configJson)
|
err = ioutil.WriteFile(configJson, []byte(config.ToJson()), 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "failed to copy file %s to %s", defaultJson, configJson)
|
return errors.Wrapf(err, "failed to write config to %s", configJson)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user