Refactoring cfg refs and load / save functions (#7749)

* refactoring cfg refs and load / save functions

* improve error output
Этот коммит содержится в:
Chris
2017-10-31 09:39:31 -05:00
коммит произвёл Joram Wilander
родитель b446d0aa0a
Коммит ce2b2be5de
28 изменённых файлов: 250 добавлений и 247 удалений

Просмотреть файл

@@ -10,7 +10,6 @@ import (
"github.com/mattermost/mattermost-server/model" "github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/store" "github.com/mattermost/mattermost-server/store"
"github.com/mattermost/mattermost-server/utils"
) )
func TestGetLogs(t *testing.T) { func TestGetLogs(t *testing.T) {
@@ -139,13 +138,13 @@ func TestSaveConfig(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin() th := Setup().InitBasic().InitSystemAdmin()
defer th.TearDown() defer th.TearDown()
if _, err := th.BasicClient.SaveConfig(utils.Cfg); err == nil { if _, err := th.BasicClient.SaveConfig(th.App.Config()); err == nil {
t.Fatal("Shouldn't have permissions") t.Fatal("Shouldn't have permissions")
} }
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = false }) th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = false })
if _, err := th.SystemAdminClient.SaveConfig(utils.Cfg); err != nil { if _, err := th.SystemAdminClient.SaveConfig(th.App.Config()); err != nil {
t.Fatal(err) t.Fatal(err)
} }

Просмотреть файл

@@ -16,20 +16,15 @@ import (
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
flag.Parse() flag.Parse()
utils.TranslationsPreInit()
// In the case where a dev just wants to run a single test, it's faster to just use the default // In the case where a dev just wants to run a single test, it's faster to just use the default
// store. // store.
if filter := flag.Lookup("test.run").Value.String(); filter != "" && filter != "." { if filter := flag.Lookup("test.run").Value.String(); filter != "" && filter != "." {
utils.TranslationsPreInit()
utils.LoadConfig("config.json")
l4g.Info("-test.run used, not creating temporary containers") l4g.Info("-test.run used, not creating temporary containers")
os.Exit(m.Run()) os.Exit(m.Run())
} }
utils.TranslationsPreInit()
utils.LoadConfig("config.json")
utils.InitTranslations(utils.Cfg.LocalizationSettings)
status := 0 status := 0
container, settings, err := storetest.NewMySQLContainer() container, settings, err := storetest.NewMySQLContainer()

Просмотреть файл

@@ -64,12 +64,6 @@ func StopTestStore() {
} }
func setupTestHelper(enterprise bool) *TestHelper { func setupTestHelper(enterprise bool) *TestHelper {
if utils.T == nil {
utils.TranslationsPreInit()
}
utils.LoadConfig("config.json")
utils.InitTranslations(utils.Cfg.LocalizationSettings)
var options []app.Option var options []app.Option
if testStore != nil { if testStore != nil {
options = append(options, app.StoreOverride(testStore)) options = append(options, app.StoreOverride(testStore))
@@ -80,9 +74,11 @@ func setupTestHelper(enterprise bool) *TestHelper {
} }
th.originalConfig = th.App.Config().Clone() th.originalConfig = th.App.Config().Clone()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.MaxUsersPerTeam = 50 }) th.App.UpdateConfig(func(cfg *model.Config) {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.RateLimitSettings.Enable = false }) *cfg.TeamSettings.MaxUsersPerTeam = 50
th.App.UpdateConfig(func(cfg *model.Config) { cfg.EmailSettings.SendEmailNotifications = true }) *cfg.RateLimitSettings.Enable = false
cfg.EmailSettings.SendEmailNotifications = true
})
utils.DisableDebugLogForTest() utils.DisableDebugLogForTest()
prevListenAddress := *th.App.Config().ServiceSettings.ListenAddress prevListenAddress := *th.App.Config().ServiceSettings.ListenAddress
if testStore != nil { if testStore != nil {

Просмотреть файл

@@ -517,7 +517,7 @@ func TestGetPublicFileOld(t *testing.T) {
// reconstruct old style of link // reconstruct old style of link
siteURL := fmt.Sprintf("http://localhost:%v", th.App.Srv.ListenAddr.Port) siteURL := fmt.Sprintf("http://localhost:%v", th.App.Srv.ListenAddr.Port)
link := generatePublicLinkOld(siteURL, th.BasicTeam.Id, channel.Id, th.BasicUser.Id, fileId+"/test.png") link := generatePublicLinkOld(siteURL, th.BasicTeam.Id, channel.Id, th.BasicUser.Id, fileId+"/test.png", *th.App.Config().FileSettings.PublicLinkSalt)
// Wait a bit for files to ready // Wait a bit for files to ready
time.Sleep(2 * time.Second) time.Sleep(2 * time.Second)
@@ -553,8 +553,8 @@ func TestGetPublicFileOld(t *testing.T) {
} }
} }
func generatePublicLinkOld(siteURL, teamId, channelId, userId, filename string) string { func generatePublicLinkOld(siteURL, teamId, channelId, userId, filename, salt string) string {
hash := app.GeneratePublicLinkHash(filename, *utils.Cfg.FileSettings.PublicLinkSalt) hash := app.GeneratePublicLinkHash(filename, salt)
return fmt.Sprintf("%s%s/public/files/get/%s/%s/%s/%s?h=%s", siteURL, model.API_URL_SUFFIX_V3, teamId, channelId, userId, filename, hash) return fmt.Sprintf("%s%s/public/files/get/%s/%s/%s/%s?h=%s", siteURL, model.API_URL_SUFFIX_V3, teamId, channelId, userId, filename, hash)
} }

Просмотреть файл

