commit 47c3363f5699ab3573a8efa2e94f91c239b14e68
parent 0fd9293a68255e1096c64e51f6866c8e611f8855
Author: Sean Enck <sean@ttypty.com>
Date: Thu, 27 Jul 2023 18:44:09 -0400
continue refactoring backend layout
Diffstat:
6 files changed, 186 insertions(+), 147 deletions(-)
diff --git a/internal/backend/actions.go b/internal/backend/actions.go
@@ -9,18 +9,12 @@ import (
"github.com/enckse/lockbox/internal/inputs"
"github.com/tobischo/gokeepasslib/v3"
- "github.com/tobischo/gokeepasslib/v3/wrappers"
)
type (
// ActionMode represents activities performed via transactions
ActionMode string
- removal struct {
- parts []string
- title string
- hook Hook
- }
- action func(t Context) error
+ action func(t Context) error
)
const (
@@ -98,10 +92,6 @@ func (t *Transaction) change(cb action) error {
})
}
-func (c Context) insertEntity(offset []string, title string, entity gokeepasslib.Entry) bool {
- return c.alterEntities(true, offset, title, &entity)
-}
-
func (c Context) alterEntities(isAdd bool, offset []string, title string, entity *gokeepasslib.Entry) bool {
g, e, ok := findAndDo(isAdd, title, offset, entity, c.db.Content.Root.Groups[0].Groups, c.db.Content.Root.Groups[0].Entries)
c.db.Content.Root.Groups[0].Groups = g
@@ -237,7 +227,7 @@ func (t *Transaction) Move(src QueryEntity, dst string) error {
}
e.Values = append(e.Values, protectedValue(field, v))
e.Values = append(e.Values, value(modTimeKey, modTime.Format(time.RFC3339)))
- c.insertEntity(dOffset, dTitle, e)
+ c.alterEntities(true, dOffset, dTitle, &e)
return nil
})
if err != nil {
@@ -264,6 +254,11 @@ func (t *Transaction) RemoveAll(entities []QueryEntity) error {
if len(entities) == 0 {
return errors.New("no entities given")
}
+ type removal struct {
+ parts []string
+ title string
+ hook Hook
+ }
removals := []removal{}
hasHooks := false
for _, entity := range entities {
@@ -303,14 +298,3 @@ func (t *Transaction) RemoveAll(entities []QueryEntity) error {
}
return nil
}
-
-func value(key string, value string) gokeepasslib.ValueData {
- return gokeepasslib.ValueData{Key: key, Value: gokeepasslib.V{Content: value}}
-}
-
-func protectedValue(key string, value string) gokeepasslib.ValueData {
- return gokeepasslib.ValueData{
- Key: key,
- Value: gokeepasslib.V{Content: value, Protected: wrappers.NewBoolWrapper(true)},
- }
-}
diff --git a/internal/backend/actions_test.go b/internal/backend/actions_test.go
@@ -28,7 +28,7 @@ func fullSetup(t *testing.T, keep bool) *backend.Transaction {
}
func TestKeyFile(t *testing.T) {
- os.Remove("file.key")
+ os.Clearenv()
os.Remove("keyfile_test.kdbx")
os.Setenv("LOCKBOX_READONLY", "no")
os.Setenv("LOCKBOX_STORE", "keyfile_test.kdbx")
@@ -243,3 +243,39 @@ func check(t *testing.T, checks ...string) error {
}
return nil
}
+
+func TestKeyAndOrKeyFile(t *testing.T) {
+ keyAndOrKeyFile(t, true, true)
+ keyAndOrKeyFile(t, false, true)
+ keyAndOrKeyFile(t, true, false)
+ keyAndOrKeyFile(t, false, false)
+}
+
+func keyAndOrKeyFile(t *testing.T, key, keyFile bool) {
+ os.Clearenv()
+ os.Remove("keyorkeyfile_test.kdbx")
+ os.Setenv("LOCKBOX_STORE", "keyorkeyfile_test.kdbx")
+ if key {
+ os.Setenv("LOCKBOX_KEY", "test")
+ os.Setenv("LOCKBOX_KEYMODE", "plaintext")
+ }
+ if keyFile {
+ os.Setenv("LOCKBOX_KEYFILE", "keyfileor.key.kdbx")
+ os.WriteFile("keyfileor.key.kdbx", []byte("test"), 0o644)
+ }
+ tr, err := backend.NewTransaction()
+ if err != nil {
+ t.Errorf("failed: %v", err)
+ }
+ invalid := !key && !keyFile
+ err = tr.Insert(backend.NewPath("a", "b"), "t")
+ if invalid {
+ if err == nil || err.Error() != "key and/or keyfile must be set" {
+ t.Errorf("invalid error: %v", err)
+ }
+ } else {
+ if err != nil {
+ t.Errorf("no error allowed: %v", err)
+ }
+ }
+}
diff --git a/internal/backend/core.go b/internal/backend/core.go
@@ -3,12 +3,14 @@ package backend
import (
"errors"
+ "fmt"
"os"
"strings"
"github.com/enckse/lockbox/internal/inputs"
"github.com/enckse/lockbox/internal/platform"
"github.com/tobischo/gokeepasslib/v3"
+ "github.com/tobischo/gokeepasslib/v3/wrappers"
)
var errPath = errors.New("input paths must contain at LEAST 2 components")
@@ -148,3 +150,57 @@ func isTOTP(title string) (bool, error) {
func getPathName(entry gokeepasslib.Entry) string {
return entry.GetTitle()
}
+
+func value(key string, value string) gokeepasslib.ValueData {
+ return gokeepasslib.ValueData{Key: key, Value: gokeepasslib.V{Content: value}}
+}
+
+func protectedValue(key string, value string) gokeepasslib.ValueData {
+ return gokeepasslib.ValueData{
+ Key: key,
+ Value: gokeepasslib.V{Content: value, Protected: wrappers.NewBoolWrapper(true)},
+ }
+}
+
+// NewSuffix creates a new user 'name' suffix
+func NewSuffix(name string) string {
+ return fmt.Sprintf("%s%s", pathSep, name)
+}
+
+// NewPath creates a new storage location path.
+func NewPath(segments ...string) string {
+ return strings.Join(segments, pathSep)
+}
+
+// Directory gets the offset location of the entry without the 'name'
+func (e QueryEntity) Directory() string {
+ return Directory(e.Path)
+}
+
+// Base will get the base name of input path
+func Base(s string) string {
+ parts := strings.Split(s, pathSep)
+ if len(parts) == 0 {
+ return s
+ }
+ return parts[len(parts)-1]
+}
+
+// Directory will get the directory/group for the given path
+func Directory(s string) string {
+ parts := strings.Split(s, pathSep)
+ return NewPath(parts[0 : len(parts)-1]...)
+}
+
+func getValue(e gokeepasslib.Entry, key string) string {
+ v := e.Get(key)
+ if v == nil {
+ return ""
+ }
+ return v.Value.Content
+}
+
+// IsDirectory will indicate if a path looks like a group/directory
+func IsDirectory(path string) bool {
+ return strings.HasSuffix(path, pathSep)
+}
diff --git a/internal/backend/core_test.go b/internal/backend/core_test.go
@@ -17,3 +17,89 @@ func TestLoad(t *testing.T) {
t.Errorf("invalid error: %v", err)
}
}
+
+func TestIsDirectory(t *testing.T) {
+ if backend.IsDirectory("") {
+ t.Error("invalid directory detection")
+ }
+ if !backend.IsDirectory("/") {
+ t.Error("invalid directory detection")
+ }
+ if backend.IsDirectory("/a") {
+ t.Error("invalid directory detection")
+ }
+}
+
+func TestBase(t *testing.T) {
+ b := backend.Base("")
+ if b != "" {
+ t.Error("invalid base")
+ }
+ b = backend.Base("aaa")
+ if b != "aaa" {
+ t.Error("invalid base")
+ }
+ b = backend.Base("aaa/")
+ if b != "" {
+ t.Error("invalid base")
+ }
+ b = backend.Base("aaa/a")
+ if b != "a" {
+ t.Error("invalid base")
+ }
+}
+
+func TestDirectory(t *testing.T) {
+ b := backend.Directory("")
+ if b != "" {
+ t.Error("invalid directory")
+ }
+ b = backend.Directory("/")
+ if b != "" {
+ t.Error("invalid directory")
+ }
+ b = backend.Directory("/a")
+ if b != "" {
+ t.Error("invalid directory")
+ }
+ b = backend.Directory("a")
+ if b != "" {
+ t.Error("invalid directory")
+ }
+ b = backend.Directory("b/a")
+ if b != "b" {
+ t.Error("invalid directory")
+ }
+}
+
+func TestEntityDir(t *testing.T) {
+ q := backend.QueryEntity{Path: backend.NewPath("abc", "xyz")}
+ if q.Directory() != "abc" {
+ t.Error("invalid query directory")
+ }
+ q = backend.QueryEntity{Path: backend.NewPath("abc", "xyz", "111")}
+ if q.Directory() != "abc/xyz" {
+ t.Error("invalid query directory")
+ }
+ q = backend.QueryEntity{Path: ""}
+ if q.Directory() != "" {
+ t.Error("invalid query directory")
+ }
+ q = backend.QueryEntity{Path: backend.NewPath("abc")}
+ if q.Directory() != "" {
+ t.Error("invalid query directory")
+ }
+}
+
+func TestNewPath(t *testing.T) {
+ p := backend.NewPath("abc", "xyz")
+ if p != backend.NewPath("abc", "xyz") {
+ t.Error("invalid new path")
+ }
+}
+
+func TestNewSuffix(t *testing.T) {
+ if backend.NewSuffix("test") != "/test" {
+ t.Error("invalid suffix")
+ }
+}
diff --git a/internal/backend/query.go b/internal/backend/query.go
@@ -213,46 +213,3 @@ func (t *Transaction) QueryCallback(args QueryOptions) ([]QueryEntity, error) {
}
return results, nil
}
-
-// NewSuffix creates a new user 'name' suffix
-func NewSuffix(name string) string {
- return fmt.Sprintf("%s%s", pathSep, name)
-}
-
-// NewPath creates a new storage location path.
-func NewPath(segments ...string) string {
- return strings.Join(segments, pathSep)
-}
-
-// Directory gets the offset location of the entry without the 'name'
-func (e QueryEntity) Directory() string {
- return Directory(e.Path)
-}
-
-// Base will get the base name of input path
-func Base(s string) string {
- parts := strings.Split(s, pathSep)
- if len(parts) == 0 {
- return s
- }
- return parts[len(parts)-1]
-}
-
-// Directory will get the directory/group for the given path
-func Directory(s string) string {
- parts := strings.Split(s, pathSep)
- return NewPath(parts[0 : len(parts)-1]...)
-}
-
-func getValue(e gokeepasslib.Entry, key string) string {
- v := e.Get(key)
- if v == nil {
- return ""
- }
- return v.Value.Content
-}
-
-// IsDirectory will indicate if a path looks like a group/directory
-func IsDirectory(path string) bool {
- return strings.HasSuffix(path, pathSep)
-}
diff --git a/internal/backend/query_test.go b/internal/backend/query_test.go
@@ -210,32 +210,6 @@ func TestQueryCallback(t *testing.T) {
}
}
-func TestEntityDir(t *testing.T) {
- q := backend.QueryEntity{Path: backend.NewPath("abc", "xyz")}
- if q.Directory() != "abc" {
- t.Error("invalid query directory")
- }
- q = backend.QueryEntity{Path: backend.NewPath("abc", "xyz", "111")}
- if q.Directory() != "abc/xyz" {
- t.Error("invalid query directory")
- }
- q = backend.QueryEntity{Path: ""}
- if q.Directory() != "" {
- t.Error("invalid query directory")
- }
- q = backend.QueryEntity{Path: backend.NewPath("abc")}
- if q.Directory() != "" {
- t.Error("invalid query directory")
- }
-}
-
-func TestNewPath(t *testing.T) {
- p := backend.NewPath("abc", "xyz")
- if p != backend.NewPath("abc", "xyz") {
- t.Error("invalid new path")
- }
-}
-
func TestSetModTime(t *testing.T) {
testDateTime := "2022-12-30T12:34:56-05:00"
tr := fullSetup(t, false)
@@ -275,57 +249,3 @@ func TestSetModTime(t *testing.T) {
t.Errorf("invalid error: %v", err)
}
}
-
-func TestIsDirectory(t *testing.T) {
- if backend.IsDirectory("") {
- t.Error("invalid directory detection")
- }
- if !backend.IsDirectory("/") {
- t.Error("invalid directory detection")
- }
- if backend.IsDirectory("/a") {
- t.Error("invalid directory detection")
- }
-}
-
-func TestBase(t *testing.T) {
- b := backend.Base("")
- if b != "" {
- t.Error("invalid base")
- }
- b = backend.Base("aaa")
- if b != "aaa" {
- t.Error("invalid base")
- }
- b = backend.Base("aaa/")
- if b != "" {
- t.Error("invalid base")
- }
- b = backend.Base("aaa/a")
- if b != "a" {
- t.Error("invalid base")
- }
-}
-
-func TestDirectory(t *testing.T) {
- b := backend.Directory("")
- if b != "" {
- t.Error("invalid directory")
- }
- b = backend.Directory("/")
- if b != "" {
- t.Error("invalid directory")
- }
- b = backend.Directory("/a")
- if b != "" {
- t.Error("invalid directory")
- }
- b = backend.Directory("a")
- if b != "" {
- t.Error("invalid directory")
- }
- b = backend.Directory("b/a")
- if b != "b" {
- t.Error("invalid directory")
- }
-}