Skip to content

Commit

Permalink
fix: take care of providing empty values to the configure command
Browse files Browse the repository at this point in the history
  • Loading branch information
cecobask committed Jul 18, 2024
1 parent ab603cd commit 176201e
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 127 deletions.
18 changes: 11 additions & 7 deletions cmd/configure/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,18 @@ func NewCommand(ctx context.Context) *cobra.Command {
if conf, err = config.New(confPath, false); err != nil {
return fmt.Errorf("error loading config: %w", err)
}
return conf.Validate()
return nil
},
RunE: func(c *cobra.Command, args []string) error {
teaModel, err := config.NewTeaProgram(conf.Flatten(), tea.WithOutput(c.OutOrStdout())).Run()
opts := []tea.ProgramOption{
tea.WithContext(ctx),
tea.WithOutput(c.OutOrStdout()),
}
teaModel, err := config.NewTeaProgram(conf.Flatten(), opts...).Run()
if err != nil {
return fmt.Errorf("error initializing text-based user interface for the %s command: %w", cmd.CommandNameConfigure, err)
}
model, ok := teaModel.(*config.Model)
if !ok {
return fmt.Errorf("error type asserting tea.Model to *config.Model")
}
model := teaModel.(*config.Model)
if err = model.Err(); err != nil {
if errors.Is(err, config.ErrUserAborted) {
return nil
Expand All @@ -49,7 +50,10 @@ func NewCommand(ctx context.Context) *cobra.Command {
if err = conf.Validate(); err != nil {
return fmt.Errorf("error validating config: %w", err)
}
return conf.WriteFile(confPath)
if err = conf.WriteFile(confPath); err != nil {
return fmt.Errorf("error writing config file: %w", err)
}
return nil
},
}
command.Flags().String(cmd.FlagNameConfigFile, cmd.ConfigFileDefault, "path to the config file")
Expand Down
10 changes: 8 additions & 2 deletions cmd/sync/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ func NewCommand(ctx context.Context) *cobra.Command {
if conf, err = config.New(confPath, true); err != nil {
return fmt.Errorf("error loading config: %w", err)
}
return conf.Validate()
if err = conf.Validate(); err != nil {
return fmt.Errorf("error validating config: %w", err)
}
return nil
},
RunE: func(c *cobra.Command, args []string) error {
timeoutCtx, cancel := context.WithTimeout(ctx, *conf.Sync.Timeout)
Expand All @@ -33,7 +36,10 @@ func NewCommand(ctx context.Context) *cobra.Command {
if err != nil {
return fmt.Errorf("error creating syncer: %w", err)
}
return s.Sync()
if err = s.Sync(); err != nil {
return fmt.Errorf("error performing sync: %w", err)
}
return nil
},
}
command.Flags().String(cmd.FlagNameConfigFile, cmd.ConfigFileDefault, "path to the config file")
Expand Down
63 changes: 29 additions & 34 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,49 +94,50 @@ func NewFromMap(data map[string]interface{}) (*Config, error) {
if err := k.Unmarshal("", &conf); err != nil {
return nil, fmt.Errorf("error unmarshalling config: %w", err)
}
conf.applyDefaults()
return &conf, nil
}

func (c *Config) Validate() error {
if c.IMDb.Auth == nil {
return fmt.Errorf("config field 'IMDB_AUTH' is required")
if isNilOrEmpty(c.IMDb.Auth) {
return fmt.Errorf("field 'IMDB_AUTH' is required")
}
switch *c.IMDb.Auth {
case IMDbAuthMethodCredentials:
if c.IMDb.Email == nil {
return fmt.Errorf("config field 'IMDB_EMAIL' is required")
if isNilOrEmpty(c.IMDb.Email) {
return fmt.Errorf("field 'IMDB_EMAIL' is required")
}
if c.IMDb.Password == nil {
return fmt.Errorf("config field 'IMDB_PASSWORD' is required")
if isNilOrEmpty(c.IMDb.Password) {
return fmt.Errorf("field 'IMDB_PASSWORD' is required")
}
case IMDbAuthMethodCookies:
if c.IMDb.CookieAtMain == nil {
return fmt.Errorf("config field 'IMDB_COOKIEATMAIN' is required")
if isNilOrEmpty(c.IMDb.CookieAtMain) {
return fmt.Errorf("field 'IMDB_COOKIEATMAIN' is required")
}
if c.IMDb.CookieUbidMain == nil {
return fmt.Errorf("config field 'IMDB_COOKIEUBIDMAIN' is required")
if isNilOrEmpty(c.IMDb.CookieUbidMain) {
return fmt.Errorf("field 'IMDB_COOKIEUBIDMAIN' is required")
}
case IMDbAuthMethodNone:
default:
return fmt.Errorf("config field 'IMDB_AUTH' must be one of: %s", strings.Join(validIMDbAuthMethods(), ", "))
return fmt.Errorf("field 'IMDB_AUTH' must be one of: %s", strings.Join(validIMDbAuthMethods(), ", "))
}
if c.Trakt.Email == nil {
return fmt.Errorf("config field 'TRAKT_EMAIL' is required")
if isNilOrEmpty(c.Trakt.Email) {
return fmt.Errorf("field 'TRAKT_EMAIL' is required")
}
if c.Trakt.Password == nil {
return fmt.Errorf("config field 'TRAKT_PASSWORD' is required")
if isNilOrEmpty(c.Trakt.Password) {
return fmt.Errorf("field 'TRAKT_PASSWORD' is required")
}
if c.Trakt.ClientID == nil {
return fmt.Errorf("config field 'TRAKT_CLIENTID' is required")
if isNilOrEmpty(c.Trakt.ClientID) {
return fmt.Errorf("field 'TRAKT_CLIENTID' is required")
}
if c.Trakt.ClientSecret == nil {
return fmt.Errorf("config field 'TRAKT_CLIENTSECRET' is required")
if isNilOrEmpty(c.Trakt.ClientSecret) {
return fmt.Errorf("field 'TRAKT_CLIENTSECRET' is required")
}
if c.Sync.Mode == nil {
return fmt.Errorf("config field 'SYNC_MODE' is required")
if isNilOrEmpty(c.Sync.Mode) {
return fmt.Errorf("field 'SYNC_MODE' is required")
}
if !slices.Contains(validSyncModes(), *c.Sync.Mode) {
return fmt.Errorf("config field 'SYNC_MODE' must be one of: %s", strings.Join(validSyncModes(), ", "))
return fmt.Errorf("field 'SYNC_MODE' must be one of: %s", strings.Join(validSyncModes(), ", "))
}
return c.checkDummies()
}
Expand All @@ -157,15 +158,15 @@ func (c *Config) checkDummies() error {
for k, v := range c.koanf.All() {
if value, ok := v.(string); ok {
if match := slices.Contains(dummyValues(), value); match {
return fmt.Errorf("config field '%s' contains dummy value '%s'", k, value)
return fmt.Errorf("field '%s' contains dummy value '%s'", k, value)
}
continue
}
if value, ok := v.([]interface{}); ok {
for _, sliceElement := range value {
if str, isStr := sliceElement.(string); isStr {
if match := slices.Contains(dummyValues(), str); match {
return fmt.Errorf("config field '%s' contains dummy value '%s'", k, str)
return fmt.Errorf("field '%s' contains dummy value '%s'", k, str)
}
}
}
Expand All @@ -175,9 +176,6 @@ func (c *Config) checkDummies() error {
}

func (c *Config) applyDefaults() {
if c.IMDb.Auth == nil {
c.IMDb.Auth = pointer(IMDbAuthMethodCredentials)
}
if c.IMDb.Lists == nil {
c.IMDb.Lists = pointer(make([]string, 0))
}
Expand All @@ -187,9 +185,6 @@ func (c *Config) applyDefaults() {
if c.IMDb.Headless == nil {
c.IMDb.Headless = pointer(true)
}
if c.Sync.Mode == nil {
c.Sync.Mode = pointer(SyncModeDryRun)
}
if c.Sync.History == nil {
c.Sync.History = pointer(false)
}
Expand Down Expand Up @@ -240,14 +235,14 @@ func dummyValues() []string {
func environmentVariableModifier(key string, value string) (string, any) {
key = strings.TrimPrefix(key, prefix)
if value == "" {
switch key {
case "IMDB_LISTS":
return key, make([]string, 0)
}
return key, nil
}
if strings.Contains(value, ",") {
return key, strings.Split(value, ",")
}
return key, value
}

func isNilOrEmpty(value *string) bool {
return value == nil || *value == ""
}
85 changes: 44 additions & 41 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ SYNC:
}

func TestConfig_Validate(t *testing.T) {
var (
email = "email"
password = "password"
clientID = "clientID"
clientSecret = "clientSecret"
cookieAtMain = "cookieAtMain"
)

type fields struct {
IMDb IMDb
Trakt Trakt
Expand All @@ -138,18 +146,17 @@ func TestConfig_Validate(t *testing.T) {
fields: fields{
IMDb: IMDb{
Auth: pointer(IMDbAuthMethodCredentials),
Email: new(string),
Password: new(string),
Email: &email,
Password: &password,
},
Trakt: Trakt{
Email: new(string),
Password: new(string),
ClientID: new(string),
ClientSecret: new(string),
Email: &email,
Password: &password,
ClientID: &clientID,
ClientSecret: &clientSecret,
},
Sync: Sync{
Mode: pointer(SyncModeFull),
History: new(bool),
Mode: pointer(SyncModeFull),
},
},
assertions: func(assertions *assert.Assertions, err error) {
Expand All @@ -174,7 +181,7 @@ func TestConfig_Validate(t *testing.T) {
fields: fields{
IMDb: IMDb{
Auth: pointer(IMDbAuthMethodCredentials),
Email: new(string),
Email: &email,
Password: nil,
},
},
Expand All @@ -201,7 +208,7 @@ func TestConfig_Validate(t *testing.T) {
fields: fields{
IMDb: IMDb{
Auth: pointer(IMDbAuthMethodCookies),
CookieAtMain: new(string),
CookieAtMain: &cookieAtMain,
CookieUbidMain: nil,
},
},
Expand All @@ -227,8 +234,8 @@ func TestConfig_Validate(t *testing.T) {
fields: fields{
IMDb: IMDb{
Auth: pointer(IMDbAuthMethodCredentials),
Email: new(string),
Password: new(string),
Email: &email,
Password: &password,
},
Trakt: Trakt{
Email: nil,
Expand All @@ -244,11 +251,11 @@ func TestConfig_Validate(t *testing.T) {
fields: fields{
IMDb: IMDb{
Auth: pointer(IMDbAuthMethodCredentials),
Email: new(string),
Password: new(string),
Email: &email,
Password: &password,
},
Trakt: Trakt{
Email: new(string),
Email: &email,
Password: nil,
},
},
Expand All @@ -262,12 +269,12 @@ func TestConfig_Validate(t *testing.T) {
fields: fields{
IMDb: IMDb{
Auth: pointer(IMDbAuthMethodCredentials),
Email: new(string),
Password: new(string),
Email: &email,
Password: &password,
},
Trakt: Trakt{
Email: new(string),
Password: new(string),
Email: &email,
Password: &password,
ClientID: nil,
},
},
Expand All @@ -281,13 +288,13 @@ func TestConfig_Validate(t *testing.T) {
fields: fields{
IMDb: IMDb{
Auth: pointer(IMDbAuthMethodCredentials),
Email: new(string),
Password: new(string),
Email: &email,
Password: &password,
},
Trakt: Trakt{
Email: new(string),
Password: new(string),
ClientID: new(string),
Email: &email,
Password: &password,
ClientID: &clientID,
ClientSecret: nil,
},
},
Expand All @@ -301,14 +308,14 @@ func TestConfig_Validate(t *testing.T) {
fields: fields{
IMDb: IMDb{
Auth: pointer(IMDbAuthMethodCredentials),
Email: new(string),
Password: new(string),
Email: &email,
Password: &password,
},
Trakt: Trakt{
Email: new(string),
Password: new(string),
ClientID: new(string),
ClientSecret: new(string),
Email: &email,
Password: &password,
ClientID: &clientID,
ClientSecret: &clientSecret,
},
Sync: Sync{
Mode: nil,
Expand All @@ -324,21 +331,17 @@ func TestConfig_Validate(t *testing.T) {
fields: fields{
IMDb: IMDb{
Auth: pointer(IMDbAuthMethodCredentials),
Email: new(string),
Password: new(string),
Email: &email,
Password: &password,
},
Trakt: Trakt{
Email: new(string),
Password: new(string),
ClientID: new(string),
ClientSecret: new(string),
Email: &email,
Password: &password,
ClientID: &clientID,
ClientSecret: &clientSecret,
},
Sync: Sync{
Mode: func() *string {
s := "invalid"
return &s
}(),
History: new(bool),
Mode: pointer("invalid"),
},
},
assertions: func(assertions *assert.Assertions, err error) {
Expand Down
Loading

0 comments on commit 176201e

Please sign in to comment.