Skip to content

Commit

Permalink
Bug fixing and improvements for 0.0.3 (#4)
Browse files Browse the repository at this point in the history
* Changes

* Headscratcher

* v0.0.3 fixes
  • Loading branch information
dkyanakiev authored Nov 30, 2023
1 parent e1b67eb commit 53355a0
Show file tree
Hide file tree
Showing 28 changed files with 467 additions and 101 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Changelog

## [0.0.3] - 2023-11-30

### Added
- Job filtering on secrets and mount views
- Better navigation options between views
- `vaul7y -v` to check the version
- Added a check and error out to prevent vaul7y from freezing if vault token and address are not set

### Fixed
- Error and Info modals tabbing out and changing focus
- Enter key constantly moving you to the Secret Engines view. Its due to the way Unix system recognize Enter and Ctrl+M
- Fixed an issue with watcher causing conflicts
- Fixed logger to discard messages and not brake rendering when debugging is not enabled
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

local-vault:
vault server -dev

Expand Down
71 changes: 41 additions & 30 deletions cmd/vaul7y/main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package main

import (
"fmt"
"log"
"os"
"time"

"github.com/dkyanakiev/vaulty/component"
Expand All @@ -11,20 +13,41 @@ import (
"github.com/dkyanakiev/vaulty/view"
"github.com/dkyanakiev/vaulty/watcher"
"github.com/gdamore/tcell/v2"
"github.com/jessevdk/go-flags"
"github.com/rivo/tview"
)

var refreshIntervalDefault = time.Second * 5
var refreshIntervalDefault = time.Second * 30
var version = "0.0.3"

type options struct {
Version bool `short:"v" long:"version" description:"Show Damon version"`
}

func main() {

// Check for required Vault env vars
checkForVaultAddress()

var opts options
_, err := flags.ParseArgs(&opts, os.Args)
if err != nil {
os.Exit(1)
}

if opts.Version {
fmt.Println("vaul7y", version)
os.Exit(0)
}

logFile, logger := config.SetupLogger()
defer logFile.Close()
tview.Styles.PrimitiveBackgroundColor = tcell.NewRGBColor(40, 44, 48)

vaultClient, err := vault.New(func(v *vault.Vault) error {
return vault.Default(v, logger)
})

state := initializeState(vaultClient)
commands := component.NewCommands()
vaultInfo := component.NewVaultInfo()
Expand All @@ -33,7 +56,7 @@ func main() {
policyAcl := component.NewPolicyAclTable()
secrets := component.NewSecretsTable()
secretObj := component.NewSecretObjTable()
logo := component.NewLogo()
logo := component.NewLogo(version)
info := component.NewInfo()
failure := component.NewInfo()
errorComp := component.NewError()
Expand All @@ -53,8 +76,9 @@ func main() {
}
watcher := watcher.NewWatcher(state, vaultClient, refreshIntervalDefault, logger)
view := view.New(components, watcher, vaultClient, state, logger)
view.Init(version)

view.Init("0.0.1")
//view.Init("0.0.1")
err = view.Layout.Container.Run()
if err != nil {
log.Fatal("cannot initialize view.")
Expand All @@ -65,36 +89,23 @@ func main() {
func initializeState(client *vault.Vault) *state.State {
state := state.New()
addr := client.Address()
version, _ := client.Version()
state.VaultAddress = addr
state.VaultVersion = version
state.Namespace = "default"

return state
}

// // LOOK AT LATER
// func main() {
// vaultClient, _ := vault.New(vault.Default)
// //ctx := context.TODO()
// // mounts, _ := vaultClient.Sys.ListMounts()

// secret, _ := vaultClient.ListSecrets("kv0FF76557")
// log.Println(secret)

// secrets, _ := vaultClient.ListNestedSecrets("kv0FF76557", "")
// //secrets, err := vaultClient.Logical.List("randomkv/metadata/test/one")

// for _, value := range secrets {
// fmt.Printf("Key: %s\n", value.PathName)
// fmt.Printf("IsSecret: %t\n", value.IsSecret)
// }
// // val, err := vaultClient.KV2.Get(ctx, "path")
// // fmt.Println(val)
// // fmt.Println(err)

// // secretClient, err := vaultClient.Logical.List("credentials/metadata/")
// // if err != nil {
// // // TODO
// // fmt.Println(err)
// // }
// // vault.DataIterator(secretClient.Data["keys"])
// }
func checkForVaultAddress() {
if os.Getenv("VAULT_ADDR") == "" {
fmt.Println("VAULT_ADDR is not set. Please set it and try again.")
os.Exit(1)
}

if os.Getenv("VAULT_TOKEN") == "" {
fmt.Println("VAULT_TOKEN is not set. Please set it and try again.")
os.Exit(1)
}

}
15 changes: 8 additions & 7 deletions component/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,35 +13,36 @@ import (
var (
MainCommands = []string{
fmt.Sprintf("%sMain Commands:", styles.HighlightSecondaryTag),
fmt.Sprintf("%s<ctrl-m>%s to display System Mounts", styles.HighlightPrimaryTag, styles.StandardColorTag),
fmt.Sprintf("%s<ctrl-b>%s to display Secret Engines", styles.HighlightPrimaryTag, styles.StandardColorTag),
fmt.Sprintf("%s<ctrl-p>%s to display ACL Policies", styles.HighlightPrimaryTag, styles.StandardColorTag),
fmt.Sprintf("%s<ctrl-c>%s to Quit", styles.HighlightPrimaryTag, styles.StandardColorTag),
}
MountsCommands = []string{
fmt.Sprintf("\n%s Secret Mounts Command List:", styles.HighlightSecondaryTag),
fmt.Sprintf("%s<e>%s to explore mount", styles.HighlightPrimaryTag, styles.StandardColorTag),
fmt.Sprintf("\n%s Secret Engines Command List:", styles.HighlightSecondaryTag),
fmt.Sprintf("%s<e> or <Enter>%s to explore mount", styles.HighlightPrimaryTag, styles.StandardColorTag),
}
NoViewCommands = []string{}
PolicyCommands = []string{
fmt.Sprintf("\n%s ACL Policy Commands:", styles.HighlightSecondaryTag),
fmt.Sprintf("%s<i>%s to inspect policy", styles.HighlightPrimaryTag, styles.StandardColorTag),
fmt.Sprintf("%s<i> or <Enter> %s to inspect policy", styles.HighlightPrimaryTag, styles.StandardColorTag),
fmt.Sprintf("%s</>%s apply filter", styles.HighlightPrimaryTag, styles.StandardColorTag),
}
PolicyACLCommands = []string{
fmt.Sprintf("\n%s ACL Policy Commands:", styles.HighlightSecondaryTag),
fmt.Sprintf("%s<Esc>%s to go back", styles.HighlightPrimaryTag, styles.StandardColorTag),
fmt.Sprintf("%s<esc>%s to go back", styles.HighlightPrimaryTag, styles.StandardColorTag),
//fmt.Sprintf("%s</>%s apply filter", styles.HighlightPrimaryTag, styles.StandardColorTag),
}
SecretsCommands = []string{
fmt.Sprintf("\n%s Secrets Commands:", styles.HighlightSecondaryTag),
fmt.Sprintf("%s<e>%s to navigate to selected the path", styles.HighlightPrimaryTag, styles.StandardColorTag),
fmt.Sprintf("%s<b>%s to go back to the previous path", styles.HighlightPrimaryTag, styles.StandardColorTag),
fmt.Sprintf("%s<e> or <enter>%s to navigate to selected the path", styles.HighlightPrimaryTag, styles.StandardColorTag),
fmt.Sprintf("%s<b> or <esc>%s to go back to the previous path", styles.HighlightPrimaryTag, styles.StandardColorTag),
}
SecretObjectCommands = []string{
fmt.Sprintf("\n%s Secret Commands:", styles.HighlightSecondaryTag),
fmt.Sprintf("%s<h>%s toggle display for secrets", styles.HighlightPrimaryTag, styles.StandardColorTag),
fmt.Sprintf("%s<c>%s copy secret to clipboard", styles.HighlightPrimaryTag, styles.StandardColorTag),
fmt.Sprintf("%s<j>%s toggle json view for secret", styles.HighlightPrimaryTag, styles.StandardColorTag),
fmt.Sprintf("%s<b> or <esc>%s to go back to the previous path", styles.HighlightPrimaryTag, styles.StandardColorTag),
//TODO: Work in progress
//fmt.Sprintf("%s<p>%s patch secret", styles.HighlightPrimaryTag, styles.StandardColorTag),
}
Expand Down
4 changes: 0 additions & 4 deletions component/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@ func (i *Info) Render(msg string) error {
return ErrComponentNotBound
}

i.Props.Done = func(buttonIndex int, buttonLabel string) {
i.pages.RemovePage(PageNameInfo)

}
i.Modal.SetDoneFunc(i.Props.Done)
i.Modal.SetText(msg)
i.pages.AddPage(PageNameInfo, i.Modal.Container(), true, true)
Expand Down
14 changes: 12 additions & 2 deletions component/logo.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package component

import (
"fmt"
"strings"

primitive "github.com/dkyanakiev/vaulty/primitives"
Expand All @@ -21,12 +22,20 @@ var LogoASCII = []string{
type Logo struct {
TextView TextView
slot *tview.Flex
Props *LogoProps
}

func NewLogo() *Logo {
type LogoProps struct {
Version string
}

func NewLogo(version string) *Logo {
t := primitive.NewTextView(tview.AlignRight)
return &Logo{
TextView: t,
Props: &LogoProps{
Version: version,
},
}
}

Expand All @@ -35,8 +44,9 @@ func (l *Logo) Render() error {
return ErrComponentNotBound
}

versionText := fmt.Sprintf("[#26ffe6]version: %s", l.Props.Version)
logo := strings.Join(LogoASCII, "\n")

logo = fmt.Sprintf("%s\n%s", logo, versionText)
l.TextView.SetText(logo)
l.slot.AddItem(l.TextView.Primitive(), 0, 1, false)
return nil
Expand Down
7 changes: 5 additions & 2 deletions component/logo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package component_test

import (
"errors"
"fmt"
"strings"
"testing"

Expand All @@ -15,7 +16,7 @@ func TestLogo_Pass(t *testing.T) {
r := require.New(t)

textView := &componentfakes.FakeTextView{}
logo := component.NewLogo()
logo := component.NewLogo("0.0.0")
logo.TextView = textView

logo.Bind(tview.NewFlex())
Expand All @@ -24,13 +25,15 @@ func TestLogo_Pass(t *testing.T) {
r.NoError(err)

text := textView.SetTextArgsForCall(0)
versionText := fmt.Sprintf("[#26ffe6]version: %s", "0.0.0")
expectedLogo := strings.Join(component.LogoASCII, "\n")
expectedLogo = fmt.Sprintf("%s\n%s", expectedLogo, versionText)
r.Equal(text, expectedLogo)
}

func TestLogo_Fail(t *testing.T) {
r := require.New(t)
logo := component.NewLogo()
logo := component.NewLogo("0.0.0")

err := logo.Render()
r.Error(err)
Expand Down
2 changes: 1 addition & 1 deletion component/mounts_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
)

const (
TableTitleMounts = "System Mounts"
TableTitleMounts = "Secret Engines"
)

var (
Expand Down
7 changes: 3 additions & 4 deletions component/policy_acl_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ var (
type SelectPolicyACLFunc func(policyName string)

type PolicyAclTable struct {
TextView TextView
InputField InputField
Props *PolicyAclTableProps
Flex *tview.Flex
TextView TextView
Props *PolicyAclTableProps
Flex *tview.Flex
//Not sure I will use this
Renderer *glamour.TermRenderer

Expand Down
2 changes: 1 addition & 1 deletion component/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/rivo/tview"
)

const searchPlaceholder = "(hit enter or esc to leave)"
const searchPlaceholder = "(hit esc to leave the filter)"

type SearchField struct {
InputField InputField
Expand Down
1 change: 0 additions & 1 deletion component/secrets_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ func (s *SecretsTable) GetIDForSelection() (string, string) {
}

func (s *SecretsTable) Render() error {

s.reset()
fullPath := fmt.Sprintf("%s%s", s.Props.SelectedMount, s.Props.SelectedPath)
s.Table.SetTitle("%s (%s)", TableTitleMounts, fullPath)
Expand Down
82 changes: 82 additions & 0 deletions component/selector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package component

import (
"github.com/dkyanakiev/vaulty/primitives"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)

const pageNameSelector = "selector"

type SelectorModal struct {
Modal Selector
Props *SelectorProps
pages *tview.Pages
keyBindings map[tcell.Key]func()
}

type SelectorProps struct {
Items []string
AllocationID string
}

func NewSelectorModal() *SelectorModal {
s := &SelectorModal{
Modal: primitives.NewSelectionModal(),
Props: &SelectorProps{},
keyBindings: map[tcell.Key]func(){},
}

s.Modal.GetTable().SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
if fn, ok := s.keyBindings[event.Key()]; ok {
fn()
}

return event
})

return s
}

func (s *SelectorModal) Render() error {
if s.pages == nil {
return ErrComponentNotBound
}

if s.Props.Items == nil {
return ErrComponentPropsNotSet
}

table := s.Modal.GetTable()
table.Clear()

for i, v := range s.Props.Items {
table.RenderRow([]string{v}, i, tcell.ColorWhite)
}

s.Modal.GetTable().SetTitle("Select a Task (alloc: %s)", s.Props.AllocationID)

s.pages.AddPage(pageNameSelector, s.Modal.Container(), true, true)

return nil
}

func (s *SelectorModal) Bind(pages *tview.Pages) {
s.pages = pages
}

func (s *SelectorModal) SetSelectedFunc(fn func(task string)) {
s.Modal.GetTable().SetSelectedFunc(func(row, column int) {
task := s.Modal.GetTable().GetCellContent(row, 0)
fn(task)
s.Close()
})
}

func (s *SelectorModal) Close() {
s.pages.RemovePage(pageNameSelector)
}

func (s *SelectorModal) BindKey(key tcell.Key, fn func()) {
s.keyBindings[key] = fn
}
Loading

0 comments on commit 53355a0

Please sign in to comment.