// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. // See License.txt for license information. package utils import ( "encoding/json" "fmt" "io/ioutil" "os" "path/filepath" "strconv" l4g "code.google.com/p/log4go" "github.com/mattermost/platform/model" ) const ( MODE_DEV = "dev" MODE_BETA = "beta" MODE_PROD = "prod" LOG_ROTATE_SIZE = 10000 ) var Cfg *model.Config = &model.Config{} var CfgLastModified int64 = 0 var CfgFileName string = "" var ClientProperties map[string]string = map[string]string{} var SanitizeOptions map[string]bool = map[string]bool{} func FindConfigFile(fileName string) string { if _, err := os.Stat("/tmp/" + fileName); err == nil { fileName, _ = filepath.Abs("/tmp/" + fileName) } else if _, err := os.Stat("./config/" + fileName); err == nil { fileName, _ = filepath.Abs("./config/" + fileName) } else if _, err := os.Stat("../config/" + fileName); err == nil { fileName, _ = filepath.Abs("../config/" + fileName) } else if _, err := os.Stat(fileName); err == nil { fileName, _ = filepath.Abs(fileName) } return fileName } func FindDir(dir string) string { fileName := "." if _, err := os.Stat("./" + dir + "/"); err == nil { fileName, _ = filepath.Abs("./" + dir + "/") } else if _, err := os.Stat("../" + dir + "/"); err == nil { fileName, _ = filepath.Abs("../" + dir + "/") } else if _, err := os.Stat("/tmp/" + dir); err == nil { fileName, _ = filepath.Abs("/tmp/" + dir) } return fileName + "/" } func ConfigureCmdLineLog() { ls := model.LogSettings{} ls.ConsoleEnable = true ls.ConsoleLevel = "ERROR" ls.FileEnable = false configureLog(&ls) } func configureLog(s *model.LogSettings) { l4g.Close() if s.ConsoleEnable { level := l4g.DEBUG if s.ConsoleLevel == "INFO" { level = l4g.INFO } else if s.ConsoleLevel == "ERROR" { level = l4g.ERROR } l4g.AddFilter("stdout", level, l4g.NewConsoleLogWriter()) } if s.FileEnable { var fileFormat = s.FileFormat if fileFormat == "" { fileFormat = "[%D %T] [%L] %M" } level := l4g.DEBUG if s.FileLevel == "INFO" { level = l4g.INFO } else if s.FileLevel == "ERROR" { level = l4g.ERROR } flw := l4g.NewFileLogWriter(GetLogFileLocation(s.FileLocation), false) flw.SetFormat(fileFormat) flw.SetRotate(true) flw.SetRotateLines(LOG_ROTATE_SIZE) l4g.AddFilter("file", level, flw) } } func GetLogFileLocation(fileLocation string) string { if fileLocation == "" { return FindDir("logs") + "mattermost.log" } else { return fileLocation } } func SaveConfig(fileName string, config *model.Config) *model.AppError { b, err := json.MarshalIndent(config, "", " ") if err != nil { return model.NewAppError("SaveConfig", "An error occurred while saving the file to "+fileName, err.Error()) } err = ioutil.WriteFile(fileName, b, 0644) if err != nil { return model.NewAppError("SaveConfig", "An error occurred while saving the file to "+fileName, err.Error()) } return nil } // LoadConfig 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 func LoadConfig(fileName string) { fileName = FindConfigFile(fileName) file, err := os.Open(fileName) if err != nil { panic("Error opening config file=" + fileName + ", err=" + err.Error()) } decoder := json.NewDecoder(file) config := model.Config{} err = decoder.Decode(&config) if err != nil { panic("Error decoding config file=" + fileName + ", err=" + err.Error()) } if info, err := file.Stat(); err != nil { panic("Error getting config info file=" + fileName + ", err=" + err.Error()) } else { CfgLastModified = info.ModTime().Unix() CfgFileName = fileName } configureLog(&config.LogSettings) Cfg = &config SanitizeOptions = getSanitizeOptions(Cfg) ClientProperties = getClientProperties(Cfg) } func getSanitizeOptions(c *model.Config) map[string]bool { options := map[string]bool{} options["fullname"] = c.PrivacySettings.ShowFullName options["email"] = c.PrivacySettings.ShowEmailAddress options["skypeid"] = c.PrivacySettings.ShowSkypeId options["phonenumber"] = c.PrivacySettings.ShowPhoneNumber return options } func getClientProperties(c *model.Config) map[string]string { props := make(map[string]string) props["Version"] = model.CurrentVersion props["BuildNumber"] = model.BuildNumber props["BuildDate"] = model.BuildDate props["BuildHash"] = model.BuildHash props["SiteName"] = c.ServiceSettings.SiteName props["ByPassEmail"] = strconv.FormatBool(c.EmailSettings.ByPassEmail) props["FeedbackEmail"] = c.EmailSettings.FeedbackEmail props["ShowEmailAddress"] = strconv.FormatBool(c.PrivacySettings.ShowEmailAddress) props["AllowPublicLink"] = strconv.FormatBool(c.TeamSettings.AllowPublicLink) props["SegmentDeveloperKey"] = c.ClientSettings.SegmentDeveloperKey props["GoogleDeveloperKey"] = c.ClientSettings.GoogleDeveloperKey props["AnalyticsUrl"] = c.ServiceSettings.AnalyticsUrl props["ByPassEmail"] = strconv.FormatBool(c.EmailSettings.ByPassEmail) props["ProfileHeight"] = fmt.Sprintf("%v", c.ImageSettings.ProfileHeight) props["ProfileWidth"] = fmt.Sprintf("%v", c.ImageSettings.ProfileWidth) props["ProfileWidth"] = fmt.Sprintf("%v", c.ImageSettings.ProfileWidth) props["EnableOAuthServiceProvider"] = strconv.FormatBool(c.ServiceSettings.EnableOAuthServiceProvider) props["AllowIncomingWebhooks"] = strconv.FormatBool(c.ServiceSettings.AllowIncomingWebhooks) return props } func IsS3Configured() bool { if Cfg.AWSSettings.S3AccessKeyId == "" || Cfg.AWSSettings.S3SecretAccessKey == "" || Cfg.AWSSettings.S3Region == "" || Cfg.AWSSettings.S3Bucket == "" { return false } return true } func GetAllowedAuthServices() []string { authServices := []string{} for name, service := range Cfg.SSOSettings { if service.Allow { authServices = append(authServices, name) } } if !Cfg.ServiceSettings.DisableEmailSignUp { authServices = append(authServices, "email") } return authServices } func IsServiceAllowed(s string) bool { if len(s) == 0 { return false } if service, ok := Cfg.SSOSettings[s]; ok { if service.Allow { return true } } return false }