lockbox

password manager
Log | Files | Refs | README | LICENSE

commit a153cb24ab6bdca9d949fefbacdcae4467fc63d0
parent d84bc870a1f56c347517d8e57247f1b9daf44a1d
Author: Sean Enck <sean@ttypty.com>
Date:   Sat,  4 Mar 2023 07:04:57 -0500

require insert -totp for inserting totp tokens

Diffstat:
Mcmd/main.go | 7++++---
Minternal/app/core.go | 15---------------
Minternal/app/insert.go | 58+++++++++++++++++++++++++++++++++++++++++++---------------
Minternal/app/insert_test.go | 44+++++++++++++++++++++++++++++++++++++++-----
Mscripts/testing/check.go | 2--
Mscripts/testing/expected.log | 1-
6 files changed, 86 insertions(+), 41 deletions(-)

diff --git a/cmd/main.go b/cmd/main.go @@ -79,12 +79,13 @@ func run() error { return app.Move(t, sub, confirm) case cli.InsertCommand: insert := app.InsertOptions{} + parser := app.InsertArgsOptions{} + parser.IsNoTOTP = inputs.IsNoTOTP + parser.TOTPToken = inputs.TOTPToken insert.Confirm = confirm insert.IsPipe = inputs.IsInputFromPipe - insert.IsNoTOTP = inputs.IsNoTOTP - insert.TOTPToken = inputs.TOTPToken insert.Input = inputs.GetUserInputPassword - insertArgs, err := app.ParseInsertArgs(insert, sub) + insertArgs, err := parser.ReadArgs(insert, sub) if err != nil { return err } diff --git a/internal/app/core.go b/internal/app/core.go @@ -4,19 +4,4 @@ package app type ( // Confirm user inputs Confirm func(string) bool - // InsertOptions are functions required for insert - InsertOptions struct { - IsNoTOTP func() (bool, error) - IsPipe func() bool - TOTPToken func() string - Input func(bool, bool) ([]byte, error) - Confirm Confirm - } - // InsertArgs are parsed insert settings for insert commands - InsertArgs struct { - Entry string - Multi bool - TOTP bool - Opts InsertOptions - } ) diff --git a/internal/app/insert.go b/internal/app/insert.go @@ -12,15 +12,39 @@ import ( "github.com/enckse/lockbox/internal/totp" ) +type ( + // InsertOptions are functions required for insert + InsertOptions struct { + IsPipe func() bool + Input func(bool, bool) ([]byte, error) + Confirm Confirm + } + // InsertArgsOptions supports cli arg parsing + InsertArgsOptions struct { + TOTPToken func() string + IsNoTOTP func() (bool, error) + } + // InsertArgs are parsed insert settings for insert commands + InsertArgs struct { + Entry string + Multi bool + Opts InsertOptions + } +) + func insertError(message string, err error) error { return fmt.Errorf("%s (%w)", message, err) } -// ParseInsertArgs will parse the input args for insert commands -func ParseInsertArgs(cmd InsertOptions, args []string) (InsertArgs, error) { +// ReadArgs will read and check insert args +func (p InsertArgsOptions) ReadArgs(cmd InsertOptions, args []string) (InsertArgs, error) { multi := false isTOTP := false idx := 0 + noTOTP, err := p.IsNoTOTP() + if err != nil { + return InsertArgs{}, err + } switch len(args) { case 0: return InsertArgs{}, errors.New("insert requires an entry") @@ -31,33 +55,37 @@ func ParseInsertArgs(cmd InsertOptions, args []string) (InsertArgs, error) { case cli.InsertMultiCommand: multi = true case cli.InsertTOTPCommand: - off, err := cmd.IsNoTOTP() - if err != nil { - return InsertArgs{}, err - } - if off { + if noTOTP { return InsertArgs{}, totp.ErrNoTOTP } isTOTP = true default: return InsertArgs{}, errors.New("unknown argument") } - multi = true idx = 1 default: return InsertArgs{}, errors.New("too many arguments") } - return InsertArgs{Opts: cmd, Multi: multi, TOTP: isTOTP, Entry: args[idx]}, nil + entry := args[idx] + if !noTOTP { + totpToken := p.TOTPToken() + hasSuffixTOTP := strings.HasSuffix(entry, backend.NewSuffix(totpToken)) + if isTOTP { + if !hasSuffixTOTP { + entry = backend.NewPath(entry, totpToken) + } + } else { + if hasSuffixTOTP { + return InsertArgs{}, errors.New("can not insert totp entry without totp flag") + } + } + + } + return InsertArgs{Opts: cmd, Multi: multi, Entry: entry}, nil } // Do will execute an insert func (args InsertArgs) Do(w io.Writer, t *backend.Transaction) error { - if args.TOTP { - totpToken := args.Opts.TOTPToken() - if !strings.HasSuffix(args.Entry, backend.NewSuffix(totpToken)) { - args.Entry = backend.NewPath(args.Entry, totpToken) - } - } existing, err := t.Get(args.Entry, backend.BlankValue) if err != nil { return insertError("unable to check for existing entry", err) diff --git a/internal/app/insert_test.go b/internal/app/insert_test.go @@ -11,29 +11,63 @@ import ( func TestInsertArgs(t *testing.T) { obj := app.InsertOptions{} - if _, err := app.ParseInsertArgs(obj, []string{}); err == nil || err.Error() != "insert requires an entry" { + p := app.InsertArgsOptions{} + p.IsNoTOTP = func() (bool, error) { + return true, nil + } + if _, err := p.ReadArgs(obj, []string{}); err == nil || err.Error() != "insert requires an entry" { t.Errorf("invalid error: %v", err) } - if _, err := app.ParseInsertArgs(obj, []string{"test", "test", "test"}); err == nil || err.Error() != "too many arguments" { + if _, err := p.ReadArgs(obj, []string{"test", "test", "test"}); err == nil || err.Error() != "too many arguments" { t.Errorf("invalid error: %v", err) } - r, err := app.ParseInsertArgs(obj, []string{"test"}) + r, err := p.ReadArgs(obj, []string{"test"}) if err != nil { t.Errorf("invalid error: %v", err) } if r.Multi || r.Entry != "test" { t.Error("invalid parse") } - if _, err := app.ParseInsertArgs(obj, []string{"-t", "b"}); err == nil || err.Error() != "unknown argument" { + if _, err := p.ReadArgs(obj, []string{"-t", "b"}); err == nil || err.Error() != "unknown argument" { t.Errorf("invalid error: %v", err) } - r, err = app.ParseInsertArgs(obj, []string{"-multi", "test3"}) + r, err = p.ReadArgs(obj, []string{"-multi", "test3"}) if err != nil { t.Errorf("invalid error: %v", err) } if !r.Multi || r.Entry != "test3" { t.Error("invalid parse") } + p.TOTPToken = func() string { + return "test3" + } + r, err = p.ReadArgs(obj, []string{"-multi", "test/test3"}) + if err != nil { + t.Errorf("invalid error: %v", err) + } + p.IsNoTOTP = func() (bool, error) { + return false, nil + } + if _, err := p.ReadArgs(obj, []string{"-multi", "test/test3"}); err == nil || err.Error() != "can not insert totp entry without totp flag" { + t.Errorf("invalid error: %v", err) + } + if _, err := p.ReadArgs(obj, []string{"test/test3"}); err == nil || err.Error() != "can not insert totp entry without totp flag" { + t.Errorf("invalid error: %v", err) + } + r, err = p.ReadArgs(obj, []string{"-totp", "test/test3"}) + if err != nil { + t.Errorf("invalid error: %v", err) + } + if r.Entry != "test/test3" { + t.Error("invalid parse") + } + r, err = p.ReadArgs(obj, []string{"-totp", "test"}) + if err != nil { + t.Errorf("invalid error: %v", err) + } + if r.Entry != "test/test3" { + t.Error("invalid parse") + } } func TestInsertDo(t *testing.T) { diff --git a/scripts/testing/check.go b/scripts/testing/check.go @@ -153,8 +153,6 @@ func execute() error { runCommand([]string{"insert", "-totp", k}, []string{"5ae472abqdekjqykoyxk7hvc2leklq5n"}) } totpList() - insert("test/k/totp", []string{"5ae472abqdekjqykoyxk7hvc2leklq5n"}) - totpList() runCommand([]string{"totp", "test/k"}, nil) runCommand([]string{"hash", store}, nil) rm("keys2/k/three") diff --git a/scripts/testing/expected.log b/scripts/testing/expected.log @@ -20,7 +20,6 @@ test3 test4 modtime: XXXX-XX-XX test/k -test/k XXXXXX key/a/one: modtime: XXXX-XX-XX