lockbox

password manager
Log | Files | Refs | README | LICENSE

commit 5e05cd038d731f04462b3fd162c738f2dd1c73ea
parent d9575777b7e5a254df56c230921b074fcca760b9
Author: Sean Enck <sean@ttypty.com>
Date:   Fri,  6 Dec 2024 22:56:55 -0500

align env vars with toml expectations

Diffstat:
Mcmd/main.go | 2+-
Minternal/app/completions.go | 28++++++++++++++--------------
Minternal/app/list_test.go | 10+++++-----
Minternal/app/pwgen.go | 6+++---
Minternal/app/pwgen_test.go | 36++++++++++++++++++------------------
Minternal/app/shell/fish.sh | 4++--
Minternal/app/totp.go | 14+++++++-------
Minternal/app/totp_test.go | 22+++++++++++-----------
Minternal/backend/actions.go | 4++--
Minternal/backend/actions_test.go | 44++++++++++++++++++++++----------------------
Minternal/backend/core.go | 2+-
Minternal/backend/hooks.go | 6+++---
Minternal/backend/hooks_test.go | 8++++----
Minternal/backend/query.go | 2+-
Minternal/backend/query_test.go | 12++++++------
Minternal/config/config.toml | 4++--
Minternal/config/core.go | 14++++++++++----
Minternal/config/core_test.go | 4++--
Minternal/config/key.go | 4++--
Minternal/config/key_test.go | 68++++++++++++++++++++++++++++++++++----------------------------------
Minternal/config/toml.go | 53++++++++++++-----------------------------------------
Minternal/config/toml_test.go | 43+++++++++++++------------------------------
Minternal/config/vars.go | 145+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Minternal/config/vars_test.go | 52++++++++++++++++++++++++++--------------------------
Minternal/platform/clipboard.go | 6+++---
Minternal/platform/clipboard_test.go | 26+++++++++++++-------------
Mtests/run.sh | 98++++++++++++++++++++++++++++++++++++++++----------------------------------------
27 files changed, 345 insertions(+), 372 deletions(-)

