From 6d20106bb5c94a628f88ba3e3db292d4c3428998 Mon Sep 17 00:00:00 2001 From: Derrick Hammer Date: Sun, 11 Feb 2024 16:27:24 -0500 Subject: [PATCH] refactor: viper can't save a struct, got to do it ourselves --- config/config.go | 114 ++++++++++++++++++++++++++++++++--------------- go.mod | 2 + 2 files changed, 81 insertions(+), 35 deletions(-) diff --git a/config/config.go b/config/config.go index bb95129..4b37639 100644 --- a/config/config.go +++ b/config/config.go @@ -3,10 +3,13 @@ package config import ( "encoding" "encoding/base64" - "github.com/mitchellh/mapstructure" + "fmt" + "github.com/fatih/structs" + "github.com/iancoleman/strcase" "github.com/spf13/viper" "go.uber.org/fx" "go.uber.org/zap" + "reflect" ) import ( @@ -17,6 +20,7 @@ type PrivateKey ed25519.PrivateKey var ( _ encoding.TextUnmarshaler = (*PrivateKey)(nil) + _ encoding.TextMarshaler = (*PrivateKey)(nil) ) func (p *PrivateKey) UnmarshalText(text []byte) error { @@ -30,23 +34,27 @@ func (p *PrivateKey) UnmarshalText(text []byte) error { return nil } +func (p *PrivateKey) MarshalText() ([]byte, error) { + return []byte(base64.StdEncoding.EncodeToString(*p)), nil +} + type Config struct { - Host string `mapstructure:"host"` - Port int `mapstructure:"port"` - GiteaUrl string `mapstructure:"gitea_url"` - DbPath string `mapstructure:"db_path"` + Host string `mapstructure:"host" structs:"host"` + Port int `mapstructure:"port" structs:"port"` + GiteaUrl string `mapstructure:"gitea_url" structs:"gitea_url"` + DbPath string `mapstructure:"db_path" structs:"db_path"` Oauth OauthConfig JwtPrivateKey PrivateKey - Domain string `mapstructure:"domain"` - GiteaWebHookSecret string `mapstructure:"gitea_webhook_secret"` + Domain string `mapstructure:"domain" structs:"domain"` + GiteaWebHookSecret string `mapstructure:"gitea_webhook_secret" structs:"gitea_webhook_secret"` } type OauthConfig struct { - Authorization string `mapstructure:"authorization"` - Token string `mapstructure:"token"` - ClientId string `mapstructure:"client_id"` - ClientSecret string `mapstructure:"client_secret"` - RefreshToken string `mapstructure:"refresh_token"` + Authorization string `mapstructure:"authorization" structs:"authorization"` + Token string `mapstructure:"token" structs:"token"` + ClientId string `mapstructure:"client_id" structs:"client_id"` + ClientSecret string `mapstructure:"client_secret" structs:"client_secret"` + RefreshToken string `mapstructure:"refresh_token" structs:"refresh_token"` } var Module = fx.Module("config", @@ -58,8 +66,6 @@ var Module = fx.Module("config", func NewConfig(logger *zap.Logger) *Config { c := &Config{} - cfg := viper.New() - _, sk, err := ed25519.GenerateKey(nil) if err != nil { @@ -67,35 +73,35 @@ func NewConfig(logger *zap.Logger) *Config { } // Set the default values - cfg.SetDefault("host", "localhost") - cfg.SetDefault("port", 8080) - cfg.SetDefault("gitea_url", "") - cfg.SetDefault("db_path", "data.db") - cfg.SetDefault("jwt_private_key", base64.StdEncoding.EncodeToString(sk)) - cfg.SetDefault("oauth.client_id", "") - cfg.SetDefault("oauth.client_secret", "") + viper.SetDefault("host", "localhost") + viper.SetDefault("port", 8080) + viper.SetDefault("gitea_url", "") + viper.SetDefault("db_path", "data.db") + viper.SetDefault("jwt_private_key", base64.StdEncoding.EncodeToString(sk)) + viper.SetDefault("oauth.client_id", "") + viper.SetDefault("oauth.client_secret", "") - cfg.AddConfigPath(".") - cfg.AddConfigPath("/etc/gitea-github-proxy") - cfg.SetConfigName("config") - cfg.SetConfigType("yaml") - err = cfg.ReadInConfig() + viper.AddConfigPath(".") + viper.AddConfigPath("/etc/gitea-github-proxy") + viper.SetConfigName("config") + viper.SetConfigType("yaml") + err = viper.ReadInConfig() if err != nil { - err = cfg.SafeWriteConfig() + err = viper.SafeWriteConfig() if err != nil { logger.Fatal("Error writing config file", zap.Error(err)) } } - err = cfg.Unmarshal(c) + err = viper.Unmarshal(c) if err != nil { logger.Fatal("Error unmarshalling config", zap.Error(err)) } - err = cfg.UnmarshalKey("jwt_private_key", &c.JwtPrivateKey, viper.DecodeHook(mapstructure.TextUnmarshallerHookFunc())) - if err != nil { - logger.Fatal("Error unmarshalling jwtPrivateKey", zap.Error(err)) - } + /* err = viper.UnmarshalKey("jwt_private_key", &c.JwtPrivateKey, viper.DecodeHook(mapstructure.TextUnmarshallerHookFunc())) + if err != nil { + logger.Fatal("Error unmarshalling jwtPrivateKey", zap.Error(err)) + }*/ if len(c.GiteaUrl) == 0 { logger.Fatal("Gitea URL is required") @@ -105,10 +111,48 @@ func NewConfig(logger *zap.Logger) *Config { } func SaveConfig(cfg *Config) error { - err := viper.Unmarshal(cfg) - if err != nil { - return err + data := structs.New(cfg) + + for _, field := range data.Fields() { + processFields(field, nil) } + /* if field, ok := interface{}(cfg.JwtPrivateKey).(encoding.TextMarshaler); ok { + text, err := field.MarshalText() + if err != nil { + return err + } + viper.Set("jwt_private_key", string(text)) + } + */ return viper.WriteConfig() } + +func processFields(f *structs.Field, parent *structs.Field) { + if f.IsZero() { + return + } + + if f.Kind() == reflect.Struct { + fields := f.Fields() + + if len(fields) > 0 { + for _, field := range fields { + processFields(field, f) + } + return + } + } + + name := "" + + if parent != nil { + name = fmt.Sprintf("%s.%s", parent.Name(), f.Name()) + } else { + name = f.Name() + } + + name = strcase.ToSnakeWithIgnore(name, ".") + + viper.Set(name, f.Value()) +} diff --git a/go.mod b/go.mod index 8c40bbf..9bb0b28 100644 --- a/go.mod +++ b/go.mod @@ -5,9 +5,11 @@ go 1.21 require ( code.gitea.io/gitea v1.21.5 code.gitea.io/sdk/gitea v0.17.1 + github.com/fatih/structs v1.1.0 github.com/golang-jwt/jwt v3.2.2+incompatible github.com/google/go-github/v59 v59.0.0 github.com/gorilla/mux v1.8.1 + github.com/iancoleman/strcase v0.3.0 github.com/mitchellh/mapstructure v1.5.0 github.com/spf13/viper v1.18.2 go.uber.org/fx v1.20.1