@@ -326,7 +326,7 @@ func getUser(c *Context, w http.ResponseWriter, r *http.Request) {
if c.HandleEtag(etag, "Get User", w, r) { if c.HandleEtag(etag, "Get User", w, r) {
return return
} else { } else {
app.SanitizeProfile(user, c.IsSystemAdmin()) c.App.SanitizeProfile(user, c.IsSystemAdmin())
w.Header().Set(model.HEADER_ETAG_SERVER, etag) w.Header().Set(model.HEADER_ETAG_SERVER, etag)
w.Write([]byte(user.ToJson())) w.Write([]byte(user.ToJson()))
return return
@@ -560,7 +560,7 @@ func getProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
} }
var img []byte var img []byte
img, readFailed, err = app.GetProfileImage(user) img, readFailed, err = c.App.GetProfileImage(user)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return

Просмотреть файл

@@ -643,7 +643,7 @@ func TestUserCreateImage(t *testing.T) {
Client := th.BasicClient Client := th.BasicClient
b, err := app.CreateProfileImage("Corey Hulen", "eo1zkdr96pdj98pjmq8zy35wba") b, err := app.CreateProfileImage("Corey Hulen", "eo1zkdr96pdj98pjmq8zy35wba", th.App.Config().FileSettings.InitialFont)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

Просмотреть файл

@@ -16,20 +16,15 @@ import (
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
flag.Parse() flag.Parse()
utils.TranslationsPreInit()
// In the case where a dev just wants to run a single test, it's faster to just use the default // In the case where a dev just wants to run a single test, it's faster to just use the default
// store. // store.
if filter := flag.Lookup("test.run").Value.String(); filter != "" && filter != "." { if filter := flag.Lookup("test.run").Value.String(); filter != "" && filter != "." {
utils.TranslationsPreInit()
utils.LoadConfig("config.json")
l4g.Info("-test.run used, not creating temporary containers") l4g.Info("-test.run used, not creating temporary containers")
os.Exit(m.Run()) os.Exit(m.Run())
} }
utils.TranslationsPreInit()
utils.LoadConfig("config.json")
utils.InitTranslations(utils.Cfg.LocalizationSettings)
status := 0 status := 0
container, settings, err := storetest.NewMySQLContainer() container, settings, err := storetest.NewMySQLContainer()

Просмотреть файл

@@ -73,12 +73,6 @@ func StopTestStore() {
} }
func setupTestHelper(enterprise bool) *TestHelper { func setupTestHelper(enterprise bool) *TestHelper {
if utils.T == nil {
utils.TranslationsPreInit()
}
utils.LoadConfig("config.json")
utils.InitTranslations(utils.Cfg.LocalizationSettings)
var options []app.Option var options []app.Option
if testStore != nil { if testStore != nil {
options = append(options, app.StoreOverride(testStore)) options = append(options, app.StoreOverride(testStore))
@@ -89,9 +83,11 @@ func setupTestHelper(enterprise bool) *TestHelper {
} }
th.originalConfig = th.App.Config().Clone() th.originalConfig = th.App.Config().Clone()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.MaxUsersPerTeam = 50 }) th.App.UpdateConfig(func(cfg *model.Config) {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.RateLimitSettings.Enable = false }) *cfg.TeamSettings.MaxUsersPerTeam = 50
th.App.UpdateConfig(func(cfg *model.Config) { cfg.EmailSettings.SendEmailNotifications = true }) *cfg.RateLimitSettings.Enable = false
cfg.EmailSettings.SendEmailNotifications = true
})
utils.DisableDebugLogForTest() utils.DisableDebugLogForTest()
prevListenAddress := *th.App.Config().ServiceSettings.ListenAddress prevListenAddress := *th.App.Config().ServiceSettings.ListenAddress
if testStore != nil { if testStore != nil {

Просмотреть файл

@@ -40,8 +40,8 @@ func getSamlMetadata(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(metadata)) w.Write([]byte(metadata))
} }
func parseSamlCertificateRequest(r *http.Request) (*multipart.FileHeader, *model.AppError) { func parseSamlCertificateRequest(r *http.Request, maxFileSize int64) (*multipart.FileHeader, *model.AppError) {
err := r.ParseMultipartForm(*utils.Cfg.FileSettings.MaxFileSize) err := r.ParseMultipartForm(maxFileSize)
if err != nil { if err != nil {
return nil, model.NewAppError("addSamlCertificate", "api.admin.add_certificate.no_file.app_error", nil, err.Error(), http.StatusBadRequest) return nil, model.NewAppError("addSamlCertificate", "api.admin.add_certificate.no_file.app_error", nil, err.Error(), http.StatusBadRequest)
} }
@@ -66,7 +66,7 @@ func addSamlPublicCertificate(c *Context, w http.ResponseWriter, r *http.Request
return return
} }
fileData, err := parseSamlCertificateRequest(r) fileData, err := parseSamlCertificateRequest(r, *c.App.Config().FileSettings.MaxFileSize)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return
@@ -85,7 +85,7 @@ func addSamlPrivateCertificate(c *Context, w http.ResponseWriter, r *http.Reques
return return
} }
fileData, err := parseSamlCertificateRequest(r) fileData, err := parseSamlCertificateRequest(r, *c.App.Config().FileSettings.MaxFileSize)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return
@@ -104,7 +104,7 @@ func addSamlIdpCertificate(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
fileData, err := parseSamlCertificateRequest(r) fileData, err := parseSamlCertificateRequest(r, *c.App.Config().FileSettings.MaxFileSize)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return

Просмотреть файл

@@ -122,7 +122,7 @@ func getUser(c *Context, w http.ResponseWriter, r *http.Request) {
if c.Session.UserId == user.Id { if c.Session.UserId == user.Id {
user.Sanitize(map[string]bool{}) user.Sanitize(map[string]bool{})
} else { } else {
app.SanitizeProfile(user, c.IsSystemAdmin()) c.App.SanitizeProfile(user, c.IsSystemAdmin())
} }
c.App.UpdateLastActivityAtIfNeeded(c.Session) c.App.UpdateLastActivityAtIfNeeded(c.Session)
w.Header().Set(model.HEADER_ETAG_SERVER, etag) w.Header().Set(model.HEADER_ETAG_SERVER, etag)
@@ -152,7 +152,7 @@ func getUserByUsername(c *Context, w http.ResponseWriter, r *http.Request) {
if c.HandleEtag(etag, "Get User", w, r) { if c.HandleEtag(etag, "Get User", w, r) {
return return
} else { } else {
app.SanitizeProfile(user, c.IsSystemAdmin()) c.App.SanitizeProfile(user, c.IsSystemAdmin())
w.Header().Set(model.HEADER_ETAG_SERVER, etag) w.Header().Set(model.HEADER_ETAG_SERVER, etag)
w.Write([]byte(user.ToJson())) w.Write([]byte(user.ToJson()))
return return
@@ -180,7 +180,7 @@ func getUserByEmail(c *Context, w http.ResponseWriter, r *http.Request) {
if c.HandleEtag(etag, "Get User", w, r) { if c.HandleEtag(etag, "Get User", w, r) {
return return
} else { } else {
app.SanitizeProfile(user, c.IsSystemAdmin()) c.App.SanitizeProfile(user, c.IsSystemAdmin())
w.Header().Set(model.HEADER_ETAG_SERVER, etag) w.Header().Set(model.HEADER_ETAG_SERVER, etag)
w.Write([]byte(user.ToJson())) w.Write([]byte(user.ToJson()))
return return
@@ -208,7 +208,7 @@ func getProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
} }
var img []byte var img []byte
img, readFailed, err := app.GetProfileImage(user) img, readFailed, err := c.App.GetProfileImage(user)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return

Просмотреть файл

@@ -131,14 +131,6 @@ func (a *App) GetConfig() *model.Config {
return cfg return cfg
} }
func (a *App) ReloadConfig() {
debug.FreeOSMemory()
utils.LoadConfig(a.ConfigFileName())
// start/restart email batching job if necessary
a.InitEmailBatching()
}
func (a *App) SaveConfig(cfg *model.Config, sendConfigChangeClusterMessage bool) *model.AppError { func (a *App) SaveConfig(cfg *model.Config, sendConfigChangeClusterMessage bool) *model.AppError {
oldCfg := a.Config() oldCfg := a.Config()
cfg.SetDefaults() cfg.SetDefaults()
@@ -157,8 +149,11 @@ func (a *App) SaveConfig(cfg *model.Config, sendConfigChangeClusterMessage bool)
} }
utils.DisableConfigWatch() utils.DisableConfigWatch()
utils.SaveConfig(a.ConfigFileName(), cfg) a.UpdateConfig(func(update *model.Config) {
utils.LoadConfig(a.ConfigFileName()) *update = *cfg
})
a.PersistConfig()
a.ReloadConfig()
utils.EnableConfigWatch() utils.EnableConfigWatch()
if a.Metrics != nil { if a.Metrics != nil {

Просмотреть файл

@@ -251,7 +251,7 @@ func (a *App) GetRecentlyActiveUsersForTeamPage(teamId string, page, perPage int
users = result.Data.([]*model.User) users = result.Data.([]*model.User)
} }
return sanitizeProfiles(users, asAdmin), nil return a.sanitizeProfiles(users, asAdmin), nil
} }
func (a *App) GetNewUsersForTeamPage(teamId string, page, perPage int, asAdmin bool) ([]*model.User, *model.AppError) { func (a *App) GetNewUsersForTeamPage(teamId string, page, perPage int, asAdmin bool) ([]*model.User, *model.AppError) {
@@ -262,5 +262,5 @@ func (a *App) GetNewUsersForTeamPage(teamId string, page, perPage int, asAdmin b
users = result.Data.([]*model.User) users = result.Data.([]*model.User)
} }
return sanitizeProfiles(users, asAdmin), nil return a.sanitizeProfiles(users, asAdmin), nil
} }

Просмотреть файл

@@ -5,6 +5,7 @@ package app
import ( import (
"net/http" "net/http"
"runtime/debug"
"sync/atomic" "sync/atomic"
l4g "github.com/alecthomas/log4go" l4g "github.com/alecthomas/log4go"
@@ -62,6 +63,12 @@ func New(options ...Option) *App {
panic("Only one App should exist at a time. Did you forget to call Shutdown()?") panic("Only one App should exist at a time. Did you forget to call Shutdown()?")
} }
if utils.T == nil {
utils.TranslationsPreInit()
}
utils.LoadGlobalConfig("config.json")
utils.InitTranslations(utils.Cfg.LocalizationSettings)
l4g.Info(utils.T("api.server.new_server.init.info")) l4g.Info(utils.T("api.server.new_server.init.info"))
app := &App{ app := &App{
@@ -246,6 +253,18 @@ func (a *App) UpdateConfig(f func(*model.Config)) {
f(utils.Cfg) f(utils.Cfg)
} }
func (a *App) PersistConfig() {
utils.SaveConfig(a.ConfigFileName(), a.Config())
}
func (a *App) ReloadConfig() {
debug.FreeOSMemory()
utils.LoadGlobalConfig(a.ConfigFileName())
// start/restart email batching job if necessary
a.InitEmailBatching()
}
func (a *App) ConfigFileName() string { func (a *App) ConfigFileName() string {
return utils.CfgFileName return utils.CfgFileName
} }

Просмотреть файл

@@ -16,20 +16,15 @@ import (
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
flag.Parse() flag.Parse()
utils.TranslationsPreInit()
// In the case where a dev just wants to run a single test, it's faster to just use the default // In the case where a dev just wants to run a single test, it's faster to just use the default
// store. // store.
if filter := flag.Lookup("test.run").Value.String(); filter != "" && filter != "." { if filter := flag.Lookup("test.run").Value.String(); filter != "" && filter != "." {
utils.TranslationsPreInit()
utils.LoadConfig("config.json")
l4g.Info("-test.run used, not creating temporary containers") l4g.Info("-test.run used, not creating temporary containers")
os.Exit(m.Run()) os.Exit(m.Run())
} }
utils.TranslationsPreInit()
utils.LoadConfig("config.json")
utils.InitTranslations(utils.Cfg.LocalizationSettings)
status := 0 status := 0
container, settings, err := storetest.NewMySQLContainer() container, settings, err := storetest.NewMySQLContainer()

Просмотреть файл

@@ -48,12 +48,6 @@ func StopTestStore() {
} }
func setupTestHelper(enterprise bool) *TestHelper { func setupTestHelper(enterprise bool) *TestHelper {
if utils.T == nil {
utils.TranslationsPreInit()
}
utils.LoadConfig("config.json")
utils.InitTranslations(utils.Cfg.LocalizationSettings)
var options []Option var options []Option
if testStore != nil { if testStore != nil {
options = append(options, StoreOverride(testStore)) options = append(options, StoreOverride(testStore))
@@ -63,8 +57,8 @@ func setupTestHelper(enterprise bool) *TestHelper {
App: New(options...), App: New(options...),
} }
*utils.Cfg.TeamSettings.MaxUsersPerTeam = 50 th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.MaxUsersPerTeam = 50 })
*utils.Cfg.RateLimitSettings.Enable = false th.App.UpdateConfig(func(cfg *model.Config) { *cfg.RateLimitSettings.Enable = false })
utils.DisableDebugLogForTest() utils.DisableDebugLogForTest()
prevListenAddress := *th.App.Config().ServiceSettings.ListenAddress prevListenAddress := *th.App.Config().ServiceSettings.ListenAddress
if testStore != nil { if testStore != nil {
@@ -76,7 +70,7 @@ func setupTestHelper(enterprise bool) *TestHelper {
utils.EnableDebugLogForTest() utils.EnableDebugLogForTest()
th.App.Srv.Store.MarkSystemRanUnitTests() th.App.Srv.Store.MarkSystemRanUnitTests()
*utils.Cfg.TeamSettings.EnableOpenServer = true th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = true })
utils.SetIsLicensed(enterprise) utils.SetIsLicensed(enterprise)
if enterprise { if enterprise {

Просмотреть файл

@@ -471,10 +471,11 @@ func (a *App) EnablePlugin(id string) *model.AppError {
return model.NewAppError("EnablePlugin", "app.plugin.not_installed.app_error", nil, "", http.StatusBadRequest) return model.NewAppError("EnablePlugin", "app.plugin.not_installed.app_error", nil, "", http.StatusBadRequest)
} }
cfg := a.Config() a.UpdateConfig(func(cfg *model.Config) {
cfg.PluginSettings.PluginStates[id] = &model.PluginState{Enable: true} cfg.PluginSettings.PluginStates[id] = &model.PluginState{Enable: true}
})
if err := a.SaveConfig(cfg, true); err != nil { if err := a.SaveConfig(a.Config(), true); err != nil {
return model.NewAppError("EnablePlugin", "app.plugin.config.app_error", nil, err.Error(), http.StatusInternalServerError) return model.NewAppError("EnablePlugin", "app.plugin.config.app_error", nil, err.Error(), http.StatusInternalServerError)
} }
@@ -504,10 +505,11 @@ func (a *App) DisablePlugin(id string) *model.AppError {
return model.NewAppError("DisablePlugin", "app.plugin.not_installed.app_error", nil, "", http.StatusBadRequest) return model.NewAppError("DisablePlugin", "app.plugin.not_installed.app_error", nil, "", http.StatusBadRequest)
} }
cfg := a.Config() a.UpdateConfig(func(cfg *model.Config) {
cfg.PluginSettings.PluginStates[id] = &model.PluginState{Enable: false} cfg.PluginSettings.PluginStates[id] = &model.PluginState{Enable: false}
})
if err := a.SaveConfig(cfg, true); err != nil { if err := a.SaveConfig(a.Config(), true); err != nil {
return model.NewAppError("DisablePlugin", "app.plugin.config.app_error", nil, err.Error(), http.StatusInternalServerError) return model.NewAppError("DisablePlugin", "app.plugin.config.app_error", nil, err.Error(), http.StatusInternalServerError)
} }

Просмотреть файл

@@ -15,7 +15,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/model" "github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/utils"
) )
func TestUpdatePostEditAt(t *testing.T) { func TestUpdatePostEditAt(t *testing.T) {
@@ -82,11 +81,9 @@ func TestPostAction(t *testing.T) {
th := Setup().InitBasic() th := Setup().InitBasic()
defer th.TearDown() defer th.TearDown()
allowedInternalConnections := *utils.Cfg.ServiceSettings.AllowedUntrustedInternalConnections th.App.UpdateConfig(func(cfg *model.Config) {
defer func() { *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost 127.0.0.1"
utils.Cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections })
}()
*utils.Cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost 127.0.0.1"
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var request model.PostActionIntegrationRequest var request model.PostActionIntegrationRequest

Просмотреть файл

@@ -65,7 +65,7 @@ func (a *App) AddSamlPublicCertificate(fileData *multipart.FileHeader) *model.Ap
} }
a.UpdateConfig(func(dest *model.Config) { *dest = *cfg }) a.UpdateConfig(func(dest *model.Config) { *dest = *cfg })
utils.SaveConfig(a.ConfigFileName(), cfg) a.PersistConfig()
return nil return nil
} }
@@ -83,7 +83,7 @@ func (a *App) AddSamlPrivateCertificate(fileData *multipart.FileHeader) *model.A
} }
a.UpdateConfig(func(dest *model.Config) { *dest = *cfg }) a.UpdateConfig(func(dest *model.Config) { *dest = *cfg })
utils.SaveConfig(a.ConfigFileName(), cfg) a.PersistConfig()
return nil return nil
} }
@@ -101,7 +101,7 @@ func (a *App) AddSamlIdpCertificate(fileData *multipart.FileHeader) *model.AppEr
} }
a.UpdateConfig(func(dest *model.Config) { *dest = *cfg }) a.UpdateConfig(func(dest *model.Config) { *dest = *cfg })
utils.SaveConfig(a.ConfigFileName(), cfg) a.PersistConfig()
return nil return nil
} }
@@ -134,7 +134,7 @@ func (a *App) RemoveSamlPublicCertificate() *model.AppError {
} }
a.UpdateConfig(func(dest *model.Config) { *dest = *cfg }) a.UpdateConfig(func(dest *model.Config) { *dest = *cfg })
utils.SaveConfig(a.ConfigFileName(), cfg) a.PersistConfig()
return nil return nil
} }
@@ -153,7 +153,7 @@ func (a *App) RemoveSamlPrivateCertificate() *model.AppError {
} }
a.UpdateConfig(func(dest *model.Config) { *dest = *cfg }) a.UpdateConfig(func(dest *model.Config) { *dest = *cfg })
utils.SaveConfig(a.ConfigFileName(), cfg) a.PersistConfig()
return nil return nil
} }
@@ -172,7 +172,7 @@ func (a *App) RemoveSamlIdpCertificate() *model.AppError {
} }
a.UpdateConfig(func(dest *model.Config) { *dest = *cfg }) a.UpdateConfig(func(dest *model.Config) { *dest = *cfg })
utils.SaveConfig(a.ConfigFileName(), cfg) a.PersistConfig()
return nil return nil
} }

