summaryrefslogtreecommitdiff
path: root/system/db
diff options
context:
space:
mode:
Diffstat (limited to 'system/db')
-rw-r--r--system/db/addon.go22
-rw-r--r--system/db/cache.go2
-rw-r--r--system/db/config.go143
-rw-r--r--system/db/content.go49
-rw-r--r--system/db/init.go36
-rw-r--r--system/db/user.go20
6 files changed, 189 insertions, 83 deletions
diff --git a/system/db/addon.go b/system/db/addon.go
index f4621fa..0f63405 100644
--- a/system/db/addon.go
+++ b/system/db/addon.go
@@ -24,6 +24,9 @@ func Addon(key string) ([]byte, error) {
err := store.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("__addons"))
+ if b == nil {
+ return bolt.ErrBucketNotFound
+ }
val := b.Get([]byte(key))
@@ -56,12 +59,16 @@ func SetAddon(data url.Values, kind interface{}) error {
v, err := json.Marshal(kind)
+ 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 = 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)
+ if b == nil {
+ return bolt.ErrBucketNotFound
}
err := b.Put([]byte(k), v)
@@ -84,6 +91,10 @@ func AddonAll() [][]byte {
err := store.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("__addons"))
+ if b == nil {
+ return bolt.ErrBucketNotFound
+ }
+
err := b.ForEach(func(k, v []byte) error {
all = append(all, v)
@@ -107,6 +118,9 @@ func AddonAll() [][]byte {
func DeleteAddon(key string) error {
err := store.Update(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("__addons"))
+ if b == nil {
+ return bolt.ErrBucketNotFound
+ }
if err := b.Delete([]byte(key)); err != nil {
return err
diff --git a/system/db/cache.go b/system/db/cache.go
index 30ecf5a..0120147 100644
--- a/system/db/cache.go
+++ b/system/db/cache.go
@@ -11,7 +11,7 @@ import (
// CacheControl sets the default cache policy on static asset responses
func CacheControl(next http.Handler) http.HandlerFunc {
return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
- etag := ConfigCache("etag")
+ etag := ConfigCache("etag").(string)
policy := fmt.Sprintf("max-age=%d, public", 60*60*24*30)
res.Header().Add("ETag", etag)
res.Header().Add("Cache-Control", policy)
diff --git a/system/db/config.go b/system/db/config.go
index 45b3952..5a93353 100644
--- a/system/db/config.go
+++ b/system/db/config.go
@@ -13,57 +13,62 @@ import (
"github.com/gorilla/schema"
)
-var configCache url.Values
+var configCache map[string]interface{}
func init() {
- configCache = make(url.Values)
+ configCache = make(map[string]interface{})
}
// SetConfig sets key:value pairs in the db for configuration settings
func SetConfig(data url.Values) error {
- err := store.Update(func(tx *bolt.Tx) error {
- b := tx.Bucket([]byte("__config"))
-
- // check for any multi-value fields (ex. checkbox fields)
- // and correctly format for db storage. Essentially, we need
- // fieldX.0: value1, fieldX.1: value2 => fieldX: []string{value1, value2}
- var discardKeys []string
- for k, v := range data {
- if strings.Contains(k, ".") {
- key := strings.Split(k, ".")[0]
-
- if data.Get(key) == "" {
- data.Set(key, v[0])
- } else {
- data.Add(key, v[0])
- }
-
- discardKeys = append(discardKeys, k)
+ var j []byte
+
+ // check for any multi-value fields (ex. checkbox fields)
+ // and correctly format for db storage. Essentially, we need
+ // fieldX.0: value1, fieldX.1: value2 => fieldX: []string{value1, value2}
+ var discardKeys []string
+ for k, v := range data {
+ if strings.Contains(k, ".") {
+ key := strings.Split(k, ".")[0]
+
+ if data.Get(key) == "" {
+ data.Set(key, v[0])
+ } else {
+ data.Add(key, v[0])
}
- }
- for _, discardKey := range discardKeys {
- data.Del(discardKey)
+ discardKeys = append(discardKeys, k)
}
+ }
- cfg := &config.Config{}
- dec := schema.NewDecoder()
- dec.SetAliasTag("json") // allows simpler struct tagging when creating a content type
- dec.IgnoreUnknownKeys(true) // will skip over form values submitted, but not in struct
- err := dec.Decode(cfg, data)
- if err != nil {
- return err
- }
+ for _, discardKey := range discardKeys {
+ data.Del(discardKey)
+ }
- // check for "invalidate" value to reset the Etag
- if len(cfg.CacheInvalidate) > 0 && cfg.CacheInvalidate[0] == "invalidate" {
- cfg.Etag = NewEtag()
- cfg.CacheInvalidate = []string{}
- }
+ cfg := &config.Config{}
+ dec := schema.NewDecoder()
+ dec.SetAliasTag("json") // allows simpler struct tagging when creating a content type
+ dec.IgnoreUnknownKeys(true) // will skip over form values submitted, but not in struct
+ err := dec.Decode(cfg, data)
+ if err != nil {
+ return err
+ }
- j, err := json.Marshal(cfg)
- if err != nil {
- return err
+ // check for "invalidate" value to reset the Etag
+ if len(cfg.CacheInvalidate) > 0 && cfg.CacheInvalidate[0] == "invalidate" {
+ cfg.Etag = NewEtag()
+ cfg.CacheInvalidate = []string{}
+ }
+
+ j, err = json.Marshal(cfg)
+ if err != nil {
+ return err
+ }
+
+ err = store.Update(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("__config"))
+ if b == nil {
+ return bolt.ErrBucketNotFound
}
err = b.Put([]byte("settings"), j)
@@ -77,7 +82,14 @@ func SetConfig(data url.Values) error {
return err
}
- configCache = data
+ // convert json => map[string]interface{}
+ var kv map[string]interface{}
+ err = json.Unmarshal(j, &kv)
+ if err != nil {
+ return err
+ }
+
+ configCache = kv
return nil
}
@@ -108,6 +120,9 @@ func ConfigAll() ([]byte, error) {
val := &bytes.Buffer{}
err := store.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("__config"))
+ if b == nil {
+ return bolt.ErrBucketNotFound
+ }
_, err := val.Write(b.Get([]byte("settings")))
if err != nil {
return err
@@ -131,6 +146,13 @@ func PutConfig(key string, value interface{}) error {
return err
}
+ if c == nil {
+ c, err = emptyConfig()
+ if err != nil {
+ return err
+ }
+ }
+
err = json.Unmarshal(c, &kv)
if err != nil {
return err
@@ -166,6 +188,43 @@ func PutConfig(key string, value interface{}) error {
// ConfigCache is a in-memory cache of the Configs for quicker lookups
// 'key' is the JSON tag associated with the config field
-func ConfigCache(key string) string {
- return configCache.Get(key)
+func ConfigCache(key string) interface{} {
+ return configCache[key]
+}
+
+// LoadCacheConfig loads the config into a cache to be accessed by ConfigCache()
+func LoadCacheConfig() error {
+ c, err := ConfigAll()
+ if err != nil {
+ return err
+ }
+
+ if c == nil {
+ c, err = emptyConfig()
+ if err != nil {
+ return err
+ }
+ }
+
+ // convert json => map[string]interface{}
+ var kv map[string]interface{}
+ err = json.Unmarshal(c, &kv)
+ if err != nil {
+ return err
+ }
+
+ configCache = kv
+
+ return nil
+}
+
+func emptyConfig() ([]byte, error) {
+ cfg := &config.Config{}
+
+ data, err := json.Marshal(cfg)
+ if err != nil {
+ return nil, err
+ }
+
+ return data, nil
}
diff --git a/system/db/content.go b/system/db/content.go
index b8d9cb8..d9096ae 100644
--- a/system/db/content.go
+++ b/system/db/content.go
@@ -49,17 +49,17 @@ func update(ns, id string, data url.Values) (int, error) {
return 0, err
}
+ j, err := postToJSON(ns, data)
+ if err != nil {
+ return 0, err
+ }
+
err = store.Update(func(tx *bolt.Tx) error {
b, err := tx.CreateBucketIfNotExists([]byte(ns + specifier))
if err != nil {
return err
}
- j, err := postToJSON(ns, data)
- if err != nil {
- return err
- }
-
err = b.Put([]byte(fmt.Sprintf("%d", cid)), j)
if err != nil {
return err
@@ -134,6 +134,10 @@ func insert(ns string, data url.Values) (int, error) {
// store the slug,type:id in contentIndex if public content
if specifier == "" {
ci := tx.Bucket([]byte("__contentIndex"))
+ if ci == nil {
+ return bolt.ErrBucketNotFound
+ }
+
k := []byte(data.Get("slug"))
v := []byte(fmt.Sprintf("%s:%d", ns, effectedID))
err := ci.Put(k, v)
@@ -168,7 +172,12 @@ func DeleteContent(target string, data url.Values) error {
ns, id := t[0], t[1]
err := store.Update(func(tx *bolt.Tx) error {
- err := tx.Bucket([]byte(ns)).Delete([]byte(id))
+ b := tx.Bucket([]byte(ns))
+ if b == nil {
+ return bolt.ErrBucketNotFound
+ }
+
+ err := b.Delete([]byte(id))
if err != nil {
return err
}
@@ -176,7 +185,12 @@ func DeleteContent(target string, data url.Values) error {
// if content has a slug, also delete it from __contentIndex
slug := data.Get("slug")
if slug != "" {
- err := tx.Bucket([]byte("__contentIndex")).Delete([]byte(slug))
+ ci := tx.Bucket([]byte("__contentIndex"))
+ if ci == nil {
+ return bolt.ErrBucketNotFound
+ }
+
+ err := ci.Delete([]byte(slug))
if err != nil {
return err
}
@@ -212,6 +226,10 @@ func Content(target string) ([]byte, error) {
val := &bytes.Buffer{}
err := store.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte(ns))
+ if b == nil {
+ return bolt.ErrBucketNotFound
+ }
+
_, err := val.Write(b.Get([]byte(id)))
if err != nil {
log.Println(err)
@@ -235,6 +253,9 @@ func ContentBySlug(slug string) (string, []byte, error) {
var t, id string
err := store.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("__contentIndex"))
+ if b == nil {
+ return bolt.ErrBucketNotFound
+ }
idx := b.Get([]byte(slug))
if idx != nil {
@@ -248,6 +269,9 @@ func ContentBySlug(slug string) (string, []byte, error) {
}
c := tx.Bucket([]byte(t))
+ if c == nil {
+ return bolt.ErrBucketNotFound
+ }
_, err := val.Write(c.Get([]byte(id)))
if err != nil {
return err
@@ -267,9 +291,8 @@ func ContentAll(namespace string) [][]byte {
var posts [][]byte
store.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte(namespace))
-
if b == nil {
- return nil
+ return bolt.ErrBucketNotFound
}
numKeys := b.Stats().KeyN
@@ -313,7 +336,7 @@ func Query(namespace string, opts QueryOptions) (int, [][]byte) {
store.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte(namespace))
if b == nil {
- return nil
+ return bolt.ErrBucketNotFound
}
c := b.Cursor()
@@ -450,13 +473,11 @@ func SortContent(namespace string) {
bname := []byte(namespace + "__sorted")
err := tx.DeleteBucket(bname)
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
}
@@ -465,7 +486,6 @@ func SortContent(namespace string) {
cid := fmt.Sprintf("%d:%d", i, posts[i].Time())
err = b.Put([]byte(cid), bb[i])
if err != nil {
- fmt.Println("Error in Put")
return err
}
}
@@ -538,6 +558,9 @@ func checkSlugForDuplicate(slug string) (string, error) {
// check for existing slug in __contentIndex
err := store.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("__contentIndex"))
+ if b == nil {
+ return bolt.ErrBucketNotFound
+ }
original := slug
exists := true
i := 0
diff --git a/system/db/init.go b/system/db/init.go
index eaf6d76..9125d3b 100644
--- a/system/db/init.go
+++ b/system/db/init.go
@@ -1,10 +1,8 @@
package db
import (
- "encoding/json"
"log"
- "github.com/ponzu-cms/ponzu/system/admin/config"
"github.com/ponzu-cms/ponzu/system/item"
"github.com/boltdb/bolt"
@@ -57,32 +55,23 @@ func Init() {
}
}
- // seed db with configs structure if not present
- b := tx.Bucket([]byte("__config"))
- if b.Get([]byte("settings")) == nil {
- j, err := json.Marshal(&config.Config{})
- if err != nil {
- return err
- }
-
- err = b.Put([]byte("settings"), j)
- if err != nil {
- return err
- }
- }
-
- clientSecret := ConfigCache("client_secret")
-
- if clientSecret != "" {
- jwt.Secret([]byte(clientSecret))
- }
-
return nil
})
if err != nil {
log.Fatalln("Coudn't initialize db with buckets.", err)
}
+ err = LoadCacheConfig()
+ if err != nil {
+ log.Fatalln("Failed to load config cache.", err)
+ }
+
+ clientSecret := ConfigCache("client_secret").(string)
+
+ if clientSecret != "" {
+ jwt.Secret([]byte(clientSecret))
+ }
+
// invalidate cache on system start
err = InvalidateCache()
if err != nil {
@@ -103,6 +92,9 @@ func SystemInitComplete() bool {
err := store.View(func(tx *bolt.Tx) error {
users := tx.Bucket([]byte("__users"))
+ if users == nil {
+ return bolt.ErrBucketNotFound
+ }
err := users.ForEach(func(k, v []byte) error {
complete = true
diff --git a/system/db/user.go b/system/db/user.go
index 02fda95..164ae7b 100644
--- a/system/db/user.go
+++ b/system/db/user.go
@@ -26,6 +26,9 @@ func SetUser(usr *user.User) (int, error) {
err := store.Update(func(tx *bolt.Tx) error {
email := []byte(usr.Email)
users := tx.Bucket([]byte("__users"))
+ if users == nil {
+ return bolt.ErrBucketNotFound
+ }
// check if user is found by email, fail if nil
exists := users.Get(email)
@@ -69,6 +72,9 @@ func UpdateUser(usr, updatedUsr *user.User) error {
err := store.Update(func(tx *bolt.Tx) error {
users := tx.Bucket([]byte("__users"))
+ if users == nil {
+ return bolt.ErrBucketNotFound
+ }
// check if user is found by email, fail if nil
exists := users.Get([]byte(usr.Email))
@@ -110,6 +116,10 @@ func UpdateUser(usr, updatedUsr *user.User) error {
func DeleteUser(email string) error {
err := store.Update(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("__users"))
+ if b == nil {
+ return bolt.ErrBucketNotFound
+ }
+
err := b.Delete([]byte(email))
if err != nil {
return err
@@ -129,6 +139,10 @@ func User(email string) ([]byte, error) {
val := &bytes.Buffer{}
err := store.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("__users"))
+ if b == nil {
+ return bolt.ErrBucketNotFound
+ }
+
usr := b.Get([]byte(email))
_, err := val.Write(usr)
@@ -154,6 +168,10 @@ func UserAll() ([][]byte, error) {
var users [][]byte
err := store.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("__users"))
+ if b == nil {
+ return bolt.ErrBucketNotFound
+ }
+
err := b.ForEach(func(k, v []byte) error {
users = append(users, v)
return nil
@@ -230,7 +248,7 @@ func RecoveryKey(email string) (string, error) {
err := store.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("__recoveryKeys"))
if b == nil {
- return errors.New("No database found for checking keys.")
+ return bolt.ErrBucketNotFound
}
_, err := key.Write(b.Get([]byte(email)))