Mercurial > gemma
view pkg/config/config.go @ 5675:b8da63027b48 sr-v2
Started to separate mesh serialisation in different files.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Sat, 10 Feb 2024 22:22:03 +0100 |
parents | a826d84485c8 |
children | 2dd155cc95ec |
line wrap: on
line source
// This is Free Software under GNU Affero General Public License v >= 3.0 // without warranty, see README.md and license for details. // // SPDX-License-Identifier: AGPL-3.0-or-later // License-Filename: LICENSES/AGPL-3.0.txt // // Copyright (C) 2018, 2019 by via donau // – Österreichische Wasserstraßen-Gesellschaft mbH // Software engineering by Intevation GmbH // // Author(s): // * Sascha L. Teichmann <sascha.teichmann@intevation.de> // * Bernhard E. Reiter <bernhard.reiter@intevation.de> package config import ( "crypto/sha256" "fmt" lg "log" "sync" "time" homedir "github.com/mitchellh/go-homedir" "github.com/spf13/cobra" "github.com/spf13/viper" "gemma.intevation.de/gemma/pkg/common" "gemma.intevation.de/gemma/pkg/log" ) // This is not part of the persistent config. var configFile string // DBHost is the hostname of the database. func DBHost() string { return viper.GetString("db-host") } // DBPort is the port of the database. func DBPort() uint { return uint(viper.GetInt32("db-port")) } // DBName is the name of the database. func DBName() string { return viper.GetString("db-name") } // DBUser is the name of the user to connect to the database. func DBUser() string { return viper.GetString("db-user") } // DBPassword is the password to connect to the database. func DBPassword() string { return viper.GetString("db-password") } // DBSSLMode selects the SSL mode to encrypt the connection to the database. func DBSSLMode() string { return viper.GetString("db-ssl") } // SessionStore is the path to the session store. // If empty the session store is kept in memory only. func SessionStore() string { return viper.GetString("sessions") } // Web is the root folder of the served web content. func Web() string { return viper.GetString("web") } // WebHost is the host to bind the web server to. func WebHost() string { return viper.GetString("host") } // WebPort is the port to bind the web server to. func WebPort() uint { return uint(viper.GetInt32("port")) } // MailHost is the server of the SMTP server. func MailHost() string { return viper.GetString("mail-host") } // MailPort is the port of the SMTP server. func MailPort() uint { return uint(viper.GetInt32("mail-port")) } // MailUser is the user to connect to the SMTP server. func MailUser() string { return viper.GetString("mail-user") } // MailPassword is the password of the user to connect to the SMTP server. func MailPassword() string { return viper.GetString("mail-password") } // MailFrom is the sender in the 'from' header in mails send. func MailFrom() string { return viper.GetString("mail-from") } // MailHelo is the helo message send to the SMTP server. func MailHelo() string { return viper.GetString("mail-helo") } // AllowedOrigins is a list of allowed host for CORS headers. func AllowedOrigins() []string { return viper.GetStringSlice("allowed-origins") } // GeoServerURL is the URL of the GeoServer used by gemma to serve map data. func GeoServerURL() string { return viper.GetString("geoserver-url") } // GeoServerUser is the adminstrative user to connect to the GeoServer. func GeoServerUser() string { return viper.GetString("geoserver-user") } // GeoServerPassword is the password of the adminstrative user // to connect to the GeoServer. func GeoServerPassword() string { return viper.GetString("geoserver-password") } // GeoServerClean is a flag to indicate that the GeoServer setup for // gemma should be freshly created at boot time. // This is useful in case of gemma update. // If false the only missing parts are added to the GeoServer setup. // This should be the default mode when running gemma after an update // as it reduces the pressure on the GeoServer and enables faster // rebooting. func GeoServerClean() bool { return viper.GetBool("geoserver-clean") } // GeoServerStartupSQL can be used to add SQL commands to GeoServers database // session start script. See // https://docs.geoserver.org/stable/en/user/data/database/sqlsession.html // Note that the commands will be executed as the user configured as 'db-user'. func GeoServerStartupSQL() string { return viper.GetString("geoserver-startup-sql") } // TmpDir is the path where to store temporary files. // If left empty the system default for temporary files is used. func TmpDir() string { return viper.GetString("tmp-dir") } // PublishedConfig is a name of a JSON file where extra configuration is stored // to be served to to the web client. func PublishedConfig() string { return viper.GetString("published-config") } // SOAPTimeout is the timeout till a SOAP request is canceled. func SOAPTimeout() time.Duration { return viper.GetDuration("soap-timeout") } // ReportPath is a path where report templates are stored. func ReportPath() string { return viper.GetString("report-path") } // LogFile is the path to the log file. func LogFile() string { return viper.GetString("log-file") } // LogLevel is the log level of the application. func LogLevel() log.Level { return log.ParseLogLevel(viper.GetString("log-level")) } // TokenURL is the ERDMS token service URL. func TokenURL() string { return viper.GetString("token-url") } var ( proxyKeyOnce sync.Once proxyKey []byte proxyPrefixOnce sync.Once proxyPrefix string externalURLOnce sync.Once externalURL string sessionTimeoutOnce sync.Once sessionTimeout time.Duration ) // ProxyKey is a crytographic key to sign the URLs generated by the proxy. // Use this to ensure that only known URLs are reachable over the proxy. // If left blank a random key is generated a gemma boot time. // Setting this value in the configuration will allow browsing proxy // generated URL across gemma reboot. // Use a strong secret key here (like pwgen -s 20). func ProxyKey() []byte { fetchKey := func() { if proxyKey == nil { key := []byte(viper.GetString("proxy-key")) if len(key) == 0 { key = common.GenerateRandomKey(64) } hash := sha256.New() hash.Write(key) proxyKey = hash.Sum(nil) } } proxyKeyOnce.Do(fetchKey) return proxyKey } // ProxyPrefix is the prefix used in generated URLs by the proxy. // You may need to set this if you run gemma behind a proxy // on a specific domain. func ProxyPrefix() string { fetchPrefix := func() { if proxyPrefix == "" { if proxyPrefix = viper.GetString("proxy-prefix"); proxyPrefix == "" { proxyPrefix = fmt.Sprintf("http://%s:%d", WebHost(), WebPort()) } } } proxyPrefixOnce.Do(fetchPrefix) return proxyPrefix } // ExternalURL is the URL to find this server from the outside. func ExternalURL() string { fetchExternal := func() { if externalURL == "" { if externalURL = viper.GetString("external-url"); externalURL == "" { externalURL = fmt.Sprintf("http://%s:%d", WebHost(), WebPort()) } } } externalURLOnce.Do(fetchExternal) return externalURL } // SessionTimeout is the duration until a session expires if not renewed func SessionTimeout() time.Duration { fetchTimeout := func() { if sessionTimeout == 0 { sessionTimeout = viper.GetDuration("session-timeout") if sessionTimeout <= 0 { lg.Println("warn: non-positive session-timeout configured.") } } } sessionTimeoutOnce.Do(fetchTimeout) return sessionTimeout } // SchemaDirs are the root directories where to find schema files. func SchemaDirs() string { return viper.GetString("schema-dirs") } // RootCmd is cobra command to be bound th the cobra/viper infrastructure. var RootCmd = &cobra.Command{ Use: "gemma", Short: "gemma is a server for waterway monitoring and management", } var allowedOrigins = []string{ // TODO: Fill me! } func init() { cobra.OnInitialize(initConfig) fl := RootCmd.PersistentFlags() fl.StringVarP(&configFile, "config", "c", "", "config file (default is $HOME/.gemma.toml)") vbind := func(name string) { viper.BindPFlag(name, fl.Lookup(name)) } str := func(name, value, usage string) { fl.String(name, value, usage) vbind(name) } strP := func(name, shorthand, value, usage string) { fl.StringP(name, shorthand, value, usage) vbind(name) } ui := func(name string, value uint, usage string) { fl.Uint(name, value, usage) vbind(name) } uiP := func(name, shorthand string, value uint, usage string) { fl.UintP(name, shorthand, value, usage) vbind(name) } strSl := func(name string, value []string, usage string) { fl.StringSlice(name, value, usage) vbind(name) } bl := func(name string, value bool, usage string) { fl.Bool(name, value, usage) vbind(name) } d := func(name string, value time.Duration, usage string) { fl.Duration(name, value, usage) vbind(name) } strP("db-host", "H", "localhost", "host of the database") uiP("db-port", "P", 5432, "port of the database") strP("db-name", "d", "gemma", "name of the database") str("db-user", "meta_login", "Metamorphic database user") str("db-password", "", "Metamorphic database user password") strP("db-ssl", "S", "prefer", "SSL mode of the database") strP("sessions", "s", "", "path to the sessions file") d("session-timeout", 3*time.Hour, "duration until sessions expire") strP("web", "w", "./web", "path to the web files") strP("host", "o", "localhost", "host of the web app") uiP("port", "p", 8000, "port of the web app") str("mail-host", "localhost", "server to send mail with") ui("mail-port", 465, "port of server to send mail with") str("mail-user", "gemma", "user to authenticate against mail-host.\n"+ "Leave empty for trying to send without auth.") str("mail-password", "", "password of user to send mail with") str("mail-from", "noreply@localhost", "from line of mails") str("mail-helo", "localhost", "name of server to send mail from.") strSl("allowed-origins", allowedOrigins, "allow access for remote origins") str("geoserver-url", "http://localhost:8080/geoserver", "URL to GeoServer") str("geoserver-user", "admin", "GeoServer user") str("geoserver-password", "geoserver", "GeoServer password") bl("geoserver-clean", false, "Clean GeoServer setup") str("proxy-key", "", "signing key for proxy URLs.\n"+ "Defaults to random key.") str("proxy-prefix", "", "URL prefix of proxy.\n"+ "Defaults to 'http://${host}:${port}'") str("external-url", "", "URL to find the server from the outside.\n"+ "Defaults to 'http://${host}:${port}'") str("tmp-dir", "", "Temp directory of gemma server.\n"+ "Defaults to system temp directory.") str("schema-dirs", ".", "Directories to find XSD schema files in (recursive).") str("published-config", "", "path to a config file served to client.") str("report-path", "", "path to a report templates.") d("soap-timeout", 3*time.Minute, "Timeout till a SOAP request is canceled.") str("log-file", "", "path to a file to log to.") str("log-level", log.InfoLogLevel.String(), "path to a file to log to.") str("token-url", "", "URL to the ERDMS token server.") } var ( configCond = sync.NewCond(new(sync.Mutex)) configReady bool ) // Ready tells if the configuration is ready to use.. func Ready() { configCond.L.Lock() defer configCond.L.Unlock() configReady = true configCond.Broadcast() } // WaitReady blocks until the configuration is ready to use. // Call this if you have a go routine that needs configuration // support. This guarantees that the initialization is done // before accessing the configuration data. func WaitReady() { configCond.L.Lock() defer configCond.L.Unlock() for !configReady { configCond.Wait() } } func initConfig() { // Don't forget to read config either from cfgFile or from home directory! if configFile != "" { // Use config file from the flag. viper.SetConfigFile(configFile) } else { // Find home directory. home, err := homedir.Dir() if err != nil { lg.Fatalf("error: %v\n", err) } // Search config in home directory with name ".cobra" (without extension). viper.AddConfigPath(home) viper.SetConfigName(".gemma") } if err := viper.ReadInConfig(); err != nil { if _, ok := err.(viper.ConfigFileNotFoundError); ok && configFile == "" { // Don't bother if not found. return } lg.Fatalf("Can't read config: %v\n", err) } }