Просмотреть файл

@@ -39,7 +39,7 @@ const (
) )
func (a *App) CreateUserWithHash(user *model.User, hash string, data string) (*model.User, *model.AppError) { func (a *App) CreateUserWithHash(user *model.User, hash string, data string) (*model.User, *model.AppError) {
if err := IsUserSignUpAllowed(); err != nil { if err := a.IsUserSignUpAllowed(); err != nil {
return nil, err return nil, err
} }
@@ -81,7 +81,7 @@ func (a *App) CreateUserWithHash(user *model.User, hash string, data string) (*m
} }
func (a *App) CreateUserWithInviteId(user *model.User, inviteId string) (*model.User, *model.AppError) { func (a *App) CreateUserWithInviteId(user *model.User, inviteId string) (*model.User, *model.AppError) {
if err := IsUserSignUpAllowed(); err != nil { if err := a.IsUserSignUpAllowed(); err != nil {
return nil, err return nil, err
} }
@@ -127,7 +127,7 @@ func (a *App) CreateUserAsAdmin(user *model.User) (*model.User, *model.AppError)
} }
func (a *App) CreateUserFromSignup(user *model.User) (*model.User, *model.AppError) { func (a *App) CreateUserFromSignup(user *model.User) (*model.User, *model.AppError) {
if err := IsUserSignUpAllowed(); err != nil { if err := a.IsUserSignUpAllowed(); err != nil {
return nil, err return nil, err
} }
@@ -150,8 +150,8 @@ func (a *App) CreateUserFromSignup(user *model.User) (*model.User, *model.AppErr
return ruser, nil return ruser, nil
} }
func IsUserSignUpAllowed() *model.AppError { func (a *App) IsUserSignUpAllowed() *model.AppError {
if !utils.Cfg.EmailSettings.EnableSignUpWithEmail || !utils.Cfg.TeamSettings.EnableUserCreation { if !a.Config().EmailSettings.EnableSignUpWithEmail || !a.Config().TeamSettings.EnableUserCreation {
err := model.NewAppError("IsUserSignUpAllowed", "api.user.create_user.signup_email_disabled.app_error", nil, "", http.StatusNotImplemented) err := model.NewAppError("IsUserSignUpAllowed", "api.user.create_user.signup_email_disabled.app_error", nil, "", http.StatusNotImplemented)
return err return err
} }
@@ -421,7 +421,7 @@ func (a *App) GetUsersMap(offset int, limit int, asAdmin bool) (map[string]*mode
userMap := make(map[string]*model.User, len(users)) userMap := make(map[string]*model.User, len(users))
for _, user := range users { for _, user := range users {
SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, asAdmin)
userMap[user.Id] = user userMap[user.Id] = user
} }
@@ -434,7 +434,7 @@ func (a *App) GetUsersPage(page int, perPage int, asAdmin bool) ([]*model.User,
return nil, err return nil, err
} }
return sanitizeProfiles(users, asAdmin), nil return a.sanitizeProfiles(users, asAdmin), nil
} }
func (a *App) GetUsersEtag() string { func (a *App) GetUsersEtag() string {
@@ -466,7 +466,7 @@ func (a *App) GetUsersInTeamMap(teamId string, offset int, limit int, asAdmin bo
userMap := make(map[string]*model.User, len(users)) userMap := make(map[string]*model.User, len(users))
for _, user := range users { for _, user := range users {
SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, asAdmin)
userMap[user.Id] = user userMap[user.Id] = user
} }
@@ -479,7 +479,7 @@ func (a *App) GetUsersInTeamPage(teamId string, page int, perPage int, asAdmin b
return nil, err return nil, err
} }
return sanitizeProfiles(users, asAdmin), nil return a.sanitizeProfiles(users, asAdmin), nil
} }
func (a *App) GetUsersNotInTeamPage(teamId string, page int, perPage int, asAdmin bool) ([]*model.User, *model.AppError) { func (a *App) GetUsersNotInTeamPage(teamId string, page int, perPage int, asAdmin bool) ([]*model.User, *model.AppError) {
@@ -488,7 +488,7 @@ func (a *App) GetUsersNotInTeamPage(teamId string, page int, perPage int, asAdmi
return nil, err return nil, err
} }
return sanitizeProfiles(users, asAdmin), nil return a.sanitizeProfiles(users, asAdmin), nil
} }
func (a *App) GetUsersInTeamEtag(teamId string) string { func (a *App) GetUsersInTeamEtag(teamId string) string {
@@ -516,7 +516,7 @@ func (a *App) GetUsersInChannelMap(channelId string, offset int, limit int, asAd
userMap := make(map[string]*model.User, len(users)) userMap := make(map[string]*model.User, len(users))
for _, user := range users { for _, user := range users {
SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, asAdmin)
userMap[user.Id] = user userMap[user.Id] = user
} }
@@ -529,7 +529,7 @@ func (a *App) GetUsersInChannelPage(channelId string, page int, perPage int, asA
return nil, err return nil, err
} }
return sanitizeProfiles(users, asAdmin), nil return a.sanitizeProfiles(users, asAdmin), nil
} }
func (a *App) GetUsersNotInChannel(teamId string, channelId string, offset int, limit int) ([]*model.User, *model.AppError) { func (a *App) GetUsersNotInChannel(teamId string, channelId string, offset int, limit int) ([]*model.User, *model.AppError) {
@@ -549,7 +549,7 @@ func (a *App) GetUsersNotInChannelMap(teamId string, channelId string, offset in
userMap := make(map[string]*model.User, len(users)) userMap := make(map[string]*model.User, len(users))
for _, user := range users { for _, user := range users {
SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, asAdmin)
userMap[user.Id] = user userMap[user.Id] = user
} }
@@ -562,7 +562,7 @@ func (a *App) GetUsersNotInChannelPage(teamId string, channelId string, page int
return nil, err return nil, err
} }
return sanitizeProfiles(users, asAdmin), nil return a.sanitizeProfiles(users, asAdmin), nil
} }
func (a *App) GetUsersWithoutTeamPage(page int, perPage int, asAdmin bool) ([]*model.User, *model.AppError) { func (a *App) GetUsersWithoutTeamPage(page int, perPage int, asAdmin bool) ([]*model.User, *model.AppError) {
@@ -571,7 +571,7 @@ func (a *App) GetUsersWithoutTeamPage(page int, perPage int, asAdmin bool) ([]*m
return nil, err return nil, err
} }
return sanitizeProfiles(users, asAdmin), nil return a.sanitizeProfiles(users, asAdmin), nil
} }
func (a *App) GetUsersWithoutTeam(offset int, limit int) ([]*model.User, *model.AppError) { func (a *App) GetUsersWithoutTeam(offset int, limit int) ([]*model.User, *model.AppError) {
@@ -587,7 +587,7 @@ func (a *App) GetUsersByIds(userIds []string, asAdmin bool) ([]*model.User, *mod
return nil, result.Err return nil, result.Err
} else { } else {
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
return sanitizeProfiles(users, asAdmin), nil return a.sanitizeProfiles(users, asAdmin), nil
} }
} }
@@ -596,13 +596,13 @@ func (a *App) GetUsersByUsernames(usernames []string, asAdmin bool) ([]*model.Us
return nil, result.Err return nil, result.Err
} else { } else {
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
return sanitizeProfiles(users, asAdmin), nil return a.sanitizeProfiles(users, asAdmin), nil
} }
} }
func sanitizeProfiles(users []*model.User, asAdmin bool) []*model.User { func (a *App) sanitizeProfiles(users []*model.User, asAdmin bool) []*model.User {
for _, u := range users { for _, u := range users {
SanitizeProfile(u, asAdmin) a.SanitizeProfile(u, asAdmin)
} }
return users return users
@@ -665,7 +665,7 @@ func (a *App) DeactivateMfa(userId string) *model.AppError {
return nil return nil
} }
func CreateProfileImage(username string, userId string) ([]byte, *model.AppError) { func CreateProfileImage(username string, userId string, initialFont string) ([]byte, *model.AppError) {
colors := []color.NRGBA{ colors := []color.NRGBA{
{197, 8, 126, 255}, {197, 8, 126, 255},
{227, 207, 18, 255}, {227, 207, 18, 255},
@@ -702,7 +702,7 @@ func CreateProfileImage(username string, userId string) ([]byte, *model.AppError
initial := string(strings.ToUpper(username)[0]) initial := string(strings.ToUpper(username)[0])
fontDir, _ := utils.FindDir("fonts") fontDir, _ := utils.FindDir("fonts")
fontBytes, err := ioutil.ReadFile(fontDir + utils.Cfg.FileSettings.InitialFont) fontBytes, err := ioutil.ReadFile(fontDir + initialFont)
if err != nil { if err != nil {
return nil, model.NewAppError("CreateProfileImage", "api.user.create_profile_image.default_font.app_error", nil, err.Error(), http.StatusInternalServerError) return nil, model.NewAppError("CreateProfileImage", "api.user.create_profile_image.default_font.app_error", nil, err.Error(), http.StatusInternalServerError)
} }
@@ -739,13 +739,13 @@ func CreateProfileImage(username string, userId string) ([]byte, *model.AppError
} }
} }
func GetProfileImage(user *model.User) ([]byte, bool, *model.AppError) { func (a *App) GetProfileImage(user *model.User) ([]byte, bool, *model.AppError) {
var img []byte var img []byte
readFailed := false readFailed := false
if len(*utils.Cfg.FileSettings.DriverName) == 0 { if len(*utils.Cfg.FileSettings.DriverName) == 0 {
var err *model.AppError var err *model.AppError
if img, err = CreateProfileImage(user.Username, user.Id); err != nil { if img, err = CreateProfileImage(user.Username, user.Id, a.Config().FileSettings.InitialFont); err != nil {
return nil, false, err return nil, false, err
} }
} else { } else {
@@ -754,7 +754,7 @@ func GetProfileImage(user *model.User) ([]byte, bool, *model.AppError) {
if data, err := utils.ReadFile(path); err != nil { if data, err := utils.ReadFile(path); err != nil {
readFailed = true readFailed = true
if img, err = CreateProfileImage(user.Username, user.Id); err != nil { if img, err = CreateProfileImage(user.Username, user.Id, a.Config().FileSettings.InitialFont); err != nil {
return nil, false, err return nil, false, err
} }
@@ -932,8 +932,8 @@ func (a *App) UpdateActive(user *model.User, active bool) (*model.User, *model.A
} }
} }
func SanitizeProfile(user *model.User, asAdmin bool) { func (a *App) SanitizeProfile(user *model.User, asAdmin bool) {
options := utils.Cfg.GetSanitizeOptions() options := a.Config().GetSanitizeOptions()
if asAdmin { if asAdmin {
options["email"] = true options["email"] = true
options["fullname"] = true options["fullname"] = true
@@ -972,7 +972,7 @@ func (a *App) PatchUser(userId string, patch *model.UserPatch, asAdmin bool) (*m
} }
func (a *App) sendUpdatedUserEvent(user model.User, asAdmin bool) { func (a *App) sendUpdatedUserEvent(user model.User, asAdmin bool) {
SanitizeProfile(&user, asAdmin) a.SanitizeProfile(&user, asAdmin)
omitUsers := make(map[string]bool, 1) omitUsers := make(map[string]bool, 1)
omitUsers[user.Id] = true omitUsers[user.Id] = true
@@ -1373,7 +1373,7 @@ func (a *App) SearchUsersInChannel(channelId string, term string, searchOptions
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
for _, user := range users { for _, user := range users {
SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, asAdmin)
} }
return users, nil return users, nil
@@ -1387,7 +1387,7 @@ func (a *App) SearchUsersNotInChannel(teamId string, channelId string, term stri
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
for _, user := range users { for _, user := range users {
SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, asAdmin)
} }
return users, nil return users, nil
@@ -1401,7 +1401,7 @@ func (a *App) SearchUsersInTeam(teamId string, term string, searchOptions map[st
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
for _, user := range users { for _, user := range users {
SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, asAdmin)
} }
return users, nil return users, nil
@@ -1415,7 +1415,7 @@ func (a *App) SearchUsersNotInTeam(notInTeamId string, term string, searchOption
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
for _, user := range users { for _, user := range users {
SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, asAdmin)
} }
return users, nil return users, nil
@@ -1429,7 +1429,7 @@ func (a *App) SearchUsersWithoutTeam(term string, searchOptions map[string]bool,
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
for _, user := range users { for _, user := range users {
SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, asAdmin)
} }
return users, nil return users, nil
@@ -1448,7 +1448,7 @@ func (a *App) AutocompleteUsersInChannel(teamId string, channelId string, term s
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
for _, user := range users { for _, user := range users {
SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, asAdmin)
} }
autocomplete.InChannel = users autocomplete.InChannel = users
@@ -1460,7 +1460,7 @@ func (a *App) AutocompleteUsersInChannel(teamId string, channelId string, term s
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
for _, user := range users { for _, user := range users {
SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, asAdmin)
} }
autocomplete.OutOfChannel = users autocomplete.OutOfChannel = users
@@ -1478,7 +1478,7 @@ func (a *App) AutocompleteUsersInTeam(teamId string, term string, searchOptions
users := result.Data.([]*model.User) users := result.Data.([]*model.User)
for _, user := range users { for _, user := range users {
SanitizeProfile(user, asAdmin) a.SanitizeProfile(user, asAdmin)
} }
autocomplete.InTeam = users autocomplete.InTeam = users

Просмотреть файл

@@ -16,7 +16,6 @@ import (
"github.com/mattermost/mattermost-server/einterfaces" "github.com/mattermost/mattermost-server/einterfaces"
"github.com/mattermost/mattermost-server/model" "github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/model/gitlab" "github.com/mattermost/mattermost-server/model/gitlab"
"github.com/mattermost/mattermost-server/utils"
) )
func TestIsUsernameTaken(t *testing.T) { func TestIsUsernameTaken(t *testing.T) {
@@ -100,9 +99,7 @@ func TestCreateOAuthUser(t *testing.T) {
} }
func TestCreateProfileImage(t *testing.T) { func TestCreateProfileImage(t *testing.T) {
utils.LoadConfig("config.json") b, err := CreateProfileImage("Corey Hulen", "eo1zkdr96pdj98pjmq8zy35wba", "luximbi.ttf")
b, err := CreateProfileImage("Corey Hulen", "eo1zkdr96pdj98pjmq8zy35wba")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

Просмотреть файл

@@ -14,6 +14,7 @@ import (
"github.com/mattermost/mattermost-server/api" "github.com/mattermost/mattermost-server/api"
"github.com/mattermost/mattermost-server/api4" "github.com/mattermost/mattermost-server/api4"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/utils" "github.com/mattermost/mattermost-server/utils"
"github.com/mattermost/mattermost-server/wsapi" "github.com/mattermost/mattermost-server/wsapi"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@@ -51,12 +52,12 @@ func webClientTestsCmdF(cmd *cobra.Command, args []string) error {
} }
defer a.Shutdown() defer a.Shutdown()
utils.InitTranslations(utils.Cfg.LocalizationSettings) utils.InitTranslations(a.Config().LocalizationSettings)
a.StartServer() a.StartServer()
api4.Init(a, a.Srv.Router, false) api4.Init(a, a.Srv.Router, false)
api.Init(a, a.Srv.Router) api.Init(a, a.Srv.Router)
wsapi.Init(a, a.Srv.WebSocketRouter) wsapi.Init(a, a.Srv.WebSocketRouter)
setupClientTests() a.UpdateConfig(setupClientTests)
runWebClientTests() runWebClientTests()
return nil return nil
@@ -69,12 +70,12 @@ func serverForWebClientTestsCmdF(cmd *cobra.Command, args []string) error {
} }
defer a.Shutdown() defer a.Shutdown()
utils.InitTranslations(utils.Cfg.LocalizationSettings) utils.InitTranslations(a.Config().LocalizationSettings)
a.StartServer() a.StartServer()
api4.Init(a, a.Srv.Router, false) api4.Init(a, a.Srv.Router, false)
api.Init(a, a.Srv.Router) api.Init(a, a.Srv.Router)
wsapi.Init(a, a.Srv.WebSocketRouter) wsapi.Init(a, a.Srv.WebSocketRouter)
setupClientTests() a.UpdateConfig(setupClientTests)
c := make(chan os.Signal) c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) signal.Notify(c, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
@@ -83,13 +84,13 @@ func serverForWebClientTestsCmdF(cmd *cobra.Command, args []string) error {
return nil return nil
} }
func setupClientTests() { func setupClientTests(cfg *model.Config) {
*utils.Cfg.TeamSettings.EnableOpenServer = true *cfg.TeamSettings.EnableOpenServer = true
*utils.Cfg.ServiceSettings.EnableCommands = false *cfg.ServiceSettings.EnableCommands = false
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false *cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
*utils.Cfg.ServiceSettings.EnableCustomEmoji = true *cfg.ServiceSettings.EnableCustomEmoji = true
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = false cfg.ServiceSettings.EnableIncomingWebhooks = false
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = false cfg.ServiceSettings.EnableOutgoingWebhooks = false
utils.SetDefaultRolesBasedOnConfig() utils.SetDefaultRolesBasedOnConfig()
} }

Просмотреть файл

@@ -289,7 +289,7 @@ func inviteUser(a *app.App, email string, team *model.Team, teamArg string) erro
return fmt.Errorf("Can't find team '%v'", teamArg) return fmt.Errorf("Can't find team '%v'", teamArg)
} }
a.SendInviteEmails(team, "Administrator", invites, *utils.Cfg.ServiceSettings.SiteURL) a.SendInviteEmails(team, "Administrator", invites, *a.Config().ServiceSettings.SiteURL)
CommandPrettyPrintln("Invites may or may not have been sent.") CommandPrettyPrintln("Invites may or may not have been sent.")
return nil return nil

Просмотреть файл

@@ -99,8 +99,6 @@ func tearDownStores() {
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
utils.TranslationsPreInit() utils.TranslationsPreInit()
utils.LoadConfig("config.json")
utils.InitTranslations(utils.Cfg.LocalizationSettings)
status := 0 status := 0

Просмотреть файл

@@ -70,16 +70,14 @@ func RemoveConfigListener(id string) {
delete(cfgListeners, id) delete(cfgListeners, id)
} }
func FindConfigFile(fileName string) string { func FindConfigFile(fileName string) (path string) {
if _, err := os.Stat("./config/" + fileName); err == nil { for _, dir := range []string{"./config", "../config", "../../config", "."} {
fileName, _ = filepath.Abs("./config/" + fileName) path, _ := filepath.Abs(filepath.Join(dir, fileName))
} else if _, err := os.Stat("../config/" + fileName); err == nil { if _, err := os.Stat(path); err == nil {
fileName, _ = filepath.Abs("../config/" + fileName) return path
} else if _, err := os.Stat(fileName); err == nil { }
fileName, _ = filepath.Abs(fileName)
} }
return ""
return fileName
} }
func FindDir(dir string) (string, bool) { func FindDir(dir string) (string, bool) {
@@ -197,12 +195,6 @@ func SaveConfig(fileName string, config *model.Config) *model.AppError {
return nil return nil
} }
func EnableConfigFromEnviromentVars() {
viper.SetEnvPrefix("mm")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()
}
func InitializeConfigWatch() { func InitializeConfigWatch() {
cfgMutex.Lock() cfgMutex.Lock()
defer cfgMutex.Unlock() defer cfgMutex.Unlock()
@@ -230,7 +222,7 @@ func InitializeConfigWatch() {
l4g.Info(fmt.Sprintf("Config file watcher detected a change reloading %v", CfgFileName)) l4g.Info(fmt.Sprintf("Config file watcher detected a change reloading %v", CfgFileName))
if configReadErr := viper.ReadInConfig(); configReadErr == nil { if configReadErr := viper.ReadInConfig(); configReadErr == nil {
LoadConfig(CfgFileName) LoadGlobalConfig(CfgFileName)
} else { } else {
l4g.Error(fmt.Sprintf("Failed to read while watching config file at %v with err=%v", CfgFileName, configReadErr.Error())) l4g.Error(fmt.Sprintf("Failed to read while watching config file at %v with err=%v", CfgFileName, configReadErr.Error()))
} }
@@ -274,83 +266,108 @@ func InitAndLoadConfig(filename string) error {
return err return err
} }
EnableConfigFromEnviromentVars() LoadGlobalConfig(filename)
LoadConfig(filename)
InitializeConfigWatch() InitializeConfigWatch()
EnableConfigWatch() EnableConfigWatch()
return nil return nil
} }
// LoadConfig will try to search around for the corresponding config file. // ReadConfig reads and parses the given configuration.
// It will search /tmp/fileName then attempt ./config/fileName, func ReadConfig(r io.Reader, allowEnvironmentOverrides bool) (*model.Config, error) {
// then ../config/fileName and last it will look at fileName v := viper.New()
func LoadConfig(fileName string) *model.Config {
if allowEnvironmentOverrides {
v.SetEnvPrefix("mm")
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
v.AutomaticEnv()
}
v.SetConfigType("json")
if err := v.ReadConfig(r); err != nil {
return nil, err
}
var config model.Config
unmarshalErr := v.Unmarshal(&config)
if unmarshalErr == nil {
// https://github.com/spf13/viper/issues/324
// https://github.com/spf13/viper/issues/348
config.PluginSettings = model.PluginSettings{}
unmarshalErr = v.UnmarshalKey("pluginsettings", &config.PluginSettings)
}
return &config, unmarshalErr
}
// ReadConfigFile reads and parses the configuration at the given file path.
func ReadConfigFile(path string, allowEnvironmentOverrides bool) (*model.Config, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
return ReadConfig(f, allowEnvironmentOverrides)
}
// EnsureConfigFile will attempt to locate a config file with the given name. If it does not exist,
// it will attempt to locate a default config file, and copy it. In either case, the config file
// path is returned.
func EnsureConfigFile(fileName string) (string, error) {
if configFile := FindConfigFile(fileName); configFile != "" {
return configFile, nil
}
if defaultPath := FindConfigFile("default.json"); defaultPath != "" {
destPath := filepath.Join(filepath.Dir(defaultPath), fileName)
src, err := os.Open(defaultPath)
if err != nil {
return "", err
}
defer src.Close()
dest, err := os.OpenFile(destPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return "", err
}
defer dest.Close()
if _, err := io.Copy(dest, src); err == nil {
return destPath, nil
}
}
return "", fmt.Errorf("no config file found")
}
// LoadGlobalConfig will try to search around for the corresponding config file. It will search
// /tmp/fileName then attempt ./config/fileName, then ../config/fileName and last it will look at
// fileName
//
// XXX: This is deprecated.
func LoadGlobalConfig(fileName string) *model.Config {
cfgMutex.Lock() cfgMutex.Lock()
defer cfgMutex.Unlock() defer cfgMutex.Unlock()
// Cfg should never be null // Cfg should never be null
oldConfig := *Cfg oldConfig := *Cfg
fileNameWithExtension := filepath.Base(fileName) var configPath string
fileExtension := filepath.Ext(fileNameWithExtension) if fileName != filepath.Base(fileName) {
fileDir := filepath.Dir(fileName) configPath = fileName
if len(fileNameWithExtension) > 0 {
fileNameOnly := fileNameWithExtension[:len(fileNameWithExtension)-len(fileExtension)]
viper.SetConfigName(fileNameOnly)
} else { } else {
viper.SetConfigName("config") if path, err := EnsureConfigFile(fileName); err != nil {
} errMsg := T("utils.config.load_config.opening.panic", map[string]interface{}{"Filename": fileName, "Error": err.Error()})
fmt.Fprintln(os.Stderr, errMsg)
if len(fileDir) > 0 { os.Exit(1)
viper.AddConfigPath(fileDir) } else {
} configPath = path
viper.SetConfigType("json")
viper.AddConfigPath("./config")
viper.AddConfigPath("../config")
viper.AddConfigPath("../../config")
viper.AddConfigPath(".")
configReadErr := viper.ReadInConfig()
if configReadErr != nil {
if _, ok := configReadErr.(viper.ConfigFileNotFoundError); ok {
// In case of a file-not-found error, try to copy default.json if it's present.
defaultPath := FindConfigFile("default.json")
if src, err := os.Open(defaultPath); err == nil {
if dest, err := os.OpenFile(filepath.Join(filepath.Dir(defaultPath), "config.json"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600); err == nil {
if _, err := io.Copy(dest, src); err == nil {
configReadErr = viper.ReadInConfig()
}
dest.Close()
}
src.Close()
}
} }
} }
if configReadErr != nil { config, err := ReadConfigFile(configPath, true)
errMsg := T("utils.config.load_config.opening.panic", map[string]interface{}{"Filename": fileName, "Error": configReadErr.Error()}) if err != nil {
errMsg := T("utils.config.load_config.decoding.panic", map[string]interface{}{"Filename": fileName, "Error": err.Error()})
fmt.Fprintln(os.Stderr, errMsg) fmt.Fprintln(os.Stderr, errMsg)
os.Exit(1) os.Exit(1)
} }
var config model.Config CfgFileName = configPath
unmarshalErr := viper.Unmarshal(&config)
if unmarshalErr == nil {
// https://github.com/spf13/viper/issues/324
// https://github.com/spf13/viper/issues/348
config.PluginSettings = model.PluginSettings{}
unmarshalErr = viper.UnmarshalKey("pluginsettings", &config.PluginSettings)
}
if unmarshalErr != nil {
errMsg := T("utils.config.load_config.decoding.panic", map[string]interface{}{"Filename": fileName, "Error": unmarshalErr.Error()})
fmt.Fprintln(os.Stderr, errMsg)
os.Exit(1)
}
CfgFileName = viper.ConfigFileUsed()
needSave := len(config.SqlSettings.AtRestEncryptKey) == 0 || len(*config.FileSettings.PublicLinkSalt) == 0 || needSave := len(config.SqlSettings.AtRestEncryptKey) == 0 || len(*config.FileSettings.PublicLinkSalt) == 0 ||
len(config.EmailSettings.InviteSalt) == 0 len(config.EmailSettings.InviteSalt) == 0
@@ -363,16 +380,16 @@ func LoadConfig(fileName string) *model.Config {
if needSave { if needSave {
cfgMutex.Unlock() cfgMutex.Unlock()
if err := SaveConfig(CfgFileName, &config); err != nil { if err := SaveConfig(CfgFileName, config); err != nil {
err.Translate(T) err.Translate(T)
l4g.Warn(err.Error()) l4g.Warn(err.Error())
} }
cfgMutex.Lock() cfgMutex.Lock()
} }
if err := ValidateLocales(&config); err != nil { if err := ValidateLocales(config); err != nil {
cfgMutex.Unlock() cfgMutex.Unlock()
if err := SaveConfig(CfgFileName, &config); err != nil { if err := SaveConfig(CfgFileName, config); err != nil {
err.Translate(T) err.Translate(T)
l4g.Warn(err.Error()) l4g.Warn(err.Error())
} }
@@ -388,7 +405,7 @@ func LoadConfig(fileName string) *model.Config {
} }
} }
Cfg = &config Cfg = config
CfgHash = fmt.Sprintf("%x", md5.Sum([]byte(Cfg.ToJson()))) CfgHash = fmt.Sprintf("%x", md5.Sum([]byte(Cfg.ToJson())))
ClientCfg = getClientConfig(Cfg) ClientCfg = getClientConfig(Cfg)
clientCfgJson, _ := json.Marshal(ClientCfg) clientCfgJson, _ := json.Marshal(ClientCfg)
@@ -398,10 +415,10 @@ func LoadConfig(fileName string) *model.Config {
SetSiteURL(*Cfg.ServiceSettings.SiteURL) SetSiteURL(*Cfg.ServiceSettings.SiteURL)
for _, listener := range cfgListeners { for _, listener := range cfgListeners {
listener(&oldConfig, &config) listener(&oldConfig, config)
} }
return &config return config
} }
func RegenerateClientConfig() { func RegenerateClientConfig() {

Просмотреть файл

@@ -9,25 +9,26 @@ import (
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/model" "github.com/mattermost/mattermost-server/model"
) )
func TestConfig(t *testing.T) { func TestConfig(t *testing.T) {
TranslationsPreInit() TranslationsPreInit()
LoadConfig("config.json") LoadGlobalConfig("config.json")
InitTranslations(Cfg.LocalizationSettings) InitTranslations(Cfg.LocalizationSettings)
} }
func TestConfigFromEnviroVars(t *testing.T) { func TestConfigFromEnviroVars(t *testing.T) {
os.Setenv("MM_TEAMSETTINGS_SITENAME", "From Enviroment") os.Setenv("MM_TEAMSETTINGS_SITENAME", "From Enviroment")
os.Setenv("MM_TEAMSETTINGS_CUSTOMBRANDTEXT", "Custom Brand") os.Setenv("MM_TEAMSETTINGS_CUSTOMBRANDTEXT", "Custom Brand")
os.Setenv("MM_SERVICESETTINGS_ENABLECOMMANDS", "false") os.Setenv("MM_SERVICESETTINGS_ENABLECOMMANDS", "false")
os.Setenv("MM_SERVICESETTINGS_READTIMEOUT", "400") os.Setenv("MM_SERVICESETTINGS_READTIMEOUT", "400")
TranslationsPreInit() TranslationsPreInit()
EnableConfigFromEnviromentVars() LoadGlobalConfig("config.json")
LoadConfig("config.json")
if Cfg.TeamSettings.SiteName != "From Enviroment" { if Cfg.TeamSettings.SiteName != "From Enviroment" {
t.Fatal("Couldn't read config from enviroment var") t.Fatal("Couldn't read config from enviroment var")
@@ -56,7 +57,7 @@ func TestConfigFromEnviroVars(t *testing.T) {
*Cfg.ServiceSettings.ReadTimeout = 300 *Cfg.ServiceSettings.ReadTimeout = 300
SaveConfig(CfgFileName, Cfg) SaveConfig(CfgFileName, Cfg)
LoadConfig("config.json") LoadGlobalConfig("config.json")
if Cfg.TeamSettings.SiteName != "Mattermost" { if Cfg.TeamSettings.SiteName != "Mattermost" {
t.Fatal("should have been reset") t.Fatal("should have been reset")
@@ -65,7 +66,7 @@ func TestConfigFromEnviroVars(t *testing.T) {
func TestRedirectStdLog(t *testing.T) { func TestRedirectStdLog(t *testing.T) {
TranslationsPreInit() TranslationsPreInit()
LoadConfig("config.json") LoadGlobalConfig("config.json")
InitTranslations(Cfg.LocalizationSettings) InitTranslations(Cfg.LocalizationSettings)
log := NewRedirectStdLog("test", false) log := NewRedirectStdLog("test", false)
@@ -110,8 +111,7 @@ func TestAddRemoveConfigListener(t *testing.T) {
func TestConfigListener(t *testing.T) { func TestConfigListener(t *testing.T) {
TranslationsPreInit() TranslationsPreInit()
EnableConfigFromEnviromentVars() LoadGlobalConfig("config.json")
LoadConfig("config.json")
SiteName := Cfg.TeamSettings.SiteName SiteName := Cfg.TeamSettings.SiteName
defer func() { defer func() {
@@ -148,7 +148,7 @@ func TestConfigListener(t *testing.T) {
listener2Id := AddConfigListener(listener2) listener2Id := AddConfigListener(listener2)
defer RemoveConfigListener(listener2Id) defer RemoveConfigListener(listener2Id)
LoadConfig("config.json") LoadGlobalConfig("config.json")
if !listenerCalled { if !listenerCalled {
t.Fatal("listener should've been called") t.Fatal("listener should've been called")
@@ -159,7 +159,7 @@ func TestConfigListener(t *testing.T) {
func TestValidateLocales(t *testing.T) { func TestValidateLocales(t *testing.T) {
TranslationsPreInit() TranslationsPreInit()
LoadConfig("config.json") LoadGlobalConfig("config.json")
defaultServerLocale := *Cfg.LocalizationSettings.DefaultServerLocale defaultServerLocale := *Cfg.LocalizationSettings.DefaultServerLocale
defaultClientLocale := *Cfg.LocalizationSettings.DefaultClientLocale defaultClientLocale := *Cfg.LocalizationSettings.DefaultClientLocale
@@ -278,10 +278,21 @@ func TestValidateLocales(t *testing.T) {
func TestGetClientConfig(t *testing.T) { func TestGetClientConfig(t *testing.T) {
TranslationsPreInit() TranslationsPreInit()
LoadConfig("config.json") LoadGlobalConfig("config.json")
configMap := getClientConfig(Cfg) configMap := getClientConfig(Cfg)
if configMap["EmailNotificationContentsType"] != *Cfg.EmailSettings.EmailNotificationContentsType { if configMap["EmailNotificationContentsType"] != *Cfg.EmailSettings.EmailNotificationContentsType {
t.Fatal("EmailSettings.EmailNotificationContentsType not exposed to client config") t.Fatal("EmailSettings.EmailNotificationContentsType not exposed to client config")
} }
} }
func TestReadConfig(t *testing.T) {
config, err := ReadConfig(strings.NewReader(`{
"ServiceSettings": {
"SiteURL": "http://foo.bar"
}
}`), false)
require.NoError(t, err)
assert.Equal(t, "http://foo.bar", *config.ServiceSettings.SiteURL)
}

Просмотреть файл

@@ -43,7 +43,7 @@ func TestFileMinioTestSuite(t *testing.T) {
func (s *FileTestSuite) SetupTest() { func (s *FileTestSuite) SetupTest() {
TranslationsPreInit() TranslationsPreInit()
LoadConfig("config.json") LoadGlobalConfig("config.json")
InitTranslations(Cfg.LocalizationSettings) InitTranslations(Cfg.LocalizationSettings)
// Save state to restore after the test has run. // Save state to restore after the test has run.

Просмотреть файл

@@ -9,7 +9,7 @@ import (
) )
func TestMailConnection(t *testing.T) { func TestMailConnection(t *testing.T) {
LoadConfig("config.json") LoadGlobalConfig("config.json")
if conn, err := connectToSMTPServer(Cfg); err != nil { if conn, err := connectToSMTPServer(Cfg); err != nil {
t.Log(err) t.Log(err)
@@ -32,7 +32,7 @@ func TestMailConnection(t *testing.T) {
} }
func TestSendMail(t *testing.T) { func TestSendMail(t *testing.T) {
LoadConfig("config.json") LoadGlobalConfig("config.json")
T = GetUserTranslations("en") T = GetUserTranslations("en")
var emailTo string = "test@example.com" var emailTo string = "test@example.com"

Просмотреть файл

@@ -38,10 +38,6 @@ func StopTestStore() {
} }
func Setup() *app.App { func Setup() *app.App {
utils.TranslationsPreInit()
utils.LoadConfig("config.json")
utils.InitTranslations(utils.Cfg.LocalizationSettings)
a := app.New(app.StoreOverride(testStore)) a := app.New(app.StoreOverride(testStore))
prevListenAddress := *a.Config().ServiceSettings.ListenAddress prevListenAddress := *a.Config().ServiceSettings.ListenAddress
a.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = ":0" }) a.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = ":0" })
@@ -55,7 +51,9 @@ func Setup() *app.App {
a.Srv.Store.MarkSystemRanUnitTests() a.Srv.Store.MarkSystemRanUnitTests()
*utils.Cfg.TeamSettings.EnableOpenServer = true a.UpdateConfig(func(cfg *model.Config) {
*cfg.TeamSettings.EnableOpenServer = true
})
return a return a
} }
@@ -106,7 +104,7 @@ func TestIncomingWebhook(t *testing.T) {
channel1 := &model.Channel{DisplayName: "Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 := &model.Channel{DisplayName: "Test API Name", Name: "zz" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = ApiClient.Must(ApiClient.CreateChannel(channel1)).Data.(*model.Channel) channel1 = ApiClient.Must(ApiClient.CreateChannel(channel1)).Data.(*model.Channel)
if utils.Cfg.ServiceSettings.EnableIncomingWebhooks { if a.Config().ServiceSettings.EnableIncomingWebhooks {
hook1 := &model.IncomingWebhook{ChannelId: channel1.Id} hook1 := &model.IncomingWebhook{ChannelId: channel1.Id}
hook1 = ApiClient.Must(ApiClient.CreateIncomingWebhook(hook1)).Data.(*model.IncomingWebhook) hook1 = ApiClient.Must(ApiClient.CreateIncomingWebhook(hook1)).Data.(*model.IncomingWebhook)
@@ -138,8 +136,6 @@ func TestIncomingWebhook(t *testing.T) {
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
utils.TranslationsPreInit() utils.TranslationsPreInit()
utils.LoadConfig("config.json")
utils.InitTranslations(utils.Cfg.LocalizationSettings)
status := 0 status := 0