lockbox

password manager
Log | Files | Refs | README | LICENSE

commit 3a20266324068de66972ca077bc95b35d92e6443
parent 75f9685e2706574beb471606eb40bcb7c9cb022e
Author: Sean Enck <sean@ttypty.com>
Date:   Thu, 30 Mar 2023 20:44:09 -0400

better output handling for json dumps

Diffstat:
Minternal/app/conv.go | 14++++++++++----
Minternal/app/json.go | 8+++++++-
Minternal/app/rekey.go | 14+++++++-------
Minternal/app/rekey_test.go | 17++++++++++-------
Minternal/backend/query.go | 4++--
Minternal/backend/query_test.go | 2+-
Minternal/backend/types.go | 1-
Mtests/expected.log | 66+++++++++++++++++++++++++++++-------------------------------------
8 files changed, 66 insertions(+), 60 deletions(-)

diff --git a/internal/app/conv.go b/internal/app/conv.go @@ -1,6 +1,8 @@ package app import ( + "bytes" + "encoding/json" "errors" "fmt" "io" @@ -32,13 +34,17 @@ func serialize(w io.Writer, tx *backend.Transaction) error { if err != nil { return err } - fmt.Fprintf(w, "[") + fmt.Fprint(w, "{\n") for idx, item := range e { if idx > 0 { - fmt.Fprint(w, ",") + fmt.Fprintf(w, ",\n") } - fmt.Fprintf(w, "\n%s\n", item.Value) + var buf bytes.Buffer + if err := json.Indent(&buf, []byte(item.Value), " ", " "); err != nil { + return err + } + fmt.Fprintf(w, " \"%s\": %s\n", item.Path, buf.String()) } - fmt.Fprintf(w, "]") + fmt.Fprintf(w, "}") return nil } diff --git a/internal/app/json.go b/internal/app/json.go @@ -2,6 +2,8 @@ package app import ( + "bytes" + "encoding/json" "errors" "fmt" @@ -23,7 +25,11 @@ func JSON(cmd CommandOptions) error { return fmt.Errorf("unable to get json: %w", err) } if v != nil { - fmt.Fprintln(cmd.Writer(), v.Value) + var buf bytes.Buffer + if err := json.Indent(&buf, []byte(v.Value), "", " "); err != nil { + return err + } + fmt.Fprintln(cmd.Writer(), buf.String()) } return nil } diff --git a/internal/app/rekey.go b/internal/app/rekey.go @@ -17,7 +17,7 @@ import ( type ( // Keyer defines how rekeying happens Keyer interface { - JSON() ([]backend.JSON, error) + JSON() (map[string]backend.JSON, error) Show(string) ([]byte, error) Insert(ReKeyEntry) error } @@ -48,12 +48,12 @@ func (r DefaultKeyer) Show(entry string) ([]byte, error) { } // JSON will get the JSON backing entries -func (r DefaultKeyer) JSON() ([]backend.JSON, error) { +func (r DefaultKeyer) JSON() (map[string]backend.JSON, error) { out, err := exec.Command(r.exe, cli.JSONCommand).Output() if err != nil { return nil, err } - var j []backend.JSON + var j map[string]backend.JSON if err := json.Unmarshal(out, &j); err != nil { return nil, err } @@ -87,22 +87,22 @@ func ReKey(writer io.Writer, r Keyer) error { if err != nil { return err } - for _, entry := range entries { - if _, err := fmt.Fprintf(writer, "rekeying: %s\n", entry.Path); err != nil { + for path, entry := range entries { + if _, err := fmt.Fprintf(writer, "rekeying: %s\n", path); err != nil { return err } modTime := strings.TrimSpace(entry.ModTime) if modTime == "" { return errors.New("did not read modtime") } - data, err := r.Show(entry.Path) + data, err := r.Show(path) if err != nil { return err } var insertEnv []string insertEnv = append(insertEnv, env...) insertEnv = append(insertEnv, fmt.Sprintf("%s=%s", inputs.ModTimeEnv, modTime)) - if err := r.Insert(ReKeyEntry{Path: entry.Path, Env: insertEnv, Data: data}); err != nil { + if err := r.Insert(ReKeyEntry{Path: path, Env: insertEnv, Data: data}); err != nil { return err } } diff --git a/internal/app/rekey_test.go b/internal/app/rekey_test.go @@ -16,11 +16,11 @@ type ( data map[string][]byte err error rekeys []app.ReKeyEntry - items []backend.JSON + items map[string]backend.JSON } ) -func (m *mockKeyer) JSON() ([]backend.JSON, error) { +func (m *mockKeyer) JSON() (map[string]backend.JSON, error) { if m.err != nil { return nil, m.err } @@ -57,18 +57,18 @@ func TestErrors(t *testing.T) { t.Errorf("invalid error: %v", err) } m.err = nil - m.items = []backend.JSON{{Path: "test1", ModTime: ""}} + m.items = map[string]backend.JSON{"test": {ModTime: ""}} if err := app.ReKey(&buf, m); err == nil || err.Error() != "did not read modtime" { t.Errorf("invalid error: %v", err) } - m.items = []backend.JSON{{Path: "test1", ModTime: "2"}} + m.items = map[string]backend.JSON{"test1": {ModTime: "2"}} if err := app.ReKey(&buf, m); err == nil || err.Error() != "no data" { t.Errorf("invalid error: %v", err) } m.data = make(map[string][]byte) m.data["test1"] = []byte{1} m.data["error"] = []byte{2} - m.items = []backend.JSON{{Path: "error", ModTime: "2"}} + m.items = map[string]backend.JSON{"error": {ModTime: "2"}} if err := app.ReKey(&buf, m); err == nil || err.Error() != "bad insert" { t.Errorf("invalid error: %v", err) } @@ -84,7 +84,10 @@ func TestReKey(t *testing.T) { t.Error("no data") } m := &mockKeyer{} - m.items = []backend.JSON{{Path: "test1", ModTime: "2"}, {Path: "test1", ModTime: "2"}} + m.items = map[string]backend.JSON{ + "test1": {ModTime: "1"}, + "test2": {ModTime: "2"}, + } m.data = make(map[string][]byte) m.data["test1"] = []byte{1} m.data["test2"] = []byte{2} @@ -97,7 +100,7 @@ func TestReKey(t *testing.T) { if len(m.rekeys) != 2 { t.Error("invalid rekeys") } - if fmt.Sprintf("%v", m.rekeys) != `[{test1 [LOCKBOX_KEYMODE= LOCKBOX_KEY=abc LOCKBOX_KEYFILE= LOCKBOX_STORE=store LOCKBOX_SET_MODTIME=2] [1]} {test1 [LOCKBOX_KEYMODE= LOCKBOX_KEY=abc LOCKBOX_KEYFILE= LOCKBOX_STORE=store LOCKBOX_SET_MODTIME=2] [1]}]` { + if fmt.Sprintf("%v", m.rekeys) != `[{test1 [LOCKBOX_KEYMODE= LOCKBOX_KEY=abc LOCKBOX_KEYFILE= LOCKBOX_STORE=store LOCKBOX_SET_MODTIME=1] [1]} {test2 [LOCKBOX_KEYMODE= LOCKBOX_KEY=abc LOCKBOX_KEYFILE= LOCKBOX_STORE=store LOCKBOX_SET_MODTIME=2] [2]}]` { t.Errorf("invalid results: %v", m.rekeys) } } diff --git a/internal/backend/query.go b/internal/backend/query.go @@ -132,8 +132,8 @@ func (t *Transaction) QueryCallback(args QueryOptions) ([]QueryEntity, error) { switch args.Values { case JSONValue: t := getValue(e.backing, modTimeKey) - s := JSON{Path: k, ModTime: t, Hash: fmt.Sprintf("%x", sha512.Sum512([]byte(val)))} - m, err := json.MarshalIndent(s, "", " ") + s := JSON{ModTime: t, Hash: fmt.Sprintf("%x", sha512.Sum512([]byte(val)))} + m, err := json.Marshal(s) if err != nil { return nil, err } diff --git a/internal/backend/query_test.go b/internal/backend/query_test.go @@ -111,7 +111,7 @@ func TestValueModes(t *testing.T) { if err := json.Unmarshal([]byte(q.Value), &m); err != nil { t.Errorf("no error: %v", err) } - if len(m.ModTime) < 20 || m.Path != "test/test/abc" { + if len(m.ModTime) < 20 || m.Hash == "" { t.Errorf("invalid json: %v", m) } } diff --git a/internal/backend/types.go b/internal/backend/types.go @@ -55,7 +55,6 @@ type ( } // JSON is an entry as a JSON string JSON struct { - Path string `json:"path"` ModTime string `json:"modtime"` Hash string `json:"hash"` } diff --git a/tests/expected.log b/tests/expected.log @@ -12,30 +12,26 @@ keys2/k/three key/a/one keys/k/one2 keys2/k/three -[ { - "path": "key/a/one", - "modtime": "XXXX-XX-XX", - "hash": "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff" -} + "key/a/one": { + "modtime": "XXXX-XX-XX", + "hash": "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff" + } , -{ - "path": "keys/k/one2", - "modtime": "XXXX-XX-XX", - "hash": "6d201beeefb589b08ef0672dac82353d0cbd9ad99e1642c83a1601f3d647bcca003257b5e8f31bdc1d73fbec84fb085c79d6e2677b7ff927e823a54e789140d9" -} + "keys/k/one2": { + "modtime": "XXXX-XX-XX", + "hash": "6d201beeefb589b08ef0672dac82353d0cbd9ad99e1642c83a1601f3d647bcca003257b5e8f31bdc1d73fbec84fb085c79d6e2677b7ff927e823a54e789140d9" + } , -{ - "path": "keys2/k/three", - "modtime": "XXXX-XX-XX", - "hash": "132ab0244293c495a027cec12d0050598616daca888449920fc652719be0987830827d069ef78cc613e348de37c9b592d3406e2fb8d99a6961bf0c58da8a334f" + "keys2/k/three": { + "modtime": "XXXX-XX-XX", + "hash": "132ab0244293c495a027cec12d0050598616daca888449920fc652719be0987830827d069ef78cc613e348de37c9b592d3406e2fb8d99a6961bf0c58da8a334f" + } } -] test2 test3 test4 { - "path": "keys2/k/three", "modtime": "XXXX-XX-XX", "hash": "132ab0244293c495a027cec12d0050598616daca888449920fc652719be0987830827d069ef78cc613e348de37c9b592d3406e2fb8d99a6961bf0c58da8a334f" } @@ -44,31 +40,27 @@ test/k XXXXXX XXXXXX XXXXXX -[ { - "path": "key/a/one", - "modtime": "XXXX-XX-XX", - "hash": "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff" -} + "key/a/one": { + "modtime": "XXXX-XX-XX", + "hash": "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff" + } , -{ - "path": "keys/k/one2", - "modtime": "XXXX-XX-XX", - "hash": "6d201beeefb589b08ef0672dac82353d0cbd9ad99e1642c83a1601f3d647bcca003257b5e8f31bdc1d73fbec84fb085c79d6e2677b7ff927e823a54e789140d9" -} + "keys/k/one2": { + "modtime": "XXXX-XX-XX", + "hash": "6d201beeefb589b08ef0672dac82353d0cbd9ad99e1642c83a1601f3d647bcca003257b5e8f31bdc1d73fbec84fb085c79d6e2677b7ff927e823a54e789140d9" + } , -{ - "path": "keys2/k/three", - "modtime": "XXXX-XX-XX", - "hash": "132ab0244293c495a027cec12d0050598616daca888449920fc652719be0987830827d069ef78cc613e348de37c9b592d3406e2fb8d99a6961bf0c58da8a334f" -} + "keys2/k/three": { + "modtime": "XXXX-XX-XX", + "hash": "132ab0244293c495a027cec12d0050598616daca888449920fc652719be0987830827d069ef78cc613e348de37c9b592d3406e2fb8d99a6961bf0c58da8a334f" + } , -{ - "path": "test/k/totp", - "modtime": "XXXX-XX-XX", - "hash": "7ef183065ba70aaa417b87ea0a96b7e550a938a52440c640a07537f7794d8a89e50078eca6a7cbcfacabd97a2db06d11e82ddf7556ca909c4df9fc0d006013b1" -} -]delete entry? (y/N) + "test/k/totp": { + "modtime": "XXXX-XX-XX", + "hash": "7ef183065ba70aaa417b87ea0a96b7e550a938a52440c640a07537f7794d8a89e50078eca6a7cbcfacabd97a2db06d11e82ddf7556ca909c4df9fc0d006013b1" + } +}delete entry? (y/N) delete entry? (y/N) delete entry? (y/N) unable to remove: no entities given