commit e80b71e1c96504b4ec04200547b035d6a838834e
parent 468fd7380db2f83537bd4adea8be2b161ca5ee11
Author: Sean Enck <sean@ttypty.com>
Date: Mon, 2 Jun 2025 21:54:28 -0400
parsing the time window and time window are really config and totp components
Diffstat:
6 files changed, 79 insertions(+), 99 deletions(-)
diff --git a/internal/app/totp.go b/internal/app/totp.go
@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"slices"
+ "strconv"
"strings"
"time"
@@ -15,7 +16,6 @@ import (
"git.sr.ht/~enckse/lockbox/internal/backend"
"git.sr.ht/~enckse/lockbox/internal/config"
"git.sr.ht/~enckse/lockbox/internal/platform/clip"
- "git.sr.ht/~enckse/lockbox/internal/util"
)
var (
@@ -78,12 +78,12 @@ func clearFunc() {
fmt.Print("\033[H\033[2J")
}
-func colorWhenRules() ([]util.TimeWindow, error) {
+func colorWhenRules() ([]config.TimeWindow, error) {
envTime := config.EnvTOTPColorBetween.Get()
if slices.Compare(envTime, config.TOTPDefaultBetween) == 0 {
return config.TOTPDefaultColorWindow, nil
}
- return util.ParseTimeWindow(envTime...)
+ return ParseTimeWindow(envTime...)
}
func (w totpWrapper) generateCode() (string, error) {
@@ -284,3 +284,34 @@ func NewTOTPArguments(args []string, tokenType string) (*TOTPArguments, error) {
}
return opts, nil
}
+
+// ParseTimeWindow will handle parsing a window of colors for TOTP operations
+func ParseTimeWindow(windows ...string) ([]config.TimeWindow, error) {
+ var rules []config.TimeWindow
+ for _, item := range windows {
+ line := strings.TrimSpace(item)
+ if line == "" {
+ continue
+ }
+ parts := strings.Split(line, config.TimeWindowSpan)
+ if len(parts) != 2 {
+ return nil, fmt.Errorf("invalid colorization rule found: %s", line)
+ }
+ s, err := strconv.Atoi(parts[0])
+ if err != nil {
+ return nil, err
+ }
+ e, err := strconv.Atoi(parts[1])
+ if err != nil {
+ return nil, err
+ }
+ if s < 0 || e < 0 || e < s || s > 59 || e > 59 {
+ return nil, fmt.Errorf("invalid time found for colorization rule: %s", line)
+ }
+ rules = append(rules, config.TimeWindow{Start: s, End: e})
+ }
+ if len(rules) == 0 {
+ return nil, errors.New("invalid colorization rules for totp, none found")
+ }
+ return rules, nil
+}
diff --git a/internal/app/totp_test.go b/internal/app/totp_test.go
@@ -235,3 +235,36 @@ func TestShow(t *testing.T) {
t.Errorf("invalid short: %s", m.buf.String())
}
}
+
+func TestParseWindows(t *testing.T) {
+ if _, err := app.ParseTimeWindow(); err.Error() != "invalid colorization rules for totp, none found" {
+ t.Errorf("invalid error: %v", err)
+ }
+ if _, err := app.ParseTimeWindow(" ", "2"); err.Error() != "invalid colorization rule found: 2" {
+ t.Errorf("invalid error: %v", err)
+ }
+ if _, err := app.ParseTimeWindow(" 1:200"); err.Error() != "invalid time found for colorization rule: 1:200" {
+ t.Errorf("invalid error: %v", err)
+ }
+ if _, err := app.ParseTimeWindow(" 1:-1"); err.Error() != "invalid time found for colorization rule: 1:-1" {
+ t.Errorf("invalid error: %v", err)
+ }
+ if _, err := app.ParseTimeWindow(" 200:1"); err.Error() != "invalid time found for colorization rule: 200:1" {
+ t.Errorf("invalid error: %v", err)
+ }
+ if _, err := app.ParseTimeWindow(" -1:1"); err.Error() != "invalid time found for colorization rule: -1:1" {
+ t.Errorf("invalid error: %v", err)
+ }
+ if _, err := app.ParseTimeWindow(" 2:1"); err.Error() != "invalid time found for colorization rule: 2:1" {
+ t.Errorf("invalid error: %v", err)
+ }
+ if _, err := app.ParseTimeWindow("xxx:1"); err.Error() != "strconv.Atoi: parsing \"xxx\": invalid syntax" {
+ t.Errorf("invalid error: %v", err)
+ }
+ if _, err := app.ParseTimeWindow(" 1:xxx"); err.Error() != "strconv.Atoi: parsing \"xxx\": invalid syntax" {
+ t.Errorf("invalid error: %v", err)
+ }
+ if _, err := app.ParseTimeWindow("1:2", " 11:22"); err != nil {
+ t.Errorf("invalid error: %v", err)
+ }
+}
diff --git a/internal/config/core.go b/internal/config/core.go
@@ -11,7 +11,6 @@ import (
"time"
"git.sr.ht/~enckse/lockbox/internal/config/store"
- "git.sr.ht/~enckse/lockbox/internal/util"
)
const (
@@ -29,10 +28,12 @@ const (
requiredKeyOrKeyFile = "a key, a key file, or both must be set"
// ModTimeFormat is the expected modtime format
ModTimeFormat = time.RFC3339
- exampleColorWindow = "start" + util.TimeWindowSpan + "end"
+ exampleColorWindow = "start" + TimeWindowSpan + "end"
detectedValue = "(detected)"
unset = "(unset)"
arrayDelimiter = " "
+ // TimeWindowSpan indicates the delineation between start -> end (start:end)
+ TimeWindowSpan = ":"
)
const (
@@ -56,18 +57,24 @@ var (
// NoValue is the string variant of 'No' (or false) items
NoValue = strconv.FormatBool(false)
// TOTPDefaultColorWindow is the default coloring rules for totp
- TOTPDefaultColorWindow = []util.TimeWindow{{Start: 0, End: 5}, {Start: 30, End: 35}}
+ TOTPDefaultColorWindow = []TimeWindow{{Start: 0, End: 5}, {Start: 30, End: 35}}
// TOTPDefaultBetween is the default color window as a 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))
+ results = append(results, fmt.Sprintf("%d%s%d", w.Start, TimeWindowSpan, w.End))
}
return results
}()
)
type (
+ // TimeWindow for handling terminal colors based on timing
+ TimeWindow struct {
+ Start int
+ End int
+ }
+
stringsFlags int
printer interface {
display() metaData
diff --git a/internal/config/vars.go b/internal/config/vars.go
@@ -172,7 +172,7 @@ var (
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).`, util.TimeWindowSpan),
+must be a list of one (or more) rules where a '%s' delimits the start and end second (0-60 for each).`, TimeWindowSpan),
}),
flags: []stringsFlags{canDefaultFlag},
allowed: exampleColorWindows,
diff --git a/internal/util/time.go b/internal/util/time.go
@@ -1,51 +0,0 @@
-// Package util has to assist with some time windowing
-package util
-
-import (
- "errors"
- "fmt"
- "strconv"
- "strings"
-)
-
-const (
- // TimeWindowSpan indicates the delineation between start -> end (start:end)
- TimeWindowSpan = ":"
-)
-
-// TimeWindow for handling terminal colors based on timing
-type TimeWindow struct {
- Start int
- End int
-}
-
-// ParseTimeWindow will handle parsing a window of colors for TOTP operations
-func ParseTimeWindow(windows ...string) ([]TimeWindow, error) {
- var rules []TimeWindow
- for _, item := range windows {
- line := strings.TrimSpace(item)
- if line == "" {
- continue
- }
- parts := strings.Split(line, TimeWindowSpan)
- if len(parts) != 2 {
- return nil, fmt.Errorf("invalid colorization rule found: %s", line)
- }
- s, err := strconv.Atoi(parts[0])
- if err != nil {
- return nil, err
- }
- e, err := strconv.Atoi(parts[1])
- if err != nil {
- return nil, err
- }
- if s < 0 || e < 0 || e < s || s > 59 || e > 59 {
- return nil, fmt.Errorf("invalid time found for colorization rule: %s", line)
- }
- rules = append(rules, TimeWindow{Start: s, End: e})
- }
- if len(rules) == 0 {
- return nil, errors.New("invalid colorization rules for totp, none found")
- }
- return rules, nil
-}
diff --git a/internal/util/time_test.go b/internal/util/time_test.go
@@ -1,40 +0,0 @@
-package util_test
-
-import (
- "testing"
-
- "git.sr.ht/~enckse/lockbox/internal/util"
-)
-
-func TestParseWindows(t *testing.T) {
- 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" {
- t.Errorf("invalid error: %v", err)
- }
- if _, err := util.ParseTimeWindow(" 1:200"); err.Error() != "invalid time found for colorization rule: 1:200" {
- t.Errorf("invalid error: %v", err)
- }
- if _, err := util.ParseTimeWindow(" 1:-1"); err.Error() != "invalid time found for colorization rule: 1:-1" {
- t.Errorf("invalid error: %v", err)
- }
- if _, err := util.ParseTimeWindow(" 200:1"); err.Error() != "invalid time found for colorization rule: 200:1" {
- t.Errorf("invalid error: %v", err)
- }
- if _, err := util.ParseTimeWindow(" -1:1"); err.Error() != "invalid time found for colorization rule: -1:1" {
- t.Errorf("invalid error: %v", err)
- }
- if _, err := util.ParseTimeWindow(" 2:1"); err.Error() != "invalid time found for colorization rule: 2:1" {
- t.Errorf("invalid error: %v", err)
- }
- if _, err := util.ParseTimeWindow("xxx:1"); err.Error() != "strconv.Atoi: parsing \"xxx\": invalid syntax" {
- t.Errorf("invalid error: %v", err)
- }
- 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 {
- t.Errorf("invalid error: %v", err)
- }
-}