diff options
Diffstat (limited to 'system/db')
-rw-r--r-- | system/db/addon.go | 22 | ||||
-rw-r--r-- | system/db/cache.go | 2 | ||||
-rw-r--r-- | system/db/config.go | 143 | ||||
-rw-r--r-- | system/db/content.go | 49 | ||||
-rw-r--r-- | system/db/init.go | 36 | ||||
-rw-r--r-- | system/db/user.go | 20 |
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))) |