pcmt/app/settings/settings.go
surtur b97e47ed1b
All checks were successful
continuous-integration/drone/push Build is passing
go(app/settings): create a file for defaults
2023-09-10 12:58:38 +02:00

477 lines
12 KiB
Go

// Copyright 2023 wanderer <a_mirre at utb dot cz>
// SPDX-License-Identifier: AGPL-3.0-only
package settings
import (
"os"
"time"
"git.dotya.ml/mirre-mt/pcmt/config"
"git.dotya.ml/mirre-mt/pcmt/slogging"
"golang.org/x/exp/slog"
)
type Settings struct {
host string
port int
appPath string
httpDomain string
httpSecure bool
httpGzipEnabled bool
httpGzipLevel int
httpRateLimitEnabled bool
httpRateLimit int
httpCSP string
isLive bool
isDevel bool
initCreateAdmin bool
initAdminPassword string
loggerJSON bool
sessionCookieName string
sessionCookieAuthSecret string
sessionCookieEncrSecret string
sessionAuthIsHex bool
sessionEncrIsHex bool
sessionMaxAge int
assetsPath string
templatesPath string
version string
dbConnstring string
dbType string
dbIsSetUp bool
RegistrationAllowed bool
hibpAPIKey string
dehashedAPIKey string
}
var log slogging.Slogger
// cleantgt is a list of ENV vars pertaining to pcmt.
var cleantgt = []string{
"PCMT_LIVE",
"PCMT_DEVEL",
"PCMT_CONNSTRING",
"PCMT_DBTYPE",
"PCMT_SESSION_AUTH_SECRET",
"PCMT_SESSION_ENCR_SECRET",
"PCMT_INIT_ADMIN_PASSWORD",
"PCMT_HIBP_API_KEY",
"PCMT_DEHASHED_API_KEY",
}
// New returns a new instance of the settings struct.
func New() *Settings {
return &Settings{}
}
// DefaultServerWriteTimeout returns the server default write timeout.
func (s *Settings) DefaultServerWriteTimeout() time.Duration {
return defaultServerWriteTimeout
}
// DefaultServerReadHeaderTimeout returns the server default read header timeout.
func (s *Settings) DefaultServerReadHeaderTimeout() time.Duration {
return defaultServerReadHeaderTimeout
}
// DefaultLoggerSkipAssets returns whether the logger skips reporting asset visits.
func (s *Settings) DefaultLoggerSkipAssets() bool {
return defaultLoggerSkipAssets
}
// Consolidate reconciles whatever values are set in config and via flags and
// sets it to one place that should be regarded as a single source of truth -
// the settings struct. Order of preference for values is (from higher to
// lower) as follows: flag -> Env var -> configuration file.
func (s *Settings) Consolidate(conf *config.Config, host *string, port *int, devel *bool, version string) {
log = *slogging.Logger() // have a local copy.
log.Logger = log.With(
slog.Group("pcmt extra", slog.String("module", "app/settings")),
)
log.Debug("starting to consolidate settings")
log.Debug("parsing config values")
if p := conf.Port; p > 0 && p < 65536 {
s.SetPort(conf.Port)
} else {
log.Warnf("port '%d', outside of bounds, setting a default of %d/tcp", p, defaultPort)
s.SetPort(defaultPort)
}
s.SetHost(conf.Host)
s.SetAppPath(conf.AppPath)
s.SetIsLive(conf.LiveMode)
s.SetIsDevel(conf.DevelMode)
s.SetLoggerIsJSON(conf.Logger.JSON)
if conf.HTTP.Secure {
// https://www.sjoerdlangkemper.nl/2017/02/09/cookie-prefixes/
// https://scotthelme.co.uk/tough-cookies/
// https://check-your-website.server-daten.de/prefix-cookies.html
s.SetSessionCookieName("__Host-" + conf.Session.CookieName)
} else {
s.SetSessionCookieName(conf.Session.CookieName)
}
s.SetSessionMaxAge(conf.Session.MaxAge)
s.SetSessionCookieAuthSecret(conf.Session.CookieAuthSecret)
s.SetSessionCookieEncrSecret(conf.Session.CookieEncrSecret)
authHex, encrHex := conf.SessionSecretsAreHex()
if authHex {
s.sessionAuthIsHex = true
}
if encrHex {
s.sessionEncrIsHex = true
}
if conf.Init.CreateAdmin {
s.SetInitCreateAdmin(true)
s.SetInitAdminPassword(conf.Init.AdminPassword)
}
if conf.Registration.Allowed {
s.RegistrationAllowed = true
}
if conf.HTTP.Gzip > 0 {
s.SetHTTPGzipEnabled(true)
s.SetHTTPGzipLevel(conf.HTTP.Gzip)
}
if conf.HTTP.RateLimit > 0 {
s.SetHTTPRateLimitEnabled(true)
s.SetHTTPRateLimit(conf.HTTP.RateLimit)
}
s.SetHTTPCSP(conf.HTTP.ContentSecurityPolicy)
s.SetHTTPDomain(conf.HTTP.Domain)
s.SetHTTPSecure(conf.HTTP.Secure)
s.setAPIKeys()
s.sortOutFlags(conf, host, port, devel)
s.SetVersion(version)
}
// Host returns the host.
func (s *Settings) Host() string {
return s.host
}
// Port returns the port.
func (s *Settings) Port() int {
return s.port
}
// AppName returns the appName.
func (s *Settings) AppName() string {
return defaultAppName
}
// AppPath returns the appPath.
func (s *Settings) AppPath() string {
return s.appPath
}
// IsLive returns the value of isLive of the receiver.
func (s *Settings) IsLive() bool {
return s.isLive
}
// IsDevel returns the value of isDevel of the receiver.
func (s *Settings) IsDevel() bool {
return s.isDevel
}
// InitCreateAdmin returns the value of initCreateAdmin of the receiver.
func (s *Settings) InitCreateAdmin() bool {
return s.initCreateAdmin
}
// InitAdminPassword returns the value of initAdminPassword of the receiver.
func (s *Settings) InitAdminPassword() string {
return s.initAdminPassword
}
// LoggerIsJSON returns whether the logger should use the JSON handler.
func (s *Settings) LoggerIsJSON() bool {
return s.loggerJSON
}
// SessionCookieName returns the name of the session cookie.
func (s *Settings) SessionCookieName() string {
return s.sessionCookieName
}
// SessionCookieAuthSecret returns the session cookie authentication secret.
func (s *Settings) SessionCookieAuthSecret() string {
return s.sessionCookieAuthSecret
}
// SessionCookieEncrSecret returns the session cookie encryption secret.
func (s *Settings) SessionCookieEncrSecret() string {
return s.sessionCookieEncrSecret
}
// SessionAuthIsHex returns whether the session cookie authentication secret is hex.
func (s *Settings) SessionAuthIsHex() bool {
return s.sessionAuthIsHex
}
// SessionEncrIsHex returns whether the session cookie encryption secret is hex.
func (s *Settings) SessionEncrIsHex() bool {
return s.sessionEncrIsHex
}
// SessionMaxAge returns the session cookie MaxAge value.
func (s *Settings) SessionMaxAge() int {
return s.sessionMaxAge
}
// HTTPDomain returns the httpDomain.
func (s *Settings) HTTPDomain() string {
return s.httpDomain
}
// HTTPSecure returns the httpSecure.
func (s *Settings) HTTPSecure() bool {
return s.httpSecure
}
// HTTPGzipEnabled returns the httpGzipEnabled variable.
func (s *Settings) HTTPGzipEnabled() bool {
return s.httpGzipEnabled
}
// HTTPGzipLevel returns the httpGzipLevel.
func (s *Settings) HTTPGzipLevel() int {
return s.httpGzipLevel
}
// HTTPRateLimitEnabled returns the httpRateLimitEnabled variable.
func (s *Settings) HTTPRateLimitEnabled() bool {
return s.httpRateLimitEnabled
}
// HTTPRateLimit returns the httpRateLimit.
func (s *Settings) HTTPRateLimit() int {
return s.httpRateLimit
}
// HTTPCSP returns the httpCSP.
func (s *Settings) HTTPCSP() string {
return s.httpCSP
}
// AssetsPath returns the assetsPath.
func (s *Settings) AssetsPath() string {
return s.assetsPath
}
// TemplatesPath returns the templatesPath.
func (s *Settings) TemplatesPath() string {
return s.templatesPath
}
// Version returns the version.
func (s *Settings) Version() string {
return s.version
}
// DbIsSetUp returns the dbIsSetUp.
func (s *Settings) DbIsSetUp() bool {
return s.dbIsSetUp
}
// APIKeyHIBP returns the hibpAPIKey.
func (s *Settings) APIKeyHIBP() string {
return s.hibpAPIKey
}
// APIKeyDehashed returns the dehashedAPIKey.
func (s *Settings) APIKeyDehashed() string {
return s.dehashedAPIKey
}
// DbConnstring returns the dbConnString.
func (s *Settings) DbConnstring() string {
return s.dbConnstring
}
// DbType returns the dbType.
func (s *Settings) DbType() string {
return s.dbType
}
// SetHost sets the host.
func (s *Settings) SetHost(host string) {
s.host = host
}
// SetPort sets the port.
func (s *Settings) SetPort(port int) {
s.port = port
}
// SetAppPath sets the appPath.
func (s *Settings) SetAppPath(appPath string) {
s.appPath = appPath
}
// SetIsLive sets the value of isLive of the receiver.
func (s *Settings) SetIsLive(live bool) {
s.isLive = live
}
// SetIsDevel sets the value of isDevel of the receiver.
func (s *Settings) SetIsDevel(devel bool) {
s.isDevel = devel
}
// SetInitCreateAdmin sets the value of initCreateAdmin of the receiver.
func (s *Settings) SetInitCreateAdmin(create bool) {
s.initCreateAdmin = create
}
// SetInitAdminPassword sets the value of initAdminPassword of the receiver.
func (s *Settings) SetInitAdminPassword(password string) {
s.initAdminPassword = password
}
// SetLoggerIsJSON sets the setting value of loggerIsJSON.
func (s *Settings) SetLoggerIsJSON(isJSON bool) {
s.loggerJSON = isJSON
}
// SetSessionCookieName sets session cookie name.
func (s *Settings) SetSessionCookieName(sessionCookieName string) {
s.sessionCookieName = sessionCookieName
}
// SetSessionCookieAuthSecret sets the session cookie authentication secret.
func (s *Settings) SetSessionCookieAuthSecret(sessionCookieAuthSecret string) {
s.sessionCookieAuthSecret = sessionCookieAuthSecret
}
// SetSessionCookieEncrSecret sets the session cookie encryption secret.
func (s *Settings) SetSessionCookieEncrSecret(sessionCookieEncrSecret string) {
s.sessionCookieEncrSecret = sessionCookieEncrSecret
}
// SetSessionMaxAge sets sessionMaxAge.
func (s *Settings) SetSessionMaxAge(sessionMaxAge int) {
if sessionMaxAge < 1 {
log.Debug("setting cookie max age to the default")
s.sessionMaxAge = defaultSessionMaxAge
} else {
log.Debug("setting cookie max age to a config-provided value", "maxAge", sessionMaxAge)
s.sessionMaxAge = sessionMaxAge
}
}
// SetHTTPDomain sets the httpDomain.
func (s *Settings) SetHTTPDomain(domain string) {
switch domain {
case "":
s.httpDomain = defaultHTTPDomain
default:
s.httpDomain = domain
}
}
// SetHTTPSecure sets the httpSecure.
func (s *Settings) SetHTTPSecure(secure bool) {
s.httpSecure = secure
}
// SetHTTPGzipEnabled sets the httpGzipEnabled variable.
func (s *Settings) SetHTTPGzipEnabled(enabled bool) {
s.httpGzipEnabled = enabled
}
// SetHTTPGzipLevel sets the httpGzipLevel.
func (s *Settings) SetHTTPGzipLevel(level int) {
s.httpGzipLevel = level
}
// SetHTTPRateLimitEnabled sets the httpRateLimitEnabled variable.
func (s *Settings) SetHTTPRateLimitEnabled(enabled bool) {
s.httpRateLimitEnabled = enabled
}
// SetHTTPRateLimit sets the httpRateLimit.
func (s *Settings) SetHTTPRateLimit(rateLimit int) {
s.httpRateLimit = rateLimit
}
// SetHTTPCSP sets the content security policy.
func (s *Settings) SetHTTPCSP(csp string) {
switch csp {
case "":
if s.isDevel {
s.httpCSP = defaultCSPDevel
} else {
s.httpCSP = defaultCSP
}
default:
s.httpCSP = csp
}
}
// SetAssetsPath sets the assetsPath.
func (s *Settings) SetAssetsPath(assetsPath string) {
s.assetsPath = assetsPath
}
// SetTemplatesPath sets the templatesPath.
func (s *Settings) SetTemplatesPath(templatesPath string) {
s.templatesPath = templatesPath
}
// SetVersion sets the version.
func (s *Settings) SetVersion(version string) {
s.version = version
}
// SetDbConnstring sets the dbConnString.
func (s *Settings) SetDbConnstring(connstring string) {
s.dbConnstring = connstring
}
// SetDbType sets the dbType.
func (s *Settings) SetDbType(dbType string) {
s.dbType = dbType
}
// SetDbIsSetUp sets the dbIsSetUp.
func (s *Settings) SetDbIsSetUp(is bool) {
s.dbIsSetUp = is
}
// SetAPIKeyHIBP sets the hibpAPIKey.
func (s *Settings) SetAPIKeyHIBP(k string) {
s.hibpAPIKey = k
}
// SetAPIKeyDehashed sets the dehashedAPIKey.
func (s *Settings) SetAPIKeyDehashed(k string) {
s.dehashedAPIKey = k
}
// EraseENVs attempts to clear environment vars pertaining to pcmt.
func (s *Settings) EraseENVs() error {
for _, v := range cleantgt {
err := os.Unsetenv(v)
if err != nil {
return err
}
}
return nil
}