feat(vault-tui): implement KV client and service for managing secrets
- Added internal/vault/client.go for creating a Vault client with configuration settings. - Introduced internal/vault/errors.go to classify Vault API errors for better UI handling. - Created internal/vault/kv.go to manage KV secrets, including listing, reading, writing, and deleting operations. - Implemented internal/vault/mounts.go to list and describe secret engine mounts. - Developed internal/vault/service.go to provide a unified entry point for Vault operations. - Added internal/vault/kv_test.go for comprehensive testing of KV operations. - Introduced internal/ui/toast.go for transient notifications in the UI. - Added renovate.json for dependency management and updates.
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
// Package keys defines the TUI's keybindings and how config.File's `keys:`
|
||||
// section can rebind them.
|
||||
package keys
|
||||
|
||||
import "charm.land/bubbles/v2/key"
|
||||
|
||||
// KeyMap holds every action the TUI's root Update dispatches on. Screens
|
||||
// consult the same KeyMap so a rebind in config.yaml takes effect
|
||||
// everywhere at once.
|
||||
type KeyMap struct {
|
||||
Up, Down key.Binding
|
||||
Top, Bottom key.Binding
|
||||
Enter, Back key.Binding
|
||||
Refresh key.Binding
|
||||
Filter key.Binding
|
||||
Palette key.Binding
|
||||
ToggleMask key.Binding
|
||||
ToggleMaskAll key.Binding
|
||||
CopyValue key.Binding
|
||||
Versions key.Binding
|
||||
Rollback key.Binding
|
||||
Undelete key.Binding
|
||||
New, Edit key.Binding
|
||||
Save, Cancel key.Binding
|
||||
AddField key.Binding
|
||||
DeleteField key.Binding
|
||||
Delete, Destroy key.Binding
|
||||
Profiles key.Binding
|
||||
Logout key.Binding
|
||||
Help, Quit key.Binding
|
||||
ForceQuit key.Binding
|
||||
}
|
||||
|
||||
// Default returns the built-in vim-flavoured keymap.
|
||||
func Default() *KeyMap {
|
||||
return &KeyMap{
|
||||
Up: key.NewBinding(key.WithKeys("k", "up"), key.WithHelp("k/↑", "up")),
|
||||
Down: key.NewBinding(key.WithKeys("j", "down"), key.WithHelp("j/↓", "down")),
|
||||
Top: key.NewBinding(key.WithKeys("g", "home"), key.WithHelp("g", "top")),
|
||||
Bottom: key.NewBinding(key.WithKeys("G", "end"), key.WithHelp("G", "bottom")),
|
||||
Enter: key.NewBinding(key.WithKeys("enter", "l"), key.WithHelp("↵", "open")),
|
||||
Back: key.NewBinding(key.WithKeys("esc", "h"), key.WithHelp("esc", "back")),
|
||||
Refresh: key.NewBinding(key.WithKeys("r"), key.WithHelp("r", "refresh")),
|
||||
Filter: key.NewBinding(key.WithKeys("/"), key.WithHelp("/", "filter")),
|
||||
Palette: key.NewBinding(key.WithKeys(":"), key.WithHelp(":", "goto path")),
|
||||
ToggleMask: key.NewBinding(key.WithKeys("s"), key.WithHelp("s", "show/hide value")),
|
||||
ToggleMaskAll: key.NewBinding(key.WithKeys("S"), key.WithHelp("S", "show/hide all")),
|
||||
CopyValue: key.NewBinding(key.WithKeys("y"), key.WithHelp("y", "copy value")),
|
||||
Versions: key.NewBinding(key.WithKeys("V"), key.WithHelp("V", "versions")),
|
||||
Rollback: key.NewBinding(key.WithKeys("R"), key.WithHelp("R", "rollback to this version")),
|
||||
Undelete: key.NewBinding(key.WithKeys("u"), key.WithHelp("u", "undelete this version")),
|
||||
New: key.NewBinding(key.WithKeys("n"), key.WithHelp("n", "new secret")),
|
||||
Edit: key.NewBinding(key.WithKeys("e"), key.WithHelp("e", "edit")),
|
||||
Save: key.NewBinding(key.WithKeys("ctrl+s"), key.WithHelp("^s", "save")),
|
||||
Cancel: key.NewBinding(key.WithKeys("esc"), key.WithHelp("esc", "cancel")),
|
||||
AddField: key.NewBinding(key.WithKeys("ctrl+a"), key.WithHelp("^a", "add field")),
|
||||
DeleteField: key.NewBinding(key.WithKeys("ctrl+x"), key.WithHelp("^x", "remove field")),
|
||||
Delete: key.NewBinding(key.WithKeys("d"), key.WithHelp("d", "delete")),
|
||||
Destroy: key.NewBinding(key.WithKeys("D"), key.WithHelp("D", "destroy")),
|
||||
Profiles: key.NewBinding(key.WithKeys("p"), key.WithHelp("p", "switch profile")),
|
||||
Logout: key.NewBinding(key.WithKeys("ctrl+l"), key.WithHelp("^l", "logout")),
|
||||
Help: key.NewBinding(key.WithKeys("?"), key.WithHelp("?", "help")),
|
||||
Quit: key.NewBinding(key.WithKeys("q"), key.WithHelp("q", "quit")),
|
||||
ForceQuit: key.NewBinding(key.WithKeys("ctrl+c"), key.WithHelp("^c", "quit")),
|
||||
}
|
||||
}
|
||||
|
||||
func (k *KeyMap) registry() map[string]*key.Binding {
|
||||
return map[string]*key.Binding{
|
||||
"up": &k.Up, "down": &k.Down, "top": &k.Top, "bottom": &k.Bottom,
|
||||
"enter": &k.Enter, "back": &k.Back, "refresh": &k.Refresh, "filter": &k.Filter,
|
||||
"palette": &k.Palette, "toggle_mask": &k.ToggleMask, "toggle_mask_all": &k.ToggleMaskAll,
|
||||
"copy_value": &k.CopyValue, "versions": &k.Versions, "rollback": &k.Rollback,
|
||||
"undelete": &k.Undelete, "new": &k.New, "edit": &k.Edit, "save": &k.Save,
|
||||
"cancel": &k.Cancel, "add_field": &k.AddField, "delete_field": &k.DeleteField,
|
||||
"delete": &k.Delete, "destroy": &k.Destroy, "profiles": &k.Profiles, "logout": &k.Logout,
|
||||
"help": &k.Help, "quit": &k.Quit, "force_quit": &k.ForceQuit,
|
||||
}
|
||||
}
|
||||
|
||||
// Apply overrides the defaults from config.File's `keys:` map. An unknown
|
||||
// action name is a startup error, not a silently ignored typo.
|
||||
func (k *KeyMap) Apply(cfg map[string][]string) error {
|
||||
reg := k.registry()
|
||||
for action, keyStrs := range cfg {
|
||||
b, ok := reg[action]
|
||||
if !ok {
|
||||
return unknownActionError(action)
|
||||
}
|
||||
*b = key.NewBinding(key.WithKeys(keyStrs...), key.WithHelp(b.Help().Key, b.Help().Desc))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type unknownActionError string
|
||||
|
||||
func (e unknownActionError) Error() string {
|
||||
return "unknown keybinding action " + string(e) + " in config `keys:` section"
|
||||
}
|
||||
|
||||
// DisableWrites turns off every write-capable binding — the UI-side half of
|
||||
// read-only enforcement (the real guard is vault.KV.ReadOnly).
|
||||
func (k *KeyMap) DisableWrites() {
|
||||
for _, b := range []*key.Binding{
|
||||
&k.New, &k.Edit, &k.Save, &k.AddField, &k.DeleteField,
|
||||
&k.Delete, &k.Destroy, &k.Rollback, &k.Undelete,
|
||||
} {
|
||||
b.SetEnabled(false)
|
||||
}
|
||||
}
|
||||
|
||||
// ShortHelp/FullHelp implement help.KeyMap for the global bindings and
|
||||
// back the "?" help overlay (screen_help.go). Individual screens' footers
|
||||
// use the narrower, screen-specific views in help.go instead.
|
||||
func (k *KeyMap) ShortHelp() []key.Binding {
|
||||
return []key.Binding{k.Up, k.Down, k.Enter, k.Back, k.Help, k.Quit}
|
||||
}
|
||||
|
||||
func (k *KeyMap) FullHelp() [][]key.Binding {
|
||||
return [][]key.Binding{
|
||||
{k.Up, k.Down, k.Top, k.Bottom, k.Enter, k.Back},
|
||||
{k.Refresh, k.Filter, k.Palette, k.ToggleMask, k.ToggleMaskAll, k.CopyValue},
|
||||
{k.Versions, k.Rollback, k.Undelete, k.New, k.Edit, k.Save},
|
||||
{k.Cancel, k.AddField, k.DeleteField, k.Delete, k.Destroy},
|
||||
{k.Profiles, k.Logout, k.Help, k.Quit, k.ForceQuit},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user