lockbox

password manager
Log | Files | Refs | README | LICENSE

commit ef72b2499c9a1fefdf3b8813eedd8bac6608173b
parent 404b9c15998d0872510ffbdaed81d2466a8c0cd6
Author: Sean Enck <sean@ttypty.com>
Date:   Mon,  9 Jun 2025 15:30:08 -0400

interactive control really wasn't needed

Diffstat:
Mcmd/lb/main_test.go | 10+++++-----
Mcmd/lb/tests/expected.log | 2+-
Minternal/app/totp.go | 14++++++--------
Minternal/app/totp_test.go | 39---------------------------------------
Minternal/config/core.go | 2+-
Minternal/config/core_test.go | 16----------------
Minternal/config/toml_test.go | 2+-
Minternal/config/vars.go | 8--------
Minternal/config/vars_test.go | 4----
9 files changed, 14 insertions(+), 83 deletions(-)

diff --git a/cmd/lb/main_test.go b/cmd/lb/main_test.go @@ -162,7 +162,6 @@ func test(profile string) error { } setConfig(r.config) c := r.newConf() - c["interactive"] = "false" keyFile := filepath.Join(r.testDir, "key.file") hasPass := profile == passProfile || profile == bothProfile hasFile := profile == keyFileProfile || profile == bothProfile @@ -180,7 +179,6 @@ func test(profile string) error { r.writeConfig(c) r.run("echo testing |", "insert test1/key1/password") c = r.newConf() - c["interactive"] = "false" if hasPass { c["credentials.password_mode"] = c.quoteString("plaintext") c["credentials.password"] = c.makePass(testPass) @@ -191,6 +189,7 @@ func test(profile string) error { c["credentials.password_mode"] = c.quoteString("none") } } + c["totp.timeout"] = "1" r.writeConfig(c) for _, k := range []string{"test2/key1/password", "test2/key1/notes", "test3", "test3/invalid/", "test3/invalid/still"} { r.run("echo testing2 |", fmt.Sprintf("insert %s", k)) @@ -216,9 +215,10 @@ func test(profile string) error { r.run(`printf "otpauth://totp/lbissuer:lbaccount?algorithm=SHA1&digits=6&issuer=lbissuer&period=30&secret=5ae472abqdekjqykoyxk7hvc2leklq5n" |`, "insert test10/key1/otp") r.run("", "totp ls") r.run("", "totp ls rooted") - r.run("", "totp show test6/multiline/otp") - r.run("", "totp show test10/key1/otp") - r.run("", "totp once test6/multiline/otp") + const grepTOTP = "| sed 's/^[[:space:]]*//g' | grep '^[0-9][0-9][0-9][0-9][0-9][0-9]$'" + r.run("", fmt.Sprintf("totp show test6/multiline/otp %s", grepTOTP)) + r.run("", fmt.Sprintf("totp show test10/key1/otp %s", grepTOTP)) + r.run("", fmt.Sprintf("totp once test6/multiline/otp %s", grepTOTP)) r.run("", "totp minimal test6/multiline/otp") r.run("", "totp url test6/multiline/otp") r.run("", "totp seed test6/multiline/otp") diff --git a/cmd/lb/tests/expected.log b/cmd/lb/tests/expected.log @@ -313,7 +313,7 @@ test6/multiline/password LOCKBOX_CLIP_COPY_COMMAND=[touch testdata/datadir/clip.copy] LOCKBOX_CLIP_PASTE_COMMAND=[touch testdata/datadir/clip.paste] LOCKBOX_CLIP_TIMEOUT=3 -LOCKBOX_INTERACTIVE=false LOCKBOX_JSON_HASH_LENGTH=3 LOCKBOX_JSON_MODE=hash LOCKBOX_STORE=testdata/datadir/pass.kdbx +LOCKBOX_TOTP_TIMEOUT=1 diff --git a/internal/app/totp.go b/internal/app/totp.go @@ -37,18 +37,16 @@ type ( } // TOTPOptions are TOTP call options TOTPOptions struct { - app CommandOptions - Clear func() - IsInteractive func() bool + app CommandOptions + Clear func() } ) // NewDefaultTOTPOptions gets the default option set func NewDefaultTOTPOptions(app CommandOptions) TOTPOptions { return TOTPOptions{ - app: app, - Clear: clearFunc, - IsInteractive: config.EnvInteractive.Get, + app: app, + Clear: clearFunc, } } @@ -69,7 +67,7 @@ func (w totpWrapper) generateCode() (string, error) { } func (args *TOTPArguments) display(opts TOTPOptions) error { - interactive := opts.IsInteractive() + interactive := true if args.Mode == commands.TOTPMinimal || args.Mode == commands.TOTPSeed || args.Mode == commands.TOTPURL { interactive = false } @@ -202,7 +200,7 @@ func (args *TOTPArguments) Do(opts TOTPOptions) error { if args.Mode == "" { return ErrUnknownTOTPMode } - if opts.Clear == nil || opts.IsInteractive == nil { + if opts.Clear == nil { return errors.New("invalid option functions") } if args.Mode == commands.TOTPList { diff --git a/internal/app/totp_test.go b/internal/app/totp_test.go @@ -29,9 +29,6 @@ func newMock(t *testing.T) (*mockOptions, app.TOTPOptions) { opts := app.NewDefaultTOTPOptions(m) opts.Clear = func() { } - opts.IsInteractive = func() bool { - return true - } return m, opts } @@ -134,15 +131,6 @@ func TestDoErrors(t *testing.T) { opts := app.TOTPOptions{} opts.Clear = func() { } - if err := args.Do(opts); err == nil || err.Error() != "invalid option functions" { - t.Errorf("invalid error: %v", err) - } - if err := args.Do(opts); err == nil || err.Error() != "invalid option functions" { - t.Errorf("invalid error: %v", err) - } - opts.IsInteractive = func() bool { - return false - } if err := args.Do(opts); err == nil || err.Error() != "'' is not a TOTP entry" { t.Errorf("invalid error: %v", err) } @@ -164,23 +152,11 @@ func TestNonListError(t *testing.T) { setupTOTP(t) args, _ := app.NewTOTPArguments([]string{"show", "test/test3"}) _, opts := newMock(t) - opts.IsInteractive = func() bool { - return false - } if err := args.Do(opts); err == nil || err.Error() != "'test/test3' is not a TOTP entry" { t.Errorf("invalid error: %v", err) } args, _ = app.NewTOTPArguments([]string{"clip", "test/test3/otp"}) _, opts = newMock(t) - opts.IsInteractive = func() bool { - return false - } - if err := args.Do(opts); err == nil || err.Error() != "clipboard not available in non-interactive mode" { - t.Errorf("invalid error: %v", err) - } - opts.IsInteractive = func() bool { - return true - } if err := args.Do(opts); err == nil || err.Error() != "entry does not exist" { t.Errorf("invalid error: %v", err) } @@ -222,21 +198,6 @@ func TestMinimal(t *testing.T) { } } -func TestNonInteractive(t *testing.T) { - setupTOTP(t) - args, _ := app.NewTOTPArguments([]string{"show", "test/test3/totp/otp"}) - m, opts := newMock(t) - opts.IsInteractive = func() bool { - return false - } - if err := args.Do(opts); err != nil { - t.Errorf("invalid error: %v", err) - } - if len(m.buf.String()) != 7 { - t.Errorf("invalid short: %s", m.buf.String()) - } -} - func TestOnce(t *testing.T) { setupTOTP(t) args, _ := app.NewTOTPArguments([]string{"once", "test/test3/totp/otp"}) diff --git a/internal/config/core.go b/internal/config/core.go @@ -153,7 +153,7 @@ func CanColor() bool { if _, noColor := os.LookupEnv("NO_COLOR"); noColor { return false } - return EnvInteractive.Get() + return true } func readNested(v reflect.Type, root string) []string { diff --git a/internal/config/core_test.go b/internal/config/core_test.go @@ -1,7 +1,6 @@ package config_test import ( - "fmt" "os" "testing" @@ -41,21 +40,6 @@ func TestCanColor(t *testing.T) { if can := config.CanColor(); !can { t.Error("should be able to color") } - for raw, expect := range map[string]bool{ - "INTERACTIVE": true, - } { - store.Clear() - key := fmt.Sprintf("LOCKBOX_%s", raw) - store.SetBool(key, true) - if can := config.CanColor(); can != expect { - t.Errorf("expect != actual: %s", key) - } - store.SetBool(key, false) - if can := config.CanColor(); can == expect { - t.Errorf("expect == actual: %s", key) - } - } - store.Clear() t.Setenv("NO_COLOR", "1") if can := config.CanColor(); can { t.Error("should NOT be able to color") diff --git a/internal/config/toml_test.go b/internal/config/toml_test.go @@ -251,7 +251,7 @@ func TestDefaultTOMLToLoadFile(t *testing.T) { if err := config.LoadConfigFile(file); err != nil { t.Errorf("invalid error: %v", err) } - if len(store.List()) != 17 { + if len(store.List()) != 16 { t.Errorf("invalid environment after load: %d", len(store.List())) } } diff --git a/internal/config/vars.go b/internal/config/vars.go @@ -45,14 +45,6 @@ var ( description: "Operate in readonly mode.", }), }) - // EnvInteractive indicates if operating in interactive mode - EnvInteractive = environmentRegister(EnvironmentBool{ - environmentDefault: newDefaultedEnvironment(true, - environmentBase{ - key: "INTERACTIVE", - description: "Enable interactive mode.", - }), - }) // EnvTOTPTimeout indicates when TOTP display should timeout EnvTOTPTimeout = environmentRegister(EnvironmentInt{ environmentDefault: newDefaultedEnvironment(120, diff --git a/internal/config/vars_test.go b/internal/config/vars_test.go @@ -24,10 +24,6 @@ func checkYesNo(key string, t *testing.T, obj config.EnvironmentBool, onEmpty bo } } -func TestInteractiveSetting(t *testing.T) { - checkYesNo("LOCKBOX_INTERACTIVE", t, config.EnvInteractive, true) -} - func TestIsReadOnly(t *testing.T) { checkYesNo("LOCKBOX_READONLY", t, config.EnvReadOnly, false) }