summaryrefslogtreecommitdiff
path: root/system
diff options
context:
space:
mode:
Diffstat (limited to 'system')
-rw-r--r--system/addon/addon.go47
-rw-r--r--system/addon/manager.go34
-rw-r--r--system/admin/handlers.go13
-rw-r--r--system/db/addon.go53
4 files changed, 100 insertions, 47 deletions
diff --git a/system/addon/addon.go b/system/addon/addon.go
index a423d07..833ce23 100644
--- a/system/addon/addon.go
+++ b/system/addon/addon.go
@@ -8,6 +8,7 @@ import (
"github.com/ponzu-cms/ponzu/system/db"
"github.com/ponzu-cms/ponzu/system/item"
+ "github.com/tidwall/sjson"
)
var (
@@ -65,8 +66,7 @@ func Register(m Meta, fn func() interface{}) Addon {
// register sets up the system to use the Addon by:
// 1. Validating the Addon struct
-// 2. Checking that the Addon parent type was added to Types (via its New())
-// 3. Saving it to the __addons bucket in DB with id/key = addon_reverse_dns
+// 2. Saving it to the __addons bucket in DB with id/key = addon_reverse_dns
func register(a Addon) error {
if a.PonzuAddonName == "" {
return fmt.Errorf(`Addon must have valid Meta struct embedded: missing %s field.`, "PonzuAddonName")
@@ -118,7 +118,12 @@ func register(a Addon) error {
// db.SetAddon is like SetContent, but rather than the key being an int64 ID,
// we need it to be a string based on the addon_reverse_dns
- err = db.SetAddon(vals)
+ kind, ok := Types[a.PonzuAddonReverseDNS]
+ if !ok {
+ return fmt.Errorf("Error: no addon to set with id: %s", a.PonzuAddonReverseDNS)
+ }
+
+ err = db.SetAddon(vals, kind())
if err != nil {
return err
}
@@ -163,9 +168,41 @@ func setStatus(key, status string) error {
return err
}
- a.Set("addon_status", status)
+ a, err = sjson.SetBytes(a, "addon_status", status)
+ if err != nil {
+ return err
+ }
+
+ kind, ok := Types[key]
+ if !ok {
+ return fmt.Errorf("Error: no addon to set with id: %s", key)
+ }
+
+ // convert json => map[string]interface{} => url.Values
+ var kv map[string]interface{}
+ err = json.Unmarshal(a, kv)
+ if err != nil {
+ return err
+ }
+
+ var vals url.Values
+ for k, v := range kv {
+ switch v.(type) {
+ case []string:
+ s := v.([]string)
+ for i := range s {
+ if i == 0 {
+ vals.Set(k, s[i])
+ }
+
+ vals.Add(k, s[i])
+ }
+ default:
+ vals.Set(k, fmt.Sprintf("%v", v))
+ }
+ }
- err = db.SetAddon(a)
+ err = db.SetAddon(vals, kind())
if err != nil {
return err
}
diff --git a/system/addon/manager.go b/system/addon/manager.go
index acd779a..eb8b44c 100644
--- a/system/addon/manager.go
+++ b/system/addon/manager.go
@@ -2,12 +2,14 @@ package addon
import (
"bytes"
+ "encoding/json"
"fmt"
"html/template"
"net/url"
"github.com/gorilla/schema"
"github.com/ponzu-cms/ponzu/management/editor"
+ "github.com/tidwall/gjson"
)
const defaultInput = `<input type="hidden" name="%s" value="%s"/>`
@@ -31,18 +33,42 @@ type manager struct {
}
// Manage ...
-func Manage(data url.Values, reverseDNS string) ([]byte, error) {
+func Manage(data []byte, reverseDNS string) ([]byte, error) {
a, ok := Types[reverseDNS]
if !ok {
return nil, fmt.Errorf("Addon has not been added to addon.Types map")
}
+ // convert json => map[string]interface{} => url.Values
+ var kv map[string]interface{}
+ err := json.Unmarshal(data, kv)
+ if err != nil {
+ return nil, err
+ }
+
+ var vals url.Values
+ for k, v := range kv {
+ switch v.(type) {
+ case []string:
+ s := v.([]string)
+ for i := range s {
+ if i == 0 {
+ vals.Set(k, s[i])
+ }
+
+ vals.Add(k, s[i])
+ }
+ default:
+ vals.Set(k, fmt.Sprintf("%v", v))
+ }
+ }
+
at := a()
dec := schema.NewDecoder()
dec.IgnoreUnknownKeys(true)
dec.SetAliasTag("json")
- err := dec.Decode(at, data)
+ err = dec.Decode(at, vals)
if err != nil {
return nil, err
}
@@ -68,7 +94,7 @@ func Manage(data url.Values, reverseDNS string) ([]byte, error) {
}
for _, f := range fields {
- input := fmt.Sprintf(defaultInput, f, data.Get(f))
+ input := fmt.Sprintf(defaultInput, f, gjson.GetBytes(data, f).String())
_, err := inputs.WriteString(input)
if err != nil {
return nil, fmt.Errorf("Failed to write input for addon view: %s", f)
@@ -78,7 +104,7 @@ func Manage(data url.Values, reverseDNS string) ([]byte, error) {
m := manager{
DefaultInputs: template.HTML(inputs.Bytes()),
Editor: template.HTML(v),
- AddonName: data.Get("addon_name"),
+ AddonName: gjson.GetBytes(data, "addon_name").String(),
}
// execute html template into buffer for func return val
diff --git a/system/admin/handlers.go b/system/admin/handlers.go
index 71f88c2..02d9d92 100644
--- a/system/admin/handlers.go
+++ b/system/admin/handlers.go
@@ -8,7 +8,6 @@ import (
"fmt"
"log"
"net/http"
- "net/url"
"strconv"
"strings"
"time"
@@ -26,6 +25,7 @@ import (
"github.com/gorilla/schema"
emailer "github.com/nilslice/email"
"github.com/nilslice/jwt"
+ "github.com/tidwall/gjson"
)
func adminHandler(res http.ResponseWriter, req *http.Request) {
@@ -2228,7 +2228,7 @@ func addonHandler(res http.ResponseWriter, req *http.Request) {
}
}
- err = db.SetAddon(req.Form)
+ err = db.SetAddon(req.Form, at())
if err != nil {
log.Println("Error saving addon:", name, err)
res.WriteHeader(http.StatusInternalServerError)
@@ -2256,10 +2256,13 @@ func addonHandler(res http.ResponseWriter, req *http.Request) {
}
}
-func adminAddonListItem(data url.Values) []byte {
+func adminAddonListItem(data []byte) []byte {
+ id := gjson.GetBytes(data, "addon_reverse_dns").String()
+ status := gjson.GetBytes(data, "addon_status").String()
+ name := gjson.GetBytes(data, "addon_name").String()
+
var action string
var buttonClass string
- status := data.Get("addon_status")
if status != addon.StatusEnabled {
action = "Enable"
buttonClass = "green"
@@ -2268,8 +2271,6 @@ func adminAddonListItem(data url.Values) []byte {
buttonClass = "red"
}
- id := data.Get("addon_reverse_dns")
- name := data.Get("addon_name")
a := `
<li class="col s12">
<a href="/admin/addon?id=` + id + `" alt="Configure '` + name + `'">` + name + `</a>
diff --git a/system/db/addon.go b/system/db/addon.go
index c77ccf0..4b3e20c 100644
--- a/system/db/addon.go
+++ b/system/db/addon.go
@@ -7,7 +7,10 @@ import (
"log"
"net/url"
+ "encoding/json"
+
"github.com/boltdb/bolt"
+ "github.com/gorilla/schema"
)
var (
@@ -16,8 +19,8 @@ var (
)
// Addon looks for an addon by its addon_reverse_dns as the key and returns
-// the url.Values representation of an addon
-func Addon(key string) (url.Values, error) {
+// 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 {
@@ -40,25 +43,21 @@ func Addon(key string) (url.Values, error) {
return nil, err
}
- data, err := url.ParseQuery(buf.String())
- if err != nil {
- return nil, err
- }
-
- return data, nil
+ 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
-func SetAddon(data url.Values) error {
- // we don't know the structure of the addon type from a addon developer, so
- // encoding to json before it's stored in the db is difficult. Instead, we
- // can just encode the url.Values to a query string using the Encode() method.
- // The downside is that we will have to parse the values out of the query
- // string when loading it from the db
- v := data.Encode()
+// `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)
- err := store.Update(func(tx *bolt.Tx) error {
+ 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 == "" {
@@ -66,7 +65,7 @@ func SetAddon(data url.Values) error {
return fmt.Errorf(`Addon "%s" has no identifier to use as key.`, name)
}
- err := b.Put([]byte(k), []byte(v))
+ err := b.Put([]byte(k), v)
if err != nil {
return err
}
@@ -80,25 +79,15 @@ func SetAddon(data url.Values) error {
return nil
}
-// AddonAll returns all registered addons as a []url.Values
-func AddonAll() []url.Values {
- var all []url.Values
- buf := &bytes.Buffer{}
+// 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 {
- _, err := buf.Write(v)
- if err != nil {
- return err
- }
-
- data, err := url.ParseQuery(buf.String())
- if err != nil {
- return err
- }
+ all = append(all, v)
- all = append(all, data)
return nil
})
if err != nil {