summaryrefslogtreecommitdiff
path: root/system/db
diff options
context:
space:
mode:
Diffstat (limited to 'system/db')
-rw-r--r--system/db/addon.go151
-rw-r--r--system/db/content.go29
-rw-r--r--system/db/init.go7
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