feat: lazysecrets list prints everything lazysecrets can find, for fzf and editor pickers (#70)
`lazysecrets list` prints every source, vault and secret lazysecrets can find, one per line, for fzf, editor pickers and scripts: what Go to searches, without the TUI. What's cached prints at once; what's missing or older than `--max-age` loads in the background and streams in. It stops when the reader goes (a pick in fzf), saving what it loaded. - Text: kind, mark (✗/⚠, ★, ◷ and the provider icon), name, status (why it couldn't be read, or expired / expires in 12d), note, account and link, tab-separated; kind first and account and link last, so new fields go between. Coloured from the theme; `--color never`, `--icons=false`, `--stars=false`, `--recent`, `--notes=false`, `--expiry=false`. - `--format json`: an object per line, with starred, recent, lastUsed and uses, expires, enabled, note, reference and url too. - `--kind` lists only some kinds, and doesn't load lists only other kinds need; `--cached` loads nothing. - `lazysecrets open --action go|copy|show` skips the "what to do" menu and ends in the list, like Go to; `open` and `get` take `--account`, the account list printed, rather than asking which. - The cache file moved to `internal/cachefile`: saves merge with the file under a lock, so list and the TUI don't undo each other. - `ui.recentIcon` marks items used lately with ◷ in the TUI's lists too; Recent now means the last 90 days. - --demo has stars, notes, recent use, and expired, expiring and disabled secrets. - docs/integration.md documents get, list and an fzf picker; docs/links.md is docs/sharing.md. Reviewed-on: #70 Co-authored-by: Karl-Einar Bergstrøm <karl-einarb@outlook.com>
This commit was merged in pull request #70.
This commit is contained in:
1 parent
dbb0eb2bbd
commit
39454d47a8
45 files changed
+2107
-222
No files matched your search
@@ -0,0 +1,122 @@
|
||||
package cachefile
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.kebcloud.no/keb/lazysecrets/internal/provider"
|
||||
)
|
||||
|
||||
func list(at time.Time, names ...string) Stamped[[]provider.Container] {
|
||||
var cs []provider.Container
|
||||
for _, n := range names {
|
||||
cs = append(cs, provider.Container{Name: n})
|
||||
}
|
||||
return Stamped[[]provider.Container]{At: at, Value: cs}
|
||||
}
|
||||
|
||||
func TestSaveMerges(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "cache.json")
|
||||
now := time.Now()
|
||||
all := func(string) bool { return true }
|
||||
|
||||
// The TUI saved two lists.
|
||||
tui := New()
|
||||
tui.Containers["az|a"] = list(now.Add(-time.Hour), "kv-a-old")
|
||||
tui.Containers["az|b"] = list(now.Add(-time.Minute), "kv-b")
|
||||
tui.Cursor["az|b"] = "kv-b"
|
||||
if err := Save(path, tui, all, now); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// lazysecrets list loads a again, and c.
|
||||
listed := Read(path)
|
||||
listed.Containers["az|a"] = list(now, "kv-a-new")
|
||||
listed.Containers["az|c"] = list(now, "kv-c")
|
||||
if err := Save(path, listed, all, now); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// The TUI saves what it has, older: list's lists stay.
|
||||
if err := Save(path, tui, all, now); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f := Read(path)
|
||||
for key, want := range map[string]string{"az|a": "kv-a-new", "az|b": "kv-b", "az|c": "kv-c"} {
|
||||
if got := f.Containers[key].Value; len(got) != 1 || got[0].Name != want {
|
||||
t.Errorf("%s = %v, want %s", key, got, want)
|
||||
}
|
||||
}
|
||||
if f.Cursor["az|b"] != "kv-b" {
|
||||
t.Error("cursor lost")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSaveDrops(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "cache.json")
|
||||
now := time.Now()
|
||||
f := New()
|
||||
f.Containers["az|old"] = list(now.Add(-MaxAge-time.Hour), "kv-old")
|
||||
f.Containers["gone|x"] = list(now, "kv-gone")
|
||||
f.Containers["az|x"] = list(now, "kv-x")
|
||||
if err := Save(path, f, func(id string) bool { return true }, now); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Signed out of "gone" since: dropped from the file too.
|
||||
if err := Save(path, New(), func(id string) bool { return id == "az" }, now); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := Read(path).Containers
|
||||
if _, ok := got["az|old"]; ok {
|
||||
t.Error("kept a list older than MaxAge")
|
||||
}
|
||||
if _, ok := got["gone|x"]; ok {
|
||||
t.Error("kept a signed-out account's list")
|
||||
}
|
||||
if _, ok := got["az|x"]; !ok {
|
||||
t.Error("dropped a list on disk the save didn't have")
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadOtherVersion(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "cache.json")
|
||||
f := New()
|
||||
f.Version = Version + 1
|
||||
f.Containers["az|x"] = list(time.Now(), "kv-x")
|
||||
if err := write(path, f); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := Read(path); len(got.Containers) != 0 || got.Version != Version {
|
||||
t.Errorf("read another version's file: %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSaveDroppedAndCursors(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "cache.json")
|
||||
now := time.Now()
|
||||
all := func(string) bool { return true }
|
||||
f := New()
|
||||
f.Containers["az|bad"] = list(now, "kv-old")
|
||||
f.Cursor["az|x"] = "kv-tui"
|
||||
if err := Save(path, f, all, now); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// The TUI fails to load it again and drops it: it stays gone.
|
||||
f = New()
|
||||
f.Dropped = map[string]bool{"az|bad": true}
|
||||
if err := Save(path, f, all, now); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := Read(path).Containers["az|bad"]; ok {
|
||||
t.Error("a dropped list came back")
|
||||
}
|
||||
// lazysecrets list saves without cursors: the TUI's stay.
|
||||
listed := New()
|
||||
listed.Cursor = nil
|
||||
listed.Containers["az|y"] = list(now, "kv-y")
|
||||
if err := Save(path, listed, all, now); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if Read(path).Cursor["az|x"] != "kv-tui" {
|
||||
t.Error("the TUI's cursor was lost")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user