lockbox

password manager
Log | Files | Refs | README | LICENSE

commit 43f81cc6359a48286e8b7806fe11c7f4ae172c4a
parent dc0e3e7f0f810b4b2aad325180dc872f2401c75d
Author: Sean Enck <sean@ttypty.com>
Date:   Fri, 31 Mar 2023 19:08:28 -0400

split out actions -> hooks

Diffstat:
Minternal/backend/actions.go | 44--------------------------------------------
Minternal/backend/actions_test.go | 54------------------------------------------------------
Ainternal/backend/hooks.go | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainternal/backend/hooks_test.go | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 117 insertions(+), 98 deletions(-)

diff --git a/internal/backend/actions.go b/internal/backend/actions.go @@ -4,8 +4,6 @@ package backend import ( "errors" "os" - "os/exec" - "path/filepath" "strings" "time" @@ -15,48 +13,6 @@ import ( "github.com/tobischo/gokeepasslib/v3/wrappers" ) -// NewHook will create a new hook type -func NewHook(path string, a ActionMode) (Hook, error) { - if strings.TrimSpace(path) == "" { - return Hook{}, errors.New("empty path is not allowed for hooks") - } - dir := env.GetOrDefault(inputs.HookDirEnv, "") - if dir == "" { - return Hook{enabled: false}, nil - } - if !pathExists(dir) { - return Hook{}, errors.New("hook directory does NOT exist") - } - entries, err := os.ReadDir(dir) - if err != nil { - return Hook{}, err - } - scripts := []string{} - for _, e := range entries { - if e.IsDir() { - return Hook{}, errors.New("found subdirectory in hookdir") - } - scripts = append(scripts, filepath.Join(dir, e.Name())) - } - return Hook{path: path, mode: a, enabled: len(scripts) > 0, scripts: scripts}, nil -} - -// Run will execute any scripts configured as hooks -func (h Hook) Run(mode HookMode) error { - if !h.enabled { - return nil - } - for _, s := range h.scripts { - c := exec.Command(s, string(mode), string(h.mode), h.path) - c.Stdout = os.Stdout - c.Stderr = os.Stderr - if err := c.Run(); err != nil { - return err - } - } - return nil -} - func (t *Transaction) act(cb action) error { if !t.valid { return errors.New("invalid transaction") diff --git a/internal/backend/actions_test.go b/internal/backend/actions_test.go @@ -3,8 +3,6 @@ package backend_test import ( "fmt" "os" - "path/filepath" - "strings" "testing" "github.com/enckse/lockbox/internal/backend" @@ -245,55 +243,3 @@ func check(t *testing.T, checks ...string) error { } return nil } - -func TestHooks(t *testing.T) { - os.Setenv("LOCKBOX_HOOKDIR", "") - h, err := backend.NewHook("a", backend.InsertAction) - if err != nil { - t.Errorf("invalid error: %v", err) - } - if err := h.Run(backend.HookPre); err != nil { - t.Errorf("invalid error: %v", err) - } - if _, err := backend.NewHook("", backend.InsertAction); err.Error() != "empty path is not allowed for hooks" { - t.Errorf("wrong error: %v", err) - } - os.Setenv("LOCKBOX_HOOKDIR", "is_garbage") - if _, err := backend.NewHook("b", backend.InsertAction); err.Error() != "hook directory does NOT exist" { - t.Errorf("wrong error: %v", err) - } - testPath := "hooks.kdbx" - os.RemoveAll(testPath) - if err := os.MkdirAll(testPath, 0o755); err != nil { - t.Errorf("failed, mkdir: %v", err) - } - os.Setenv("LOCKBOX_HOOKDIR", testPath) - h, err = backend.NewHook("a", backend.InsertAction) - if err != nil { - t.Errorf("invalid error: %v", err) - } - if err := h.Run(backend.HookPre); err != nil { - t.Errorf("invalid error: %v", err) - } - sub := filepath.Join(testPath, "subdir") - if err := os.MkdirAll(sub, 0o755); err != nil { - t.Errorf("failed, mkdir sub: %v", err) - } - if _, err := backend.NewHook("b", backend.InsertAction); err.Error() != "found subdirectory in hookdir" { - t.Errorf("wrong error: %v", err) - } - if err := os.RemoveAll(sub); err != nil { - t.Errorf("failed rmdir: %v", err) - } - script := filepath.Join(testPath, "testscript") - if err := os.WriteFile(script, []byte{}, 0o644); err != nil { - t.Errorf("unable to write script: %v", err) - } - h, err = backend.NewHook("a", backend.InsertAction) - if err != nil { - t.Errorf("invalid error: %v", err) - } - if err := h.Run(backend.HookPre); strings.Contains("fork/exec", err.Error()) { - t.Errorf("wrong error: %v", err) - } -} diff --git a/internal/backend/hooks.go b/internal/backend/hooks.go @@ -0,0 +1,55 @@ +// Package backend handles kdbx interactions +package backend + +import ( + "errors" + "os" + "os/exec" + "path/filepath" + "strings" + + "github.com/enckse/lockbox/internal/inputs" + "github.com/enckse/pgl/os/env" +) + +// NewHook will create a new hook type +func NewHook(path string, a ActionMode) (Hook, error) { + if strings.TrimSpace(path) == "" { + return Hook{}, errors.New("empty path is not allowed for hooks") + } + dir := env.GetOrDefault(inputs.HookDirEnv, "") + if dir == "" { + return Hook{enabled: false}, nil + } + if !pathExists(dir) { + return Hook{}, errors.New("hook directory does NOT exist") + } + entries, err := os.ReadDir(dir) + if err != nil { + return Hook{}, err + } + scripts := []string{} + for _, e := range entries { + if e.IsDir() { + return Hook{}, errors.New("found subdirectory in hookdir") + } + scripts = append(scripts, filepath.Join(dir, e.Name())) + } + return Hook{path: path, mode: a, enabled: len(scripts) > 0, scripts: scripts}, nil +} + +// Run will execute any scripts configured as hooks +func (h Hook) Run(mode HookMode) error { + if !h.enabled { + return nil + } + for _, s := range h.scripts { + c := exec.Command(s, string(mode), string(h.mode), h.path) + c.Stdout = os.Stdout + c.Stderr = os.Stderr + if err := c.Run(); err != nil { + return err + } + } + return nil +} diff --git a/internal/backend/hooks_test.go b/internal/backend/hooks_test.go @@ -0,0 +1,62 @@ +package backend_test + +import ( + "os" + "path/filepath" + "strings" + "testing" + + "github.com/enckse/lockbox/internal/backend" +) + +func TestHooks(t *testing.T) { + os.Setenv("LOCKBOX_HOOKDIR", "") + h, err := backend.NewHook("a", backend.InsertAction) + if err != nil { + t.Errorf("invalid error: %v", err) + } + if err := h.Run(backend.HookPre); err != nil { + t.Errorf("invalid error: %v", err) + } + if _, err := backend.NewHook("", backend.InsertAction); err.Error() != "empty path is not allowed for hooks" { + t.Errorf("wrong error: %v", err) + } + os.Setenv("LOCKBOX_HOOKDIR", "is_garbage") + if _, err := backend.NewHook("b", backend.InsertAction); err.Error() != "hook directory does NOT exist" { + t.Errorf("wrong error: %v", err) + } + testPath := "hooks.kdbx" + os.RemoveAll(testPath) + if err := os.MkdirAll(testPath, 0o755); err != nil { + t.Errorf("failed, mkdir: %v", err) + } + os.Setenv("LOCKBOX_HOOKDIR", testPath) + h, err = backend.NewHook("a", backend.InsertAction) + if err != nil { + t.Errorf("invalid error: %v", err) + } + if err := h.Run(backend.HookPre); err != nil { + t.Errorf("invalid error: %v", err) + } + sub := filepath.Join(testPath, "subdir") + if err := os.MkdirAll(sub, 0o755); err != nil { + t.Errorf("failed, mkdir sub: %v", err) + } + if _, err := backend.NewHook("b", backend.InsertAction); err.Error() != "found subdirectory in hookdir" { + t.Errorf("wrong error: %v", err) + } + if err := os.RemoveAll(sub); err != nil { + t.Errorf("failed rmdir: %v", err) + } + script := filepath.Join(testPath, "testscript") + if err := os.WriteFile(script, []byte{}, 0o644); err != nil { + t.Errorf("unable to write script: %v", err) + } + h, err = backend.NewHook("a", backend.InsertAction) + if err != nil { + t.Errorf("invalid error: %v", err) + } + if err := h.Run(backend.HookPre); strings.Contains("fork/exec", err.Error()) { + t.Errorf("wrong error: %v", err) + } +}