summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Keuning <kkeuning@gmail.com>2017-03-05 22:11:42 -0600
committerKevin Keuning <kkeuning@gmail.com>2017-03-05 22:11:42 -0600
commit92a96fe470b39ae5c16f66fce8023f04ad3a37ae (patch)
treefd9a03089b1a6ba1a45bcc733858851a394fa718
parent266b7834c586f3c6be20d6772b36347d1f2a6b35 (diff)
consolidate UpdateContent into SetContent
-rw-r--r--system/api/update.go6
-rw-r--r--system/db/content.go125
2 files changed, 50 insertions, 81 deletions
diff --git a/system/api/update.go b/system/api/update.go
index 00933fb..507d3af 100644
--- a/system/api/update.go
+++ b/system/api/update.go
@@ -52,8 +52,8 @@ func updateContentHandler(res http.ResponseWriter, req *http.Request) {
}
id := req.URL.Query().Get("id")
- if id == "" {
- log.Println("[Update] attempt to submit update with missing id from:", req.RemoteAddr)
+ if !db.IsValidID(id) {
+ log.Println("[Update] attempt to submit update with missing or invalid id from:", req.RemoteAddr)
res.WriteHeader(http.StatusBadRequest)
return
}
@@ -160,7 +160,7 @@ func updateContentHandler(res http.ResponseWriter, req *http.Request) {
// set specifier for db bucket in case content is/isn't Trustable
var spec string
- _, err = db.UpdateContent(t+spec+":"+id, req.PostForm)
+ _, err = db.SetContent(t+spec+":"+id, req.PostForm)
if err != nil {
log.Println("[Update] error calling UpdateContent:", err)
res.WriteHeader(http.StatusInternalServerError)
diff --git a/system/db/content.go b/system/db/content.go
index 8064b03..4517fbe 100644
--- a/system/db/content.go
+++ b/system/db/content.go
@@ -3,6 +3,7 @@ package db
import (
"bytes"
"encoding/json"
+ "errors"
"fmt"
"log"
"net/url"
@@ -17,29 +18,18 @@ import (
uuid "github.com/satori/go.uuid"
)
-// SetContent inserts or updates values in the database.
-// The `target` argument is a string made up of namespace:id (string:int)
-func SetContent(target string, data url.Values) (int, error) {
- t := strings.Split(target, ":")
- ns, id := t[0], t[1]
-
- // check if content id == -1 (indicating new post).
- // if so, run an insert which will assign the next auto incremented int.
- // this is done because boltdb begins its bucket auto increment value at 0,
- // which is the zero-value of an int in the Item struct field for ID.
- // this is a problem when the original first post (with auto ID = 0) gets
- // overwritten by any new post, originally having no ID, defauting to 0.
- if id == "-1" {
- return insert(ns, data)
+func IsValidID(id string) bool {
+ // ID should be a non-negative integer.
+ // ID of -1 is special for new posts, not updates.
+ if i, err := strconv.Atoi(id); err != nil || i < 0 {
+ return false
}
-
- return update(ns, id, data)
+ return true
}
-// UpdateContent inserts or updates values in the database.
-// Updated content will be merged into existing values from the database.
+// SetContent inserts or updates values in the database.
// The `target` argument is a string made up of namespace:id (string:int)
-func UpdateContent(target string, data url.Values) (int, error) {
+func SetContent(target string, data url.Values) (int, error) {
t := strings.Split(target, ":")
ns, id := t[0], t[1]
@@ -58,16 +48,11 @@ func UpdateContent(target string, data url.Values) (int, error) {
if err != nil {
return 0, err
}
+ return update(ns, id, data, &existingContent)
+}
- // Unmarsal the existing values
- s := item.Types[ns]()
-
- err = json.Unmarshal(existingContent, &s)
- if err != nil {
- log.Println("Error decoding json while updating", ns, ":", err)
- return 0, err
- }
-
+// update can support merge or replace behavior
+func update(ns, id string, data url.Values, existingContent *[]byte) (int, error) {
var specifier string // i.e. __pending, __sorted, etc.
if strings.Contains(ns, "__") {
spec := strings.Split(ns, "__")
@@ -80,22 +65,17 @@ func UpdateContent(target string, data url.Values) (int, error) {
return 0, err
}
- // Don't allow the Item fields to be updated from form values
- data.Del("id")
- data.Del("uuid")
- data.Del("slug")
-
- 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(s, data)
- if err != nil {
- return 0, err
- }
-
- j, err := json.Marshal(s)
- if err != nil {
- return 0, err
+ var j []byte
+ if existingContent == nil {
+ j, err = postToJSON(ns, data)
+ if err != nil {
+ return 0, err
+ }
+ } else {
+ j, err = mergeData(ns, data, *existingContent)
+ if err != nil {
+ return 0, err
+ }
}
err = store.Update(func(tx *bolt.Tx) error {
@@ -128,52 +108,41 @@ func UpdateContent(target string, data url.Values) (int, error) {
return cid, nil
}
-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
+func mergeData(ns string, data url.Values, existingContent []byte) ([]byte, error) {
+ var j []byte
+ t, ok := item.Types[ns]
+ if !ok {
+ return j, errors.New("Invalid type.")
+ // handle
}
- j, err := postToJSON(ns, data)
+ // Unmarsal the existing values
+ s := t()
+ err := json.Unmarshal(existingContent, &s)
if err != nil {
- return 0, err
+ log.Println("Error decoding json while updating", ns, ":", err)
+ return j, err
}
- err = store.Update(func(tx *bolt.Tx) error {
- b, err := tx.CreateBucketIfNotExists([]byte(ns + specifier))
- if err != nil {
- return err
- }
-
- err = b.Put([]byte(fmt.Sprintf("%d", cid)), j)
- if err != nil {
- return err
- }
+ // Don't allow the Item fields to be updated from form values
+ data.Del("id")
+ data.Del("uuid")
+ data.Del("slug")
- return nil
- })
+ 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(s, data)
if err != nil {
- return 0, nil
- }
-
- if specifier == "" {
- go SortContent(ns)
+ return j, err
}
- // update changes data, so invalidate client caching
- err = InvalidateCache()
+ j, err = json.Marshal(s)
if err != nil {
- return 0, err
+ return j, err
}
- return cid, nil
+ return j, nil
}
func insert(ns string, data url.Values) (int, error) {