commit 8c2660e464d603826a937d4c9a8b3e8fc60ec1a6
parent cf802f3d85ab3ff974ce7670ffeb15d566a03fc3
Author: Sean Enck <sean@ttypty.com>
Date: Sat, 24 Dec 2022 10:58:43 -0500
allow for stats
Diffstat:
10 files changed, 50 insertions(+), 13 deletions(-)
diff --git a/Makefile b/Makefile
@@ -6,6 +6,7 @@ DOC := $(BUILD)doc.text
MAN := $(BUILD)lb.man
DOCTEXT := scripts/doc.sections
ACTUAL := $(BUILD)actual.log
+DATE := $(shell date +%Y-%m-%d)
.PHONY: $(TESTDIR)
@@ -22,7 +23,7 @@ $(TESTDIR):
check: $(TARGET) $(TESTDIR)
rm -f $(BUILD)*.kdbx
- LB_BUILD=$(TARGET) TEST_DATA=$(BUILD) SCRIPTS=$(PWD)/scripts/ go run scripts/check.go 2>&1 | sed "s#$(PWD)/$(DATA)##g" | sed 's/^[0-9][0-9][0-9][0-9][0-9][0-9]$$/XXXXXX/g' > $(ACTUAL)
+ LB_BUILD=$(TARGET) TEST_DATA=$(BUILD) SCRIPTS=$(PWD)/scripts/ go run scripts/check.go 2>&1 | sed "s#$(PWD)/$(DATA)##g" | sed 's/^[0-9][0-9][0-9][0-9][0-9][0-9]$$/XXXXXX/g' | sed 's/ ($(DATE).*//g' | sed 's/$(DATE).*//g' > $(ACTUAL)
diff -u $(ACTUAL) scripts/tests.expected.log
clean:
diff --git a/cmd/main.go b/cmd/main.go
@@ -241,11 +241,21 @@ func run() error {
return wrapped("unable to remove entry", err)
}
}
- case cli.ShowCommand, cli.ClipCommand:
+ case cli.ShowCommand, cli.ClipCommand, cli.StatsCommand:
if len(args) != 3 {
return errors.New("entry required")
}
entry := args[2]
+ if command == cli.StatsCommand {
+ v, err := t.Get(entry, backend.TimeValue)
+ if err != nil {
+ return wrapped("unable to get stats", err)
+ }
+ if v != nil {
+ fmt.Printf("modtime: %s\n", v.Value)
+ }
+ return nil
+ }
clipboard := platform.Clipboard{}
isShow := command == cli.ShowCommand
if !isShow {
diff --git a/cmd/vers.txt b/cmd/vers.txt
@@ -1 +1 @@
-v22.12.02
-\ No newline at end of file
+v22.12.03
+\ No newline at end of file
diff --git a/internal/backend/actions.go b/internal/backend/actions.go
@@ -7,6 +7,7 @@ import (
"os/exec"
"path/filepath"
"strings"
+ "time"
"github.com/enckse/lockbox/internal/inputs"
"github.com/tobischo/gokeepasslib/v3"
@@ -262,8 +263,8 @@ func (t *Transaction) Move(src QueryEntity, dst string) error {
v = inputs.FormatTOTP(v)
e.Values = append(e.Values, protectedValue("otp", v))
}
-
e.Values = append(e.Values, protectedValue(field, v))
+ e.Values = append(e.Values, value(modTimeKey, time.Now().Format(time.RFC3339)))
c.insertEntity(dOffset, dTitle, e)
return nil
})
diff --git a/internal/backend/query.go b/internal/backend/query.go
@@ -129,8 +129,16 @@ func (t *Transaction) QueryCallback(args QueryOptions) ([]QueryEntity, error) {
switch args.Values {
case SecretValue:
entity.Value = val
- case HashedValue:
- entity.Value = fmt.Sprintf("%x", sha512.Sum512([]byte(val)))
+ case HashedValue, TimeValue:
+ t := getValue(e.backing, modTimeKey)
+ if args.Values == TimeValue {
+ entity.Value = t
+ } else {
+ if t != "" {
+ t = fmt.Sprintf(" (%s)", t)
+ }
+ entity.Value = fmt.Sprintf("%x%s", sha512.Sum512([]byte(val)), t)
+ }
}
}
results = append(results, entity)
diff --git a/internal/backend/query_test.go b/internal/backend/query_test.go
@@ -1,6 +1,7 @@
package backend_test
import (
+ "strings"
"testing"
"github.com/enckse/lockbox/internal/backend"
@@ -83,9 +84,18 @@ func TestValueModes(t *testing.T) {
if err != nil {
t.Errorf("no error: %v", err)
}
- if q.Value != "44276ba24db13df5568aa6db81e0190ab9d35d2168dce43dca61e628f5c666b1d8b091f1dda59c2359c86e7d393d59723a421d58496d279031e7f858c11d893e" {
+ hash := q.Value
+ parts := strings.Split(hash, " ")
+ if len(parts) != 2 {
+ t.Errorf("invalid hash output: %v", parts)
+ }
+ if parts[0] != "44276ba24db13df5568aa6db81e0190ab9d35d2168dce43dca61e628f5c666b1d8b091f1dda59c2359c86e7d393d59723a421d58496d279031e7f858c11d893e" {
t.Errorf("invalid result value: %s", q.Value)
}
+ dt := parts[1]
+ if !strings.HasPrefix(dt, "(") || !strings.HasSuffix(dt, ")") || len(dt) != 27 {
+ t.Errorf("invalid date/time: %s", dt)
+ }
q, err = fullSetup(t, true).Get("test/test/ab11c", backend.SecretValue)
if err != nil {
t.Errorf("no error: %v", err)
diff --git a/internal/backend/types.go b/internal/backend/types.go
@@ -89,14 +89,17 @@ const (
HashedValue
// SecretValue will have the raw secret onboard
SecretValue
+ // TimeValue will show the last modification time
+ TimeValue
)
const (
- notesKey = "Notes"
- titleKey = "Title"
- passKey = "Password"
- pathSep = "/"
- isGlob = pathSep + "*"
+ notesKey = "Notes"
+ titleKey = "Title"
+ passKey = "Password"
+ pathSep = "/"
+ isGlob = pathSep + "*"
+ modTimeKey = "ModTime"
)
var (
diff --git a/internal/cli/core.go b/internal/cli/core.go
@@ -14,6 +14,8 @@ import (
)
const (
+ // StatsCommand will display additional entry stat information
+ StatsCommand = "stats"
// TOTPCommand is the parent of totp and by defaults generates a rotating token
TOTPCommand = "totp"
// HashCommand handles hashing the data store
diff --git a/scripts/check.go b/scripts/check.go
@@ -77,6 +77,7 @@ func main() {
runCommand([]string{"find", "e"}, nil)
show("keys/k/one2")
show("keys2/k/three")
+ runCommand([]string{"stats", "keys2/k/three"}, nil)
for _, k := range []string{"test/k", "test/k/totp"} {
runCommand([]string{"insert", "-totp", k}, []string{"5ae472abqdekjqykoyxk7hvc2leklq5n"})
}
diff --git a/scripts/tests.expected.log b/scripts/tests.expected.log
@@ -23,6 +23,7 @@ keys2/k/three
test2
test3
test4
+modtime:
test/k