diff options
author | 2022-05-30 13:41:24 +0100 | |
---|---|---|
committer | 2022-05-30 14:41:24 +0200 | |
commit | 43ac0cdb9c4eea9d3c5eceb2c11b9e5b98b87b00 (patch) | |
tree | f0d5967d0ce639b6bc82aaf607f62e228fdf4559 /internal/config | |
parent | [chore] Mastodon api fixups (#617) (diff) | |
download | gotosocial-43ac0cdb9c4eea9d3c5eceb2c11b9e5b98b87b00.tar.xz |
[chore] Global server configuration overhaul (#575)
* move config flag names and usage to config package, rewrite config package to use global Configuration{} struct
Signed-off-by: kim <grufwub@gmail.com>
* improved code comment
Signed-off-by: kim <grufwub@gmail.com>
* linter
Signed-off-by: kim <grufwub@gmail.com>
* fix unmarshaling
Signed-off-by: kim <grufwub@gmail.com>
* remove kim's custom go compiler changes
Signed-off-by: kim <grufwub@gmail.com>
* generate setter and flag-name functions, implement these in codebase
Signed-off-by: kim <grufwub@gmail.com>
* update deps
Signed-off-by: kim <grufwub@gmail.com>
* small change
Signed-off-by: kim <grufwub@gmail.com>
* appease the linter...
Signed-off-by: kim <grufwub@gmail.com>
* move configuration into ConfigState structure, ensure reloading to/from viper settings to keep in sync
Signed-off-by: kim <grufwub@gmail.com>
* lint
Signed-off-by: kim <grufwub@gmail.com>
* update code comments
Signed-off-by: kim <grufwub@gmail.com>
* fix merge issue
Signed-off-by: kim <grufwub@gmail.com>
* fix merge issue
Signed-off-by: kim <grufwub@gmail.com>
* improved version string (removes time + go version)
Signed-off-by: kim <grufwub@gmail.com>
* fix version string build to pass test script + consolidate logic in func
Signed-off-by: kim <grufwub@gmail.com>
* add license text, update config.Defaults comment
Signed-off-by: kim <grufwub@gmail.com>
* add license text to generated config helpers file
Signed-off-by: kim <grufwub@gmail.com>
* defer unlock on config.Set___(), to ensure unlocked on panic
Signed-off-by: kim <grufwub@gmail.com>
* make it more obvious which cmd flags are being attached
Signed-off-by: kim <grufwub@gmail.com>
Diffstat (limited to 'internal/config')
-rw-r--r-- | internal/config/config.go | 139 | ||||
-rw-r--r-- | internal/config/defaults.go | 6 | ||||
-rw-r--r-- | internal/config/file.go | 38 | ||||
-rw-r--r-- | internal/config/flags.go | 157 | ||||
-rw-r--r-- | internal/config/gen/gen.go | 112 | ||||
-rw-r--r-- | internal/config/global.go | 53 | ||||
-rw-r--r-- | internal/config/helpers.gen.go | 1494 | ||||
-rw-r--r-- | internal/config/keys.go | 182 | ||||
-rw-r--r-- | internal/config/state.go | 136 | ||||
-rw-r--r-- | internal/config/validate.go | 14 | ||||
-rw-r--r-- | internal/config/validate_test.go | 15 | ||||
-rw-r--r-- | internal/config/values.go | 93 | ||||
-rw-r--r-- | internal/config/viper.go | 42 |
13 files changed, 2107 insertions, 374 deletions
diff --git a/internal/config/config.go b/internal/config/config.go new file mode 100644 index 000000000..431fbbe4d --- /dev/null +++ b/internal/config/config.go @@ -0,0 +1,139 @@ +/* + GoToSocial + Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +package config + +import ( + "reflect" + + "github.com/mitchellh/mapstructure" +) + +// cfgtype is the reflected type information of Configuration{}. +var cfgtype = reflect.TypeOf(Configuration{}) + +// fieldtag will fetch the string value for the given tag name +// on the given field name in the Configuration{} struct. +func fieldtag(field, tag string) string { + sfield, ok := cfgtype.FieldByName(field) + if !ok { + panic("unknown struct field") + } + return sfield.Tag.Get(tag) +} + +// Configuration represents global GTS server runtime configuration. +// +// Please note that if you update this struct's fields or tags, you +// will need to regenerate the global Getter/Setter helpers by running: +// `go run ./internal/config/gen/ -out ./internal/config/helpers.gen.go` +type Configuration struct { + LogLevel string `name:"log-level" usage:"Log level to run at: [trace, debug, info, warn, fatal]"` + LogDbQueries bool `name:"log-db-queries" usage:"Log database queries verbosely when log-level is trace or debug"` + ApplicationName string `name:"application-name" usage:"Name of the application, used in various places internally"` + ConfigPath string `name:"config-path" usage:"Path to a file containing gotosocial configuration. Values set in this file will be overwritten by values set as env vars or arguments"` + Host string `name:"host" usage:"Hostname to use for the server (eg., example.org, gotosocial.whatever.com). DO NOT change this on a server that's already run!"` + AccountDomain string `name:"account-domain" usage:"Domain to use in account names (eg., example.org, whatever.com). If not set, will default to the setting for host. DO NOT change this on a server that's already run!"` + Protocol string `name:"protocol" usage:"Protocol to use for the REST api of the server (only use http if you are debugging or behind a reverse proxy!)"` + BindAddress string `name:"bind-address" usage:"Bind address to use for the GoToSocial server (eg., 0.0.0.0, 172.138.0.9, [::], localhost). For ipv6, enclose the address in square brackets, eg [2001:db8::fed1]. Default binds to all interfaces."` + Port int `name:"port" usage:"Port to use for GoToSocial. Change this to 443 if you're running the binary directly on the host machine."` + TrustedProxies []string `name:"trusted-proxies" usage:"Proxies to trust when parsing x-forwarded headers into real IPs."` + SoftwareVersion string `name:"software-version" usage:""` + + DbType string `name:"db-type" usage:"Database type: eg., postgres"` + DbAddress string `name:"db-address" usage:"Database ipv4 address, hostname, or filename"` + DbPort int `name:"db-port" usage:"Database port"` + DbUser string `name:"db-user" usage:"Database username"` + DbPassword string `name:"db-password" usage:"Database password"` + DbDatabase string `name:"db-database" usage:"Database name"` + DbTLSMode string `name:"db-tls-mode" usage:"Database tls mode"` + DbTLSCACert string `name:"db-tls-ca-cert" usage:"Path to CA cert for db tls connection"` + + WebTemplateBaseDir string `name:"web-template-base-dir" usage:"Basedir for html templating files for rendering pages and composing emails."` + WebAssetBaseDir string `name:"web-asset-base-dir" usage:"Directory to serve static assets from, accessible at example.org/assets/"` + + AccountsRegistrationOpen bool `name:"accounts-registration-open" usage:"Allow anyone to submit an account signup request. If false, server will be invite-only."` + AccountsApprovalRequired bool `name:"accounts-approval-required" usage:"Do account signups require approval by an admin or moderator before user can log in? If false, new registrations will be automatically approved."` + AccountsReasonRequired bool `name:"accounts-reason-required" usage:"Do new account signups require a reason to be submitted on registration?"` + + MediaImageMaxSize int `name:"media-image-max-size" usage:"Max size of accepted images in bytes"` + MediaVideoMaxSize int `name:"media-video-max-size" usage:"Max size of accepted videos in bytes"` + MediaDescriptionMinChars int `name:"media-description-min-chars" usage:"Min required chars for an image description"` + MediaDescriptionMaxChars int `name:"media-description-max-chars" usage:"Max permitted chars for an image description"` + MediaRemoteCacheDays int `name:"media-remote-cache-days" usage:"Number of days to locally cache media from remote instances. If set to 0, remote media will be kept indefinitely."` + + StorageBackend string `name:"storage-backend" usage:"Storage backend to use for media attachments"` + StorageLocalBasePath string `name:"storage-local-base-path" usage:"Full path to an already-created directory where gts should store/retrieve media files. Subfolders will be created within this dir."` + + StatusesMaxChars int `name:"statuses-max-chars" usage:"Max permitted characters for posted statuses"` + StatusesCWMaxChars int `name:"statuses-cw-max-chars" usage:"Max permitted characters for content/spoiler warnings on statuses"` + StatusesPollMaxOptions int `name:"statuses-poll-max-options" usage:"Max amount of options permitted on a poll"` + StatusesPollOptionMaxChars int `name:"statuses-poll-option-max-chars" usage:"Max amount of characters for a poll option"` + StatusesMediaMaxFiles int `name:"statuses-media-max-files" usage:"Maximum number of media files/attachments per status"` + + LetsEncryptEnabled bool `name:"letsencrypt-enabled" usage:"Enable letsencrypt TLS certs for this server. If set to true, then cert dir also needs to be set (or take the default)."` + LetsEncryptPort int `name:"letsencrypt-port" usage:"Port to listen on for letsencrypt certificate challenges. Must not be the same as the GtS webserver/API port."` + LetsEncryptCertDir string `name:"letsencrypt-cert-dir" usage:"Directory to store acquired letsencrypt certificates."` + LetsEncryptEmailAddress string `name:"letsencrypt-email-address" usage:"Email address to use when requesting letsencrypt certs. Will receive updates on cert expiry etc."` + + OIDCEnabled bool `name:"oidc-enabled" usage:"Enabled OIDC authorization for this instance. If set to true, then the other OIDC flags must also be set."` + OIDCIdpName string `name:"oidc-idp-name" usage:"Name of the OIDC identity provider. Will be shown to the user when logging in."` + OIDCSkipVerification bool `name:"oidc-skip-verification" usage:"Skip verification of tokens returned by the OIDC provider. Should only be set to 'true' for testing purposes, never in a production environment!"` + OIDCIssuer string `name:"oidc-issuer" usage:"Address of the OIDC issuer. Should be the web address, including protocol, at which the issuer can be reached. Eg., 'https://example.org/auth'"` + OIDCClientID string `name:"oidc-client-id" usage:"ClientID of GoToSocial, as registered with the OIDC provider."` + OIDCClientSecret string `name:"oidc-client-secret" usage:"ClientSecret of GoToSocial, as registered with the OIDC provider."` + OIDCScopes []string `name:"oidc-scopes" usage:"OIDC scopes."` + + SMTPHost string `name:"smtp-host" usage:"Host of the smtp server. Eg., 'smtp.eu.mailgun.org'"` + SMTPPort int `name:"smtp-port" usage:"Port of the smtp server. Eg., 587"` + SMTPUsername string `name:"smtp-username" usage:"Username to authenticate with the smtp server as. Eg., 'postmaster@mail.example.org'"` + SMTPPassword string `name:"smtp-password" usage:"Password to pass to the smtp server."` + SMTPFrom string `name:"smtp-from" usage:"Address to use as the 'from' field of the email. Eg., 'gotosocial@example.org'"` + + SyslogEnabled bool `name:"syslog-enabled" usage:"Enable the syslog logging hook. Logs will be mirrored to the configured destination."` + SyslogProtocol string `name:"syslog-protocol" usage:"Protocol to use when directing logs to syslog. Leave empty to connect to local syslog."` + SyslogAddress string `name:"syslog-address" usage:"Address:port to send syslog logs to. Leave empty to connect to local syslog."` + + // TODO: move these elsewhere, these are more ephemeral vs long-running flags like above + AdminAccountUsername string `name:"username" usage:"the username to create/delete/etc"` + AdminAccountEmail string `name:"email" usage:"the email address of this account"` + AdminAccountPassword string `name:"password" usage:"the password to set for this account"` + AdminTransPath string `name:"path" usage:"the path of the file to import from/export to"` +} + +// MarshalMap will marshal current Configuration into a map structure (useful for JSON). +func (cfg *Configuration) MarshalMap() (map[string]interface{}, error) { + var dst map[string]interface{} + dec, _ := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + TagName: "name", + Result: &dst, + }) + if err := dec.Decode(cfg); err != nil { + return nil, err + } + return dst, nil +} + +// UnmarshalMap will unmarshal a map structure into the receiving Configuration. +func (cfg *Configuration) UnmarshalMap(src map[string]interface{}) error { + dec, _ := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + TagName: "name", + Result: cfg, + }) + return dec.Decode(src) +} diff --git a/internal/config/defaults.go b/internal/config/defaults.go index 847f10c81..75af21222 100644 --- a/internal/config/defaults.go +++ b/internal/config/defaults.go @@ -20,9 +20,9 @@ package config import "github.com/coreos/go-oidc/v3/oidc" -// Defaults returns a populated Values struct with most of the values set to reasonable defaults. -// Note that if you use this, you still need to set Host and, if desired, ConfigPath. -var Defaults = Values{ +// Defaults contains a populated Configuration with reasonable defaults. Note that +// if you use this, you will still need to set Host, and, if desired, ConfigPath. +var Defaults = Configuration{ LogLevel: "info", LogDbQueries: false, ApplicationName: "gotosocial", diff --git a/internal/config/file.go b/internal/config/file.go deleted file mode 100644 index 75d273fed..000000000 --- a/internal/config/file.go +++ /dev/null @@ -1,38 +0,0 @@ -/* - GoToSocial - Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -package config - -import ( - "github.com/spf13/viper" -) - -// ReadFromFile checks if there's already a path to the config file set in viper. -// If there is, it will attempt to read the config file into viper. -func ReadFromFile() error { - // config file stuff - // check if we have a config path set (either by cli arg or env var) - if configPath := viper.GetString(Keys.ConfigPath); configPath != "" { - viper.SetConfigFile(configPath) - if err := viper.ReadInConfig(); err != nil { - return err - } - } - - return nil -} diff --git a/internal/config/flags.go b/internal/config/flags.go new file mode 100644 index 000000000..0be372551 --- /dev/null +++ b/internal/config/flags.go @@ -0,0 +1,157 @@ +/* + GoToSocial + Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +package config + +import ( + "github.com/spf13/cobra" +) + +// TODO: consolidate these methods into the Configuration{} or ConfigState{} structs. + +// AddGlobalFlags will attach global configuration flags to given cobra command, loading defaults from global config. +func AddGlobalFlags(cmd *cobra.Command) { + Config(func(cfg *Configuration) { + // General + cmd.PersistentFlags().String(ApplicationNameFlag(), cfg.ApplicationName, fieldtag("ApplicationName", "usage")) + cmd.PersistentFlags().String(HostFlag(), cfg.Host, fieldtag("Host", "usage")) + cmd.PersistentFlags().String(AccountDomainFlag(), cfg.AccountDomain, fieldtag("AccountDomain", "usage")) + cmd.PersistentFlags().String(ProtocolFlag(), cfg.Protocol, fieldtag("Protocol", "usage")) + cmd.PersistentFlags().String(LogLevelFlag(), cfg.LogLevel, fieldtag("LogLevel", "usage")) + cmd.PersistentFlags().Bool(LogDbQueriesFlag(), cfg.LogDbQueries, fieldtag("LogDbQueries", "usage")) + cmd.PersistentFlags().String(ConfigPathFlag(), cfg.ConfigPath, fieldtag("ConfigPath", "usage")) + + // Database + cmd.PersistentFlags().String(DbTypeFlag(), cfg.DbType, fieldtag("DbType", "usage")) + cmd.PersistentFlags().String(DbAddressFlag(), cfg.DbAddress, fieldtag("DbAddress", "usage")) + cmd.PersistentFlags().Int(DbPortFlag(), cfg.DbPort, fieldtag("DbPort", "usage")) + cmd.PersistentFlags().String(DbUserFlag(), cfg.DbUser, fieldtag("DbUser", "usage")) + cmd.PersistentFlags().String(DbPasswordFlag(), cfg.DbPassword, fieldtag("DbPassword", "usage")) + cmd.PersistentFlags().String(DbDatabaseFlag(), cfg.DbDatabase, fieldtag("DbDatabase", "usage")) + cmd.PersistentFlags().String(DbTLSModeFlag(), cfg.DbTLSMode, fieldtag("DbTLSMode", "usage")) + cmd.PersistentFlags().String(DbTLSCACertFlag(), cfg.DbTLSCACert, fieldtag("DbTLSCACert", "usage")) + }) +} + +// AddServerFlags will attach server configuration flags to given cobra command, loading defaults from global config. +func AddServerFlags(cmd *cobra.Command) { + Config(func(cfg *Configuration) { + // Router + cmd.PersistentFlags().String(BindAddressFlag(), cfg.BindAddress, fieldtag("BindAddress", "usage")) + cmd.PersistentFlags().Int(PortFlag(), cfg.Port, fieldtag("Port", "usage")) + cmd.PersistentFlags().StringSlice(TrustedProxiesFlag(), cfg.TrustedProxies, fieldtag("TrustedProxies", "usage")) + + // Template + cmd.Flags().String(WebTemplateBaseDirFlag(), cfg.WebTemplateBaseDir, fieldtag("WebTemplateBaseDir", "usage")) + cmd.Flags().String(WebAssetBaseDirFlag(), cfg.WebAssetBaseDir, fieldtag("WebAssetBaseDir", "usage")) + + // Accounts + cmd.Flags().Bool(AccountsRegistrationOpenFlag(), cfg.AccountsRegistrationOpen, fieldtag("AccountsRegistrationOpen", "usage")) + cmd.Flags().Bool(AccountsApprovalRequiredFlag(), cfg.AccountsApprovalRequired, fieldtag("AccountsApprovalRequired", "usage")) + cmd.Flags().Bool(AccountsReasonRequiredFlag(), cfg.AccountsReasonRequired, fieldtag("AccountsReasonRequired", "usage")) + + // Media + cmd.Flags().Int(MediaImageMaxSizeFlag(), cfg.MediaImageMaxSize, fieldtag("MediaImageMaxSize", "usage")) + cmd.Flags().Int(MediaVideoMaxSizeFlag(), cfg.MediaVideoMaxSize, fieldtag("MediaVideoMaxSize", "usage")) + cmd.Flags().Int(MediaDescriptionMinCharsFlag(), cfg.MediaDescriptionMinChars, fieldtag("MediaDescriptionMinChars", "usage")) + cmd.Flags().Int(MediaDescriptionMaxCharsFlag(), cfg.MediaDescriptionMaxChars, fieldtag("MediaDescriptionMaxChars", "usage")) + cmd.Flags().Int(MediaRemoteCacheDaysFlag(), cfg.MediaRemoteCacheDays, fieldtag("MediaRemoteCacheDays", "usage")) + + // Storage + cmd.Flags().String(StorageBackendFlag(), cfg.StorageBackend, fieldtag("StorageBackend", "usage")) + cmd.Flags().String(StorageLocalBasePathFlag(), cfg.StorageLocalBasePath, fieldtag("StorageLocalBasePath", "usage")) + + // Statuses + cmd.Flags().Int(StatusesMaxCharsFlag(), cfg.StatusesMaxChars, fieldtag("StatusesMaxChars", "usage")) + cmd.Flags().Int(StatusesCWMaxCharsFlag(), cfg.StatusesCWMaxChars, fieldtag("StatusesCWMaxChars", "usage")) + cmd.Flags().Int(StatusesPollMaxOptionsFlag(), cfg.StatusesPollMaxOptions, fieldtag("StatusesPollMaxOptions", "usage")) + cmd.Flags().Int(StatusesPollOptionMaxCharsFlag(), cfg.StatusesPollOptionMaxChars, fieldtag("StatusesPollOptionMaxChars", "usage")) + cmd.Flags().Int(StatusesMediaMaxFilesFlag(), cfg.StatusesMediaMaxFiles, fieldtag("StatusesMediaMaxFiles", "usage")) + + // LetsEncrypt + cmd.Flags().Bool(LetsEncryptEnabledFlag(), cfg.LetsEncryptEnabled, fieldtag("LetsEncryptEnabled", "usage")) + cmd.Flags().Int(LetsEncryptPortFlag(), cfg.LetsEncryptPort, fieldtag("LetsEncryptPort", "usage")) + cmd.Flags().String(LetsEncryptCertDirFlag(), cfg.LetsEncryptCertDir, fieldtag("LetsEncryptCertDir", "usage")) + cmd.Flags().String(LetsEncryptEmailAddressFlag(), cfg.LetsEncryptEmailAddress, fieldtag("LetsEncryptEmailAddress", "usage")) + + // OIDC + cmd.Flags().Bool(OIDCEnabledFlag(), cfg.OIDCEnabled, fieldtag("OIDCEnabled", "usage")) + cmd.Flags().String(OIDCIdpNameFlag(), cfg.OIDCIdpName, fieldtag("OIDCIdpName", "usage")) + cmd.Flags().Bool(OIDCSkipVerificationFlag(), cfg.OIDCSkipVerification, fieldtag("OIDCSkipVerification", "usage")) + cmd.Flags().String(OIDCIssuerFlag(), cfg.OIDCIssuer, fieldtag("OIDCIssuer", "usage")) + cmd.Flags().String(OIDCClientIDFlag(), cfg.OIDCClientID, fieldtag("OIDCClientID", "usage")) + cmd.Flags().String(OIDCClientSecretFlag(), cfg.OIDCClientSecret, fieldtag("OIDCClientSecret", "usage")) + cmd.Flags().StringSlice(OIDCScopesFlag(), cfg.OIDCScopes, fieldtag("OIDCScopes", "usage")) + + // SMTP + cmd.Flags().String(SMTPHostFlag(), cfg.SMTPHost, fieldtag("SMTPHost", "usage")) + cmd.Flags().Int(SMTPPortFlag(), cfg.SMTPPort, fieldtag("SMTPPort", "usage")) + cmd.Flags().String(SMTPUsernameFlag(), cfg.SMTPUsername, fieldtag("SMTPUsername", "usage")) + cmd.Flags().String(SMTPPasswordFlag(), cfg.SMTPPassword, fieldtag("SMTPPassword", "usage")) + cmd.Flags().String(SMTPFromFlag(), cfg.SMTPFrom, fieldtag("SMTPFrom", "usage")) + + // Syslog + cmd.Flags().Bool(SyslogEnabledFlag(), cfg.SyslogEnabled, fieldtag("SyslogEnabled", "usage")) + cmd.Flags().String(SyslogProtocolFlag(), cfg.SyslogProtocol, fieldtag("SyslogProtocol", "usage")) + cmd.Flags().String(SyslogAddressFlag(), cfg.SyslogAddress, fieldtag("SyslogAddress", "usage")) + }) +} + +// AddAdminAccount attaches flags pertaining to admin account actions. +func AddAdminAccount(cmd *cobra.Command) { + name := AdminAccountUsernameFlag() + usage := fieldtag("AdminAccountUsername", "usage") + cmd.Flags().String(name, "", usage) // REQUIRED + if err := cmd.MarkFlagRequired(name); err != nil { + panic(err) + } +} + +// AddAdminAccountPassword attaches flags pertaining to admin account password reset. +func AddAdminAccountPassword(cmd *cobra.Command) { + name := AdminAccountPasswordFlag() + usage := fieldtag("AdminAccountPassword", "usage") + cmd.Flags().String(name, "", usage) // REQUIRED + if err := cmd.MarkFlagRequired(name); err != nil { + panic(err) + } +} + +// AddAdminAccountCreate attaches flags pertaining to admin account creation. +func AddAdminAccountCreate(cmd *cobra.Command) { + // Requires both account and password + AddAdminAccount(cmd) + AddAdminAccountPassword(cmd) + + name := AdminAccountEmailFlag() + usage := fieldtag("AdminAccountEmail", "usage") + cmd.Flags().String(name, "", usage) // REQUIRED + if err := cmd.MarkFlagRequired(name); err != nil { + panic(err) + } +} + +// AddAdminTrans attaches flags pertaining to import/export commands. +func AddAdminTrans(cmd *cobra.Command) { + name := AdminTransPathFlag() + usage := fieldtag("AdminTransPath", "usage") + cmd.Flags().String(name, "", usage) // REQUIRED + if err := cmd.MarkFlagRequired(name); err != nil { + panic(err) + } +} diff --git a/internal/config/gen/gen.go b/internal/config/gen/gen.go new file mode 100644 index 000000000..d36fee0e9 --- /dev/null +++ b/internal/config/gen/gen.go @@ -0,0 +1,112 @@ +/* + GoToSocial + Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +package main + +import ( + "flag" + "fmt" + "os" + "os/exec" + "reflect" + + "github.com/superseriousbusiness/gotosocial/internal/config" +) + +const license = `/* + GoToSocial + Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +` + +func main() { + var ( + out string + gen string + ) + + // Load runtime config flags + flag.StringVar(&out, "out", "", "Generated file output path") + flag.StringVar(&gen, "gen", "helpers", "Type of file to generate (helpers)") + flag.Parse() + + // Open output file path + output, err := os.OpenFile(out, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o644) + if err != nil { + panic(err) + } + + switch gen { + // Generate config field helper methods + case "helpers": + fmt.Fprint(output, "// THIS IS A GENERATED FILE, DO NOT EDIT BY HAND\n") + fmt.Fprint(output, license) + fmt.Fprint(output, "package config\n\n") + t := reflect.TypeOf(config.Configuration{}) + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + + // ConfigState structure helper methods + fmt.Fprintf(output, "// Get%s safely fetches the Configuration value for state's '%s' field\n", field.Name, field.Name) + fmt.Fprintf(output, "func (st *ConfigState) Get%s() (v %s) {\n", field.Name, field.Type.String()) + fmt.Fprintf(output, "\tst.mutex.Lock()\n") + fmt.Fprintf(output, "\tv = st.config.%s\n", field.Name) + fmt.Fprintf(output, "\tst.mutex.Unlock()\n") + fmt.Fprintf(output, "\treturn\n") + fmt.Fprintf(output, "}\n\n") + fmt.Fprintf(output, "// Set%s safely sets the Configuration value for state's '%s' field\n", field.Name, field.Name) + fmt.Fprintf(output, "func (st *ConfigState) Set%s(v %s) {\n", field.Name, field.Type.String()) + fmt.Fprintf(output, "\tst.mutex.Lock()\n") + fmt.Fprintf(output, "\tdefer st.mutex.Unlock()\n") + fmt.Fprintf(output, "\tst.config.%s = v\n", field.Name) + fmt.Fprintf(output, "\tst.reloadToViper()\n") + fmt.Fprintf(output, "}\n\n") + + // Global ConfigState helper methods + // TODO: remove when we pass around a ConfigState{} + fmt.Fprintf(output, "// %sFlag returns the flag name for the '%s' field\n", field.Name, field.Name) + fmt.Fprintf(output, "func %sFlag() string { return \"%s\" }\n\n", field.Name, field.Tag.Get("name")) + fmt.Fprintf(output, "// Get%s safely fetches the value for global configuration '%s' field\n", field.Name, field.Name) + fmt.Fprintf(output, "func Get%[1]s() %[2]s { return global.Get%[1]s() }\n\n", field.Name, field.Type.String()) + fmt.Fprintf(output, "// Set%s safely sets the value for global configuration '%s' field\n", field.Name, field.Name) + fmt.Fprintf(output, "func Set%[1]s(v %[2]s) { global.Set%[1]s(v) }\n\n", field.Name, field.Type.String()) + } + _ = output.Close() + _ = exec.Command("gofmt", "-w", out).Run() + + // The plain here is that eventually we might be able + // to generate an example configuration from struct tags + + // Unknown type + default: + panic("unknown generation type: " + gen) + } +} diff --git a/internal/config/global.go b/internal/config/global.go new file mode 100644 index 000000000..8752fc925 --- /dev/null +++ b/internal/config/global.go @@ -0,0 +1,53 @@ +/* + GoToSocial + Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +package config + +import "github.com/spf13/cobra" + +var global *ConfigState + +func init() { + // init global state + global = NewState() +} + +// TODO: in the future we should move away from using globals in this config +// package, and instead pass the ConfigState round in a global gts state. + +// Config provides you safe access to the global configuration. +func Config(fn func(cfg *Configuration)) { + global.Config(fn) +} + +// Reload will reload the current configuration values from file. +func Reload() error { + return global.Reload() +} + +// LoadEarlyFlags will bind specific flags from given Cobra command to global viper +// instance, and load the current configuration values. This is useful for flags like +// .ConfigPath which have to parsed first in order to perform early configuration load. +func LoadEarlyFlags(cmd *cobra.Command) error { + return global.LoadEarlyFlags(cmd) +} + +// BindFlags binds given command's pflags to the global viper instance. +func BindFlags(cmd *cobra.Command) error { + return global.BindFlags(cmd) +} diff --git a/internal/config/helpers.gen.go b/internal/config/helpers.gen.go new file mode 100644 index 000000000..a90199495 --- /dev/null +++ b/internal/config/helpers.gen.go @@ -0,0 +1,1494 @@ +// THIS IS A GENERATED FILE, DO NOT EDIT BY HAND +/* + GoToSocial + Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package config + +// GetLogLevel safely fetches the Configuration value for state's 'LogLevel' field +func (st *ConfigState) GetLogLevel() (v string) { + st.mutex.Lock() + v = st.config.LogLevel + st.mutex.Unlock() + return +} + +// SetLogLevel safely sets the Configuration value for state's 'LogLevel' field +func (st *ConfigState) SetLogLevel(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.LogLevel = v + st.reloadToViper() +} + +// LogLevelFlag returns the flag name for the 'LogLevel' field +func LogLevelFlag() string { return "log-level" } + +// GetLogLevel safely fetches the value for global configuration 'LogLevel' field +func GetLogLevel() string { return global.GetLogLevel() } + +// SetLogLevel safely sets the value for global configuration 'LogLevel' field +func SetLogLevel(v string) { global.SetLogLevel(v) } + +// GetLogDbQueries safely fetches the Configuration value for state's 'LogDbQueries' field +func (st *ConfigState) GetLogDbQueries() (v bool) { + st.mutex.Lock() + v = st.config.LogDbQueries + st.mutex.Unlock() + return +} + +// SetLogDbQueries safely sets the Configuration value for state's 'LogDbQueries' field +func (st *ConfigState) SetLogDbQueries(v bool) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.LogDbQueries = v + st.reloadToViper() +} + +// LogDbQueriesFlag returns the flag name for the 'LogDbQueries' field +func LogDbQueriesFlag() string { return "log-db-queries" } + +// GetLogDbQueries safely fetches the value for global configuration 'LogDbQueries' field +func GetLogDbQueries() bool { return global.GetLogDbQueries() } + +// SetLogDbQueries safely sets the value for global configuration 'LogDbQueries' field +func SetLogDbQueries(v bool) { global.SetLogDbQueries(v) } + +// GetApplicationName safely fetches the Configuration value for state's 'ApplicationName' field +func (st *ConfigState) GetApplicationName() (v string) { + st.mutex.Lock() + v = st.config.ApplicationName + st.mutex.Unlock() + return +} + +// SetApplicationName safely sets the Configuration value for state's 'ApplicationName' field +func (st *ConfigState) SetApplicationName(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.ApplicationName = v + st.reloadToViper() +} + +// ApplicationNameFlag returns the flag name for the 'ApplicationName' field +func ApplicationNameFlag() string { return "application-name" } + +// GetApplicationName safely fetches the value for global configuration 'ApplicationName' field +func GetApplicationName() string { return global.GetApplicationName() } + +// SetApplicationName safely sets the value for global configuration 'ApplicationName' field +func SetApplicationName(v string) { global.SetApplicationName(v) } + +// GetConfigPath safely fetches the Configuration value for state's 'ConfigPath' field +func (st *ConfigState) GetConfigPath() (v string) { + st.mutex.Lock() + v = st.config.ConfigPath + st.mutex.Unlock() + return +} + +// SetConfigPath safely sets the Configuration value for state's 'ConfigPath' field +func (st *ConfigState) SetConfigPath(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.ConfigPath = v + st.reloadToViper() +} + +// ConfigPathFlag returns the flag name for the 'ConfigPath' field +func ConfigPathFlag() string { return "config-path" } + +// GetConfigPath safely fetches the value for global configuration 'ConfigPath' field +func GetConfigPath() string { return global.GetConfigPath() } + +// SetConfigPath safely sets the value for global configuration 'ConfigPath' field +func SetConfigPath(v string) { global.SetConfigPath(v) } + +// GetHost safely fetches the Configuration value for state's 'Host' field +func (st *ConfigState) GetHost() (v string) { + st.mutex.Lock() + v = st.config.Host + st.mutex.Unlock() + return +} + +// SetHost safely sets the Configuration value for state's 'Host' field +func (st *ConfigState) SetHost(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Host = v + st.reloadToViper() +} + +// HostFlag returns the flag name for the 'Host' field +func HostFlag() string { return "host" } + +// GetHost safely fetches the value for global configuration 'Host' field +func GetHost() string { return global.GetHost() } + +// SetHost safely sets the value for global configuration 'Host' field +func SetHost(v string) { global.SetHost(v) } + +// GetAccountDomain safely fetches the Configuration value for state's 'AccountDomain' field +func (st *ConfigState) GetAccountDomain() (v string) { + st.mutex.Lock() + v = st.config.AccountDomain + st.mutex.Unlock() + return +} + +// SetAccountDomain safely sets the Configuration value for state's 'AccountDomain' field +func (st *ConfigState) SetAccountDomain(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.AccountDomain = v + st.reloadToViper() +} + +// AccountDomainFlag returns the flag name for the 'AccountDomain' field +func AccountDomainFlag() string { return "account-domain" } + +// GetAccountDomain safely fetches the value for global configuration 'AccountDomain' field +func GetAccountDomain() string { return global.GetAccountDomain() } + +// SetAccountDomain safely sets the value for global configuration 'AccountDomain' field +func SetAccountDomain(v string) { global.SetAccountDomain(v) } + +// GetProtocol safely fetches the Configuration value for state's 'Protocol' field +func (st *ConfigState) GetProtocol() (v string) { + st.mutex.Lock() + v = st.config.Protocol + st.mutex.Unlock() + return +} + +// SetProtocol safely sets the Configuration value for state's 'Protocol' field +func (st *ConfigState) SetProtocol(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Protocol = v + st.reloadToViper() +} + +// ProtocolFlag returns the flag name for the 'Protocol' field +func ProtocolFlag() string { return "protocol" } + +// GetProtocol safely fetches the value for global configuration 'Protocol' field +func GetProtocol() string { return global.GetProtocol() } + +// SetProtocol safely sets the value for global configuration 'Protocol' field +func SetProtocol(v string) { global.SetProtocol(v) } + +// GetBindAddress safely fetches the Configuration value for state's 'BindAddress' field +func (st *ConfigState) GetBindAddress() (v string) { + st.mutex.Lock() + v = st.config.BindAddress + st.mutex.Unlock() + return +} + +// SetBindAddress safely sets the Configuration value for state's 'BindAddress' field +func (st *ConfigState) SetBindAddress(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.BindAddress = v + st.reloadToViper() +} + +// BindAddressFlag returns the flag name for the 'BindAddress' field +func BindAddressFlag() string { return "bind-address" } + +// GetBindAddress safely fetches the value for global configuration 'BindAddress' field +func GetBindAddress() string { return global.GetBindAddress() } + +// SetBindAddress safely sets the value for global configuration 'BindAddress' field +func SetBindAddress(v string) { global.SetBindAddress(v) } + +// GetPort safely fetches the Configuration value for state's 'Port' field +func (st *ConfigState) GetPort() (v int) { + st.mutex.Lock() + v = st.config.Port + st.mutex.Unlock() + return +} + +// SetPort safely sets the Configuration value for state's 'Port' field +func (st *ConfigState) SetPort(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.Port = v + st.reloadToViper() +} + +// PortFlag returns the flag name for the 'Port' field +func PortFlag() string { return "port" } + +// GetPort safely fetches the value for global configuration 'Port' field +func GetPort() int { return global.GetPort() } + +// SetPort safely sets the value for global configuration 'Port' field +func SetPort(v int) { global.SetPort(v) } + +// GetTrustedProxies safely fetches the Configuration value for state's 'TrustedProxies' field +func (st *ConfigState) GetTrustedProxies() (v []string) { + st.mutex.Lock() + v = st.config.TrustedProxies + st.mutex.Unlock() + return +} + +// SetTrustedProxies safely sets the Configuration value for state's 'TrustedProxies' field +func (st *ConfigState) SetTrustedProxies(v []string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.TrustedProxies = v + st.reloadToViper() +} + +// TrustedProxiesFlag returns the flag name for the 'TrustedProxies' field +func TrustedProxiesFlag() string { return "trusted-proxies" } + +// GetTrustedProxies safely fetches the value for global configuration 'TrustedProxies' field +func GetTrustedProxies() []string { return global.GetTrustedProxies() } + +// SetTrustedProxies safely sets the value for global configuration 'TrustedProxies' field +func SetTrustedProxies(v []string) { global.SetTrustedProxies(v) } + +// GetSoftwareVersion safely fetches the Configuration value for state's 'SoftwareVersion' field +func (st *ConfigState) GetSoftwareVersion() (v string) { + st.mutex.Lock() + v = st.config.SoftwareVersion + st.mutex.Unlock() + return +} + +// SetSoftwareVersion safely sets the Configuration value for state's 'SoftwareVersion' field +func (st *ConfigState) SetSoftwareVersion(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.SoftwareVersion = v + st.reloadToViper() +} + +// SoftwareVersionFlag returns the flag name for the 'SoftwareVersion' field +func SoftwareVersionFlag() string { return "software-version" } + +// GetSoftwareVersion safely fetches the value for global configuration 'SoftwareVersion' field +func GetSoftwareVersion() string { return global.GetSoftwareVersion() } + +// SetSoftwareVersion safely sets the value for global configuration 'SoftwareVersion' field +func SetSoftwareVersion(v string) { global.SetSoftwareVersion(v) } + +// GetDbType safely fetches the Configuration value for state's 'DbType' field +func (st *ConfigState) GetDbType() (v string) { + st.mutex.Lock() + v = st.config.DbType + st.mutex.Unlock() + return +} + +// SetDbType safely sets the Configuration value for state's 'DbType' field +func (st *ConfigState) SetDbType(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.DbType = v + st.reloadToViper() +} + +// DbTypeFlag returns the flag name for the 'DbType' field +func DbTypeFlag() string { return "db-type" } + +// GetDbType safely fetches the value for global configuration 'DbType' field +func GetDbType() string { return global.GetDbType() } + +// SetDbType safely sets the value for global configuration 'DbType' field +func SetDbType(v string) { global.SetDbType(v) } + +// GetDbAddress safely fetches the Configuration value for state's 'DbAddress' field +func (st *ConfigState) GetDbAddress() (v string) { + st.mutex.Lock() + v = st.config.DbAddress + st.mutex.Unlock() + return +} + +// SetDbAddress safely sets the Configuration value for state's 'DbAddress' field +func (st *ConfigState) SetDbAddress(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.DbAddress = v + st.reloadToViper() +} + +// DbAddressFlag returns the flag name for the 'DbAddress' field +func DbAddressFlag() string { return "db-address" } + +// GetDbAddress safely fetches the value for global configuration 'DbAddress' field +func GetDbAddress() string { return global.GetDbAddress() } + +// SetDbAddress safely sets the value for global configuration 'DbAddress' field +func SetDbAddress(v string) { global.SetDbAddress(v) } + +// GetDbPort safely fetches the Configuration value for state's 'DbPort' field +func (st *ConfigState) GetDbPort() (v int) { + st.mutex.Lock() + v = st.config.DbPort + st.mutex.Unlock() + return +} + +// SetDbPort safely sets the Configuration value for state's 'DbPort' field +func (st *ConfigState) SetDbPort(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.DbPort = v + st.reloadToViper() +} + +// DbPortFlag returns the flag name for the 'DbPort' field +func DbPortFlag() string { return "db-port" } + +// GetDbPort safely fetches the value for global configuration 'DbPort' field +func GetDbPort() int { return global.GetDbPort() } + +// SetDbPort safely sets the value for global configuration 'DbPort' field +func SetDbPort(v int) { global.SetDbPort(v) } + +// GetDbUser safely fetches the Configuration value for state's 'DbUser' field +func (st *ConfigState) GetDbUser() (v string) { + st.mutex.Lock() + v = st.config.DbUser + st.mutex.Unlock() + return +} + +// SetDbUser safely sets the Configuration value for state's 'DbUser' field +func (st *ConfigState) SetDbUser(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.DbUser = v + st.reloadToViper() +} + +// DbUserFlag returns the flag name for the 'DbUser' field +func DbUserFlag() string { return "db-user" } + +// GetDbUser safely fetches the value for global configuration 'DbUser' field +func GetDbUser() string { return global.GetDbUser() } + +// SetDbUser safely sets the value for global configuration 'DbUser' field +func SetDbUser(v string) { global.SetDbUser(v) } + +// GetDbPassword safely fetches the Configuration value for state's 'DbPassword' field +func (st *ConfigState) GetDbPassword() (v string) { + st.mutex.Lock() + v = st.config.DbPassword + st.mutex.Unlock() + return +} + +// SetDbPassword safely sets the Configuration value for state's 'DbPassword' field +func (st *ConfigState) SetDbPassword(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.DbPassword = v + st.reloadToViper() +} + +// DbPasswordFlag returns the flag name for the 'DbPassword' field +func DbPasswordFlag() string { return "db-password" } + +// GetDbPassword safely fetches the value for global configuration 'DbPassword' field +func GetDbPassword() string { return global.GetDbPassword() } + +// SetDbPassword safely sets the value for global configuration 'DbPassword' field +func SetDbPassword(v string) { global.SetDbPassword(v) } + +// GetDbDatabase safely fetches the Configuration value for state's 'DbDatabase' field +func (st *ConfigState) GetDbDatabase() (v string) { + st.mutex.Lock() + v = st.config.DbDatabase + st.mutex.Unlock() + return +} + +// SetDbDatabase safely sets the Configuration value for state's 'DbDatabase' field +func (st *ConfigState) SetDbDatabase(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.DbDatabase = v + st.reloadToViper() +} + +// DbDatabaseFlag returns the flag name for the 'DbDatabase' field +func DbDatabaseFlag() string { return "db-database" } + +// GetDbDatabase safely fetches the value for global configuration 'DbDatabase' field +func GetDbDatabase() string { return global.GetDbDatabase() } + +// SetDbDatabase safely sets the value for global configuration 'DbDatabase' field +func SetDbDatabase(v string) { global.SetDbDatabase(v) } + +// GetDbTLSMode safely fetches the Configuration value for state's 'DbTLSMode' field +func (st *ConfigState) GetDbTLSMode() (v string) { + st.mutex.Lock() + v = st.config.DbTLSMode + st.mutex.Unlock() + return +} + +// SetDbTLSMode safely sets the Configuration value for state's 'DbTLSMode' field +func (st *ConfigState) SetDbTLSMode(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.DbTLSMode = v + st.reloadToViper() +} + +// DbTLSModeFlag returns the flag name for the 'DbTLSMode' field +func DbTLSModeFlag() string { return "db-tls-mode" } + +// GetDbTLSMode safely fetches the value for global configuration 'DbTLSMode' field +func GetDbTLSMode() string { return global.GetDbTLSMode() } + +// SetDbTLSMode safely sets the value for global configuration 'DbTLSMode' field +func SetDbTLSMode(v string) { global.SetDbTLSMode(v) } + +// GetDbTLSCACert safely fetches the Configuration value for state's 'DbTLSCACert' field +func (st *ConfigState) GetDbTLSCACert() (v string) { + st.mutex.Lock() + v = st.config.DbTLSCACert + st.mutex.Unlock() + return +} + +// SetDbTLSCACert safely sets the Configuration value for state's 'DbTLSCACert' field +func (st *ConfigState) SetDbTLSCACert(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.DbTLSCACert = v + st.reloadToViper() +} + +// DbTLSCACertFlag returns the flag name for the 'DbTLSCACert' field +func DbTLSCACertFlag() string { return "db-tls-ca-cert" } + +// GetDbTLSCACert safely fetches the value for global configuration 'DbTLSCACert' field +func GetDbTLSCACert() string { return global.GetDbTLSCACert() } + +// SetDbTLSCACert safely sets the value for global configuration 'DbTLSCACert' field +func SetDbTLSCACert(v string) { global.SetDbTLSCACert(v) } + +// GetWebTemplateBaseDir safely fetches the Configuration value for state's 'WebTemplateBaseDir' field +func (st *ConfigState) GetWebTemplateBaseDir() (v string) { + st.mutex.Lock() + v = st.config.WebTemplateBaseDir + st.mutex.Unlock() + return +} + +// SetWebTemplateBaseDir safely sets the Configuration value for state's 'WebTemplateBaseDir' field +func (st *ConfigState) SetWebTemplateBaseDir(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.WebTemplateBaseDir = v + st.reloadToViper() +} + +// WebTemplateBaseDirFlag returns the flag name for the 'WebTemplateBaseDir' field +func WebTemplateBaseDirFlag() string { return "web-template-base-dir" } + +// GetWebTemplateBaseDir safely fetches the value for global configuration 'WebTemplateBaseDir' field +func GetWebTemplateBaseDir() string { return global.GetWebTemplateBaseDir() } + +// SetWebTemplateBaseDir safely sets the value for global configuration 'WebTemplateBaseDir' field +func SetWebTemplateBaseDir(v string) { global.SetWebTemplateBaseDir(v) } + +// GetWebAssetBaseDir safely fetches the Configuration value for state's 'WebAssetBaseDir' field +func (st *ConfigState) GetWebAssetBaseDir() (v string) { + st.mutex.Lock() + v = st.config.WebAssetBaseDir + st.mutex.Unlock() + return +} + +// SetWebAssetBaseDir safely sets the Configuration value for state's 'WebAssetBaseDir' field +func (st *ConfigState) SetWebAssetBaseDir(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.WebAssetBaseDir = v + st.reloadToViper() +} + +// WebAssetBaseDirFlag returns the flag name for the 'WebAssetBaseDir' field +func WebAssetBaseDirFlag() string { return "web-asset-base-dir" } + +// GetWebAssetBaseDir safely fetches the value for global configuration 'WebAssetBaseDir' field +func GetWebAssetBaseDir() string { return global.GetWebAssetBaseDir() } + +// SetWebAssetBaseDir safely sets the value for global configuration 'WebAssetBaseDir' field +func SetWebAssetBaseDir(v string) { global.SetWebAssetBaseDir(v) } + +// GetAccountsRegistrationOpen safely fetches the Configuration value for state's 'AccountsRegistrationOpen' field +func (st *ConfigState) GetAccountsRegistrationOpen() (v bool) { + st.mutex.Lock() + v = st.config.AccountsRegistrationOpen + st.mutex.Unlock() + return +} + +// SetAccountsRegistrationOpen safely sets the Configuration value for state's 'AccountsRegistrationOpen' field +func (st *ConfigState) SetAccountsRegistrationOpen(v bool) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.AccountsRegistrationOpen = v + st.reloadToViper() +} + +// AccountsRegistrationOpenFlag returns the flag name for the 'AccountsRegistrationOpen' field +func AccountsRegistrationOpenFlag() string { return "accounts-registration-open" } + +// GetAccountsRegistrationOpen safely fetches the value for global configuration 'AccountsRegistrationOpen' field +func GetAccountsRegistrationOpen() bool { return global.GetAccountsRegistrationOpen() } + +// SetAccountsRegistrationOpen safely sets the value for global configuration 'AccountsRegistrationOpen' field +func SetAccountsRegistrationOpen(v bool) { global.SetAccountsRegistrationOpen(v) } + +// GetAccountsApprovalRequired safely fetches the Configuration value for state's 'AccountsApprovalRequired' field +func (st *ConfigState) GetAccountsApprovalRequired() (v bool) { + st.mutex.Lock() + v = st.config.AccountsApprovalRequired + st.mutex.Unlock() + return +} + +// SetAccountsApprovalRequired safely sets the Configuration value for state's 'AccountsApprovalRequired' field +func (st *ConfigState) SetAccountsApprovalRequired(v bool) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.AccountsApprovalRequired = v + st.reloadToViper() +} + +// AccountsApprovalRequiredFlag returns the flag name for the 'AccountsApprovalRequired' field +func AccountsApprovalRequiredFlag() string { return "accounts-approval-required" } + +// GetAccountsApprovalRequired safely fetches the value for global configuration 'AccountsApprovalRequired' field +func GetAccountsApprovalRequired() bool { return global.GetAccountsApprovalRequired() } + +// SetAccountsApprovalRequired safely sets the value for global configuration 'AccountsApprovalRequired' field +func SetAccountsApprovalRequired(v bool) { global.SetAccountsApprovalRequired(v) } + +// GetAccountsReasonRequired safely fetches the Configuration value for state's 'AccountsReasonRequired' field +func (st *ConfigState) GetAccountsReasonRequired() (v bool) { + st.mutex.Lock() + v = st.config.AccountsReasonRequired + st.mutex.Unlock() + return +} + +// SetAccountsReasonRequired safely sets the Configuration value for state's 'AccountsReasonRequired' field +func (st *ConfigState) SetAccountsReasonRequired(v bool) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.AccountsReasonRequired = v + st.reloadToViper() +} + +// AccountsReasonRequiredFlag returns the flag name for the 'AccountsReasonRequired' field +func AccountsReasonRequiredFlag() string { return "accounts-reason-required" } + +// GetAccountsReasonRequired safely fetches the value for global configuration 'AccountsReasonRequired' field +func GetAccountsReasonRequired() bool { return global.GetAccountsReasonRequired() } + +// SetAccountsReasonRequired safely sets the value for global configuration 'AccountsReasonRequired' field +func SetAccountsReasonRequired(v bool) { global.SetAccountsReasonRequired(v) } + +// GetMediaImageMaxSize safely fetches the Configuration value for state's 'MediaImageMaxSize' field +func (st *ConfigState) GetMediaImageMaxSize() (v int) { + st.mutex.Lock() + v = st.config.MediaImageMaxSize + st.mutex.Unlock() + return +} + +// SetMediaImageMaxSize safely sets the Configuration value for state's 'MediaImageMaxSize' field +func (st *ConfigState) SetMediaImageMaxSize(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.MediaImageMaxSize = v + st.reloadToViper() +} + +// MediaImageMaxSizeFlag returns the flag name for the 'MediaImageMaxSize' field +func MediaImageMaxSizeFlag() string { return "media-image-max-size" } + +// GetMediaImageMaxSize safely fetches the value for global configuration 'MediaImageMaxSize' field +func GetMediaImageMaxSize() int { return global.GetMediaImageMaxSize() } + +// SetMediaImageMaxSize safely sets the value for global configuration 'MediaImageMaxSize' field +func SetMediaImageMaxSize(v int) { global.SetMediaImageMaxSize(v) } + +// GetMediaVideoMaxSize safely fetches the Configuration value for state's 'MediaVideoMaxSize' field +func (st *ConfigState) GetMediaVideoMaxSize() (v int) { + st.mutex.Lock() + v = st.config.MediaVideoMaxSize + st.mutex.Unlock() + return +} + +// SetMediaVideoMaxSize safely sets the Configuration value for state's 'MediaVideoMaxSize' field +func (st *ConfigState) SetMediaVideoMaxSize(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.MediaVideoMaxSize = v + st.reloadToViper() +} + +// MediaVideoMaxSizeFlag returns the flag name for the 'MediaVideoMaxSize' field +func MediaVideoMaxSizeFlag() string { return "media-video-max-size" } + +// GetMediaVideoMaxSize safely fetches the value for global configuration 'MediaVideoMaxSize' field +func GetMediaVideoMaxSize() int { return global.GetMediaVideoMaxSize() } + +// SetMediaVideoMaxSize safely sets the value for global configuration 'MediaVideoMaxSize' field +func SetMediaVideoMaxSize(v int) { global.SetMediaVideoMaxSize(v) } + +// GetMediaDescriptionMinChars safely fetches the Configuration value for state's 'MediaDescriptionMinChars' field +func (st *ConfigState) GetMediaDescriptionMinChars() (v int) { + st.mutex.Lock() + v = st.config.MediaDescriptionMinChars + st.mutex.Unlock() + return +} + +// SetMediaDescriptionMinChars safely sets the Configuration value for state's 'MediaDescriptionMinChars' field +func (st *ConfigState) SetMediaDescriptionMinChars(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.MediaDescriptionMinChars = v + st.reloadToViper() +} + +// MediaDescriptionMinCharsFlag returns the flag name for the 'MediaDescriptionMinChars' field +func MediaDescriptionMinCharsFlag() string { return "media-description-min-chars" } + +// GetMediaDescriptionMinChars safely fetches the value for global configuration 'MediaDescriptionMinChars' field +func GetMediaDescriptionMinChars() int { return global.GetMediaDescriptionMinChars() } + +// SetMediaDescriptionMinChars safely sets the value for global configuration 'MediaDescriptionMinChars' field +func SetMediaDescriptionMinChars(v int) { global.SetMediaDescriptionMinChars(v) } + +// GetMediaDescriptionMaxChars safely fetches the Configuration value for state's 'MediaDescriptionMaxChars' field +func (st *ConfigState) GetMediaDescriptionMaxChars() (v int) { + st.mutex.Lock() + v = st.config.MediaDescriptionMaxChars + st.mutex.Unlock() + return +} + +// SetMediaDescriptionMaxChars safely sets the Configuration value for state's 'MediaDescriptionMaxChars' field +func (st *ConfigState) SetMediaDescriptionMaxChars(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.MediaDescriptionMaxChars = v + st.reloadToViper() +} + +// MediaDescriptionMaxCharsFlag returns the flag name for the 'MediaDescriptionMaxChars' field +func MediaDescriptionMaxCharsFlag() string { return "media-description-max-chars" } + +// GetMediaDescriptionMaxChars safely fetches the value for global configuration 'MediaDescriptionMaxChars' field +func GetMediaDescriptionMaxChars() int { return global.GetMediaDescriptionMaxChars() } + +// SetMediaDescriptionMaxChars safely sets the value for global configuration 'MediaDescriptionMaxChars' field +func SetMediaDescriptionMaxChars(v int) { global.SetMediaDescriptionMaxChars(v) } + +// GetMediaRemoteCacheDays safely fetches the Configuration value for state's 'MediaRemoteCacheDays' field +func (st *ConfigState) GetMediaRemoteCacheDays() (v int) { + st.mutex.Lock() + v = st.config.MediaRemoteCacheDays + st.mutex.Unlock() + return +} + +// SetMediaRemoteCacheDays safely sets the Configuration value for state's 'MediaRemoteCacheDays' field +func (st *ConfigState) SetMediaRemoteCacheDays(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.MediaRemoteCacheDays = v + st.reloadToViper() +} + +// MediaRemoteCacheDaysFlag returns the flag name for the 'MediaRemoteCacheDays' field +func MediaRemoteCacheDaysFlag() string { return "media-remote-cache-days" } + +// GetMediaRemoteCacheDays safely fetches the value for global configuration 'MediaRemoteCacheDays' field +func GetMediaRemoteCacheDays() int { return global.GetMediaRemoteCacheDays() } + +// SetMediaRemoteCacheDays safely sets the value for global configuration 'MediaRemoteCacheDays' field +func SetMediaRemoteCacheDays(v int) { global.SetMediaRemoteCacheDays(v) } + +// GetStorageBackend safely fetches the Configuration value for state's 'StorageBackend' field +func (st *ConfigState) GetStorageBackend() (v string) { + st.mutex.Lock() + v = st.config.StorageBackend + st.mutex.Unlock() + return +} + +// SetStorageBackend safely sets the Configuration value for state's 'StorageBackend' field +func (st *ConfigState) SetStorageBackend(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.StorageBackend = v + st.reloadToViper() +} + +// StorageBackendFlag returns the flag name for the 'StorageBackend' field +func StorageBackendFlag() string { return "storage-backend" } + +// GetStorageBackend safely fetches the value for global configuration 'StorageBackend' field +func GetStorageBackend() string { return global.GetStorageBackend() } + +// SetStorageBackend safely sets the value for global configuration 'StorageBackend' field +func SetStorageBackend(v string) { global.SetStorageBackend(v) } + +// GetStorageLocalBasePath safely fetches the Configuration value for state's 'StorageLocalBasePath' field +func (st *ConfigState) GetStorageLocalBasePath() (v string) { + st.mutex.Lock() + v = st.config.StorageLocalBasePath + st.mutex.Unlock() + return +} + +// SetStorageLocalBasePath safely sets the Configuration value for state's 'StorageLocalBasePath' field +func (st *ConfigState) SetStorageLocalBasePath(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.StorageLocalBasePath = v + st.reloadToViper() +} + +// StorageLocalBasePathFlag returns the flag name for the 'StorageLocalBasePath' field +func StorageLocalBasePathFlag() string { return "storage-local-base-path" } + +// GetStorageLocalBasePath safely fetches the value for global configuration 'StorageLocalBasePath' field +func GetStorageLocalBasePath() string { return global.GetStorageLocalBasePath() } + +// SetStorageLocalBasePath safely sets the value for global configuration 'StorageLocalBasePath' field +func SetStorageLocalBasePath(v string) { global.SetStorageLocalBasePath(v) } + +// GetStatusesMaxChars safely fetches the Configuration value for state's 'StatusesMaxChars' field +func (st *ConfigState) GetStatusesMaxChars() (v int) { + st.mutex.Lock() + v = st.config.StatusesMaxChars + st.mutex.Unlock() + return +} + +// SetStatusesMaxChars safely sets the Configuration value for state's 'StatusesMaxChars' field +func (st *ConfigState) SetStatusesMaxChars(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.StatusesMaxChars = v + st.reloadToViper() +} + +// StatusesMaxCharsFlag returns the flag name for the 'StatusesMaxChars' field +func StatusesMaxCharsFlag() string { return "statuses-max-chars" } + +// GetStatusesMaxChars safely fetches the value for global configuration 'StatusesMaxChars' field +func GetStatusesMaxChars() int { return global.GetStatusesMaxChars() } + +// SetStatusesMaxChars safely sets the value for global configuration 'StatusesMaxChars' field +func SetStatusesMaxChars(v int) { global.SetStatusesMaxChars(v) } + +// GetStatusesCWMaxChars safely fetches the Configuration value for state's 'StatusesCWMaxChars' field +func (st *ConfigState) GetStatusesCWMaxChars() (v int) { + st.mutex.Lock() + v = st.config.StatusesCWMaxChars + st.mutex.Unlock() + return +} + +// SetStatusesCWMaxChars safely sets the Configuration value for state's 'StatusesCWMaxChars' field +func (st *ConfigState) SetStatusesCWMaxChars(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.StatusesCWMaxChars = v + st.reloadToViper() +} + +// StatusesCWMaxCharsFlag returns the flag name for the 'StatusesCWMaxChars' field +func StatusesCWMaxCharsFlag() string { return "statuses-cw-max-chars" } + +// GetStatusesCWMaxChars safely fetches the value for global configuration 'StatusesCWMaxChars' field +func GetStatusesCWMaxChars() int { return global.GetStatusesCWMaxChars() } + +// SetStatusesCWMaxChars safely sets the value for global configuration 'StatusesCWMaxChars' field +func SetStatusesCWMaxChars(v int) { global.SetStatusesCWMaxChars(v) } + +// GetStatusesPollMaxOptions safely fetches the Configuration value for state's 'StatusesPollMaxOptions' field +func (st *ConfigState) GetStatusesPollMaxOptions() (v int) { + st.mutex.Lock() + v = st.config.StatusesPollMaxOptions + st.mutex.Unlock() + return +} + +// SetStatusesPollMaxOptions safely sets the Configuration value for state's 'StatusesPollMaxOptions' field +func (st *ConfigState) SetStatusesPollMaxOptions(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.StatusesPollMaxOptions = v + st.reloadToViper() +} + +// StatusesPollMaxOptionsFlag returns the flag name for the 'StatusesPollMaxOptions' field +func StatusesPollMaxOptionsFlag() string { return "statuses-poll-max-options" } + +// GetStatusesPollMaxOptions safely fetches the value for global configuration 'StatusesPollMaxOptions' field +func GetStatusesPollMaxOptions() int { return global.GetStatusesPollMaxOptions() } + +// SetStatusesPollMaxOptions safely sets the value for global configuration 'StatusesPollMaxOptions' field +func SetStatusesPollMaxOptions(v int) { global.SetStatusesPollMaxOptions(v) } + +// GetStatusesPollOptionMaxChars safely fetches the Configuration value for state's 'StatusesPollOptionMaxChars' field +func (st *ConfigState) GetStatusesPollOptionMaxChars() (v int) { + st.mutex.Lock() + v = st.config.StatusesPollOptionMaxChars + st.mutex.Unlock() + return +} + +// SetStatusesPollOptionMaxChars safely sets the Configuration value for state's 'StatusesPollOptionMaxChars' field +func (st *ConfigState) SetStatusesPollOptionMaxChars(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.StatusesPollOptionMaxChars = v + st.reloadToViper() +} + +// StatusesPollOptionMaxCharsFlag returns the flag name for the 'StatusesPollOptionMaxChars' field +func StatusesPollOptionMaxCharsFlag() string { return "statuses-poll-option-max-chars" } + +// GetStatusesPollOptionMaxChars safely fetches the value for global configuration 'StatusesPollOptionMaxChars' field +func GetStatusesPollOptionMaxChars() int { return global.GetStatusesPollOptionMaxChars() } + +// SetStatusesPollOptionMaxChars safely sets the value for global configuration 'StatusesPollOptionMaxChars' field +func SetStatusesPollOptionMaxChars(v int) { global.SetStatusesPollOptionMaxChars(v) } + +// GetStatusesMediaMaxFiles safely fetches the Configuration value for state's 'StatusesMediaMaxFiles' field +func (st *ConfigState) GetStatusesMediaMaxFiles() (v int) { + st.mutex.Lock() + v = st.config.StatusesMediaMaxFiles + st.mutex.Unlock() + return +} + +// SetStatusesMediaMaxFiles safely sets the Configuration value for state's 'StatusesMediaMaxFiles' field +func (st *ConfigState) SetStatusesMediaMaxFiles(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.StatusesMediaMaxFiles = v + st.reloadToViper() +} + +// StatusesMediaMaxFilesFlag returns the flag name for the 'StatusesMediaMaxFiles' field +func StatusesMediaMaxFilesFlag() string { return "statuses-media-max-files" } + +// GetStatusesMediaMaxFiles safely fetches the value for global configuration 'StatusesMediaMaxFiles' field +func GetStatusesMediaMaxFiles() int { return global.GetStatusesMediaMaxFiles() } + +// SetStatusesMediaMaxFiles safely sets the value for global configuration 'StatusesMediaMaxFiles' field +func SetStatusesMediaMaxFiles(v int) { global.SetStatusesMediaMaxFiles(v) } + +// GetLetsEncryptEnabled safely fetches the Configuration value for state's 'LetsEncryptEnabled' field +func (st *ConfigState) GetLetsEncryptEnabled() (v bool) { + st.mutex.Lock() + v = st.config.LetsEncryptEnabled + st.mutex.Unlock() + return +} + +// SetLetsEncryptEnabled safely sets the Configuration value for state's 'LetsEncryptEnabled' field +func (st *ConfigState) SetLetsEncryptEnabled(v bool) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.LetsEncryptEnabled = v + st.reloadToViper() +} + +// LetsEncryptEnabledFlag returns the flag name for the 'LetsEncryptEnabled' field +func LetsEncryptEnabledFlag() string { return "letsencrypt-enabled" } + +// GetLetsEncryptEnabled safely fetches the value for global configuration 'LetsEncryptEnabled' field +func GetLetsEncryptEnabled() bool { return global.GetLetsEncryptEnabled() } + +// SetLetsEncryptEnabled safely sets the value for global configuration 'LetsEncryptEnabled' field +func SetLetsEncryptEnabled(v bool) { global.SetLetsEncryptEnabled(v) } + +// GetLetsEncryptPort safely fetches the Configuration value for state's 'LetsEncryptPort' field +func (st *ConfigState) GetLetsEncryptPort() (v int) { + st.mutex.Lock() + v = st.config.LetsEncryptPort + st.mutex.Unlock() + return +} + +// SetLetsEncryptPort safely sets the Configuration value for state's 'LetsEncryptPort' field +func (st *ConfigState) SetLetsEncryptPort(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.LetsEncryptPort = v + st.reloadToViper() +} + +// LetsEncryptPortFlag returns the flag name for the 'LetsEncryptPort' field +func LetsEncryptPortFlag() string { return "letsencrypt-port" } + +// GetLetsEncryptPort safely fetches the value for global configuration 'LetsEncryptPort' field +func GetLetsEncryptPort() int { return global.GetLetsEncryptPort() } + +// SetLetsEncryptPort safely sets the value for global configuration 'LetsEncryptPort' field +func SetLetsEncryptPort(v int) { global.SetLetsEncryptPort(v) } + +// GetLetsEncryptCertDir safely fetches the Configuration value for state's 'LetsEncryptCertDir' field +func (st *ConfigState) GetLetsEncryptCertDir() (v string) { + st.mutex.Lock() + v = st.config.LetsEncryptCertDir + st.mutex.Unlock() + return +} + +// SetLetsEncryptCertDir safely sets the Configuration value for state's 'LetsEncryptCertDir' field +func (st *ConfigState) SetLetsEncryptCertDir(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.LetsEncryptCertDir = v + st.reloadToViper() +} + +// LetsEncryptCertDirFlag returns the flag name for the 'LetsEncryptCertDir' field +func LetsEncryptCertDirFlag() string { return "letsencrypt-cert-dir" } + +// GetLetsEncryptCertDir safely fetches the value for global configuration 'LetsEncryptCertDir' field +func GetLetsEncryptCertDir() string { return global.GetLetsEncryptCertDir() } + +// SetLetsEncryptCertDir safely sets the value for global configuration 'LetsEncryptCertDir' field +func SetLetsEncryptCertDir(v string) { global.SetLetsEncryptCertDir(v) } + +// GetLetsEncryptEmailAddress safely fetches the Configuration value for state's 'LetsEncryptEmailAddress' field +func (st *ConfigState) GetLetsEncryptEmailAddress() (v string) { + st.mutex.Lock() + v = st.config.LetsEncryptEmailAddress + st.mutex.Unlock() + return +} + +// SetLetsEncryptEmailAddress safely sets the Configuration value for state's 'LetsEncryptEmailAddress' field +func (st *ConfigState) SetLetsEncryptEmailAddress(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.LetsEncryptEmailAddress = v + st.reloadToViper() +} + +// LetsEncryptEmailAddressFlag returns the flag name for the 'LetsEncryptEmailAddress' field +func LetsEncryptEmailAddressFlag() string { return "letsencrypt-email-address" } + +// GetLetsEncryptEmailAddress safely fetches the value for global configuration 'LetsEncryptEmailAddress' field +func GetLetsEncryptEmailAddress() string { return global.GetLetsEncryptEmailAddress() } + +// SetLetsEncryptEmailAddress safely sets the value for global configuration 'LetsEncryptEmailAddress' field +func SetLetsEncryptEmailAddress(v string) { global.SetLetsEncryptEmailAddress(v) } + +// GetOIDCEnabled safely fetches the Configuration value for state's 'OIDCEnabled' field +func (st *ConfigState) GetOIDCEnabled() (v bool) { + st.mutex.Lock() + v = st.config.OIDCEnabled + st.mutex.Unlock() + return +} + +// SetOIDCEnabled safely sets the Configuration value for state's 'OIDCEnabled' field +func (st *ConfigState) SetOIDCEnabled(v bool) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.OIDCEnabled = v + st.reloadToViper() +} + +// OIDCEnabledFlag returns the flag name for the 'OIDCEnabled' field +func OIDCEnabledFlag() string { return "oidc-enabled" } + +// GetOIDCEnabled safely fetches the value for global configuration 'OIDCEnabled' field +func GetOIDCEnabled() bool { return global.GetOIDCEnabled() } + +// SetOIDCEnabled safely sets the value for global configuration 'OIDCEnabled' field +func SetOIDCEnabled(v bool) { global.SetOIDCEnabled(v) } + +// GetOIDCIdpName safely fetches the Configuration value for state's 'OIDCIdpName' field +func (st *ConfigState) GetOIDCIdpName() (v string) { + st.mutex.Lock() + v = st.config.OIDCIdpName + st.mutex.Unlock() + return +} + +// SetOIDCIdpName safely sets the Configuration value for state's 'OIDCIdpName' field +func (st *ConfigState) SetOIDCIdpName(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.OIDCIdpName = v + st.reloadToViper() +} + +// OIDCIdpNameFlag returns the flag name for the 'OIDCIdpName' field +func OIDCIdpNameFlag() string { return "oidc-idp-name" } + +// GetOIDCIdpName safely fetches the value for global configuration 'OIDCIdpName' field +func GetOIDCIdpName() string { return global.GetOIDCIdpName() } + +// SetOIDCIdpName safely sets the value for global configuration 'OIDCIdpName' field +func SetOIDCIdpName(v string) { global.SetOIDCIdpName(v) } + +// GetOIDCSkipVerification safely fetches the Configuration value for state's 'OIDCSkipVerification' field +func (st *ConfigState) GetOIDCSkipVerification() (v bool) { + st.mutex.Lock() + v = st.config.OIDCSkipVerification + st.mutex.Unlock() + return +} + +// SetOIDCSkipVerification safely sets the Configuration value for state's 'OIDCSkipVerification' field +func (st *ConfigState) SetOIDCSkipVerification(v bool) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.OIDCSkipVerification = v + st.reloadToViper() +} + +// OIDCSkipVerificationFlag returns the flag name for the 'OIDCSkipVerification' field +func OIDCSkipVerificationFlag() string { return "oidc-skip-verification" } + +// GetOIDCSkipVerification safely fetches the value for global configuration 'OIDCSkipVerification' field +func GetOIDCSkipVerification() bool { return global.GetOIDCSkipVerification() } + +// SetOIDCSkipVerification safely sets the value for global configuration 'OIDCSkipVerification' field +func SetOIDCSkipVerification(v bool) { global.SetOIDCSkipVerification(v) } + +// GetOIDCIssuer safely fetches the Configuration value for state's 'OIDCIssuer' field +func (st *ConfigState) GetOIDCIssuer() (v string) { + st.mutex.Lock() + v = st.config.OIDCIssuer + st.mutex.Unlock() + return +} + +// SetOIDCIssuer safely sets the Configuration value for state's 'OIDCIssuer' field +func (st *ConfigState) SetOIDCIssuer(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.OIDCIssuer = v + st.reloadToViper() +} + +// OIDCIssuerFlag returns the flag name for the 'OIDCIssuer' field +func OIDCIssuerFlag() string { return "oidc-issuer" } + +// GetOIDCIssuer safely fetches the value for global configuration 'OIDCIssuer' field +func GetOIDCIssuer() string { return global.GetOIDCIssuer() } + +// SetOIDCIssuer safely sets the value for global configuration 'OIDCIssuer' field +func SetOIDCIssuer(v string) { global.SetOIDCIssuer(v) } + +// GetOIDCClientID safely fetches the Configuration value for state's 'OIDCClientID' field +func (st *ConfigState) GetOIDCClientID() (v string) { + st.mutex.Lock() + v = st.config.OIDCClientID + st.mutex.Unlock() + return +} + +// SetOIDCClientID safely sets the Configuration value for state's 'OIDCClientID' field +func (st *ConfigState) SetOIDCClientID(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.OIDCClientID = v + st.reloadToViper() +} + +// OIDCClientIDFlag returns the flag name for the 'OIDCClientID' field +func OIDCClientIDFlag() string { return "oidc-client-id" } + +// GetOIDCClientID safely fetches the value for global configuration 'OIDCClientID' field +func GetOIDCClientID() string { return global.GetOIDCClientID() } + +// SetOIDCClientID safely sets the value for global configuration 'OIDCClientID' field +func SetOIDCClientID(v string) { global.SetOIDCClientID(v) } + +// GetOIDCClientSecret safely fetches the Configuration value for state's 'OIDCClientSecret' field +func (st *ConfigState) GetOIDCClientSecret() (v string) { + st.mutex.Lock() + v = st.config.OIDCClientSecret + st.mutex.Unlock() + return +} + +// SetOIDCClientSecret safely sets the Configuration value for state's 'OIDCClientSecret' field +func (st *ConfigState) SetOIDCClientSecret(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.OIDCClientSecret = v + st.reloadToViper() +} + +// OIDCClientSecretFlag returns the flag name for the 'OIDCClientSecret' field +func OIDCClientSecretFlag() string { return "oidc-client-secret" } + +// GetOIDCClientSecret safely fetches the value for global configuration 'OIDCClientSecret' field +func GetOIDCClientSecret() string { return global.GetOIDCClientSecret() } + +// SetOIDCClientSecret safely sets the value for global configuration 'OIDCClientSecret' field +func SetOIDCClientSecret(v string) { global.SetOIDCClientSecret(v) } + +// GetOIDCScopes safely fetches the Configuration value for state's 'OIDCScopes' field +func (st *ConfigState) GetOIDCScopes() (v []string) { + st.mutex.Lock() + v = st.config.OIDCScopes + st.mutex.Unlock() + return +} + +// SetOIDCScopes safely sets the Configuration value for state's 'OIDCScopes' field +func (st *ConfigState) SetOIDCScopes(v []string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.OIDCScopes = v + st.reloadToViper() +} + +// OIDCScopesFlag returns the flag name for the 'OIDCScopes' field +func OIDCScopesFlag() string { return "oidc-scopes" } + +// GetOIDCScopes safely fetches the value for global configuration 'OIDCScopes' field +func GetOIDCScopes() []string { return global.GetOIDCScopes() } + +// SetOIDCScopes safely sets the value for global configuration 'OIDCScopes' field +func SetOIDCScopes(v []string) { global.SetOIDCScopes(v) } + +// GetSMTPHost safely fetches the Configuration value for state's 'SMTPHost' field +func (st *ConfigState) GetSMTPHost() (v string) { + st.mutex.Lock() + v = st.config.SMTPHost + st.mutex.Unlock() + return +} + +// SetSMTPHost safely sets the Configuration value for state's 'SMTPHost' field +func (st *ConfigState) SetSMTPHost(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.SMTPHost = v + st.reloadToViper() +} + +// SMTPHostFlag returns the flag name for the 'SMTPHost' field +func SMTPHostFlag() string { return "smtp-host" } + +// GetSMTPHost safely fetches the value for global configuration 'SMTPHost' field +func GetSMTPHost() string { return global.GetSMTPHost() } + +// SetSMTPHost safely sets the value for global configuration 'SMTPHost' field +func SetSMTPHost(v string) { global.SetSMTPHost(v) } + +// GetSMTPPort safely fetches the Configuration value for state's 'SMTPPort' field +func (st *ConfigState) GetSMTPPort() (v int) { + st.mutex.Lock() + v = st.config.SMTPPort + st.mutex.Unlock() + return +} + +// SetSMTPPort safely sets the Configuration value for state's 'SMTPPort' field +func (st *ConfigState) SetSMTPPort(v int) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.SMTPPort = v + st.reloadToViper() +} + +// SMTPPortFlag returns the flag name for the 'SMTPPort' field +func SMTPPortFlag() string { return "smtp-port" } + +// GetSMTPPort safely fetches the value for global configuration 'SMTPPort' field +func GetSMTPPort() int { return global.GetSMTPPort() } + +// SetSMTPPort safely sets the value for global configuration 'SMTPPort' field +func SetSMTPPort(v int) { global.SetSMTPPort(v) } + +// GetSMTPUsername safely fetches the Configuration value for state's 'SMTPUsername' field +func (st *ConfigState) GetSMTPUsername() (v string) { + st.mutex.Lock() + v = st.config.SMTPUsername + st.mutex.Unlock() + return +} + +// SetSMTPUsername safely sets the Configuration value for state's 'SMTPUsername' field +func (st *ConfigState) SetSMTPUsername(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.SMTPUsername = v + st.reloadToViper() +} + +// SMTPUsernameFlag returns the flag name for the 'SMTPUsername' field +func SMTPUsernameFlag() string { return "smtp-username" } + +// GetSMTPUsername safely fetches the value for global configuration 'SMTPUsername' field +func GetSMTPUsername() string { return global.GetSMTPUsername() } + +// SetSMTPUsername safely sets the value for global configuration 'SMTPUsername' field +func SetSMTPUsername(v string) { global.SetSMTPUsername(v) } + +// GetSMTPPassword safely fetches the Configuration value for state's 'SMTPPassword' field +func (st *ConfigState) GetSMTPPassword() (v string) { + st.mutex.Lock() + v = st.config.SMTPPassword + st.mutex.Unlock() + return +} + +// SetSMTPPassword safely sets the Configuration value for state's 'SMTPPassword' field +func (st *ConfigState) SetSMTPPassword(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.SMTPPassword = v + st.reloadToViper() +} + +// SMTPPasswordFlag returns the flag name for the 'SMTPPassword' field +func SMTPPasswordFlag() string { return "smtp-password" } + +// GetSMTPPassword safely fetches the value for global configuration 'SMTPPassword' field +func GetSMTPPassword() string { return global.GetSMTPPassword() } + +// SetSMTPPassword safely sets the value for global configuration 'SMTPPassword' field +func SetSMTPPassword(v string) { global.SetSMTPPassword(v) } + +// GetSMTPFrom safely fetches the Configuration value for state's 'SMTPFrom' field +func (st *ConfigState) GetSMTPFrom() (v string) { + st.mutex.Lock() + v = st.config.SMTPFrom + st.mutex.Unlock() + return +} + +// SetSMTPFrom safely sets the Configuration value for state's 'SMTPFrom' field +func (st *ConfigState) SetSMTPFrom(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.SMTPFrom = v + st.reloadToViper() +} + +// SMTPFromFlag returns the flag name for the 'SMTPFrom' field +func SMTPFromFlag() string { return "smtp-from" } + +// GetSMTPFrom safely fetches the value for global configuration 'SMTPFrom' field +func GetSMTPFrom() string { return global.GetSMTPFrom() } + +// SetSMTPFrom safely sets the value for global configuration 'SMTPFrom' field +func SetSMTPFrom(v string) { global.SetSMTPFrom(v) } + +// GetSyslogEnabled safely fetches the Configuration value for state's 'SyslogEnabled' field +func (st *ConfigState) GetSyslogEnabled() (v bool) { + st.mutex.Lock() + v = st.config.SyslogEnabled + st.mutex.Unlock() + return +} + +// SetSyslogEnabled safely sets the Configuration value for state's 'SyslogEnabled' field +func (st *ConfigState) SetSyslogEnabled(v bool) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.SyslogEnabled = v + st.reloadToViper() +} + +// SyslogEnabledFlag returns the flag name for the 'SyslogEnabled' field +func SyslogEnabledFlag() string { return "syslog-enabled" } + +// GetSyslogEnabled safely fetches the value for global configuration 'SyslogEnabled' field +func GetSyslogEnabled() bool { return global.GetSyslogEnabled() } + +// SetSyslogEnabled safely sets the value for global configuration 'SyslogEnabled' field +func SetSyslogEnabled(v bool) { global.SetSyslogEnabled(v) } + +// GetSyslogProtocol safely fetches the Configuration value for state's 'SyslogProtocol' field +func (st *ConfigState) GetSyslogProtocol() (v string) { + st.mutex.Lock() + v = st.config.SyslogProtocol + st.mutex.Unlock() + return +} + +// SetSyslogProtocol safely sets the Configuration value for state's 'SyslogProtocol' field +func (st *ConfigState) SetSyslogProtocol(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.SyslogProtocol = v + st.reloadToViper() +} + +// SyslogProtocolFlag returns the flag name for the 'SyslogProtocol' field +func SyslogProtocolFlag() string { return "syslog-protocol" } + +// GetSyslogProtocol safely fetches the value for global configuration 'SyslogProtocol' field +func GetSyslogProtocol() string { return global.GetSyslogProtocol() } + +// SetSyslogProtocol safely sets the value for global configuration 'SyslogProtocol' field +func SetSyslogProtocol(v string) { global.SetSyslogProtocol(v) } + +// GetSyslogAddress safely fetches the Configuration value for state's 'SyslogAddress' field +func (st *ConfigState) GetSyslogAddress() (v string) { + st.mutex.Lock() + v = st.config.SyslogAddress + st.mutex.Unlock() + return +} + +// SetSyslogAddress safely sets the Configuration value for state's 'SyslogAddress' field +func (st *ConfigState) SetSyslogAddress(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.SyslogAddress = v + st.reloadToViper() +} + +// SyslogAddressFlag returns the flag name for the 'SyslogAddress' field +func SyslogAddressFlag() string { return "syslog-address" } + +// GetSyslogAddress safely fetches the value for global configuration 'SyslogAddress' field +func GetSyslogAddress() string { return global.GetSyslogAddress() } + +// SetSyslogAddress safely sets the value for global configuration 'SyslogAddress' field +func SetSyslogAddress(v string) { global.SetSyslogAddress(v) } + +// GetAdminAccountUsername safely fetches the Configuration value for state's 'AdminAccountUsername' field +func (st *ConfigState) GetAdminAccountUsername() (v string) { + st.mutex.Lock() + v = st.config.AdminAccountUsername + st.mutex.Unlock() + return +} + +// SetAdminAccountUsername safely sets the Configuration value for state's 'AdminAccountUsername' field +func (st *ConfigState) SetAdminAccountUsername(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.AdminAccountUsername = v + st.reloadToViper() +} + +// AdminAccountUsernameFlag returns the flag name for the 'AdminAccountUsername' field +func AdminAccountUsernameFlag() string { return "username" } + +// GetAdminAccountUsername safely fetches the value for global configuration 'AdminAccountUsername' field +func GetAdminAccountUsername() string { return global.GetAdminAccountUsername() } + +// SetAdminAccountUsername safely sets the value for global configuration 'AdminAccountUsername' field +func SetAdminAccountUsername(v string) { global.SetAdminAccountUsername(v) } + +// GetAdminAccountEmail safely fetches the Configuration value for state's 'AdminAccountEmail' field +func (st *ConfigState) GetAdminAccountEmail() (v string) { + st.mutex.Lock() + v = st.config.AdminAccountEmail + st.mutex.Unlock() + return +} + +// SetAdminAccountEmail safely sets the Configuration value for state's 'AdminAccountEmail' field +func (st *ConfigState) SetAdminAccountEmail(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.AdminAccountEmail = v + st.reloadToViper() +} + +// AdminAccountEmailFlag returns the flag name for the 'AdminAccountEmail' field +func AdminAccountEmailFlag() string { return "email" } + +// GetAdminAccountEmail safely fetches the value for global configuration 'AdminAccountEmail' field +func GetAdminAccountEmail() string { return global.GetAdminAccountEmail() } + +// SetAdminAccountEmail safely sets the value for global configuration 'AdminAccountEmail' field +func SetAdminAccountEmail(v string) { global.SetAdminAccountEmail(v) } + +// GetAdminAccountPassword safely fetches the Configuration value for state's 'AdminAccountPassword' field +func (st *ConfigState) GetAdminAccountPassword() (v string) { + st.mutex.Lock() + v = st.config.AdminAccountPassword + st.mutex.Unlock() + return +} + +// SetAdminAccountPassword safely sets the Configuration value for state's 'AdminAccountPassword' field +func (st *ConfigState) SetAdminAccountPassword(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.AdminAccountPassword = v + st.reloadToViper() +} + +// AdminAccountPasswordFlag returns the flag name for the 'AdminAccountPassword' field +func AdminAccountPasswordFlag() string { return "password" } + +// GetAdminAccountPassword safely fetches the value for global configuration 'AdminAccountPassword' field +func GetAdminAccountPassword() string { return global.GetAdminAccountPassword() } + +// SetAdminAccountPassword safely sets the value for global configuration 'AdminAccountPassword' field +func SetAdminAccountPassword(v string) { global.SetAdminAccountPassword(v) } + +// GetAdminTransPath safely fetches the Configuration value for state's 'AdminTransPath' field +func (st *ConfigState) GetAdminTransPath() (v string) { + st.mutex.Lock() + v = st.config.AdminTransPath + st.mutex.Unlock() + return +} + +// SetAdminTransPath safely sets the Configuration value for state's 'AdminTransPath' field +func (st *ConfigState) SetAdminTransPath(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.AdminTransPath = v + st.reloadToViper() +} + +// AdminTransPathFlag returns the flag name for the 'AdminTransPath' field +func AdminTransPathFlag() string { return "path" } + +// GetAdminTransPath safely fetches the value for global configuration 'AdminTransPath' field +func GetAdminTransPath() string { return global.GetAdminTransPath() } + +// SetAdminTransPath safely sets the value for global configuration 'AdminTransPath' field +func SetAdminTransPath(v string) { global.SetAdminTransPath(v) } diff --git a/internal/config/keys.go b/internal/config/keys.go deleted file mode 100644 index 50a9c2fa7..000000000 --- a/internal/config/keys.go +++ /dev/null @@ -1,182 +0,0 @@ -/* - GoToSocial - Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -package config - -// KeyNames is a struct that just contains the names of configuration keys. -type KeyNames struct { - // root - LogLevel string - LogDbQueries string - ConfigPath string - - // general - ApplicationName string - Host string - AccountDomain string - Protocol string - BindAddress string - Port string - TrustedProxies string - SoftwareVersion string - - // database - DbType string - DbAddress string - DbPort string - DbUser string - DbPassword string - DbDatabase string - DbTLSMode string - DbTLSCACert string - - // template - WebTemplateBaseDir string - WebAssetBaseDir string - - // accounts - AccountsRegistrationOpen string - AccountsApprovalRequired string - AccountsReasonRequired string - - // media - MediaImageMaxSize string - MediaVideoMaxSize string - MediaDescriptionMinChars string - MediaDescriptionMaxChars string - MediaRemoteCacheDays string - - // storage - StorageBackend string - StorageLocalBasePath string - - // statuses - StatusesMaxChars string - StatusesCWMaxChars string - StatusesPollMaxOptions string - StatusesPollOptionMaxChars string - StatusesMediaMaxFiles string - - // letsencrypt - LetsEncryptEnabled string - LetsEncryptCertDir string - LetsEncryptEmailAddress string - LetsEncryptPort string - - // oidc - OIDCEnabled string - OIDCIdpName string - OIDCSkipVerification string - OIDCIssuer string - OIDCClientID string - OIDCClientSecret string - OIDCScopes string - - // smtp - SMTPHost string - SMTPPort string - SMTPUsername string - SMTPPassword string - SMTPFrom string - - // syslog - SyslogEnabled string - SyslogProtocol string - SyslogAddress string - - // admin - AdminAccountUsername string - AdminAccountEmail string - AdminAccountPassword string - AdminTransPath string -} - -// Keys contains the names of the various keys used for initializing and storing flag variables, -// and retrieving values from the viper config store. -var Keys = KeyNames{ - LogLevel: "log-level", - LogDbQueries: "log-db-queries", - ApplicationName: "application-name", - ConfigPath: "config-path", - Host: "host", - AccountDomain: "account-domain", - Protocol: "protocol", - BindAddress: "bind-address", - Port: "port", - TrustedProxies: "trusted-proxies", - SoftwareVersion: "software-version", - - DbType: "db-type", - DbAddress: "db-address", - DbPort: "db-port", - DbUser: "db-user", - DbPassword: "db-password", - DbDatabase: "db-database", - DbTLSMode: "db-tls-mode", - DbTLSCACert: "db-tls-ca-cert", - - WebTemplateBaseDir: "web-template-base-dir", - WebAssetBaseDir: "web-asset-base-dir", - - AccountsRegistrationOpen: "accounts-registration-open", - AccountsApprovalRequired: "accounts-approval-required", - AccountsReasonRequired: "accounts-reason-required", - - MediaImageMaxSize: "media-image-max-size", - MediaVideoMaxSize: "media-video-max-size", - MediaDescriptionMinChars: "media-description-min-chars", - MediaDescriptionMaxChars: "media-description-max-chars", - MediaRemoteCacheDays: "media-remote-cache-days", - - StorageBackend: "storage-backend", - StorageLocalBasePath: "storage-local-base-path", - - StatusesMaxChars: "statuses-max-chars", - StatusesCWMaxChars: "statuses-cw-max-chars", - StatusesPollMaxOptions: "statuses-poll-max-options", - StatusesPollOptionMaxChars: "statuses-poll-option-max-chars", - StatusesMediaMaxFiles: "statuses-media-max-files", - - LetsEncryptEnabled: "letsencrypt-enabled", - LetsEncryptPort: "letsencrypt-port", - LetsEncryptCertDir: "letsencrypt-cert-dir", - LetsEncryptEmailAddress: "letsencrypt-email-address", - - OIDCEnabled: "oidc-enabled", - OIDCIdpName: "oidc-idp-name", - OIDCSkipVerification: "oidc-skip-verification", - OIDCIssuer: "oidc-issuer", - OIDCClientID: "oidc-client-id", - OIDCClientSecret: "oidc-client-secret", - OIDCScopes: "oidc-scopes", - - SMTPHost: "smtp-host", - SMTPPort: "smtp-port", - SMTPUsername: "smtp-username", - SMTPPassword: "smtp-password", - SMTPFrom: "smtp-from", - - SyslogEnabled: "syslog-enabled", - SyslogProtocol: "syslog-protocol", - SyslogAddress: "syslog-address", - - AdminAccountUsername: "username", - AdminAccountEmail: "email", - AdminAccountPassword: "password", - AdminTransPath: "path", -} diff --git a/internal/config/state.go b/internal/config/state.go new file mode 100644 index 000000000..70972a835 --- /dev/null +++ b/internal/config/state.go @@ -0,0 +1,136 @@ +/* + GoToSocial + Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +package config + +import ( + "strings" + "sync" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// ConfigState manages safe concurrent access to Configuration{} values, +// and provides ease of linking them (including reloading) via viper to +// environment, CLI and configuration file variables. +type ConfigState struct { //nolint + viper *viper.Viper + config Configuration + mutex sync.Mutex +} + +// NewState returns a new initialized ConfigState instance. +func NewState() *ConfigState { + viper := viper.New() + + // Flag 'some-flag-name' becomes env var 'GTS_SOME_FLAG_NAME' + viper.SetEnvPrefix("gts") + viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) + + // Load appropriate named vals from env + viper.AutomaticEnv() + + // Create new ConfigState with defaults + state := &ConfigState{ + viper: viper, + config: Defaults, + } + + // Perform initial load into viper + state.reloadToViper() + + return state +} + +// Config provides safe access to the ConfigState's contained Configuration, +// and will reload the current Configuration back into viper settings. +func (st *ConfigState) Config(fn func(*Configuration)) { + st.mutex.Lock() + defer func() { + st.reloadToViper() + st.mutex.Unlock() + }() + fn(&st.config) +} + +// Viper provides safe access to the ConfigState's contained viper instance, +// and will reload the current viper setting state back into Configuration. +func (st *ConfigState) Viper(fn func(*viper.Viper)) { + st.mutex.Lock() + defer func() { + st.reloadFromViper() + st.mutex.Unlock() + }() + fn(st.viper) +} + +// LoadEarlyFlags will bind specific flags from given Cobra command to ConfigState's viper +// instance, and load the current configuration values. This is useful for flags like +// .ConfigPath which have to parsed first in order to perform early configuration load. +func (st *ConfigState) LoadEarlyFlags(cmd *cobra.Command) (err error) { + name := ConfigPathFlag() + flag := cmd.Flags().Lookup(name) + st.Viper(func(v *viper.Viper) { + err = v.BindPFlag(name, flag) + }) + return +} + +// BindFlags will bind given Cobra command's pflags to this ConfigState's viper instance. +func (st *ConfigState) BindFlags(cmd *cobra.Command) (err error) { + st.Viper(func(v *viper.Viper) { + err = v.BindPFlags(cmd.Flags()) + }) + return +} + +// Reload will reload the Configuration values from ConfigState's viper instance, and from file if set. +func (st *ConfigState) Reload() (err error) { + st.Viper(func(v *viper.Viper) { + if st.config.ConfigPath != "" { + // Ensure configuration path is set + v.SetConfigFile(st.config.ConfigPath) + + // Read in configuration from file + if err = v.ReadInConfig(); err != nil { + return + } + } + }) + return +} + +// reloadToViper will reload Configuration{} values into viper. +func (st *ConfigState) reloadToViper() { + raw, err := st.config.MarshalMap() + if err != nil { + panic(err) + } + if err := st.viper.MergeConfigMap(raw); err != nil { + panic(err) + } +} + +// reloadFromViper will reload Configuration{} values from viper. +func (st *ConfigState) reloadFromViper() { + err := st.config.UnmarshalMap(st.viper.AllSettings()) + if err != nil { + panic(err) + } +} diff --git a/internal/config/validate.go b/internal/config/validate.go index d229e5418..b9dab0f56 100644 --- a/internal/config/validate.go +++ b/internal/config/validate.go @@ -24,7 +24,6 @@ import ( "strings" "github.com/sirupsen/logrus" - "github.com/spf13/viper" ) // Validate validates global config settings which don't have defaults, to make sure they are set sensibly. @@ -32,22 +31,21 @@ func Validate() error { errs := []error{} // host - if viper.GetString(Keys.Host) == "" { - errs = append(errs, fmt.Errorf("%s must be set", Keys.Host)) + if GetHost() == "" { + errs = append(errs, fmt.Errorf("%s must be set", HostFlag())) } // protocol - protocol := viper.GetString(Keys.Protocol) - switch protocol { + switch proto := GetProtocol(); proto { case "https": // no problem break case "http": - logrus.Warnf("%s was set to 'http'; this should *only* be used for debugging and tests!", Keys.Protocol) + logrus.Warnf("%s was set to 'http'; this should *only* be used for debugging and tests!", ProtocolFlag()) case "": - errs = append(errs, fmt.Errorf("%s must be set", Keys.Protocol)) + errs = append(errs, fmt.Errorf("%s must be set", ProtocolFlag())) default: - errs = append(errs, fmt.Errorf("%s must be set to either http or https, provided value was %s", Keys.Protocol, protocol)) + errs = append(errs, fmt.Errorf("%s must be set to either http or https, provided value was %s", ProtocolFlag(), proto)) } if len(errs) > 0 { diff --git a/internal/config/validate_test.go b/internal/config/validate_test.go index 6d8294205..066f1807b 100644 --- a/internal/config/validate_test.go +++ b/internal/config/validate_test.go @@ -21,7 +21,6 @@ package config_test import ( "testing" - "github.com/spf13/viper" "github.com/stretchr/testify/suite" "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/testrig" @@ -41,7 +40,7 @@ func (suite *ConfigValidateTestSuite) TestValidateConfigOK() { func (suite *ConfigValidateTestSuite) TestValidateConfigNoHost() { testrig.InitTestConfig() - viper.Set(config.Keys.Host, "") + config.SetHost("") err := config.Validate() suite.EqualError(err, "host must be set") @@ -50,7 +49,7 @@ func (suite *ConfigValidateTestSuite) TestValidateConfigNoHost() { func (suite *ConfigValidateTestSuite) TestValidateConfigNoProtocol() { testrig.InitTestConfig() - viper.Set(config.Keys.Protocol, "") + config.SetProtocol("") err := config.Validate() suite.EqualError(err, "protocol must be set") @@ -59,8 +58,8 @@ func (suite *ConfigValidateTestSuite) TestValidateConfigNoProtocol() { func (suite *ConfigValidateTestSuite) TestValidateConfigNoProtocolOrHost() { testrig.InitTestConfig() - viper.Set(config.Keys.Host, "") - viper.Set(config.Keys.Protocol, "") + config.SetHost("") + config.SetProtocol("") err := config.Validate() suite.EqualError(err, "host must be set; protocol must be set") @@ -69,7 +68,7 @@ func (suite *ConfigValidateTestSuite) TestValidateConfigNoProtocolOrHost() { func (suite *ConfigValidateTestSuite) TestValidateConfigBadProtocol() { testrig.InitTestConfig() - viper.Set(config.Keys.Protocol, "foo") + config.SetProtocol("foo") err := config.Validate() suite.EqualError(err, "protocol must be set to either http or https, provided value was foo") @@ -78,8 +77,8 @@ func (suite *ConfigValidateTestSuite) TestValidateConfigBadProtocol() { func (suite *ConfigValidateTestSuite) TestValidateConfigBadProtocolNoHost() { testrig.InitTestConfig() - viper.Set(config.Keys.Host, "") - viper.Set(config.Keys.Protocol, "foo") + config.SetHost("") + config.SetProtocol("foo") err := config.Validate() suite.EqualError(err, "host must be set; protocol must be set to either http or https, provided value was foo") diff --git a/internal/config/values.go b/internal/config/values.go deleted file mode 100644 index 1c71e4e30..000000000 --- a/internal/config/values.go +++ /dev/null @@ -1,93 +0,0 @@ -/* - GoToSocial - Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -package config - -// Values contains contains the type of each configuration value. -type Values struct { - LogLevel string - LogDbQueries bool - ApplicationName string - ConfigPath string - Host string - AccountDomain string - Protocol string - BindAddress string - Port int - TrustedProxies []string - SoftwareVersion string - - DbType string - DbAddress string - DbPort int - DbUser string - DbPassword string - DbDatabase string - DbTLSMode string - DbTLSCACert string - - WebTemplateBaseDir string - WebAssetBaseDir string - - AccountsRegistrationOpen bool - AccountsApprovalRequired bool - AccountsReasonRequired bool - - MediaImageMaxSize int - MediaVideoMaxSize int - MediaDescriptionMinChars int - MediaDescriptionMaxChars int - MediaRemoteCacheDays int - - StorageBackend string - StorageLocalBasePath string - - StatusesMaxChars int - StatusesCWMaxChars int - StatusesPollMaxOptions int - StatusesPollOptionMaxChars int - StatusesMediaMaxFiles int - - LetsEncryptEnabled bool - LetsEncryptCertDir string - LetsEncryptEmailAddress string - LetsEncryptPort int - - OIDCEnabled bool - OIDCIdpName string - OIDCSkipVerification bool - OIDCIssuer string - OIDCClientID string - OIDCClientSecret string - OIDCScopes []string - - SMTPHost string - SMTPPort int - SMTPUsername string - SMTPPassword string - SMTPFrom string - - SyslogEnabled bool - SyslogProtocol string - SyslogAddress string - - AdminAccountUsername string - AdminAccountEmail string - AdminAccountPassword string - AdminTransPath string -} diff --git a/internal/config/viper.go b/internal/config/viper.go deleted file mode 100644 index 8ed241e1b..000000000 --- a/internal/config/viper.go +++ /dev/null @@ -1,42 +0,0 @@ -/* - GoToSocial - Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -package config - -import ( - "strings" - - "github.com/spf13/pflag" - "github.com/spf13/viper" -) - -func InitViper(f *pflag.FlagSet) error { - // environment variable stuff - // flag 'some-flag-name' becomes env var 'GTS_SOME_FLAG_NAME' - viper.SetEnvPrefix("gts") - viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) - viper.AutomaticEnv() - - // flag stuff - // bind all of the flags in flagset to viper so that we can retrieve their values from the viper store - if err := viper.BindPFlags(f); err != nil { - return err - } - - return nil -} |