diff options
Diffstat (limited to 'system/db')
-rw-r--r-- | system/db/addon.go | 151 | ||||
-rw-r--r-- | system/db/content.go | 29 | ||||
-rw-r--r-- | system/db/init.go | 7 |
3 files changed, 176 insertions, 11 deletions
diff --git a/system/db/addon.go b/system/db/addon.go new file mode 100644 index 0000000..f4621fa --- /dev/null +++ b/system/db/addon.go @@ -0,0 +1,151 @@ +package db + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "log" + "net/url" + + "github.com/boltdb/bolt" + "github.com/gorilla/schema" +) + +var ( + // ErrNoAddonExists indicates that there was not addon found in the db + ErrNoAddonExists = errors.New("No addon exists.") +) + +// Addon looks for an addon by its addon_reverse_dns as the key and returns +// the []byte as json representation of an addon +func Addon(key string) ([]byte, error) { + buf := &bytes.Buffer{} + + err := store.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("__addons")) + + val := b.Get([]byte(key)) + + if val == nil { + return ErrNoAddonExists + } + + _, err := buf.Write(val) + if err != nil { + return err + } + + return nil + }) + if err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +// SetAddon stores the values of an addon into the __addons bucket with a the +// `addon_reverse_dns` field used as the key. `kind` is the interface{} type for +// the provided addon (as in the result of calling addon.Types[id]) +func SetAddon(data url.Values, kind interface{}) error { + dec := schema.NewDecoder() + dec.IgnoreUnknownKeys(true) + dec.SetAliasTag("json") + err := dec.Decode(kind, data) + + v, err := json.Marshal(kind) + + err = store.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("__addons")) + k := data.Get("addon_reverse_dns") + if k == "" { + name := data.Get("addon_name") + return fmt.Errorf(`Addon "%s" has no identifier to use as key.`, name) + } + + err := b.Put([]byte(k), v) + if err != nil { + return err + } + + return nil + }) + if err != nil { + return err + } + + return nil +} + +// AddonAll returns all registered addons as a [][]byte +func AddonAll() [][]byte { + var all [][]byte + + err := store.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("__addons")) + err := b.ForEach(func(k, v []byte) error { + all = append(all, v) + + return nil + }) + if err != nil { + return err + } + + return nil + }) + if err != nil { + log.Println("Error finding addons in db with db.AddonAll:", err) + return nil + } + + return all +} + +// DeleteAddon removes an addon from the db by its key, the addon_reverse_dns +func DeleteAddon(key string) error { + err := store.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("__addons")) + + if err := b.Delete([]byte(key)); err != nil { + return err + } + + return nil + }) + if err != nil { + return err + } + + return nil +} + +// AddonExists checks if there is an existing addon stored. The key is an the +// value at addon_reverse_dns +func AddonExists(key string) bool { + var exists bool + + if store == nil { + Init() + } + + err := store.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte("__addons")) + if err != nil { + return err + } + if b.Get([]byte(key)) == nil { + return nil + } + + exists = true + return nil + }) + if err != nil { + log.Println("Error checking existence of addon with key:", key, "-", err) + return false + } + + return exists +} diff --git a/system/db/content.go b/system/db/content.go index dc4477f..b8d9cb8 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -432,29 +432,40 @@ func SortContent(namespace string) { // sort posts sort.Sort(posts) + // marshal posts to json + var bb [][]byte + for i := range posts { + j, err := json.Marshal(posts[i]) + if err != nil { + // log error and kill sort so __sorted is not in invalid state + log.Println("Error marshal post to json in SortContent:", err) + return + } + + bb = append(bb, j) + } + // store in <namespace>_sorted bucket, first delete existing err := store.Update(func(tx *bolt.Tx) error { bname := []byte(namespace + "__sorted") err := tx.DeleteBucket(bname) - if err != nil { + if err != nil && err != bolt.ErrBucketNotFound { + fmt.Println("Error in DeleteBucket") return err } b, err := tx.CreateBucketIfNotExists(bname) if err != nil { + fmt.Println("Error in CreateBucketIfNotExists") return err } // encode to json and store as 'i:post.Time()':post - for i := range posts { - j, err := json.Marshal(posts[i]) - if err != nil { - return err - } - + for i := range bb { cid := fmt.Sprintf("%d:%d", i, posts[i].Time()) - err = b.Put([]byte(cid), j) + err = b.Put([]byte(cid), bb[i]) if err != nil { + fmt.Println("Error in Put") return err } } @@ -485,7 +496,7 @@ func postToJSON(ns string, data url.Values) ([]byte, error) { // find the content type and decode values into it t, ok := item.Types[ns] if !ok { - return nil, fmt.Errorf(item.ErrTypeNotRegistered, ns) + return nil, fmt.Errorf(item.ErrTypeNotRegistered.Error(), ns) } post := t() diff --git a/system/db/init.go b/system/db/init.go index bf93bc6..eaf6d76 100644 --- a/system/db/init.go +++ b/system/db/init.go @@ -24,6 +24,10 @@ func Close() { // Init creates a db connection, initializes db with required info, sets secrets func Init() { + if store != nil { + return + } + var err error store, err = bolt.Open("system.db", 0666, nil) if err != nil { @@ -45,7 +49,7 @@ func Init() { } // init db with other buckets as needed - buckets := []string{"__config", "__users", "__contentIndex"} + buckets := []string{"__config", "__users", "__contentIndex", "__addons"} for _, name := range buckets { _, err := tx.CreateBucketIfNotExists([]byte(name)) if err != nil { @@ -90,7 +94,6 @@ func Init() { SortContent(t) } }() - } // SystemInitComplete checks if there is at least 1 admin user in the db which |