lockbox

password manager
Log | Files | Refs | README | LICENSE

commit 1c36decc72a49eab7de29f9787d0b043110bded9
parent 95b7766aad5a7c8e28e33d8facef1192b2d33aea
Author: Sean Enck <sean@ttypty.com>
Date:   Sun,  8 Dec 2024 18:50:37 -0500

fix time windows

Diffstat:
Minternal/app/totp.go | 7++++---
Minternal/config/core.go | 7++++---
Minternal/config/env.go | 21+++++++++++----------
Minternal/config/vars.go | 6+++---
Minternal/config/vars_test.go | 45+++++++++++++++++++++++++++++++++++++++++++++
Minternal/util/time.go | 6++----
Minternal/util/time_test.go | 6+++---
7 files changed, 72 insertions(+), 26 deletions(-)

diff --git a/internal/app/totp.go b/internal/app/totp.go @@ -4,6 +4,7 @@ package app import ( "errors" "fmt" + "slices" "strings" "time" @@ -78,11 +79,11 @@ func clearFunc() { } func colorWhenRules() ([]util.TimeWindow, error) { - envTime := config.EnvTOTPColorBetween.Get() - if envTime == config.TOTPDefaultBetween { + envTime := config.EnvTOTPColorBetween.AsArray() + if slices.Compare(envTime, config.TOTPDefaultBetween) == 0 { return config.TOTPDefaultColorWindow, nil } - return util.ParseTimeWindow(envTime) + return util.ParseTimeWindow(envTime...) } func (w totpWrapper) generateCode() (string, error) { diff --git a/internal/config/core.go b/internal/config/core.go @@ -32,6 +32,7 @@ const ( exampleColorWindow = "start" + util.TimeWindowSpan + "end" detectedValue = "(detected)" unset = "(unset)" + arrayDelimiter = " " ) const ( @@ -42,7 +43,7 @@ const ( ) var ( - exampleColorWindows = []string{fmt.Sprintf("[%s]", strings.Join([]string{exampleColorWindow, exampleColorWindow, exampleColorWindow + "..."}, util.TimeWindowDelimiter))} + exampleColorWindows = []string{fmt.Sprintf("[%s]", strings.Join([]string{exampleColorWindow, exampleColorWindow, exampleColorWindow + "..."}, arrayDelimiter))} configDirFile = filepath.Join("lockbox", "config.toml") registry = map[string]printer{} // ConfigXDG is the offset to the config for XDG @@ -58,12 +59,12 @@ var ( // TOTPDefaultColorWindow is the default coloring rules for totp TOTPDefaultColorWindow = []util.TimeWindow{{Start: 0, End: 5}, {Start: 30, End: 35}} // TOTPDefaultBetween is the default color window as a string - TOTPDefaultBetween = func() string { + TOTPDefaultBetween = func() []string { var results []string for _, w := range TOTPDefaultColorWindow { results = append(results, fmt.Sprintf("%d%s%d", w.Start, util.TimeWindowSpan, w.End)) } - return strings.Join(results, util.TimeWindowDelimiter) + return results }() ) diff --git a/internal/config/env.go b/internal/config/env.go @@ -88,23 +88,24 @@ func (e EnvironmentInt) Get() (int64, error) { // Get will read the string from the environment func (e EnvironmentStrings) Get() string { - val, ok := store.GetString(e.Key()) - if !ok { - flags := e.flattenFlags() - if slices.Contains(flags, canDefaultFlag) { - val = e.value - } - } - return val + return stringsGet(e, store.GetString, func(val string) string { + return val + }) } // AsArray indicates the item should be queried as an array func (e EnvironmentStrings) AsArray() []string { - val, ok := store.GetArray(e.Key()) + return stringsGet(e, store.GetArray, func(val string) []string { + return strings.Split(val, arrayDelimiter) + }) +} + +func stringsGet[T string | []string](e EnvironmentStrings, getter func(string) (T, bool), conv func(string) T) T { + val, ok := getter(e.Key()) if !ok { flags := e.flattenFlags() if slices.Contains(flags, canDefaultFlag) { - val = []string{e.value} + val = conv(e.value) } } return val diff --git a/internal/config/vars.go b/internal/config/vars.go @@ -3,6 +3,7 @@ package config import ( "fmt" + "strings" "github.com/seanenck/lockbox/internal/output" "github.com/seanenck/lockbox/internal/platform" @@ -170,12 +171,11 @@ var ( // EnvTOTPColorBetween handles terminal coloring for TOTP windows (seconds) EnvTOTPColorBetween = environmentRegister( EnvironmentStrings{ - environmentDefault: newDefaultedEnvironment(TOTPDefaultBetween, + environmentDefault: newDefaultedEnvironment(strings.Join(TOTPDefaultBetween, arrayDelimiter), environmentBase{ key: totpCategory + "COLOR_WINDOWS", description: fmt.Sprintf(`Override when to set totp generated outputs to different colors, -must be a list of one (or more) rules where a '%s' delimits the start and end second (0-60 for each), -and '%s' allows for multiple windows.`, util.TimeWindowSpan, util.TimeWindowDelimiter), +must be a list of one (or more) rules where a '%s' delimits the start and end second (0-60 for each).`, util.TimeWindowSpan), }), flags: []stringsFlags{isArrayFlag, canDefaultFlag}, allowed: exampleColorWindows, diff --git a/internal/config/vars_test.go b/internal/config/vars_test.go @@ -2,6 +2,7 @@ package config_test import ( "fmt" + "slices" "testing" "github.com/seanenck/lockbox/internal/config" @@ -138,3 +139,47 @@ func checkInt(e config.EnvironmentInt, key, text string, def int64, allowZero bo } } } + +func TestStringsGetDefault(t *testing.T) { + store.Clear() + val := config.EnvPlatform.Get() + if val != "" { + t.Errorf("invalid read: %v", val) + } + val = config.EnvJSONMode.Get() + if val != "hash" { + t.Errorf("invalid read: %v", val) + } + store.SetString("LOCKBOX_PLATFORM", "1") + store.SetString("LOCKBOX_JSON_MODE", "a") + val = config.EnvPlatform.Get() + if val != "1" { + t.Errorf("invalid read: %v", val) + } + val = config.EnvJSONMode.Get() + if val != "a" { + t.Errorf("invalid read: %v", val) + } +} + +func TestStringsArray(t *testing.T) { + store.Clear() + val := config.EnvTOTPColorBetween.AsArray() + if slices.Compare(val, config.TOTPDefaultBetween) != 0 { + t.Errorf("invalid read: %v", val) + } + val = config.EnvClipCopy.AsArray() + if len(val) != 0 { + t.Errorf("invalid read: %v", val) + } + store.SetArray("LOCKBOX_CLIP_COPY_COMMAND", []string{"1"}) + store.SetArray("LOCKBOX_TOTP_COLOR_WINDOWS", []string{"1", "2", "3"}) + val = config.EnvTOTPColorBetween.AsArray() + if len(val) != 3 { + t.Errorf("invalid read: %v", val) + } + val = config.EnvClipCopy.AsArray() + if len(val) != 1 { + t.Errorf("invalid read: %v", val) + } +} diff --git a/internal/util/time.go b/internal/util/time.go @@ -9,8 +9,6 @@ import ( ) const ( - // TimeWindowDelimiter indicates how windows are split in env/config keys - TimeWindowDelimiter = " " // TimeWindowSpan indicates the delineation between start -> end (start:end) TimeWindowSpan = ":" ) @@ -22,9 +20,9 @@ type TimeWindow struct { } // ParseTimeWindow will handle parsing a window of colors for TOTP operations -func ParseTimeWindow(windowString string) ([]TimeWindow, error) { +func ParseTimeWindow(windows ...string) ([]TimeWindow, error) { var rules []TimeWindow - for _, item := range strings.Split(windowString, TimeWindowDelimiter) { + for _, item := range windows { line := strings.TrimSpace(item) if line == "" { continue diff --git a/internal/util/time_test.go b/internal/util/time_test.go @@ -7,10 +7,10 @@ import ( ) func TestParseWindows(t *testing.T) { - if _, err := util.ParseTimeWindow(""); err.Error() != "invalid colorization rules for totp, none found" { + if _, err := util.ParseTimeWindow(); err.Error() != "invalid colorization rules for totp, none found" { t.Errorf("invalid error: %v", err) } - if _, err := util.ParseTimeWindow(" 2"); err.Error() != "invalid colorization rule found: 2" { + if _, err := util.ParseTimeWindow(" ", "2"); err.Error() != "invalid colorization rule found: 2" { t.Errorf("invalid error: %v", err) } if _, err := util.ParseTimeWindow(" 1:200"); err.Error() != "invalid time found for colorization rule: 1:200" { @@ -34,7 +34,7 @@ func TestParseWindows(t *testing.T) { if _, err := util.ParseTimeWindow(" 1:xxx"); err.Error() != "strconv.Atoi: parsing \"xxx\": invalid syntax" { t.Errorf("invalid error: %v", err) } - if _, err := util.ParseTimeWindow("1:2 11:22"); err != nil { + if _, err := util.ParseTimeWindow("1:2", " 11:22"); err != nil { t.Errorf("invalid error: %v", err) } }