From 9afca9115995ec8a82ebe0cdc27f5078a51ac372 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Wed, 1 Jan 2025 18:08:43 +0100 Subject: [PATCH] fixed crash in api list, added filter support to api list --- README.md | 5 +++++ TODO.md | 20 -------------------- anydb.1 | 2 +- app/attr.go | 3 +++ app/db.go | 15 +++++++++++++-- cfg/config.go | 2 +- cmd/crud.go | 2 +- output/list.go | 1 - rest/handlers.go | 3 +-- rest/serve.go | 7 ++++++- 10 files changed, 31 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 27afcbc..f72a403 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,11 @@ curl localhost:8787/anydb/v1/foo # list keys curl localhost:8787/anydb/v1/ +# same, but do a full text search by content, searching for "foo" +curl -X POST http://127.0.0.1:8787/anydb/v1/ \ + -H 'Content-Type: application/json' + -d '{"key":"foo", "fulltext": true}' + # as you might correctly suspect you can store multi-line values or # the content of text files. but what to do if you want to change it? # here's one way: diff --git a/TODO.md b/TODO.md index fa278e2..ee91abd 100644 --- a/TODO.md +++ b/TODO.md @@ -4,36 +4,16 @@ - mime-type => exec app + value - add waitgroup to db.go funcs - RestList does not support any params? -- lc() incoming tags+keys ## DB Structure - put tags into sub bucket see #1 -- change structure to: - -data bucket -key => {key,value[0:60],isbin:bool} - -value bucket -key => value (maybe always use []byte here) tags bucket key/tag => tag/key tag/key => tag -So, list just uses the data bucket, no large contents. -A tag search only looksup matching tags, see #1. -Only a full text search and get would need to dig into the value bucket. - A delete would just delete all keys from all values and then: lookup in tags bucket for all key/*, then iterate over the values and remove all tag/key's. Then deleting a key would not leave any residue behind. - -However, maybe change the list command to just list everything and add -an extra find command for fulltext or tag search. Maybe still provide -filter options in list command but only filter for keys. - -DONE: most of the above, except the tag stuff. manpage needs update and tests. - -maybe stitch the find command and just add -f (full text search) to list. diff --git a/anydb.1 b/anydb.1 index 367a284..90953b9 100644 --- a/anydb.1 +++ b/anydb.1 @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "ANYDB 1" -.TH ANYDB 1 "2024-12-30" "1" "User Commands" +.TH ANYDB 1 "2025-01-01" "1" "User Commands" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/app/attr.go b/app/attr.go index 27501ba..ecc08bf 100644 --- a/app/attr.go +++ b/app/attr.go @@ -33,6 +33,9 @@ type DbAttr struct { File string Encrypted bool Binary bool + + // conf flags, needed for incoming rest requests + Fulltext bool } // check if value is to be read from a file or stdin, setup preview diff --git a/app/db.go b/app/db.go index 27b1850..4dbeacc 100644 --- a/app/db.go +++ b/app/db.go @@ -95,9 +95,15 @@ func (db *DB) List(attr *DbAttr, fulltext bool) (DbEntries, error) { var filter *regexp.Regexp if len(attr.Args) > 0 { + // via cli filter = regexp.MustCompile(attr.Args[0]) } + if len(attr.Key) > 0 { + // via api + filter = regexp.MustCompile(attr.Key) + } + err := db.DB.View(func(tx *bolt.Tx) error { root := tx.Bucket([]byte(db.Bucket)) if root == nil { @@ -120,7 +126,13 @@ func (db *DB) List(attr *DbAttr, fulltext bool) (DbEntries, error) { return fmt.Errorf("failed to unmarshal from protobuf: %w", err) } - entry.Value = databucket.Get([]byte(entry.Key)) // empty is ok + if fulltext { + // avoid crash due to access fault + value := databucket.Get([]byte(entry.Key)) // empty is ok + vc := make([]byte, len(value)) + copy(vc, value) + entry.Value = vc + } var include bool @@ -327,7 +339,6 @@ func (db *DB) Get(attr *DbAttr) (*DbEntry, error) { } func (db *DB) Del(attr *DbAttr) error { - // FIXME: check if it exists prior to just call bucket.Delete()? if err := db.Open(); err != nil { return err } diff --git a/cfg/config.go b/cfg/config.go index 3297a31..893c464 100644 --- a/cfg/config.go +++ b/cfg/config.go @@ -26,7 +26,7 @@ import ( "github.com/tlinden/anydb/common" ) -var Version string = "v0.1.0" +var Version string = "v0.1.1" type BucketConfig struct { Encrypt bool diff --git a/cmd/crud.go b/cmd/crud.go index 00bdeab..9fe8404 100644 --- a/cmd/crud.go +++ b/cmd/crud.go @@ -182,7 +182,7 @@ func List(conf *cfg.Config) *cobra.Command { ) var cmd = &cobra.Command{ - Use: "list [ | -t ] [-m ] [-nNif] [-T ]", + Use: "list [ | -t ] [-m ] [-nNis] [-T ]", Short: "List database contents", Long: `List database contents`, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/output/list.go b/output/list.go index cc4e479..a7659a7 100644 --- a/output/list.go +++ b/output/list.go @@ -33,7 +33,6 @@ import ( ) func List(writer io.Writer, conf *cfg.Config, entries app.DbEntries) error { - // FIXME: call sort here switch conf.Mode { case "wide", "", "table": return ListTable(writer, conf, entries) diff --git a/rest/handlers.go b/rest/handlers.go index c375545..d49e4de 100644 --- a/rest/handlers.go +++ b/rest/handlers.go @@ -44,7 +44,6 @@ func RestList(c *fiber.Ctx, conf *cfg.Config) error { attr := new(app.DbAttr) if len(c.Body()) > 0 { - if err := c.BodyParser(attr); err != nil { return c.Status(fiber.StatusUnprocessableEntity).JSON(fiber.Map{ "errors": err.Error(), @@ -54,7 +53,7 @@ func RestList(c *fiber.Ctx, conf *cfg.Config) error { } // get list - entries, err := conf.DB.List(attr, false) + entries, err := conf.DB.List(attr, attr.Fulltext) if err != nil { return JsonStatus(c, fiber.StatusForbidden, "Unable to list keys: "+err.Error()) diff --git a/rest/serve.go b/rest/serve.go index e2ab485..1484ea7 100644 --- a/rest/serve.go +++ b/rest/serve.go @@ -42,6 +42,11 @@ func Runserver(conf *cfg.Config, args []string) error { return RestList(c, conf) }) + api.Post("/", func(c *fiber.Ctx) error { + // same thing as above but allows to supply parameters, see app.Dbattr{} + return RestList(c, conf) + }) + api.Get("/:key", func(c *fiber.Ctx) error { return RestGet(c, conf) }) @@ -78,7 +83,7 @@ func SetupServer(conf *cfg.Config) *fiber.App { }) router.Use(logger.New(logger.Config{ - Format: "${pid} ${ip}:${port} ${status} - ${method} ${path}\n", + Format: "${pid} ${ip}:${port} ${status} - ${method} ${path}\n", DisableColors: true, }))