diff --git a/cmd/main.go b/cmd/main.go @@ -88,7 +88,7 @@ func run() error { case app.ConvCommand: return app.Conv(p) case app.TOTPCommand: - args, err := app.NewTOTPArguments(sub, config.EnvTOTPToken.Get()) + args, err := app.NewTOTPArguments(sub, config.EnvTOTPEntry.Get()) if err != nil { return err } diff --git a/internal/app/completions.go b/internal/app/completions.go @@ -37,12 +37,12 @@ type ( TOTPSubCommands []CompletionOption Conditionals struct { Not struct { - ReadOnly string - NoClip string - NoTOTP string - AskMode string - Ever string - NoPasswordGen string + ReadOnly string + CanClip string + CanTOTP string + AskMode string + Ever string + CanPasswordGen string } } } @@ -99,25 +99,25 @@ func GenerateCompletions(completionType, exe string) ([]string, error) { DoTOTPList: fmt.Sprintf("%s %s %s", exe, TOTPCommand, TOTPListCommand), } c.Conditionals.Not.ReadOnly = newShellIsNotEqualConditional(config.EnvReadOnly, config.YesValue) - c.Conditionals.Not.NoClip = newShellIsNotEqualConditional(config.EnvNoClip, config.YesValue) - c.Conditionals.Not.NoTOTP = newShellIsNotEqualConditional(config.EnvNoTOTP, config.YesValue) - c.Conditionals.Not.AskMode = newShellIsNotEqualConditional(config.EnvKeyMode, string(config.AskKeyMode)) - c.Conditionals.Not.NoPasswordGen = newShellIsNotEqualConditional(config.EnvNoPasswordGen, config.YesValue) + c.Conditionals.Not.CanClip = newShellIsNotEqualConditional(config.EnvClipEnabled, config.NoValue) + c.Conditionals.Not.CanTOTP = newShellIsNotEqualConditional(config.EnvTOTPEnabled, config.NoValue) + c.Conditionals.Not.AskMode = newShellIsNotEqualConditional(config.EnvPasswordMode, string(config.AskKeyMode)) + c.Conditionals.Not.CanPasswordGen = newShellIsNotEqualConditional(config.EnvPasswordGenEnabled, config.NoValue) c.Conditionals.Not.Ever = fmt.Sprintf(shellIsNotText, "1", "0") c.Options = c.newGenOptions([]string{EnvCommand, HelpCommand, ListCommand, ShowCommand, VersionCommand, JSONCommand}, map[string]string{ - ClipCommand: c.Conditionals.Not.NoClip, - TOTPCommand: c.Conditionals.Not.NoTOTP, + ClipCommand: c.Conditionals.Not.CanClip, + TOTPCommand: c.Conditionals.Not.CanTOTP, MoveCommand: c.Conditionals.Not.ReadOnly, RemoveCommand: c.Conditionals.Not.ReadOnly, InsertCommand: c.Conditionals.Not.ReadOnly, MultiLineCommand: c.Conditionals.Not.ReadOnly, - PasswordGenerateCommand: c.Conditionals.Not.NoPasswordGen, + PasswordGenerateCommand: c.Conditionals.Not.CanPasswordGen, }) c.TOTPSubCommands = c.newGenOptions([]string{TOTPMinimalCommand, TOTPOnceCommand, TOTPShowCommand}, map[string]string{ - TOTPClipCommand: c.Conditionals.Not.NoClip, + TOTPClipCommand: c.Conditionals.Not.CanClip, TOTPInsertCommand: c.Conditionals.Not.ReadOnly, }) using, err := readShell(completionType) diff --git a/internal/app/list_test.go b/internal/app/list_test.go @@ -26,11 +26,11 @@ func fullSetup(t *testing.T, keep bool) *backend.Transaction { } t.Setenv("LOCKBOX_READONLY", "no") t.Setenv("LOCKBOX_STORE", file) - t.Setenv("LOCKBOX_KEY", "test") - t.Setenv("LOCKBOX_KEYFILE", "") - t.Setenv("LOCKBOX_KEYMODE", "plaintext") - t.Setenv("LOCKBOX_TOTP", "totp") - t.Setenv("LOCKBOX_HOOKDIR", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "test") + t.Setenv("LOCKBOX_CREDENTIALS_KEY_FILE", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "plaintext") + t.Setenv("LOCKBOX_TOTP_ENTRY", "totp") + t.Setenv("LOCKBOX_HOOKS_DIRECTORY", "") t.Setenv("LOCKBOX_SET_MODTIME", "") tr, err := backend.NewTransaction() if err != nil { diff --git a/internal/app/pwgen.go b/internal/app/pwgen.go @@ -18,14 +18,14 @@ import ( // GeneratePassword generates a password func GeneratePassword(cmd CommandOptions) error { - ok, err := config.EnvNoPasswordGen.Get() + enabled, err := config.EnvPasswordGenEnabled.Get() if err != nil { return err } - if ok { + if !enabled { return errors.New("password generation is disabled") } - length, err := config.EnvPasswordGenCount.Get() + length, err := config.EnvPasswordGenWordCount.Get() if err != nil { return err } diff --git a/internal/app/pwgen_test.go b/internal/app/pwgen_test.go @@ -25,31 +25,31 @@ done func TestGenerateError(t *testing.T) { m := newMockCommand(t) pwgenPath := setupGenScript() - t.Setenv("LOCKBOX_PWGEN_COUNT", "0") + t.Setenv("LOCKBOX_PWGEN_WORD_COUNT", "0") if err := app.GeneratePassword(m); err == nil || err.Error() != "word count must be > 0" { t.Errorf("invalid error: %v", err) } - t.Setenv("LOCKBOX_PWGEN_COUNT", "1") + t.Setenv("LOCKBOX_PWGEN_WORD_COUNT", "1") if err := app.GeneratePassword(m); err == nil || err.Error() != "word list command must set" { t.Errorf("invalid error: %v", err) } - t.Setenv("LOCKBOX_PWGEN_WORDLIST", "1 x") + t.Setenv("LOCKBOX_PWGEN_WORDS_COMMAND", "1 x") if err := app.GeneratePassword(m); err == nil || !strings.Contains(err.Error(), "exec: \"1\":") { t.Errorf("invalid error: %v", err) } - t.Setenv("LOCKBOX_PWGEN_WORDLIST", pwgenPath) + t.Setenv("LOCKBOX_PWGEN_WORDS_COMMAND", pwgenPath) if err := app.GeneratePassword(m); err == nil || err.Error() != "no sources given" { t.Errorf("invalid error: %v", err) } - t.Setenv("LOCKBOX_PWGEN_WORDLIST", fmt.Sprintf("%s 1", pwgenPath)) + t.Setenv("LOCKBOX_PWGEN_WORDS_COMMAND", fmt.Sprintf("%s 1", pwgenPath)) if err := app.GeneratePassword(m); err != nil { t.Errorf("invalid error: %v", err) } - t.Setenv("LOCKBOX_PWGEN_WORDLIST", fmt.Sprintf("%s aloj 1", pwgenPath)) + t.Setenv("LOCKBOX_PWGEN_WORDS_COMMAND", fmt.Sprintf("%s aloj 1", pwgenPath)) if err := app.GeneratePassword(m); err != nil { t.Errorf("invalid error: %v", err) } - t.Setenv("LOCKBOX_NOPWGEN", "yes") + t.Setenv("LOCKBOX_PWGEN_ENABLED", "no") if err := app.GeneratePassword(m); err == nil || err.Error() != "password generation is disabled" { t.Errorf("invalid error: %v", err) } @@ -68,21 +68,21 @@ func testPasswordGen(t *testing.T, expect string) { func TestGenerate(t *testing.T) { pwgenPath := setupGenScript() - t.Setenv("LOCKBOX_PWGEN_COUNT", "1") - t.Setenv("LOCKBOX_PWGEN_WORDLIST", fmt.Sprintf("%s 1", pwgenPath)) + t.Setenv("LOCKBOX_PWGEN_WORD_COUNT", "1") + t.Setenv("LOCKBOX_PWGEN_WORDS_COMMAND", fmt.Sprintf("%s 1", pwgenPath)) testPasswordGen(t, "1") - t.Setenv("LOCKBOX_PWGEN_COUNT", "10") - t.Setenv("LOCKBOX_PWGEN_WORDLIST", fmt.Sprintf("%s 1 1 1 1 1 1 1 1 1 1 1 1", pwgenPath)) + t.Setenv("LOCKBOX_PWGEN_WORD_COUNT", "10") + t.Setenv("LOCKBOX_PWGEN_WORDS_COMMAND", fmt.Sprintf("%s 1 1 1 1 1 1 1 1 1 1 1 1", pwgenPath)) testPasswordGen(t, "1-1-1-1-1-1-1-1-1-1") - t.Setenv("LOCKBOX_PWGEN_COUNT", "4") + t.Setenv("LOCKBOX_PWGEN_WORD_COUNT", "4") t.Setenv("LOCKBOX_PWGEN_TITLE", "yes") - t.Setenv("LOCKBOX_PWGEN_WORDLIST", fmt.Sprintf("%s a a a a a a a a a a a a a a a", pwgenPath)) + t.Setenv("LOCKBOX_PWGEN_WORDS_COMMAND", fmt.Sprintf("%s a a a a a a a a a a a a a a a", pwgenPath)) testPasswordGen(t, "A-A-A-A") - t.Setenv("LOCKBOX_PWGEN_CHARS", "bc") - t.Setenv("LOCKBOX_PWGEN_WORDLIST", fmt.Sprintf("%s abc abc abc abc abc aaa aaa aa a", pwgenPath)) + t.Setenv("LOCKBOX_PWGEN_CHARACTERS", "bc") + t.Setenv("LOCKBOX_PWGEN_WORDS_COMMAND", fmt.Sprintf("%s abc abc abc abc abc aaa aaa aa a", pwgenPath)) testPasswordGen(t, "Bc-Bc-Bc-Bc") - os.Unsetenv("LOCKBOX_PWGEN_CHARS") - t.Setenv("LOCKBOX_PWGEN_WORDLIST", fmt.Sprintf("%s a a a a a a a a a a a a a a a", pwgenPath)) + os.Unsetenv("LOCKBOX_PWGEN_CHARACTERS") + t.Setenv("LOCKBOX_PWGEN_WORDS_COMMAND", fmt.Sprintf("%s a a a a a a a a a a a a a a a", pwgenPath)) t.Setenv("LOCKBOX_PWGEN_TITLE", "no") t.Setenv("LOCKBOX_PWGEN_TITLE", "no") testPasswordGen(t, "a-a-a-a") @@ -94,7 +94,7 @@ func TestGenerate(t *testing.T) { testPasswordGen(t, "-a-a-a-a") os.Unsetenv("LOCKBOX_PWGEN_TEMPLATE") t.Setenv("LOCKBOX_PWGEN_TITLE", "yes") - t.Setenv("LOCKBOX_PWGEN_WORDLIST", fmt.Sprintf("%s abc axy axY aZZZ aoijafea aoiajfoea afaeoa", pwgenPath)) + t.Setenv("LOCKBOX_PWGEN_WORDS_COMMAND", fmt.Sprintf("%s abc axy axY aZZZ aoijafea aoiajfoea afaeoa", pwgenPath)) m := newMockCommand(t) if err := app.GeneratePassword(m); err != nil { t.Errorf("invalid error: %v", err) diff --git a/internal/app/shell/fish.sh b/internal/app/shell/fish.sh @@ -19,7 +19,7 @@ function {{ $.Executable }}-completion complete -c {{ $.Executable }} -n "__fish_seen_subcommand_from {{ $.MoveCommand }}; and test (count (commandline -opc)) -lt 4" -a "({{ $.DoList }})" end end - if {{ $.Conditionals.Not.NoTOTP }} + if {{ $.Conditionals.Not.CanTOTP }} set -f totps "" {{- range $idx, $value := $.TOTPSubCommands }} {{- if gt $idx 0 }} @@ -34,7 +34,7 @@ function {{ $.Executable }}-completion complete -c {{ $.Executable }} -n "__fish_seen_subcommand_from {{ $.TOTPCommand }}; and __fish_seen_subcommand_from $totps; and test (count (commandline -opc)) -lt 4" -a "({{ $.DoTOTPList }})" end end - if {{ $.Conditionals.Not.NoClip }} + if {{ $.Conditionals.Not.CanClip }} if {{ $.Conditionals.Not.AskMode }} complete -c {{ $.Executable }} -n "__fish_seen_subcommand_from {{ $.ClipCommand }}; and test (count (commandline -opc)) -lt 3" -a "({{ $.DoList}})" end diff --git a/internal/app/totp.go b/internal/app/totp.go @@ -39,7 +39,7 @@ type ( TOTPOptions struct { app CommandOptions Clear func() - IsNoTOTP func() (bool, error) + CanTOTP func() (bool, error) IsInteractive func() (bool, error) } ) @@ -67,7 +67,7 @@ func NewDefaultTOTPOptions(app CommandOptions) TOTPOptions { app: app, Clear: clearFunc, IsInteractive: config.EnvInteractive.Get, - IsNoTOTP: config.EnvNoTOTP.Get, + CanTOTP: config.EnvTOTPEnabled.Get, } } @@ -108,7 +108,7 @@ func (args *TOTPArguments) display(opts TOTPOptions) error { return errors.New("object does not exist") } totpToken := string(entity.Value) - k, err := coreotp.NewKeyFromURL(config.EnvFormatTOTP.Get(totpToken)) + k, err := coreotp.NewKeyFromURL(config.EnvTOTPFormat.Get(totpToken)) if err != nil { return err } @@ -146,7 +146,7 @@ func (args *TOTPArguments) display(opts TOTPOptions) error { if err != nil { return err } - runFor, err := config.EnvMaxTOTP.Get() + runFor, err := config.EnvTOTPTimeout.Get() if err != nil { return err } @@ -216,14 +216,14 @@ func (args *TOTPArguments) Do(opts TOTPOptions) error { if args.Mode == UnknownTOTPMode { return ErrUnknownTOTPMode } - if opts.Clear == nil || opts.IsNoTOTP == nil || opts.IsInteractive == nil { + if opts.Clear == nil || opts.CanTOTP == nil || opts.IsInteractive == nil { return errors.New("invalid option functions") } - off, err := opts.IsNoTOTP() + can, err := opts.CanTOTP() if err != nil { return err } - if off { + if !can { return ErrNoTOTP } if args.Mode == ListTOTPMode { diff --git a/internal/app/totp_test.go b/internal/app/totp_test.go @@ -29,8 +29,8 @@ func newMock(t *testing.T) (*mockOptions, app.TOTPOptions) { opts := app.NewDefaultTOTPOptions(m) opts.Clear = func() { } - opts.IsNoTOTP = func() (bool, error) { - return false, nil + opts.CanTOTP = func() (bool, error) { + return true, nil } opts.IsInteractive = func() (bool, error) { return true, nil @@ -45,13 +45,13 @@ func fullTOTPSetup(t *testing.T, keep bool) *backend.Transaction { } t.Setenv("LOCKBOX_READONLY", "no") t.Setenv("LOCKBOX_STORE", file) - t.Setenv("LOCKBOX_KEY", "test") - t.Setenv("LOCKBOX_KEYFILE", "") - t.Setenv("LOCKBOX_KEYMODE", "plaintext") - t.Setenv("LOCKBOX_TOTP", "totp") - t.Setenv("LOCKBOX_HOOKDIR", "") - t.Setenv("LOCKBOX_SET_MODTIME", "") - t.Setenv("LOCKBOX_TOTP_MAX", "1") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "test") + t.Setenv("LOCKBOX_CREDENTIALS_KEY_FILE", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "plaintext") + t.Setenv("LOCKBOX_TOTP_ENTRY", "totp") + t.Setenv("LOCKBOX_HOOKS_DIRECTORY", "") + t.Setenv("LOCKBOX_DEFAULTS_MODTIME", "") + t.Setenv("LOCKBOX_TOTP_TIMEOUT", "1") tr, err := backend.NewTransaction() if err != nil { t.Errorf("failed: %v", err) @@ -143,8 +143,8 @@ func TestDoErrors(t *testing.T) { if err := args.Do(opts); err == nil || err.Error() != "invalid option functions" { t.Errorf("invalid error: %v", err) } - opts.IsNoTOTP = func() (bool, error) { - return true, nil + opts.CanTOTP = func() (bool, error) { + return false, nil } if err := args.Do(opts); err == nil || err.Error() != "invalid option functions" { t.Errorf("invalid error: %v", err) diff --git a/internal/backend/actions.go b/internal/backend/actions.go @@ -192,7 +192,7 @@ func (t *Transaction) Move(src *Entity, dst string) error { if strings.TrimSpace(src.Value) == "" { return errors.New("empty secret not allowed") } - mod := config.EnvModTime.Get() + mod := config.EnvDefaultModTime.Get() modTime := time.Now() if mod != "" { p, err := time.Parse(config.ModTimeFormat, mod) @@ -241,7 +241,7 @@ func (t *Transaction) Move(src *Entity, dst string) error { if multi { return errors.New("totp tokens can NOT be multi-line") } - otp := config.EnvFormatTOTP.Get(v) + otp := config.EnvTOTPFormat.Get(v) e.Values = append(e.Values, protectedValue("otp", otp)) } e.Values = append(e.Values, protectedValue(field, v)) diff --git a/internal/backend/actions_test.go b/internal/backend/actions_test.go @@ -29,12 +29,12 @@ func fullSetup(t *testing.T, keep bool) *backend.Transaction { } t.Setenv("LOCKBOX_READONLY", "no") t.Setenv("LOCKBOX_STORE", file) - t.Setenv("LOCKBOX_KEY", "test") - t.Setenv("LOCKBOX_KEYFILE", "") - t.Setenv("LOCKBOX_KEYMODE", "plaintext") - t.Setenv("LOCKBOX_TOTP", "totp") - t.Setenv("LOCKBOX_HOOKDIR", "") - t.Setenv("LOCKBOX_SET_MODTIME", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "test") + t.Setenv("LOCKBOX_CREDENTIALS_KEY_FILE", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "plaintext") + t.Setenv("LOCKBOX_TOTP_ENTRY", "totp") + t.Setenv("LOCKBOX_HOOKS_DIRECTORY", "") + t.Setenv("LOCKBOX_DEFAULTS_MODTIME", "") tr, err := backend.NewTransaction() if err != nil { t.Errorf("failed: %v", err) @@ -49,12 +49,12 @@ func TestKeyFile(t *testing.T) { os.Remove(file) t.Setenv("LOCKBOX_READONLY", "no") t.Setenv("LOCKBOX_STORE", file) - t.Setenv("LOCKBOX_KEY", "test") - t.Setenv("LOCKBOX_KEYFILE", keyFile) - t.Setenv("LOCKBOX_KEYMODE", "plaintext") - t.Setenv("LOCKBOX_TOTP", "totp") - t.Setenv("LOCKBOX_HOOKDIR", "") - t.Setenv("LOCKBOX_SET_MODTIME", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "test") + t.Setenv("LOCKBOX_CREDENTIALS_KEY_FILE", keyFile) + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "plaintext") + t.Setenv("LOCKBOX_TOTP_ENTRY", "totp") + t.Setenv("LOCKBOX_HOOKS_DIRECTORY", "") + t.Setenv("LOCKBOX_DEFAULTS_MODTIME", "") os.WriteFile(keyFile, []byte("test"), 0o644) tr, err := backend.NewTransaction() if err != nil { @@ -80,7 +80,7 @@ func TestNoWriteOnRO(t *testing.T) { func TestBadTOTP(t *testing.T) { tr := setup(t) - t.Setenv("LOCKBOX_TOTP", "Title") + t.Setenv("LOCKBOX_TOTP_ENTRY", "Title") if err := tr.Insert("a/a/a", "a"); err.Error() != "invalid totp field, uses restricted name" { t.Errorf("wrong error: %v", err) } @@ -285,14 +285,14 @@ func keyAndOrKeyFile(t *testing.T, key, keyFile bool) { os.Remove(file) t.Setenv("LOCKBOX_STORE", file) if key { - t.Setenv("LOCKBOX_KEY", "test") - t.Setenv("LOCKBOX_KEYMODE", "plaintext") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "test") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "plaintext") } else { - t.Setenv("LOCKBOX_KEYMODE", "none") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "none") } if keyFile { key := testFile("keyfileor.key") - t.Setenv("LOCKBOX_KEYFILE", key) + t.Setenv("LOCKBOX_CREDENTIALS_KEY_FILE", key) os.WriteFile(key, []byte("test"), 0o644) } tr, err := backend.NewTransaction() @@ -319,11 +319,11 @@ func TestReKey(t *testing.T) { defer os.Remove(filepath.Join(testDir, f)) t.Setenv("LOCKBOX_READONLY", "no") t.Setenv("LOCKBOX_STORE", file) - t.Setenv("LOCKBOX_KEY", "test") - t.Setenv("LOCKBOX_KEYMODE", "plaintext") - t.Setenv("LOCKBOX_TOTP", "totp") - t.Setenv("LOCKBOX_HOOKDIR", "") - t.Setenv("LOCKBOX_SET_MODTIME", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "test") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "plaintext") + t.Setenv("LOCKBOX_TOTP_ENTRY", "totp") + t.Setenv("LOCKBOX_HOOKS_DIRECTORY", "") + t.Setenv("LOCKBOX_DEFAULTS_MODTIME", "") tr, err := backend.NewTransaction() if err != nil { t.Errorf("failed: %v", err) diff --git a/internal/backend/core.go b/internal/backend/core.go @@ -142,7 +142,7 @@ func encode(f *os.File, db *gokeepasslib.Database) error { } func isTOTP(title string) (bool, error) { - t := config.EnvTOTPToken.Get() + t := config.EnvTOTPEntry.Get() if t == notesKey || t == passKey || t == titleKey { return false, errors.New("invalid totp field, uses restricted name") } diff --git a/internal/backend/hooks.go b/internal/backend/hooks.go @@ -33,11 +33,11 @@ const ( // NewHook will create a new hook type func NewHook(path string, a ActionMode) (Hook, error) { - disabled, err := config.EnvNoHooks.Get() + enabled, err := config.EnvHooksEnabled.Get() if err != nil { return Hook{}, err } - if disabled { + if !enabled { return Hook{enabled: false}, nil } if strings.TrimSpace(path) == "" { @@ -70,7 +70,7 @@ func (h Hook) Run(mode HookMode) error { return nil } env := os.Environ() - env = append(env, config.EnvNoHooks.KeyValue(config.YesValue)) + env = append(env, config.EnvHooksEnabled.KeyValue(config.NoValue)) for _, s := range h.scripts { c := exec.Command(s, string(mode), string(h.mode), h.path) c.Stdout = os.Stdout diff --git a/internal/backend/hooks_test.go b/internal/backend/hooks_test.go @@ -10,7 +10,7 @@ import ( ) func TestHooks(t *testing.T) { - t.Setenv("LOCKBOX_HOOKDIR", "") + t.Setenv("LOCKBOX_HOOKS_DIRECTORY", "") h, err := backend.NewHook("a", backend.InsertAction) if err != nil { t.Errorf("invalid error: %v", err) @@ -21,7 +21,7 @@ func TestHooks(t *testing.T) { if _, err := backend.NewHook("", backend.InsertAction); err.Error() != "empty path is not allowed for hooks" { t.Errorf("wrong error: %v", err) } - t.Setenv("LOCKBOX_HOOKDIR", "is_garbage") + t.Setenv("LOCKBOX_HOOKS_DIRECTORY", "is_garbage") if _, err := backend.NewHook("b", backend.InsertAction); err.Error() != "hook directory does NOT exist" { t.Errorf("wrong error: %v", err) } @@ -30,7 +30,7 @@ func TestHooks(t *testing.T) { if err := os.MkdirAll(testPath, 0o755); err != nil { t.Errorf("failed, mkdir: %v", err) } - t.Setenv("LOCKBOX_HOOKDIR", testPath) + t.Setenv("LOCKBOX_HOOKS_DIRECTORY", testPath) h, err = backend.NewHook("a", backend.InsertAction) if err != nil { t.Errorf("invalid error: %v", err) @@ -59,7 +59,7 @@ func TestHooks(t *testing.T) { if err := h.Run(backend.HookPre); strings.Contains("fork/exec", err.Error()) { t.Errorf("wrong error: %v", err) } - t.Setenv("LOCKBOX_NOHOOKS", "yes") + t.Setenv("LOCKBOX_HOOKS_ENABLED", "no") h, err = backend.NewHook("a", backend.InsertAction) if err != nil { t.Errorf("invalid error: %v", err) diff --git a/internal/backend/query.go b/internal/backend/query.go @@ -184,7 +184,7 @@ func (t *Transaction) QueryCallback(args QueryOptions) (QuerySeq2, error) { } var hashLength int if jsonMode == config.JSONOutputs.Hash { - hashLength, err = config.EnvHashLength.Get() + hashLength, err = config.EnvJSONHashLength.Get() if err != nil { return nil, err } diff --git a/internal/backend/query_test.go b/internal/backend/query_test.go @@ -97,7 +97,7 @@ func TestValueModes(t *testing.T) { if len(m.ModTime) < 20 { t.Errorf("invalid date/time") } - t.Setenv("LOCKBOX_JSON_DATA_HASH_LENGTH", "10") + t.Setenv("LOCKBOX_JSON_HASH_LENGTH", "10") q, err = fullSetup(t, true).Get("test/test/abc", backend.JSONValue) if err != nil { t.Errorf("no error: %v", err) @@ -127,7 +127,7 @@ func TestValueModes(t *testing.T) { if len(m.ModTime) < 20 || m.Data == "" { t.Errorf("invalid json: %v", m) } - t.Setenv("LOCKBOX_JSON_DATA", "plAINtExt") + t.Setenv("LOCKBOX_JSON_MODE", "plAINtExt") q, err = fullSetup(t, true).Get("test/test/abc", backend.JSONValue) if err != nil { t.Errorf("no error: %v", err) @@ -139,7 +139,7 @@ func TestValueModes(t *testing.T) { if len(m.ModTime) < 20 || m.Data != "tedst" { t.Errorf("invalid json: %v", m) } - t.Setenv("LOCKBOX_JSON_DATA", "emPTY") + t.Setenv("LOCKBOX_JSON_MODE", "emPTY") q, err = fullSetup(t, true).Get("test/test/abc", backend.JSONValue) if err != nil { t.Errorf("no error: %v", err) @@ -211,7 +211,7 @@ func TestQueryCallback(t *testing.T) { func TestSetModTime(t *testing.T) { testDateTime := "2022-12-30T12:34:56-05:00" tr := fullSetup(t, false) - t.Setenv("LOCKBOX_SET_MODTIME", testDateTime) + t.Setenv("LOCKBOX_DEFAULTS_MODTIME", testDateTime) tr.Insert("test/xyz", "test") q, err := fullSetup(t, true).Get("test/xyz", backend.JSONValue) if err != nil { @@ -226,7 +226,7 @@ func TestSetModTime(t *testing.T) { } tr = fullSetup(t, false) - t.Setenv("LOCKBOX_SET_MODTIME", "") + t.Setenv("LOCKBOX_DEFAULTS_MODTIME", "") tr.Insert("test/xyz", "test") q, err = fullSetup(t, true).Get("test/xyz", backend.JSONValue) if err != nil { @@ -241,7 +241,7 @@ func TestSetModTime(t *testing.T) { } tr = fullSetup(t, false) - t.Setenv("LOCKBOX_SET_MODTIME", "garbage") + t.Setenv("LOCKBOX_DEFAULTS_MODTIME", "garbage") err = tr.Insert("test/xyz", "test") if err == nil || !strings.Contains(err.Error(), "parsing time") { t.Errorf("invalid error: %v", err) diff --git a/internal/config/config.toml b/internal/config/config.toml @@ -35,14 +35,14 @@ password = [] [pwgen] enabled = true characters = "" -count = 0 +word_count = 0 template = "" title = true words_command = [] [totp] enabled = true -attribute = "" +entry = "" color_windows = [] otp_format = "" timeout = 0 diff --git a/internal/config/core.go b/internal/config/core.go @@ -27,11 +27,17 @@ const ( tomlFile = "lockbox.toml" unknownPlatform = "" // sub categories - clipCategory keyCategory = "CLIP_" - totpCategory keyCategory = "TOTP_" - genCategory keyCategory = "PWGEN_" + clipCategory keyCategory = "CLIP_" + totpCategory keyCategory = "TOTP_" + genCategory keyCategory = "PWGEN_" + jsonCategory keyCategory = "JSON_" + credsCategory keyCategory = "CREDENTIALS_" + defaultCategory keyCategory = "DEFAULTS_" + hookCategory keyCategory = "HOOKS_" // YesValue are yes (on) values YesValue = yes + // NoValue are no (off) values + NoValue = no // TemplateVariable is used to handle '$' in shell vars (due to expansion) TemplateVariable = "[%]" configDirName = "lockbox" @@ -245,7 +251,7 @@ func (e EnvironmentInt) values() (string, []string) { } func (e EnvironmentFormatter) values() (string, []string) { - return strings.ReplaceAll(strings.ReplaceAll(EnvFormatTOTP.Get("%s"), "%25s", "%s"), "&", " \\\n &"), []string{e.allowed} + return strings.ReplaceAll(strings.ReplaceAll(EnvTOTPFormat.Get("%s"), "%25s", "%s"), "&", " \\\n &"), []string{e.allowed} } func (e EnvironmentCommand) values() (string, []string) { diff --git a/internal/config/core_test.go b/internal/config/core_test.go @@ -166,10 +166,10 @@ func TestEnviron(t *testing.T) { } t.Setenv("LOCKBOX_STORE", "1") t.Setenv("LOCKBOX_2", "2") - t.Setenv("LOCKBOX_KEY", "2") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "2") t.Setenv("LOCKBOX_ENV", "2") e = config.Environ() - if len(e) != 2 || fmt.Sprintf("%v", e) != "[LOCKBOX_KEY=2 LOCKBOX_STORE=1]" { + if len(e) != 2 || fmt.Sprintf("%v", e) != "[LOCKBOX_CREDENTIALS_PASSWORD=2 LOCKBOX_STORE=1]" { t.Errorf("invalid environ: %v", e) } } diff --git a/internal/config/key.go b/internal/config/key.go @@ -35,8 +35,8 @@ const ( // NewKey will create a new key func NewKey(defaultKeyModeType KeyModeType) (Key, error) { - useKey := envKey.Get() - keyMode := EnvKeyMode.Get() + useKey := envPassword.Get() + keyMode := EnvPasswordMode.Get() if keyMode == "" { keyMode = string(defaultKeyModeType) } diff --git a/internal/config/key_test.go b/internal/config/key_test.go @@ -9,46 +9,46 @@ import ( ) func TestDefaultKey(t *testing.T) { - t.Setenv("LOCKBOX_KEYMODE", "") - t.Setenv("LOCKBOX_KEY", "test") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "test") if _, err := config.NewKey(config.IgnoreKeyMode); err != nil { t.Errorf("invalid error: %v", err) } - t.Setenv("LOCKBOX_KEYMODE", "") - t.Setenv("LOCKBOX_KEY", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "") if _, err := config.NewKey(config.DefaultKeyMode); err == nil || err.Error() != "key MUST be set in this key mode" { t.Errorf("invalid error: %v", err) } } func TestNewKeyErrors(t *testing.T) { - t.Setenv("LOCKBOX_KEYMODE", "invalid") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "invalid") if _, err := config.NewKey(config.IgnoreKeyMode); err == nil || err.Error() != "unknown key mode: invalid" { t.Errorf("invalid error: %v", err) } - t.Setenv("LOCKBOX_KEYMODE", "none") - t.Setenv("LOCKBOX_KEY", " test") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "none") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", " test") if _, err := config.NewKey(config.IgnoreKeyMode); err == nil || err.Error() != "key can NOT be set in this key mode" { t.Errorf("invalid error: %v", err) } - t.Setenv("LOCKBOX_KEYMODE", "ask") - t.Setenv("LOCKBOX_KEY", "test") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "ask") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "test") if _, err := config.NewKey(config.IgnoreKeyMode); err == nil || err.Error() != "key can NOT be set in this key mode" { t.Errorf("invalid error: %v", err) } - t.Setenv("LOCKBOX_KEYMODE", "command") - t.Setenv("LOCKBOX_KEY", " ") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "command") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", " ") if _, err := config.NewKey(config.IgnoreKeyMode); err == nil || err.Error() != "key MUST be set in this key mode" { t.Errorf("invalid error: %v", err) } - t.Setenv("LOCKBOX_KEYMODE", "plaintext") - t.Setenv("LOCKBOX_KEY", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "plaintext") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "") if _, err := config.NewKey(config.IgnoreKeyMode); err == nil || err.Error() != "key MUST be set in this key mode" { t.Errorf("invalid error: %v", err) } t.Setenv("LOCKBOX_INTERACTIVE", "yes") - t.Setenv("LOCKBOX_KEYMODE", "ask") - t.Setenv("LOCKBOX_KEY", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "ask") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "") if _, err := config.NewKey(config.IgnoreKeyMode); err != nil { t.Errorf("invalid error: %v", err) } @@ -59,21 +59,21 @@ func TestNewKeyErrors(t *testing.T) { } func TestAskKey(t *testing.T) { - t.Setenv("LOCKBOX_KEYMODE", "") - t.Setenv("LOCKBOX_KEY", "test") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "test") k, _ := config.NewKey(config.IgnoreKeyMode) if k.Ask() { t.Error("invalid ask key") } - t.Setenv("LOCKBOX_KEYMODE", "ask") - t.Setenv("LOCKBOX_KEY", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "ask") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "") t.Setenv("LOCKBOX_INTERACTIVE", "no") k, _ = config.NewKey(config.IgnoreKeyMode) if k.Ask() { t.Error("invalid ask key") } - t.Setenv("LOCKBOX_KEYMODE", "ask") - t.Setenv("LOCKBOX_KEY", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "ask") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "") t.Setenv("LOCKBOX_INTERACTIVE", "yes") k, _ = config.NewKey(config.IgnoreKeyMode) if !k.Ask() { @@ -103,13 +103,13 @@ func TestAskKey(t *testing.T) { } func TestIgnoreKey(t *testing.T) { - t.Setenv("LOCKBOX_KEYMODE", "ignore") - t.Setenv("LOCKBOX_KEY", "test") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "ignore") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "test") if _, err := config.NewKey(config.IgnoreKeyMode); err != nil { t.Errorf("invalid error: %v", err) } - t.Setenv("LOCKBOX_KEYMODE", "ignore") - t.Setenv("LOCKBOX_KEY", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "ignore") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "") if _, err := config.NewKey(config.IgnoreKeyMode); err != nil { t.Errorf("invalid error: %v", err) } @@ -129,8 +129,8 @@ func TestReadErrors(t *testing.T) { } func TestPlainKey(t *testing.T) { - t.Setenv("LOCKBOX_KEYMODE", "plaintext") - t.Setenv("LOCKBOX_KEY", " test ") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "plaintext") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", " test ") k, err := config.NewKey(config.IgnoreKeyMode) if err != nil { t.Errorf("invalid error: %v", err) @@ -145,8 +145,8 @@ func TestPlainKey(t *testing.T) { } func TestReadIgnoreOrNoKey(t *testing.T) { - t.Setenv("LOCKBOX_KEYMODE", "ignore") - t.Setenv("LOCKBOX_KEY", "test") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "ignore") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "test") k, err := config.NewKey(config.IgnoreKeyMode) if err != nil { t.Errorf("invalid error: %v", err) @@ -158,8 +158,8 @@ func TestReadIgnoreOrNoKey(t *testing.T) { if err != nil || val != "" { t.Errorf("invalid error: %v", err) } - t.Setenv("LOCKBOX_KEYMODE", "ignore") - t.Setenv("LOCKBOX_KEY", "") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "ignore") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "") k, err = config.NewKey(config.IgnoreKeyMode) if err != nil { t.Errorf("invalid error: %v", err) @@ -168,7 +168,7 @@ func TestReadIgnoreOrNoKey(t *testing.T) { if err != nil || val != "" { t.Errorf("invalid error: %v", err) } - t.Setenv("LOCKBOX_KEYMODE", "none") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "none") k, err = config.NewKey(config.IgnoreKeyMode) if err != nil { t.Errorf("invalid error: %v", err) @@ -180,8 +180,8 @@ func TestReadIgnoreOrNoKey(t *testing.T) { } func TestCommandKey(t *testing.T) { - t.Setenv("LOCKBOX_KEYMODE", "command") - t.Setenv("LOCKBOX_KEY", "thisisagarbagekey") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD_MODE", "command") + t.Setenv("LOCKBOX_CREDENTIALS_PASSWORD", "thisisagarbagekey") k, err := config.NewKey(config.IgnoreKeyMode) if err != nil { t.Errorf("invalid error: %v", err) diff --git a/internal/config/toml.go b/internal/config/toml.go @@ -34,50 +34,26 @@ var ( // ExampleTOML is an example TOML file of viable fields //go:embed "config.toml" ExampleTOML string - redirects = map[string]string{ - "HOOKS_DIRECTORY": EnvHookDir.Key(), - "HOOKS_ENABLED": EnvNoHooks.Key(), - "JSON_MODE": EnvJSONDataOutput.Key(), - "JSON_HASH_LENGTH": EnvHashLength.Key(), - "CREDENTIALS_KEY_FILE": EnvKeyFile.Key(), - "CREDENTIALS_PASSWORD_MODE": EnvKeyMode.Key(), - "CREDENTIALS_PASSWORD": envKey.Key(), - "CLIP_ENABLED": EnvNoClip.Key(), - "COLOR_ENABLED": EnvNoColor.Key(), - "PWGEN_ENABLED": EnvNoPasswordGen.Key(), - "TOTP_ENABLED": EnvNoTOTP.Key(), - "TOTP_ATTRIBUTE": EnvTOTPToken.Key(), - "TOTP_OTP_FORMAT": EnvFormatTOTP.Key(), - "TOTP_COLOR_WINDOWS": EnvTOTPColorBetween.Key(), - "TOTP_TIMEOUT": EnvMaxTOTP.Key(), - "DEFAULTS_MODTIME": EnvModTime.Key(), - "DEFAULTS_COMPLETION": EnvDefaultCompletion.Key(), - "PWGEN_WORDS_COMMAND": EnvPasswordGenWordList.Key(), - "CLIP_COPY_COMMAND": EnvClipCopy.Key(), - "CLIP_PASTE_COMMAND": EnvClipPaste.Key(), - "CLIP_TIMEOUT": EnvClipMax.Key(), - "PWGEN_CHARACTERS": EnvPasswordGenChars.Key(), - } - arrayTypes = []string{ + arrayTypes = []string{ EnvClipCopy.Key(), EnvClipPaste.Key(), EnvPasswordGenWordList.Key(), - envKey.Key(), + envPassword.Key(), EnvTOTPColorBetween.Key(), } intTypes = []string{ - EnvClipMax.Key(), - EnvMaxTOTP.Key(), - EnvHashLength.Key(), - EnvPasswordGenCount.Key(), + EnvClipTimeout.Key(), + EnvTOTPTimeout.Key(), + EnvJSONHashLength.Key(), + EnvPasswordGenWordCount.Key(), } boolTypes = []string{ EnvClipOSC52.Key(), - EnvNoClip.Key(), - EnvNoColor.Key(), - EnvNoHooks.Key(), - EnvNoPasswordGen.Key(), - EnvNoTOTP.Key(), + EnvClipEnabled.Key(), + EnvTOTPEnabled.Key(), + EnvColorEnabled.Key(), + EnvHooksEnabled.Key(), + EnvPasswordGenEnabled.Key(), EnvPasswordGenTitle.Key(), EnvReadOnly.Key(), EnvInteractive.Key(), @@ -211,12 +187,7 @@ func LoadConfig(r io.Reader, loader Loader) ([]ShellEnv, error) { } var res []ShellEnv for k, v := range m { - export := strings.ToUpper(k) - if r, ok := redirects[export]; ok { - export = r - } else { - export = environmentPrefix + export - } + export := environmentPrefix + strings.ToUpper(k) if _, ok := registry[export]; !ok { return nil, fmt.Errorf("unknown key: %s (%s)", k, export) } diff --git a/internal/config/toml_test.go b/internal/config/toml_test.go @@ -83,7 +83,7 @@ func TestArrayLoad(t *testing.T) { t.Setenv("TEST", "abc") data := `store="xyz" [clip] -copy = ["'xyz/$TEST'", "s", 1] +copy_command = ["'xyz/$TEST'", "s", 1] ` r := strings.NewReader(data) _, err := config.LoadConfig(r, func(p string) (io.Reader, error) { @@ -95,7 +95,7 @@ copy = ["'xyz/$TEST'", "s", 1] data = `include = [] store="xyz" [clip] -copy = ["'xyz/$TEST'", "s"] +copy_command = ["'xyz/$TEST'", "s"] ` r = strings.NewReader(data) env, err := config.LoadConfig(r, func(p string) (io.Reader, error) { @@ -107,13 +107,13 @@ copy = ["'xyz/$TEST'", "s"] slices.SortFunc(env, func(x, y config.ShellEnv) int { return strings.Compare(x.Key, y.Key) }) - if len(env) != 2 || env[1].Key != "LOCKBOX_STORE" || env[1].Value != "xyz" || env[0].Key != "LOCKBOX_CLIP_COPY" || env[0].Value != "'xyz/abc' s" { + if len(env) != 2 || env[1].Key != "LOCKBOX_STORE" || env[1].Value != "xyz" || env[0].Key != "LOCKBOX_CLIP_COPY_COMMAND" || env[0].Value != "'xyz/abc' s" { t.Errorf("invalid object: %v", env) } data = `include = [] store="xyz" [clip] -copy = "'xyz/$TEST' s" +copy_command = "'xyz/$TEST' s" ` r = strings.NewReader(data) env, err = config.LoadConfig(r, func(p string) (io.Reader, error) { @@ -125,24 +125,7 @@ copy = "'xyz/$TEST' s" slices.SortFunc(env, func(x, y config.ShellEnv) int { return strings.Compare(x.Key, y.Key) }) - if len(env) != 2 || env[1].Key != "LOCKBOX_STORE" || env[1].Value != "xyz" || env[0].Key != "LOCKBOX_CLIP_COPY" || env[0].Value != "'xyz/abc' s" { - t.Errorf("invalid object: %v", env) - } -} - -func TestRedirect(t *testing.T) { - data := `include = [] -[hooks] -directory = "xyz" -` - r := strings.NewReader(data) - env, err := config.LoadConfig(r, func(p string) (io.Reader, error) { - return nil, nil - }) - if err != nil { - t.Errorf("invalid error: %v", err) - } - if len(env) != 1 || env[0].Key != "LOCKBOX_HOOKDIR" || env[0].Value != "xyz" { + if len(env) != 2 || env[1].Key != "LOCKBOX_STORE" || env[1].Value != "xyz" || env[0].Key != "LOCKBOX_CLIP_COPY_COMMAND" || env[0].Value != "'xyz/abc' s" { t.Errorf("invalid object: %v", env) } } @@ -150,7 +133,7 @@ directory = "xyz" func TestReadInt(t *testing.T) { data := ` [clip] -max = true +timeout = true ` r := strings.NewReader(data) _, err := config.LoadConfig(r, func(p string) (io.Reader, error) { @@ -161,7 +144,7 @@ max = true } data = `include = [] [clip] -max = 1 +timeout = 1 ` r = strings.NewReader(data) env, err := config.LoadConfig(r, func(p string) (io.Reader, error) { @@ -170,12 +153,12 @@ max = 1 if err != nil { t.Errorf("invalid error: %v", err) } - if len(env) != 1 || env[0].Key != "LOCKBOX_CLIP_MAX" || env[0].Value != "1" { + if len(env) != 1 || env[0].Key != "LOCKBOX_CLIP_TIMEOUT" || env[0].Value != "1" { t.Errorf("invalid object: %v", env) } data = `include = [] [clip] -max = -1 +timeout = -1 ` r = strings.NewReader(data) _, err = config.LoadConfig(r, func(p string) (io.Reader, error) { @@ -211,7 +194,7 @@ enabled = true if err != nil { t.Errorf("invalid error: %v", err) } - if len(env) != 1 || env[0].Key != "LOCKBOX_NOTOTP" || env[0].Value != "yes" { + if len(env) != 1 || env[0].Key != "LOCKBOX_TOTP_ENABLED" || env[0].Value != "yes" { t.Errorf("invalid object: %v", env) } data = `include = [] @@ -225,7 +208,7 @@ enabled = false if err != nil { t.Errorf("invalid error: %v", err) } - if len(env) != 1 || env[0].Key != "LOCKBOX_NOTOTP" || env[0].Value != "no" { + if len(env) != 1 || env[0].Key != "LOCKBOX_TOTP_ENABLED" || env[0].Value != "no" { t.Errorf("invalid object: %v", env) } } @@ -246,13 +229,13 @@ enabled = "false" } data = `include = [] [totp] -format = -1 +otp_format = -1 ` r = strings.NewReader(data) _, err = config.LoadConfig(r, func(p string) (io.Reader, error) { return nil, nil }) - if err == nil || err.Error() != "unknown field, can't determine type: totp_format (-1)" { + if err == nil || err.Error() != "unknown field, can't determine type: totp_otp_format (-1)" { t.Errorf("invalid error: %v", err) } } diff --git a/internal/config/vars.go b/internal/config/vars.go @@ -49,24 +49,25 @@ var ( } return strings.Join(results, colorWindowDelimiter) }() - // EnvClipMax gets the maximum clipboard time - EnvClipMax = environmentRegister( + // EnvClipTimeout gets the maximum clipboard time + EnvClipTimeout = environmentRegister( EnvironmentInt{ environmentDefault: newDefaultedEnvironment(45, environmentBase{ - subKey: "MAX", + subKey: "TIMEOUT", cat: clipCategory, desc: "Override the amount of time before totp clears the clipboard (seconds).", }), shortDesc: "clipboard max time", allowZero: false, }) - // EnvHashLength handles the hashing output length - EnvHashLength = environmentRegister( + // EnvJSONHashLength handles the hashing output length + EnvJSONHashLength = environmentRegister( EnvironmentInt{ environmentDefault: newDefaultedEnvironment(0, environmentBase{ - subKey: EnvJSONDataOutput.subKey + "_HASH_LENGTH", + cat: jsonCategory, + subKey: "HASH_LENGTH", desc: fmt.Sprintf("Maximum string length of the JSON value when '%s' mode is set for JSON output.", JSONOutputs.Hash), }), shortDesc: "hash length", @@ -82,13 +83,14 @@ var ( desc: "Enable OSC52 clipboard mode.", }), }) - // EnvNoTOTP indicates if TOTP is disabled - EnvNoTOTP = environmentRegister( + // EnvTOTPEnabled indicates if TOTP is allowed + EnvTOTPEnabled = environmentRegister( EnvironmentBool{ - environmentDefault: newDefaultedEnvironment(false, + environmentDefault: newDefaultedEnvironment(true, environmentBase{ - subKey: "NOTOTP", - desc: "Disable TOTP integrations.", + cat: totpCategory, + subKey: "ENABLED", + desc: "Enable TOTP integrations.", }), }) // EnvReadOnly indicates if in read-only mode @@ -100,13 +102,14 @@ var ( desc: "Operate in readonly mode.", }), }) - // EnvNoClip indicates clipboard functionality is off - EnvNoClip = environmentRegister( + // EnvClipEnabled indicates if clipboard is enabled + EnvClipEnabled = environmentRegister( EnvironmentBool{ - environmentDefault: newDefaultedEnvironment(false, + environmentDefault: newDefaultedEnvironment(true, environmentBase{ - subKey: "NOCLIP", - desc: "Disable clipboard operations.", + cat: clipCategory, + subKey: "ENABLED", + desc: "Enable clipboard operations.", }), }) // EnvDefaultCompletion disable completion detection @@ -114,28 +117,30 @@ var ( EnvironmentBool{ environmentDefault: newDefaultedEnvironment(false, environmentBase{ - subKey: "DEFAULT_COMPLETION", + cat: defaultCategory, + subKey: "COMPLETION", desc: "Use the default completion set (disable detection).", }), }) // EnvDefaultCompletionKey is the key for default completion handling EnvDefaultCompletionKey = EnvDefaultCompletion.Key() - // EnvNoColor indicates if color outputs are disabled - EnvNoColor = environmentRegister( + // EnvColorEnabled indicates if colors are enabled + EnvColorEnabled = environmentRegister( EnvironmentBool{ - environmentDefault: newDefaultedEnvironment(false, + environmentDefault: newDefaultedEnvironment(true, environmentBase{ - subKey: "NOCOLOR", - desc: "Disable terminal colors.", + subKey: "COLOR_ENABLED", + desc: "Enable terminal colors.", }), }) - // EnvNoHooks disables hooks - EnvNoHooks = environmentRegister( + // EnvHooksEnabled indicates if hooks are enabled + EnvHooksEnabled = environmentRegister( EnvironmentBool{ - environmentDefault: newDefaultedEnvironment(false, + environmentDefault: newDefaultedEnvironment(true, environmentBase{ - subKey: "NOHOOKS", - desc: "Disable hooks", + cat: hookCategory, + subKey: "ENABLED", + desc: "Enable hooks", }), }) // EnvInteractive indicates if operating in interactive mode @@ -147,25 +152,26 @@ var ( desc: "Enable interactive mode.", }), }) - // EnvMaxTOTP is the max TOTP time to run (default) - EnvMaxTOTP = environmentRegister( + // EnvTOTPTimeout indicates when TOTP display should timeout + EnvTOTPTimeout = environmentRegister( EnvironmentInt{ environmentDefault: newDefaultedEnvironment(120, environmentBase{ - subKey: "MAX", + subKey: "TIMEOUT", cat: totpCategory, desc: "Time, in seconds, to show a TOTP token before automatically exiting.", }), shortDesc: "max totp time", allowZero: false, }) - // EnvTOTPToken is the leaf token to use to store TOTP tokens - EnvTOTPToken = environmentRegister( + // EnvTOTPEntry is the leaf token to use to store TOTP tokens + EnvTOTPEntry = environmentRegister( EnvironmentString{ environmentDefault: newDefaultedEnvironment("totp", environmentBase{ - subKey: "TOTP", - desc: "Attribute name to store TOTP tokens within the database.", + cat: totpCategory, + subKey: "ENTRY", + desc: "Entry name to store TOTP tokens within the database.", }), allowed: []string{"<string>"}, canDefault: true, @@ -198,7 +204,8 @@ var ( EnvironmentString{ environmentDefault: newDefaultedEnvironment("", environmentBase{ - subKey: "HOOKDIR", + cat: hookCategory, + subKey: "DIRECTORY", desc: "The path to hooks to execute on actions against the database.", }), allowed: []string{"<directory>"}, @@ -206,13 +213,13 @@ var ( }) // EnvClipCopy allows overriding the clipboard copy command EnvClipCopy = environmentRegister(EnvironmentCommand{environmentBase: environmentBase{ - subKey: "COPY", + subKey: "COPY_COMMAND", cat: clipCategory, desc: "Override the detected platform copy command.", }}) // EnvClipPaste allows overriding the clipboard paste command EnvClipPaste = environmentRegister(EnvironmentCommand{environmentBase: environmentBase{ - subKey: "PASTE", + subKey: "PASTE_COMMAND", cat: clipCategory, desc: "Override the detected platform paste command.", }}) @@ -221,7 +228,7 @@ var ( EnvironmentString{ environmentDefault: newDefaultedEnvironment(TOTPDefaultBetween, environmentBase{ - subKey: "BETWEEN", + subKey: "COLOR_WINDOWS", cat: totpCategory, desc: 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), @@ -235,38 +242,41 @@ and '%s' allows for multiple windows.`, colorWindowSpan, colorWindowDelimiter), EnvironmentString{ environmentDefault: newDefaultedEnvironment("", environmentBase{ - subKey: "KEYFILE", + cat: credsCategory, + subKey: "KEY_FILE", requirement: requiredKeyOrKeyFile, desc: "A keyfile to access/protect the database.", }), allowed: []string{"keyfile"}, canDefault: true, }) - // EnvModTime is modtime override ability for entries - EnvModTime = environmentRegister( + // EnvDefaultModTime is modtime override ability for entries + EnvDefaultModTime = environmentRegister( EnvironmentString{ environmentDefault: newDefaultedEnvironment("", environmentBase{ - subKey: "SET_MODTIME", + cat: defaultCategory, + subKey: "MODTIME", desc: fmt.Sprintf("Input modification time to set for the entry\n\nExpected format: %s.", ModTimeFormat), }), canDefault: true, allowed: []string{"modtime"}, }) - // EnvJSONDataOutput controls how JSON is output in the 'data' field - EnvJSONDataOutput = environmentRegister( + // EnvJSONMode controls how JSON is output in the 'data' field + EnvJSONMode = environmentRegister( EnvironmentString{ environmentDefault: newDefaultedEnvironment(string(JSONOutputs.Hash), environmentBase{ - subKey: "JSON_DATA", + cat: jsonCategory, + subKey: "MODE", desc: fmt.Sprintf("Changes what the data field in JSON outputs will contain.\n\nUse '%s' with CAUTION.", JSONOutputs.Raw), }), canDefault: true, allowed: JSONOutputs.List(), }) - // EnvFormatTOTP supports formatting the TOTP tokens for generation of tokens - EnvFormatTOTP = environmentRegister(EnvironmentFormatter{environmentBase: environmentBase{ - subKey: "FORMAT", + // EnvTOTPFormat supports formatting the TOTP tokens for generation of tokens + EnvTOTPFormat = environmentRegister(EnvironmentFormatter{environmentBase: environmentBase{ + subKey: "OTP_FORMAT", cat: totpCategory, desc: "Override the otpauth url used to store totp tokens. It must have ONE format string ('%s') to insert the totp base code.", }, fxn: formatterTOTP, allowed: "otpauth//url/%s/args..."}) @@ -288,12 +298,13 @@ can it be set via TOML configuration.`, noEnvironment, detectEnvironment, string canDefault: true, allowed: []string{detectEnvironment, fileExample, noEnvironment}, }) - // EnvKeyMode is the variable for indicating the keymode used to get the key - EnvKeyMode = environmentRegister( + // EnvPasswordMode indicates how the password is read + EnvPasswordMode = environmentRegister( EnvironmentString{ environmentDefault: newDefaultedEnvironment(string(DefaultKeyMode), environmentBase{ - subKey: "KEYMODE", + cat: credsCategory, + subKey: "PASSWORD_MODE", requirement: "must be set to a valid mode when using a key", desc: fmt.Sprintf(`How to retrieve the database store password. Set to '%s' when only using a key file. Set to '%s' to ignore the set key value`, noKeyMode, IgnoreKeyMode), @@ -301,12 +312,13 @@ Set to '%s' to ignore the set key value`, noKeyMode, IgnoreKeyMode), allowed: []string{string(AskKeyMode), string(commandKeyMode), string(IgnoreKeyMode), string(noKeyMode), string(plainKeyMode)}, canDefault: true, }) - envKey = environmentRegister( + envPassword = environmentRegister( EnvironmentString{ environmentDefault: newDefaultedEnvironment("", environmentBase{ + cat: credsCategory, requirement: requiredKeyOrKeyFile, - subKey: "KEY", + subKey: "PASSWORD", desc: fmt.Sprintf("The database key ('%s' mode) or command to run ('%s' mode) to retrieve the database password.", plainKeyMode, commandKeyMode), @@ -314,12 +326,12 @@ Set to '%s' to ignore the set key value`, noKeyMode, IgnoreKeyMode), allowed: []string{commandArgsExample, "password"}, canDefault: false, }) - // EnvPasswordGenCount is the number of words that will be selected for password generation - EnvPasswordGenCount = environmentRegister( + // EnvPasswordGenWordCount is the number of words that will be selected for password generation + EnvPasswordGenWordCount = environmentRegister( EnvironmentInt{ environmentDefault: newDefaultedEnvironment(8, environmentBase{ - subKey: "COUNT", + subKey: "WORD_COUNT", cat: genCategory, desc: "Number of words to select and include in the generated password.", }), @@ -350,7 +362,7 @@ Set to '%s' to ignore the set key value`, noKeyMode, IgnoreKeyMode), }) // EnvPasswordGenWordList is the command text to generate the word list EnvPasswordGenWordList = environmentRegister(EnvironmentCommand{environmentBase: environmentBase{ - subKey: "WORDLIST", + subKey: "WORDS_COMMAND", cat: genCategory, desc: "Command to retrieve the word list to use for password generation (must be split by newline).", }}) @@ -365,13 +377,14 @@ Set to '%s' to ignore the set key value`, noKeyMode, IgnoreKeyMode), allowed: []string{"<language code>"}, canDefault: true, }) - // EnvNoPasswordGen disables password generation. - EnvNoPasswordGen = environmentRegister( + // EnvPasswordGenEnabled indicates if password generation is enabled + EnvPasswordGenEnabled = environmentRegister( EnvironmentBool{ - environmentDefault: newDefaultedEnvironment(false, + environmentDefault: newDefaultedEnvironment(true, environmentBase{ - subKey: "NOPWGEN", - desc: "Disable password generation.", + cat: genCategory, + subKey: "ENABLED", + desc: "Enable password generation.", }), }) // EnvPasswordGenChars allows for restricting which characters can be used @@ -379,7 +392,7 @@ Set to '%s' to ignore the set key value`, noKeyMode, IgnoreKeyMode), EnvironmentString{ environmentDefault: newDefaultedEnvironment("", environmentBase{ - subKey: "CHARS", + subKey: "CHARACTERS", cat: genCategory, desc: "The set of allowed characters in output words (empty means any character is allowed).", }), @@ -433,7 +446,7 @@ func formatterTOTP(key, value string) string { // ParseJSONOutput handles detecting the JSON output mode func ParseJSONOutput() (JSONOutputMode, error) { - val := JSONOutputMode(strings.ToLower(strings.TrimSpace(EnvJSONDataOutput.Get()))) + val := JSONOutputMode(strings.ToLower(strings.TrimSpace(EnvJSONMode.Get()))) switch val { case JSONOutputs.Hash, JSONOutputs.Blank, JSONOutputs.Raw: return val, nil @@ -452,11 +465,11 @@ func CanColor() (bool, error) { } colors := interactive if colors { - isColored, err := EnvNoColor.Get() + isColored, err := EnvColorEnabled.Get() if err != nil { return false, err } - colors = !isColored + colors = isColored } return colors, nil } diff --git a/internal/config/vars_test.go b/internal/config/vars_test.go @@ -41,11 +41,11 @@ func checkYesNo(key string, t *testing.T, obj config.EnvironmentBool, onEmpty bo } func TestColorSetting(t *testing.T) { - checkYesNo("LOCKBOX_NOCOLOR", t, config.EnvNoColor, false) + checkYesNo("LOCKBOX_COLOR_ENABLED", t, config.EnvColorEnabled, true) } func TestNoHook(t *testing.T) { - checkYesNo("LOCKBOX_NOHOOKS", t, config.EnvNoHooks, false) + checkYesNo("LOCKBOX_HOOKS_ENABLED", t, config.EnvHooksEnabled, true) } func TestInteractiveSetting(t *testing.T) { @@ -61,15 +61,15 @@ func TestIsOSC52(t *testing.T) { } func TestIsNoTOTP(t *testing.T) { - checkYesNo("LOCKBOX_NOTOTP", t, config.EnvNoTOTP, false) + checkYesNo("LOCKBOX_TOTP_ENABLED", t, config.EnvTOTPEnabled, true) } func TestIsNoClip(t *testing.T) { - checkYesNo("LOCKBOX_NOCLIP", t, config.EnvNoClip, false) + checkYesNo("LOCKBOX_CLIP_ENABLED", t, config.EnvClipEnabled, true) } func TestIsNoGeneratePassword(t *testing.T) { - checkYesNo("LOCKBOX_NOPWGEN", t, config.EnvNoPasswordGen, false) + checkYesNo("LOCKBOX_PWGEN_ENABLED", t, config.EnvPasswordGenEnabled, true) } func TestIsTitle(t *testing.T) { @@ -77,16 +77,16 @@ func TestIsTitle(t *testing.T) { } func TestDefaultCompletions(t *testing.T) { - checkYesNo("LOCKBOX_DEFAULT_COMPLETION", t, config.EnvDefaultCompletion, false) + checkYesNo("LOCKBOX_DEFAULTS_COMPLETION", t, config.EnvDefaultCompletion, false) } func TestTOTP(t *testing.T) { - t.Setenv("LOCKBOX_TOTP", "abc") - if config.EnvTOTPToken.Get() != "abc" { + t.Setenv("LOCKBOX_TOTP_ENTRY", "abc") + if config.EnvTOTPEntry.Get() != "abc" { t.Error("invalid totp token field") } - t.Setenv("LOCKBOX_TOTP", "") - if config.EnvTOTPToken.Get() != "totp" { + t.Setenv("LOCKBOX_TOTP_ENTRY", "") + if config.EnvTOTPEntry.Get() != "totp" { t.Error("invalid totp token field") } } @@ -112,21 +112,21 @@ func TestReKey(t *testing.T) { } func TestFormatTOTP(t *testing.T) { - otp := config.EnvFormatTOTP.Get("otpauth://abc") + otp := config.EnvTOTPFormat.Get("otpauth://abc") if otp != "otpauth://abc" { t.Errorf("invalid totp token: %s", otp) } - otp = config.EnvFormatTOTP.Get("abc") + otp = config.EnvTOTPFormat.Get("abc") if otp != "otpauth://totp/lbissuer:lbaccount?algorithm=SHA1&digits=6&issuer=lbissuer&period=30&secret=abc" { t.Errorf("invalid totp token: %s", otp) } - t.Setenv("LOCKBOX_TOTP_FORMAT", "test/%s") - otp = config.EnvFormatTOTP.Get("abc") + t.Setenv("LOCKBOX_TOTP_OTP_FORMAT", "test/%s") + otp = config.EnvTOTPFormat.Get("abc") if otp != "test/abc" { t.Errorf("invalid totp token: %s", otp) } - t.Setenv("LOCKBOX_TOTP_FORMAT", "") - otp = config.EnvFormatTOTP.Get("abc") + t.Setenv("LOCKBOX_TOTP_OTP_FORMAT", "") + otp = config.EnvTOTPFormat.Get("abc") if otp != "otpauth://totp/lbissuer:lbaccount?algorithm=SHA1&digits=6&issuer=lbissuer&period=30&secret=abc" { t.Errorf("invalid totp token: %s", otp) } @@ -137,41 +137,41 @@ func TestParseJSONMode(t *testing.T) { if m != config.JSONOutputs.Hash || err != nil { t.Error("invalid mode read") } - t.Setenv("LOCKBOX_JSON_DATA", "hAsH ") + t.Setenv("LOCKBOX_JSON_MODE", "hAsH ") m, err = config.ParseJSONOutput() if m != config.JSONOutputs.Hash || err != nil { t.Error("invalid mode read") } - t.Setenv("LOCKBOX_JSON_DATA", "EMPTY") + t.Setenv("LOCKBOX_JSON_MODE", "EMPTY") m, err = config.ParseJSONOutput() if m != config.JSONOutputs.Blank || err != nil { t.Error("invalid mode read") } - t.Setenv("LOCKBOX_JSON_DATA", " PLAINtext ") + t.Setenv("LOCKBOX_JSON_MODE", " PLAINtext ") m, err = config.ParseJSONOutput() if m != config.JSONOutputs.Raw || err != nil { t.Error("invalid mode read") } - t.Setenv("LOCKBOX_JSON_DATA", "a") + t.Setenv("LOCKBOX_JSON_MODE", "a") if _, err = config.ParseJSONOutput(); err == nil || err.Error() != "invalid JSON output mode: a" { t.Errorf("invalid error: %v", err) } } func TestClipboardMax(t *testing.T) { - checkInt(config.EnvClipMax, "LOCKBOX_CLIP_MAX", "clipboard max time", 45, false, t) + checkInt(config.EnvClipTimeout, "LOCKBOX_CLIP_TIMEOUT", "clipboard max time", 45, false, t) } func TestHashLength(t *testing.T) { - checkInt(config.EnvHashLength, "LOCKBOX_JSON_DATA_HASH_LENGTH", "hash length", 0, true, t) + checkInt(config.EnvJSONHashLength, "LOCKBOX_JSON_HASH_LENGTH", "hash length", 0, true, t) } func TestMaxTOTP(t *testing.T) { - checkInt(config.EnvMaxTOTP, "LOCKBOX_TOTP_MAX", "max totp time", 120, false, t) + checkInt(config.EnvTOTPTimeout, "LOCKBOX_TOTP_TIMEOUT", "max totp time", 120, false, t) } func TestWordCount(t *testing.T) { - checkInt(config.EnvPasswordGenCount, "LOCKBOX_PWGEN_COUNT", "word count", 8, false, t) + checkInt(config.EnvPasswordGenWordCount, "LOCKBOX_PWGEN_WORD_COUNT", "word count", 8, false, t) } func checkInt(e config.EnvironmentInt, key, text string, def int, allowZero bool, t *testing.T) { @@ -216,8 +216,8 @@ func TestCanColor(t *testing.T) { t.Error("should be able to color") } for raw, expect := range map[string]bool{ - "INTERACTIVE": true, - "NOCOLOR": false, + "INTERACTIVE": true, + "COLOR_ENABLED": true, } { os.Clearenv() key := fmt.Sprintf("LOCKBOX_%s", raw) diff --git a/internal/platform/clipboard.go b/internal/platform/clipboard.go @@ -22,7 +22,7 @@ type ( ) func newClipboard(copying, pasting []string) (Clipboard, error) { - maximum, err := config.EnvClipMax.Get() + maximum, err := config.EnvClipTimeout.Get() if err != nil { return Clipboard{}, err } @@ -31,11 +31,11 @@ func newClipboard(copying, pasting []string) (Clipboard, error) { // NewClipboard will retrieve the commands to use for clipboard operations. func NewClipboard() (Clipboard, error) { - noClip, err := config.EnvNoClip.Get() + canClip, err := config.EnvClipEnabled.Get() if err != nil { return Clipboard{}, err } - if noClip { + if !canClip { return Clipboard{}, errors.New("clipboard is off") } overridePaste, err := config.EnvClipPaste.Get() diff --git a/internal/platform/clipboard_test.go b/internal/platform/clipboard_test.go @@ -10,8 +10,8 @@ import ( func TestNoClipboard(t *testing.T) { t.Setenv("LOCKBOX_CLIP_OSC52", "no") - t.Setenv("LOCKBOX_CLIP_MAX", "") - t.Setenv("LOCKBOX_NOCLIP", "yes") + t.Setenv("LOCKBOX_CLIP_TIMEOUT", "") + t.Setenv("LOCKBOX_CLIP_ENABLED", "no") _, err := platform.NewClipboard() if err == nil || err.Error() != "clipboard is off" { t.Errorf("invalid error: %v", err) @@ -19,10 +19,10 @@ func TestNoClipboard(t *testing.T) { } func TestMaxTime(t *testing.T) { - t.Setenv("LOCKBOX_NOCLIP", "no") + t.Setenv("LOCKBOX_CLIP_ENABLED", "yes") t.Setenv("LOCKBOX_CLIP_OSC52", "no") t.Setenv("LOCKBOX_PLATFORM", string(config.Platforms.LinuxWaylandPlatform)) - t.Setenv("LOCKBOX_CLIP_MAX", "") + t.Setenv("LOCKBOX_CLIP_TIMEOUT", "") c, err := platform.NewClipboard() if err != nil { t.Errorf("invalid clipboard: %v", err) @@ -30,7 +30,7 @@ func TestMaxTime(t *testing.T) { if c.MaxTime != 45 { t.Error("invalid default") } - t.Setenv("LOCKBOX_CLIP_MAX", "1") + t.Setenv("LOCKBOX_CLIP_TIMEOUT", "1") c, err = platform.NewClipboard() if err != nil { t.Errorf("invalid clipboard: %v", err) @@ -38,12 +38,12 @@ func TestMaxTime(t *testing.T) { if c.MaxTime != 1 { t.Error("invalid default") } - t.Setenv("LOCKBOX_CLIP_MAX", "-1") + t.Setenv("LOCKBOX_CLIP_TIMEOUT", "-1") _, err = platform.NewClipboard() if err == nil || err.Error() != "clipboard max time must be > 0" { t.Errorf("invalid max time error: %v", err) } - t.Setenv("LOCKBOX_CLIP_MAX", "$&(+") + t.Setenv("LOCKBOX_CLIP_TIMEOUT", "$&(+") _, err = platform.NewClipboard() if err == nil || err.Error() != "strconv.Atoi: parsing \"$&(+\": invalid syntax" { t.Errorf("invalid max time error: %v", err) @@ -51,8 +51,8 @@ func TestMaxTime(t *testing.T) { } func TestClipboardInstances(t *testing.T) { - t.Setenv("LOCKBOX_NOCLIP", "no") - t.Setenv("LOCKBOX_CLIP_MAX", "") + t.Setenv("LOCKBOX_CLIP_ENABLED", "yes") + t.Setenv("LOCKBOX_CLIP_TIMEOUT", "") t.Setenv("LOCKBOX_CLIP_OSC52", "no") for _, item := range config.Platforms.List() { t.Setenv("LOCKBOX_PLATFORM", item) @@ -77,7 +77,7 @@ func TestOSC52(t *testing.T) { } func TestArgsOverride(t *testing.T) { - t.Setenv("LOCKBOX_CLIP_PASTE", "abc xyz 111") + t.Setenv("LOCKBOX_CLIP_PASTE_COMMAND", "abc xyz 111") t.Setenv("LOCKBOX_CLIP_OSC52", "no") t.Setenv("LOCKBOX_PLATFORM", string(config.Platforms.WindowsLinuxPlatform)) c, _ := platform.NewClipboard() @@ -89,7 +89,7 @@ func TestArgsOverride(t *testing.T) { if cmd != "abc" || len(args) != 2 || args[0] != "xyz" || args[1] != "111" || !ok { t.Error("invalid parse") } - t.Setenv("LOCKBOX_CLIP_COPY", "zzz lll 123") + t.Setenv("LOCKBOX_CLIP_COPY_COMMAND", "zzz lll 123") c, _ = platform.NewClipboard() cmd, args, ok = c.Args(true) if cmd != "zzz" || len(args) != 2 || args[0] != "lll" || args[1] != "123" || !ok { @@ -99,8 +99,8 @@ func TestArgsOverride(t *testing.T) { if cmd != "abc" || len(args) != 2 || args[0] != "xyz" || args[1] != "111" || !ok { t.Error("invalid parse") } - t.Setenv("LOCKBOX_CLIP_PASTE", "") - t.Setenv("LOCKBOX_CLIP_COPY", "") + t.Setenv("LOCKBOX_CLIP_PASTE_COMMAND", "") + t.Setenv("LOCKBOX_CLIP_COPY_COMMAND", "") c, _ = platform.NewClipboard() cmd, args, ok = c.Args(true) if cmd != "clip.exe" || len(args) != 0 || !ok { diff --git a/tests/run.sh b/tests/run.sh @@ -38,18 +38,18 @@ fi mkdir -p "$DATA" find "$DATA" -type f -delete -export LOCKBOX_KEYFILE="" -export LOCKBOX_KEY="" +export LOCKBOX_CREDENTIALS_KEY_FILE="" +export LOCKBOX_CREDENTIALS_PASSWORD="" VALID=0 if [ "$1" = "$PASS_TEST" ] || [ "$1" = "$BOTH_TEST" ]; then VALID=1 - export LOCKBOX_KEY="testingkey" + export LOCKBOX_CREDENTIALS_PASSWORD="testingkey" fi if [ "$1" = "$KEYF_TEST" ] || [ "$1" = "$BOTH_TEST" ]; then VALID=1 KEYFILE="$DATA/test.key" echo "thisisatest" > "$KEYFILE" - export LOCKBOX_KEYFILE="$KEYFILE" + export LOCKBOX_CREDENTIALS_KEY_FILE="$KEYFILE" fi if [ "$VALID" -eq 0 ]; then echo "invalid test" @@ -59,32 +59,32 @@ fi LOGFILE="$DATA/actual.log" printf "%-10s ... " "$1" { - export LOCKBOX_HOOKDIR="" + export LOCKBOX_HOOKS_DIRECTORY="" export LOCKBOX_STORE="${DATA}/passwords.kdbx" - export LOCKBOX_TOTP=totp + export LOCKBOX_TOTP_ENTRY=totp export LOCKBOX_INTERACTIVE=no export LOCKBOX_READONLY=no - if [ "$LOCKBOX_KEY" = "" ]; then - export LOCKBOX_KEYMODE=none + if [ "$LOCKBOX_CREDENTIALS_PASSWORD" = "" ]; then + export LOCKBOX_CREDENTIALS_PASSWORD_MODE=none else - export LOCKBOX_KEYMODE=plaintext + export LOCKBOX_CREDENTIALS_PASSWORD_MODE=plaintext fi - export LOCKBOX_JSON_DATA_HASH_LENGTH=0 + export LOCKBOX_JSON_HASH_LENGTH=0 echo test2 |${LB_BINARY} insert keys/k/one2 - OLDMODE="$LOCKBOX_KEYMODE" - OLDKEY="$LOCKBOX_KEY" + OLDMODE="$LOCKBOX_CREDENTIALS_PASSWORD_MODE" + OLDKEY="$LOCKBOX_CREDENTIALS_PASSWORD" if [ "$OLDKEY" != "" ]; then export LOCKBOX_INTERACTIVE=yes - export LOCKBOX_KEYMODE=ask - export LOCKBOX_KEY="" + export LOCKBOX_CREDENTIALS_PASSWORD_MODE=ask + export LOCKBOX_CREDENTIALS_PASSWORD="" else printf "password: " fi echo "$OLDKEY" | ${LB_BINARY} ls 2>/dev/null if [ "$OLDKEY" != "" ]; then export LOCKBOX_INTERACTIVE=no - export LOCKBOX_KEYMODE="$OLDMODE" - export LOCKBOX_KEY="$OLDKEY" + export LOCKBOX_CREDENTIALS_PASSWORD_MODE="$OLDMODE" + export LOCKBOX_CREDENTIALS_PASSWORD="$OLDKEY" fi echo test |${LB_BINARY} insert keys/k/one echo test |${LB_BINARY} insert key/a/one @@ -141,7 +141,7 @@ printf "%-10s ... " "$1" echo test2 |${LB_BINARY} insert keys/k2/t1/one2 echo test |${LB_BINARY} insert keys/k2/t1/one echo test2 |${LB_BINARY} insert keys/k2/t2/one2 - export LOCKBOX_HOOKDIR="$PWD/hooks" + export LOCKBOX_HOOKS_DIRECTORY="$PWD/hooks" echo test |${LB_BINARY} insert keys/k2/t2/one echo ${LB_BINARY} ls @@ -155,34 +155,34 @@ printf "%-10s ... " "$1" # rekeying REKEY_ARGS="" NEWKEY="newkey$1" - export LOCKBOX_HOOKDIR="" - if [ -n "$LOCKBOX_KEYFILE" ]; then + export LOCKBOX_HOOKS_DIRECTORY="" + if [ -n "$LOCKBOX_CREDENTIALS_KEY_FILE" ]; then REKEYFILE="$DATA/newkeyfile" REKEY_ARGS="-keyfile $REKEYFILE" echo "thisisanewkey" > "$REKEYFILE" - if [ -z "$LOCKBOX_KEY" ]; then + if [ -z "$LOCKBOX_CREDENTIALS_PASSWORD" ]; then REKEY_ARGS="$REKEY_ARGS -nokey" NEWKEY="" fi fi # shellcheck disable=SC2086 echo "$NEWKEY" | ${LB_BINARY} rekey $REKEY_ARGS - export LOCKBOX_KEY="$NEWKEY" - export LOCKBOX_KEYFILE="$REKEYFILE" + export LOCKBOX_CREDENTIALS_PASSWORD="$NEWKEY" + export LOCKBOX_CREDENTIALS_KEY_FILE="$REKEYFILE" echo ${LB_BINARY} ls ${LB_BINARY} show keys/k/one2 - export LOCKBOX_JSON_DATA=plaintext + export LOCKBOX_JSON_MODE=plaintext ${LB_BINARY} json k - export LOCKBOX_JSON_DATA=empty + export LOCKBOX_JSON_MODE=empty ${LB_BINARY} json k - export LOCKBOX_JSON_DATA=hash - export LOCKBOX_JSON_DATA_HASH_LENGTH=3 + export LOCKBOX_JSON_MODE=hash + export LOCKBOX_JSON_HASH_LENGTH=3 ${LB_BINARY} json k # clipboard - export LOCKBOX_CLIP_COPY="touch $CLIP_COPY" - export LOCKBOX_CLIP_PASTE="touch $CLIP_PASTE" - export LOCKBOX_CLIP_MAX=5 + export LOCKBOX_CLIP_COPY_COMMAND="touch $CLIP_COPY" + export LOCKBOX_CLIP_PASTE_COMMAND="touch $CLIP_PASTE" + export LOCKBOX_CLIP_TIMEOUT=5 ${LB_BINARY} clip keys/k/one2 CLIP_PASSED=0 while [ "$CLIP_TRIES" -gt 0 ] ; do @@ -197,26 +197,26 @@ printf "%-10s ... " "$1" echo "clipboard test failed" fi # invalid settings - OLDKEY="$LOCKBOX_KEY" - OLDMODE="$LOCKBOX_KEYMODE" - OLDKEYFILE="$LOCKBOX_KEYFILE" - if [ -n "$LOCKBOX_KEYFILE" ]; then - export LOCKBOX_KEYFILE="" - if [ -z "$LOCKBOX_KEY" ]; then - export LOCKBOX_KEY="garbage" + OLDKEY="$LOCKBOX_CREDENTIALS_PASSWORD" + OLDMODE="$LOCKBOX_CREDENTIALS_PASSWORD_MODE" + OLDKEYFILE="$LOCKBOX_CREDENTIALS_KEY_FILE" + if [ -n "$LOCKBOX_CREDENTIALS_KEY_FILE" ]; then + export LOCKBOX_CREDENTIALS_KEY_FILE="" + if [ -z "$LOCKBOX_CREDENTIALS_PASSWORD" ]; then + export LOCKBOX_CREDENTIALS_PASSWORD="garbage" fi else KEYFILE="$DATA/invalid.key" echo "invalid" > "$KEYFILE" - export LOCKBOX_KEYFILE="$KEYFILE" + export LOCKBOX_CREDENTIALS_KEY_FILE="$KEYFILE" fi if [ "$OLDMODE" = "none" ]; then - export LOCKBOX_KEYMODE="plaintext" + export LOCKBOX_CREDENTIALS_PASSWORD_MODE="plaintext" fi ${LB_BINARY} ls - export LOCKBOX_KEYFILE="$OLDKEYFILE" - export LOCKBOX_KEY="$OLDKEY" - export LOCKBOX_KEYMODE="$OLDMODE" + export LOCKBOX_CREDENTIALS_KEY_FILE="$OLDKEYFILE" + export LOCKBOX_CREDENTIALS_PASSWORD="$OLDKEY" + export LOCKBOX_CREDENTIALS_PASSWORD_MODE="$OLDMODE" # configuration { cat << EOF @@ -224,18 +224,18 @@ store = "$LOCKBOX_STORE" interactive = false [clip] -copy_command = [$(echo "$LOCKBOX_CLIP_COPY" | sed 's/ /", "/g;s/^/"/g;s/$/"/g')] -copy_command = [$(echo "$LOCKBOX_CLIP_PASTE" | sed 's/ /", "/g;s/^/"/g;s/$/"/g')] -timeout = $LOCKBOX_CLIP_MAX +copy_command = [$(echo "$LOCKBOX_CLIP_COPY_COMMAND" | sed 's/ /", "/g;s/^/"/g;s/$/"/g')] +copy_command = [$(echo "$LOCKBOX_CLIP_PASTE_COMMAND" | sed 's/ /", "/g;s/^/"/g;s/$/"/g')] +timeout = $LOCKBOX_CLIP_TIMEOUT [json] -mode = "$LOCKBOX_JSON_DATA" -hash_length = $LOCKBOX_JSON_DATA_HASH_LENGTH +mode = "$LOCKBOX_JSON_MODE" +hash_length = $LOCKBOX_JSON_HASH_LENGTH [credentials] -key_file = "$LOCKBOX_KEYFILE" -password_mode = "$LOCKBOX_KEYMODE" -password = "$LOCKBOX_KEY" +key_file = "$LOCKBOX_CREDENTIALS_KEY_FILE" +password_mode = "$LOCKBOX_CREDENTIALS_PASSWORD_MODE" +password = "$LOCKBOX_CREDENTIALS_PASSWORD" EOF } > "$TOML" _unset