diff options
author | Steve Manuel <nilslice@gmail.com> | 2016-10-31 01:06:36 -0700 |
---|---|---|
committer | Steve Manuel <nilslice@gmail.com> | 2016-10-31 01:06:36 -0700 |
commit | 76f1af6aad8de62f3df540767e713959c3385c01 (patch) | |
tree | 5cb9c7184b94be344492d8fd89c7709a14ccaee9 /system/db | |
parent | 519c5b44d0b36e1f61cb0228889401fa1e33357e (diff) | |
parent | 12cd2d10d79b7b8f0666c7f3f145e773f6edaac5 (diff) |
Merge branch 'ponzu-dev'
Diffstat (limited to 'system/db')
-rw-r--r-- | system/db/content.go | 124 | ||||
-rw-r--r-- | system/db/init.go | 18 | ||||
-rw-r--r-- | system/db/user.go | 114 |
3 files changed, 197 insertions, 59 deletions
diff --git a/system/db/content.go b/system/db/content.go index 2d6e8ea..bd1ee4b 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -38,13 +38,20 @@ func SetContent(target string, data url.Values) (int, error) { } func update(ns, id string, data url.Values) (int, error) { + var specifier string // i.e. _pending, _sorted, etc. + if strings.Contains(ns, "_") { + spec := strings.Split(ns, "_") + ns = spec[0] + specifier = "_" + spec[1] + } + cid, err := strconv.Atoi(id) if err != nil { return 0, err } err = store.Update(func(tx *bolt.Tx) error { - b, err := tx.CreateBucketIfNotExists([]byte(ns)) + b, err := tx.CreateBucketIfNotExists([]byte(ns + specifier)) if err != nil { return err } @@ -65,15 +72,24 @@ func update(ns, id string, data url.Values) (int, error) { return 0, nil } - go SortContent(ns) + if specifier == "" { + go SortContent(ns) + } return cid, nil } func insert(ns string, data url.Values) (int, error) { var effectedID int + var specifier string // i.e. _pending, _sorted, etc. + if strings.Contains(ns, "_") { + spec := strings.Split(ns, "_") + ns = spec[0] + specifier = "_" + spec[1] + } + err := store.Update(func(tx *bolt.Tx) error { - b, err := tx.CreateBucketIfNotExists([]byte(ns)) + b, err := tx.CreateBucketIfNotExists([]byte(ns + specifier)) if err != nil { return err } @@ -89,7 +105,7 @@ func insert(ns string, data url.Values) (int, error) { if err != nil { return err } - data.Add("id", cid) + data.Set("id", cid) j, err := postToJSON(ns, data) if err != nil { @@ -107,40 +123,11 @@ func insert(ns string, data url.Values) (int, error) { return 0, err } - go SortContent(ns) - - return effectedID, nil -} - -func postToJSON(ns string, data url.Values) ([]byte, error) { - // find the content type and decode values into it - t, ok := content.Types[ns] - if !ok { - return nil, fmt.Errorf(content.ErrTypeNotRegistered, ns) - } - post := t() - - 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(post, data) - if err != nil { - return nil, err - } - - slug, err := manager.Slug(post.(editor.Editable)) - if err != nil { - return nil, err - } - post.(editor.Editable).SetSlug(slug) - - // marshall content struct to json for db storage - j, err := json.Marshal(post) - if err != nil { - return nil, err + if specifier == "" { + go SortContent(ns) } - return j, nil + return effectedID, nil } // DeleteContent removes an item from the database. Deleting a non-existent item @@ -153,7 +140,6 @@ func DeleteContent(target string) error { tx.Bucket([]byte(ns)).Delete([]byte(id)) return nil }) - if err != nil { return err } @@ -178,7 +164,7 @@ func Content(target string) ([]byte, error) { b := tx.Bucket([]byte(ns)) _, err := val.Write(b.Get([]byte(id))) if err != nil { - fmt.Println(err) + log.Println(err) return err } @@ -197,8 +183,12 @@ func ContentAll(namespace string) [][]byte { store.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte(namespace)) - len := b.Stats().KeyN - posts = make([][]byte, 0, len) + if b == nil { + return nil + } + + numKeys := b.Stats().KeyN + posts = make([][]byte, 0, numKeys) b.ForEach(func(k, v []byte) error { posts = append(posts, v) @@ -216,10 +206,15 @@ func ContentAll(namespace string) [][]byte { // in descending order, from most recent to least recent // Should be called from a goroutine after SetContent is successful func SortContent(namespace string) { + // only sort main content types i.e. Post + if strings.Contains(namespace, "_") { + return + } + all := ContentAll(namespace) var posts sortablePosts - // decode each (json) into Editable + // decode each (json) into type to then sort for i := range all { j := all[i] post := content.Types[namespace]() @@ -238,18 +233,14 @@ func SortContent(namespace string) { // store in <namespace>_sorted bucket, first delete existing err := store.Update(func(tx *bolt.Tx) error { - err := tx.DeleteBucket([]byte(namespace + "_sorted")) + bname := []byte(namespace + "_sorted") + err := tx.DeleteBucket(bname) if err != nil { return err } - b, err := tx.CreateBucket([]byte(namespace + "_sorted")) + b, err := tx.CreateBucketIfNotExists(bname) if err != nil { - err := tx.Rollback() - if err != nil { - return err - } - return err } @@ -263,11 +254,6 @@ func SortContent(namespace string) { cid := fmt.Sprintf("%d:%d", i, posts[i].Time()) err = b.Put([]byte(cid), j) if err != nil { - err := tx.Rollback() - if err != nil { - return err - } - return err } } @@ -293,3 +279,35 @@ func (s sortablePosts) Less(i, j int) bool { func (s sortablePosts) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +func postToJSON(ns string, data url.Values) ([]byte, error) { + // find the content type and decode values into it + ns = strings.TrimSuffix(ns, "_external") + t, ok := content.Types[ns] + if !ok { + return nil, fmt.Errorf(content.ErrTypeNotRegistered, ns) + } + post := t() + + 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(post, data) + if err != nil { + return nil, err + } + + slug, err := manager.Slug(post.(editor.Editable)) + if err != nil { + return nil, err + } + post.(editor.Editable).SetSlug(slug) + + // marshall content struct to json for db storage + j, err := json.Marshal(post) + if err != nil { + return nil, err + } + + return j, nil +} diff --git a/system/db/init.go b/system/db/init.go index 1a5ed25..63804e1 100644 --- a/system/db/init.go +++ b/system/db/init.go @@ -13,12 +13,21 @@ import ( var store *bolt.DB +// Close exports the abillity to close our db file. Should be called with defer +// after call to Init() from the same place. +func Close() { + err := store.Close() + if err != nil { + log.Println(err) + } +} + // Init creates a db connection, initializes db with required info, sets secrets func Init() { var err error - store, err = bolt.Open("store.db", 0666, nil) + store, err = bolt.Open("system.db", 0666, nil) if err != nil { - log.Fatal(err) + log.Fatalln(err) } err = store.Update(func(tx *bolt.Tx) error { @@ -67,10 +76,9 @@ func Init() { return nil }) if err != nil { - log.Fatal("Coudn't initialize db with buckets.", err) + log.Fatalln("Coudn't initialize db with buckets.", err) } - // sort all content into type_sorted buckets go func() { for t := range content.Types { SortContent(t) @@ -99,7 +107,7 @@ func SystemInitComplete() bool { }) if err != nil { complete = false - log.Fatal(err) + log.Fatalln(err) } return complete diff --git a/system/db/user.go b/system/db/user.go index a3a0be3..d2dc3a9 100644 --- a/system/db/user.go +++ b/system/db/user.go @@ -4,15 +4,21 @@ import ( "bytes" "encoding/json" "errors" + "fmt" + "net/http" "github.com/bosssauce/ponzu/system/admin/user" "github.com/boltdb/bolt" + "github.com/nilslice/jwt" ) // ErrUserExists is used for the db to report to admin user of existing user var ErrUserExists = errors.New("Error. User exists.") +// ErrNoUserExists is used for the db to report to admin user of non-existing user +var ErrNoUserExists = errors.New("Error. No user exists.") + // SetUser sets key:value pairs in the db for user settings func SetUser(usr *user.User) (int, error) { err := store.Update(func(tx *bolt.Tx) error { @@ -38,7 +44,7 @@ func SetUser(usr *user.User) (int, error) { return err } - err = users.Put([]byte(usr.Email), j) + err = users.Put(email, j) if err != nil { return err } @@ -52,6 +58,65 @@ func SetUser(usr *user.User) (int, error) { return usr.ID, nil } +// UpdateUser sets key:value pairs in the db for existing user settings +func UpdateUser(usr, updatedUsr *user.User) error { + err := store.Update(func(tx *bolt.Tx) error { + users := tx.Bucket([]byte("_users")) + + // check if user is found by email, fail if nil + exists := users.Get([]byte(usr.Email)) + if exists == nil { + return ErrNoUserExists + } + + // marshal User to json and put into bucket + j, err := json.Marshal(updatedUsr) + if err != nil { + return err + } + + err = users.Put([]byte(updatedUsr.Email), j) + if err != nil { + return err + } + + // if email address was changed, delete the old record of former + // user with original email address + if usr.Email != updatedUsr.Email { + err = users.Delete([]byte(usr.Email)) + if err != nil { + return err + } + + } + + return nil + }) + if err != nil { + return err + } + + return nil +} + +// DeleteUser deletes a user from the db by email +func DeleteUser(email string) error { + err := store.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("_users")) + err := b.Delete([]byte(email)) + if err != nil { + return err + } + + return nil + }) + if err != nil { + return err + } + + return nil +} + // User gets the user by email from the db func User(email string) ([]byte, error) { val := &bytes.Buffer{} @@ -72,3 +137,50 @@ func User(email string) ([]byte, error) { return val.Bytes(), nil } + +// UserAll returns all users from the db +func UserAll() ([][]byte, error) { + var users [][]byte + err := store.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("_users")) + err := b.ForEach(func(k, v []byte) error { + users = append(users, v) + return nil + }) + if err != nil { + return err + } + + return nil + }) + if err != nil { + return nil, err + } + + return users, nil +} + +// CurrentUser extracts the user from the request data and returns the current user from the db +func CurrentUser(req *http.Request) ([]byte, error) { + if !user.IsValid(req) { + return nil, fmt.Errorf("Error. Invalid User.") + } + + token, err := req.Cookie("_token") + if err != nil { + return nil, err + } + + claims := jwt.GetClaims(token.Value) + email, ok := claims["user"] + if !ok { + return nil, fmt.Errorf("Error. No user data found in request token.") + } + + usr, err := User(email.(string)) + if err != nil { + return nil, err + } + + return usr, nil +} |