🔧 Replaced viper config to environment variables
due 12factor, see: https://12factor.net/config
This commit is contained in:
parent
30f8be2c6c
commit
b67c386ce7
|
@ -11,68 +11,68 @@ import (
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Config struct {
|
Config struct {
|
||||||
Code ConfigCode `yaml:"code"`
|
Code ConfigCode `envPrefix:"CODE_"`
|
||||||
Database ConfigDatabase `yaml:"database"`
|
Database ConfigDatabase `envPrefix:"DATABASE_"`
|
||||||
IndieAuth ConfigIndieAuth `yaml:"indieAuth"`
|
IndieAuth ConfigIndieAuth `envPrefix:"INDIEAUTH_"`
|
||||||
JWT ConfigJWT `yaml:"jwt"`
|
JWT ConfigJWT `envPrefix:"JWT_"`
|
||||||
Server ConfigServer `yaml:"server"`
|
Server ConfigServer `envPrefix:"SERVER_"`
|
||||||
TicketAuth ConfigTicketAuth `yaml:"ticketAuth"`
|
TicketAuth ConfigTicketAuth `envPrefix:"TICKETAUTH_"`
|
||||||
Name string `yaml:"name"`
|
Name string `env:"NAME" envDefault:"IndieAuth"`
|
||||||
RunMode string `yaml:"runMode"`
|
RunMode string `env:"RUN_MODE" envDefault:"dev"`
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigServer struct {
|
ConfigServer struct {
|
||||||
CertificateFile string `yaml:"certFile"`
|
CertificateFile string `env:"CERT_FILE"`
|
||||||
Domain string `yaml:"domain"`
|
Domain string `env:"DOMAIN" envDefault:"localhost"`
|
||||||
Host string `yaml:"host"`
|
Host string `env:"HOST" envDefault:"0.0.0.0"`
|
||||||
KeyFile string `yaml:"keyFile"`
|
KeyFile string `env:"KEY_FILE"`
|
||||||
Port string `yaml:"port"`
|
Port string `env:"PORT" envDefault:"3000"`
|
||||||
Protocol string `yaml:"protocol"`
|
Protocol string `env:"PROTOCOL" envDefault:"http"`
|
||||||
RootURL string `yaml:"rootUrl"`
|
RootURL string `env:"ROOT_URL" envDefault:"{{protocol}}://{{domain}}:{{port}}/"`
|
||||||
StaticURLPrefix string `yaml:"staticUrlPrefix"`
|
StaticURLPrefix string `env:"STATIC_URL_PREFIX"`
|
||||||
EnablePprof bool `yaml:"enablePprof"`
|
EnablePprof bool `env:"ENABLE_PPROF"`
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigDatabase struct {
|
ConfigDatabase struct {
|
||||||
Path string `yaml:"path"`
|
Path string `env:"PATH"`
|
||||||
Type string `yaml:"type"` // memory
|
Type string `env:"TYPE" envDefault:"memory"` // memory
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configuration of a one-time code after giving permission to an
|
// Configuration of a one-time code after giving permission to an
|
||||||
// application. The client needs to request the server with this code to
|
// application. The client needs to request the server with this code to
|
||||||
// exchange it for a token or user information.
|
// exchange it for a token or user information.
|
||||||
ConfigCode struct {
|
ConfigCode struct {
|
||||||
Expiry time.Duration `yaml:"expiry"` // 10m
|
Expiry time.Duration `env:"EXPIRY" envDefault:"10m"` // 10m
|
||||||
Length uint8 `yaml:"length"` // 32
|
Length uint8 `env:"LENGTH" envDefault:"32"` // 32
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigJWT struct {
|
ConfigJWT struct {
|
||||||
Expiry time.Duration `yaml:"expiry"` // 1h
|
Expiry time.Duration `env:"EXPIRY" envDefault:"1h"` // 1h
|
||||||
Algorithm string `yaml:"algorithm"` // HS256
|
Algorithm string `env:"ALGORITHM" envDefault:"HS256"` // HS256
|
||||||
Secret string `yaml:"secret"`
|
Secret string `env:"SECRET"`
|
||||||
NonceLength uint8 `yaml:"nonceLength"` // 22
|
NonceLength uint8 `env:"NONCE_LENGTH" envDefault:"22"` // 22
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigIndieAuth struct {
|
ConfigIndieAuth struct {
|
||||||
Password string `yaml:"password"`
|
Password string `env:"PASSWORD"`
|
||||||
Username string `yaml:"username"`
|
Username string `env:"USERNAME"`
|
||||||
Enabled bool `yaml:"enabled"` // true
|
Enabled bool `env:"ENABLED" envDefault:"true"` // true
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigTicketAuth struct {
|
ConfigTicketAuth struct {
|
||||||
Expiry time.Duration `yaml:"expiry"` // 1m
|
Expiry time.Duration `env:"EXPIRY" envDefault:"1m"` // 1m
|
||||||
Length uint8 `yaml:"length"` // 24
|
Length uint8 `env:"LENGTH" envDefault:"24"` // 24
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigRelMeAuth struct {
|
ConfigRelMeAuth struct {
|
||||||
Providers []ConfigRelMeAuthProvider `yaml:"providers"`
|
Providers []ConfigRelMeAuthProvider `envPrefix:"PROVIDERS_"`
|
||||||
Enabled bool `yaml:"enabled"` // true
|
Enabled bool `env:"ENABLED" envDefault:"true"` // true
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigRelMeAuthProvider struct {
|
ConfigRelMeAuthProvider struct {
|
||||||
ID string `yaml:"id"`
|
ID string `env:"ID"`
|
||||||
Secret string `yaml:"secret"`
|
Secret string `env:"SECRET"`
|
||||||
Type string `yaml:"type"`
|
Type string `env:"TYPE"`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
59
main.go
59
main.go
|
@ -17,15 +17,14 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/caarlos0/env/v6"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/spf13/viper"
|
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
"golang.org/x/text/message"
|
"golang.org/x/text/message"
|
||||||
_ "modernc.org/sqlite"
|
_ "modernc.org/sqlite"
|
||||||
|
@ -86,9 +85,8 @@ type (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefaultCacheDuration time.Duration = 8760 * time.Hour // NOTE(toby3d): year
|
DefaultReadTimeout time.Duration = 5 * time.Second
|
||||||
DefaultReadTimeout time.Duration = 5 * time.Second
|
DefaultWriteTimeout time.Duration = 10 * time.Second
|
||||||
DefaultWriteTimeout time.Duration = 10 * time.Second
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//nolint:gochecknoglobals
|
//nolint:gochecknoglobals
|
||||||
|
@ -96,12 +94,16 @@ var (
|
||||||
// NOTE(toby3d): write logs in stdout, see: https://12factor.net/logs
|
// NOTE(toby3d): write logs in stdout, see: https://12factor.net/logs
|
||||||
logger = log.New(os.Stdout, "IndieAuth\t", log.Lmsgprefix|log.LstdFlags|log.LUTC)
|
logger = log.New(os.Stdout, "IndieAuth\t", log.Lmsgprefix|log.LstdFlags|log.LUTC)
|
||||||
config = new(domain.Config)
|
config = new(domain.Config)
|
||||||
indieAuthClient = new(domain.Client)
|
indieAuthClient = &domain.Client{
|
||||||
|
URL: make([]*url.URL, 1),
|
||||||
|
Logo: make([]*url.URL, 1),
|
||||||
|
RedirectURI: make([]*url.URL, 1),
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
configPath, cpuProfilePath, memProfilePath string
|
cpuProfilePath, memProfilePath string
|
||||||
enablePprof bool
|
enablePprof bool
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed assets/*
|
//go:embed assets/*
|
||||||
|
@ -109,31 +111,15 @@ var staticFS embed.FS
|
||||||
|
|
||||||
//nolint:gochecknoinits
|
//nolint:gochecknoinits
|
||||||
func init() {
|
func init() {
|
||||||
flag.StringVar(&configPath, "config", filepath.Join(".", "config.yml"), "load specific config")
|
|
||||||
flag.BoolVar(&enablePprof, "pprof", false, "enable pprof mode")
|
flag.BoolVar(&enablePprof, "pprof", false, "enable pprof mode")
|
||||||
|
flag.StringVar(&cpuProfilePath, "cpuprofile", "", "set path to saving CPU memory profile")
|
||||||
|
flag.StringVar(&memProfilePath, "memprofile", "", "set path to saving pprof memory profile")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
viper.AddConfigPath(".")
|
if err := env.Parse(&config, env.Options{
|
||||||
viper.AddConfigPath(filepath.Join(".", "configs"))
|
Prefix: "INDIEAUTH_",
|
||||||
viper.SetConfigName("config")
|
}); err != nil {
|
||||||
viper.SetConfigType("yml")
|
logger.Fatalln(err)
|
||||||
|
|
||||||
if configPath != "" {
|
|
||||||
viper.SetConfigFile(configPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
viper.SetEnvPrefix("INDIEAUTH_")
|
|
||||||
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
|
||||||
viper.AutomaticEnv()
|
|
||||||
viper.WatchConfig()
|
|
||||||
|
|
||||||
var err error
|
|
||||||
if err = viper.ReadInConfig(); err != nil {
|
|
||||||
logger.Fatalf("cannot load config from file %s: %v", viper.ConfigFileUsed(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = viper.Unmarshal(&config); err != nil {
|
|
||||||
logger.Fatalln("failed to read config:", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(toby3d): The server instance itself can be as a client.
|
// NOTE(toby3d): The server instance itself can be as a client.
|
||||||
|
@ -147,24 +133,17 @@ func init() {
|
||||||
|
|
||||||
indieAuthClient.ID = *cid
|
indieAuthClient.ID = *cid
|
||||||
|
|
||||||
u, err := url.Parse(rootURL)
|
if indieAuthClient.URL[0], err = url.Parse(rootURL); err != nil {
|
||||||
if err != nil {
|
|
||||||
logger.Fatalln("cannot parse root URL as client URL:", err)
|
logger.Fatalln("cannot parse root URL as client URL:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
logo, err := url.Parse(rootURL + config.Server.StaticURLPrefix + "/icon.svg")
|
if indieAuthClient.Logo[0], err = url.Parse(rootURL + config.Server.StaticURLPrefix + "/icon.svg"); err != nil {
|
||||||
if err != nil {
|
|
||||||
logger.Fatalln("cannot parse root URL as client URL:", err)
|
logger.Fatalln("cannot parse root URL as client URL:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
redirectURI, err := url.Parse(rootURL + "callback")
|
if indieAuthClient.RedirectURI[0], err = url.Parse(rootURL + "callback"); err != nil {
|
||||||
if err != nil {
|
|
||||||
logger.Fatalln("cannot parse root URL as client URL:", err)
|
logger.Fatalln("cannot parse root URL as client URL:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
indieAuthClient.URL = []*url.URL{u}
|
|
||||||
indieAuthClient.Logo = []*url.URL{logo}
|
|
||||||
indieAuthClient.RedirectURI = []*url.URL{redirectURI}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:funlen,cyclop // "god object" and the entry point of all modules
|
//nolint:funlen,cyclop // "god object" and the entry point of all modules
|
||||||
|
|
Loading…
Reference in New Issue