From e8945192276de251022bd4732178cd0143f41f78 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 26 Oct 2016 01:53:15 -0700 Subject: code reorganizing --- system/api/handlers.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'system') diff --git a/system/api/handlers.go b/system/api/handlers.go index 2ec82bb..a56a667 100644 --- a/system/api/handlers.go +++ b/system/api/handlers.go @@ -3,7 +3,6 @@ package api import ( "bytes" "encoding/json" - "fmt" "log" "net/http" "strconv" @@ -69,8 +68,6 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { all = append(all, post) } - fmt.Println(len(posts)) - var start, end int switch count { case -1: @@ -203,6 +200,7 @@ func SendJSON(res http.ResponseWriter, j map[string]interface{}) { data, err = json.Marshal(j) if err != nil { + log.Println(err) data, _ = json.Marshal(map[string]interface{}{ "status": "fail", "message": err.Error(), -- cgit v1.2.3 From d6147f3fc99151687e08d40c91555e65578515d8 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 26 Oct 2016 03:55:15 -0700 Subject: adding capability to accept external content type submissions --- system/db/content.go | 5 ++++- system/external/server.go | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 system/external/server.go (limited to 'system') diff --git a/system/db/content.go b/system/db/content.go index 9ab1f89..c50706d 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -107,7 +107,10 @@ func insert(ns string, data url.Values) (int, error) { return 0, err } - go SortContent(ns) + // since sorting can be expensive, limit sort to non-externally created posts + if !strings.Contains(ns, "_external") { + go SortContent(ns) + } return effectedID, nil } diff --git a/system/external/server.go b/system/external/server.go new file mode 100644 index 0000000..1efb23f --- /dev/null +++ b/system/external/server.go @@ -0,0 +1,48 @@ +package external + +import ( + "net/http" + + "github.com/bosssauce/ponzu/content" + "github.com/bosssauce/ponzu/system/db" +) + +// Externalable accepts or rejects external POST requests to /external/posts?type=Review +type Externalable interface { + Accept() bool +} + +func init() { + http.HandleFunc("/api/external/posts", externalPostsHandler) +} + +func externalPostsHandler(res http.ResponseWriter, req *http.Request) { + if req.Method != http.MethodPost { + res.WriteHeader(http.StatusMethodNotAllowed) + return + } + + t := req.URL.Query().Get("type") + if t == "" { + res.WriteHeader(http.StatusBadRequest) + return + } + + p, found := content.Types[t] + if !found { + res.WriteHeader(http.StatusNotFound) + return + } + + post := p() + + ext, ok := post.(Externalable) + if !ok { + res.WriteHeader(http.StatusNotFound) + return + } + + if ext.Accept() { + db.SetContent(t+"_external"+":-1", req.Form) + } +} -- cgit v1.2.3 From 3c7748c5ae51441d00c29bdc4cd35e2e6ec0fa8f Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 26 Oct 2016 04:09:18 -0700 Subject: specifying http response code more appropriately --- system/external/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system') diff --git a/system/external/server.go b/system/external/server.go index 1efb23f..e765014 100644 --- a/system/external/server.go +++ b/system/external/server.go @@ -38,7 +38,7 @@ func externalPostsHandler(res http.ResponseWriter, req *http.Request) { ext, ok := post.(Externalable) if !ok { - res.WriteHeader(http.StatusNotFound) + res.WriteHeader(http.StatusInternalServerError) return } -- cgit v1.2.3 From 4807ed6caa702a27994799c1f799d25f3630f3ac Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 26 Oct 2016 12:21:58 -0700 Subject: debugging --- system/external/server.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'system') diff --git a/system/external/server.go b/system/external/server.go index e765014..08f4137 100644 --- a/system/external/server.go +++ b/system/external/server.go @@ -1,9 +1,11 @@ package external import ( + "fmt" "net/http" "github.com/bosssauce/ponzu/content" + "github.com/bosssauce/ponzu/system/api" "github.com/bosssauce/ponzu/system/db" ) @@ -13,7 +15,7 @@ type Externalable interface { } func init() { - http.HandleFunc("/api/external/posts", externalPostsHandler) + http.HandleFunc("/api/external/posts", api.CORS(externalPostsHandler)) } func externalPostsHandler(res http.ResponseWriter, req *http.Request) { @@ -30,6 +32,7 @@ func externalPostsHandler(res http.ResponseWriter, req *http.Request) { p, found := content.Types[t] if !found { + fmt.Println(t, content.Types, p) res.WriteHeader(http.StatusNotFound) return } -- cgit v1.2.3 From fcea30925bfadb43d0b5895e8aa2ec22bec14b35 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 26 Oct 2016 12:24:53 -0700 Subject: debugging --- system/external/server.go | 2 ++ 1 file changed, 2 insertions(+) (limited to 'system') diff --git a/system/external/server.go b/system/external/server.go index 08f4137..8f40ad1 100644 --- a/system/external/server.go +++ b/system/external/server.go @@ -19,6 +19,8 @@ func init() { } func externalPostsHandler(res http.ResponseWriter, req *http.Request) { + fmt.Println("got request") + res.Header().Set("X-TEST", "Request ack") if req.Method != http.MethodPost { res.WriteHeader(http.StatusMethodNotAllowed) return -- cgit v1.2.3 From 699a1a5076d683d0e59b2edbe9e05b6886c0bc88 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 26 Oct 2016 12:30:48 -0700 Subject: debugging and code reorg --- system/api/external.go | 46 ++++++++++++++++++++++++++++++++++++++++ system/api/server.go | 2 ++ system/external/server.go | 53 ----------------------------------------------- 3 files changed, 48 insertions(+), 53 deletions(-) create mode 100644 system/api/external.go delete mode 100644 system/external/server.go (limited to 'system') diff --git a/system/api/external.go b/system/api/external.go new file mode 100644 index 0000000..19dc1d0 --- /dev/null +++ b/system/api/external.go @@ -0,0 +1,46 @@ +package api + +import ( + "log" + "net/http" + + "github.com/bosssauce/ponzu/content" + "github.com/bosssauce/ponzu/system/db" +) + +// Externalable accepts or rejects external POST requests to /external/posts?type=Review +type Externalable interface { + Accept() bool +} + +func externalPostsHandler(res http.ResponseWriter, req *http.Request) { + if req.Method != http.MethodPost { + res.WriteHeader(http.StatusMethodNotAllowed) + return + } + + t := req.URL.Query().Get("type") + if t == "" { + res.WriteHeader(http.StatusBadRequest) + return + } + + p, found := content.Types[t] + if !found { + log.Println("Attempt to submit content", t, "by", req.RemoteAddr) + res.WriteHeader(http.StatusNotFound) + return + } + + post := p() + + ext, ok := post.(Externalable) + if !ok { + res.WriteHeader(http.StatusInternalServerError) + return + } + + if ext.Accept() { + db.SetContent(t+"_external"+":-1", req.Form) + } +} diff --git a/system/api/server.go b/system/api/server.go index da73382..816bc21 100644 --- a/system/api/server.go +++ b/system/api/server.go @@ -9,4 +9,6 @@ func Run() { http.HandleFunc("/api/posts", CORS(postsHandler)) http.HandleFunc("/api/post", CORS(postHandler)) + + http.HandleFunc("/api/external/posts", CORS(externalPostsHandler)) } diff --git a/system/external/server.go b/system/external/server.go deleted file mode 100644 index 8f40ad1..0000000 --- a/system/external/server.go +++ /dev/null @@ -1,53 +0,0 @@ -package external - -import ( - "fmt" - "net/http" - - "github.com/bosssauce/ponzu/content" - "github.com/bosssauce/ponzu/system/api" - "github.com/bosssauce/ponzu/system/db" -) - -// Externalable accepts or rejects external POST requests to /external/posts?type=Review -type Externalable interface { - Accept() bool -} - -func init() { - http.HandleFunc("/api/external/posts", api.CORS(externalPostsHandler)) -} - -func externalPostsHandler(res http.ResponseWriter, req *http.Request) { - fmt.Println("got request") - res.Header().Set("X-TEST", "Request ack") - if req.Method != http.MethodPost { - res.WriteHeader(http.StatusMethodNotAllowed) - return - } - - t := req.URL.Query().Get("type") - if t == "" { - res.WriteHeader(http.StatusBadRequest) - return - } - - p, found := content.Types[t] - if !found { - fmt.Println(t, content.Types, p) - res.WriteHeader(http.StatusNotFound) - return - } - - post := p() - - ext, ok := post.(Externalable) - if !ok { - res.WriteHeader(http.StatusInternalServerError) - return - } - - if ext.Accept() { - db.SetContent(t+"_external"+":-1", req.Form) - } -} -- cgit v1.2.3 From db0c05fa1f0b270fc00c9bcb190a03a5389df061 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 26 Oct 2016 12:35:57 -0700 Subject: debugging --- system/api/external.go | 1 + 1 file changed, 1 insertion(+) (limited to 'system') diff --git a/system/api/external.go b/system/api/external.go index 19dc1d0..111204e 100644 --- a/system/api/external.go +++ b/system/api/external.go @@ -14,6 +14,7 @@ type Externalable interface { } func externalPostsHandler(res http.ResponseWriter, req *http.Request) { + log.Println("External request") if req.Method != http.MethodPost { res.WriteHeader(http.StatusMethodNotAllowed) return -- cgit v1.2.3 From c9dc7199aeedeff6bd9a923d2ebd59147abd3a94 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 26 Oct 2016 12:41:48 -0700 Subject: debugging --- system/api/external.go | 2 ++ 1 file changed, 2 insertions(+) (limited to 'system') diff --git a/system/api/external.go b/system/api/external.go index 111204e..c437d33 100644 --- a/system/api/external.go +++ b/system/api/external.go @@ -26,6 +26,8 @@ func externalPostsHandler(res http.ResponseWriter, req *http.Request) { return } + log.Println("type:", t) + log.Println("of:", content.Types) p, found := content.Types[t] if !found { log.Println("Attempt to submit content", t, "by", req.RemoteAddr) -- cgit v1.2.3 From 54a245a5c4db84db527ae19af6f1f724a16d35d2 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 26 Oct 2016 12:50:38 -0700 Subject: debugging --- system/api/external.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'system') diff --git a/system/api/external.go b/system/api/external.go index c437d33..b34da93 100644 --- a/system/api/external.go +++ b/system/api/external.go @@ -44,6 +44,11 @@ func externalPostsHandler(res http.ResponseWriter, req *http.Request) { } if ext.Accept() { - db.SetContent(t+"_external"+":-1", req.Form) + _, err := db.SetContent(t+"_external"+":-1", req.Form) + if err != nil { + log.Println("[External]", err) + res.WriteHeader(http.StatusInternalServerError) + return + } } } -- cgit v1.2.3 From 38cfdbcba06d46718b0b5994ef3eb79e70620724 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 26 Oct 2016 12:53:34 -0700 Subject: debugging --- system/db/content.go | 1 + 1 file changed, 1 insertion(+) (limited to 'system') diff --git a/system/db/content.go b/system/db/content.go index c50706d..a55725a 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -72,6 +72,7 @@ func update(ns, id string, data url.Values) (int, error) { func insert(ns string, data url.Values) (int, error) { var effectedID int + log.Println(ns) err := store.Update(func(tx *bolt.Tx) error { b, err := tx.CreateBucketIfNotExists([]byte(ns)) if err != nil { -- cgit v1.2.3 From ec97784d44b5413a7689fd918276a5dbd1f7351e Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 26 Oct 2016 12:59:30 -0700 Subject: debugging --- system/db/content.go | 2 ++ 1 file changed, 2 insertions(+) (limited to 'system') diff --git a/system/db/content.go b/system/db/content.go index a55725a..71184af 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -24,6 +24,8 @@ func SetContent(target string, data url.Values) (int, error) { t := strings.Split(target, ":") ns, id := t[0], t[1] + log.Println(ns, id, data) + // 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, -- cgit v1.2.3 From dfe66cc52d9088dbf56ff38c50d791da2eefed78 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 26 Oct 2016 13:01:22 -0700 Subject: fixing Externalable interface implementation for Post type --- system/api/external.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'system') diff --git a/system/api/external.go b/system/api/external.go index b34da93..abb52c9 100644 --- a/system/api/external.go +++ b/system/api/external.go @@ -10,7 +10,7 @@ import ( // Externalable accepts or rejects external POST requests to /external/posts?type=Review type Externalable interface { - Accept() bool + Accepts() bool } func externalPostsHandler(res http.ResponseWriter, req *http.Request) { @@ -43,7 +43,7 @@ func externalPostsHandler(res http.ResponseWriter, req *http.Request) { return } - if ext.Accept() { + if ext.Accepts() { _, err := db.SetContent(t+"_external"+":-1", req.Form) if err != nil { log.Println("[External]", err) -- cgit v1.2.3 From 319322acc70a79772f28ec03b8618cb507664426 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 26 Oct 2016 13:07:30 -0700 Subject: implementation of insert content update to support types with no prior id --- system/db/content.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system') diff --git a/system/db/content.go b/system/db/content.go index 71184af..f41d7bb 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -92,7 +92,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 { -- cgit v1.2.3 From 2079258497d2a4e685663a6b2324b8da8ca6bd48 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 26 Oct 2016 13:18:05 -0700 Subject: debugging --- system/db/content.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system') diff --git a/system/db/content.go b/system/db/content.go index f41d7bb..089426e 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -74,7 +74,7 @@ func update(ns, id string, data url.Values) (int, error) { func insert(ns string, data url.Values) (int, error) { var effectedID int - log.Println(ns) + err := store.Update(func(tx *bolt.Tx) error { b, err := tx.CreateBucketIfNotExists([]byte(ns)) if err != nil { -- cgit v1.2.3 From 4d0201d360620cf3d3af4eec2661b1ae6c914e1d Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 26 Oct 2016 13:31:39 -0700 Subject: forgot to parse form data on external post handler --- system/api/external.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'system') diff --git a/system/api/external.go b/system/api/external.go index abb52c9..e6e75f0 100644 --- a/system/api/external.go +++ b/system/api/external.go @@ -14,23 +14,27 @@ type Externalable interface { } func externalPostsHandler(res http.ResponseWriter, req *http.Request) { - log.Println("External request") if req.Method != http.MethodPost { res.WriteHeader(http.StatusMethodNotAllowed) return } + err := req.ParseMultipartForm(1024 * 1024 * 4) // maxMemory 4MB + if err != nil { + log.Println("[External]", err) + res.WriteHeader(http.StatusInternalServerError) + return + } + t := req.URL.Query().Get("type") if t == "" { res.WriteHeader(http.StatusBadRequest) return } - log.Println("type:", t) - log.Println("of:", content.Types) p, found := content.Types[t] if !found { - log.Println("Attempt to submit content", t, "by", req.RemoteAddr) + log.Println("[External] Attempt to submit content", t, "by", req.RemoteAddr) res.WriteHeader(http.StatusNotFound) return } @@ -39,6 +43,7 @@ func externalPostsHandler(res http.ResponseWriter, req *http.Request) { ext, ok := post.(Externalable) if !ok { + log.Println("[External]", err) res.WriteHeader(http.StatusInternalServerError) return } -- cgit v1.2.3 From dbdd46e5477d8288970b564550616e0ba8fcd5e2 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Wed, 26 Oct 2016 13:34:34 -0700 Subject: need to process string in case external suffix is found where it should not be --- system/db/content.go | 1 + 1 file changed, 1 insertion(+) (limited to 'system') diff --git a/system/db/content.go b/system/db/content.go index 089426e..39ab5c2 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -120,6 +120,7 @@ func insert(ns string, data url.Values) (int, error) { 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) -- cgit v1.2.3 From c178f2e403b0b711d8aa3c0155d1368827f88afd Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Fri, 28 Oct 2016 12:58:25 -0700 Subject: adding some clean up code and UI toggle for future external vs. internal posted content --- system/admin/handlers.go | 55 +++++++++++++++++++++++++++++++++++++++++++++--- system/db/content.go | 2 -- system/db/init.go | 18 +++++++++++----- 3 files changed, 65 insertions(+), 10 deletions(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index d508ef2..8cbfe0a 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -15,6 +15,7 @@ import ( "github.com/bosssauce/ponzu/management/manager" "github.com/bosssauce/ponzu/system/admin/config" "github.com/bosssauce/ponzu/system/admin/user" + "github.com/bosssauce/ponzu/system/api" "github.com/bosssauce/ponzu/system/db" "github.com/nilslice/jwt" @@ -535,7 +536,21 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { posts := db.ContentAll(t + "_sorted") b := &bytes.Buffer{} - p, ok := content.Types[t]().(editor.Editable) + + if _, ok := content.Types[t]; !ok { + res.WriteHeader(http.StatusBadRequest) + errView, err := Error405() + if err != nil { + return + } + + res.Write(errView) + return + } + + pt := content.Types[t]() + + p, ok := pt.(editor.Editable) if !ok { res.WriteHeader(http.StatusInternalServerError) errView, err := Error500() @@ -547,6 +562,12 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { return } + var hasExt bool + ext, ok := pt.(api.Externalable) + if ok { + hasExt = true + } + html := `
@@ -604,8 +625,36 @@ func postsHandler(res http.ResponseWriter, req *http.Request) {
-
-
    ` +
` + if hasExt { + created := q.Get("created") + switch created { + q.Set("created", "internal") + intURL := strings.TrimPrefix(req.URL.String(), req.URL.Scheme+req.URL.Host) + + q.Set("created", "external") + extURL := strings.TrimPrefix(req.URL.String(), req.URL.Scheme+req.URL.Host) + + case "internal": + + html += `
+ Created by: + Internal +  |  + External +
` + + case "external": + html += `
+ Created by: + Internal +  |  + External +
` + } + + } + html += `
    ` if order == "desc" || order == "" { // keep natural order of posts slice, as returned from sorted bucket diff --git a/system/db/content.go b/system/db/content.go index 39ab5c2..6e70c1b 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -24,8 +24,6 @@ func SetContent(target string, data url.Values) (int, error) { t := strings.Split(target, ":") ns, id := t[0], t[1] - log.Println(ns, id, data) - // 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, diff --git a/system/db/init.go b/system/db/init.go index 1a5ed25..e5a588a 100644 --- a/system/db/init.go +++ b/system/db/init.go @@ -13,12 +13,20 @@ 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,7 +75,7 @@ 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 @@ -99,7 +107,7 @@ func SystemInitComplete() bool { }) if err != nil { complete = false - log.Fatal(err) + log.Fatalln(err) } return complete -- cgit v1.2.3 From 8ff77bc0aa766dcd33fd4458557444defa76d87b Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Fri, 28 Oct 2016 13:05:23 -0700 Subject: adding initial components for anayltics tracking API requests --- system/api/analytics/analytics.go | 97 +++++++++++++++++++++++++++++++++++++++ system/api/external.go | 11 +++-- system/api/handlers.go | 13 ++++-- 3 files changed, 113 insertions(+), 8 deletions(-) create mode 100644 system/api/analytics/analytics.go (limited to 'system') diff --git a/system/api/analytics/analytics.go b/system/api/analytics/analytics.go new file mode 100644 index 0000000..c30ce26 --- /dev/null +++ b/system/api/analytics/analytics.go @@ -0,0 +1,97 @@ +// Package analytics provides the methods to run an analytics reporting system +// for API requests which may be useful to users for measuring access and +// possibly identifying bad actors abusing requests. +package analytics + +import ( + "log" + "net/http" + "strings" + "time" + + "github.com/boltdb/bolt" +) + +type apiRequest struct { + URL string `json:"url"` + Method string `json:"http_method"` + RemoteAddr string `json:"ip_address"` + Timestamp int64 `json:"timestamp"` + External bool `json:"external"` +} + +var ( + store *bolt.DB + recordChan chan apiRequest +) + +// Record queues an apiRequest for metrics +func Record(req *http.Request) { + external := strings.Contains(req.URL.Path, "/external/") + + r := apiRequest{ + URL: req.URL.String(), + Method: req.Method, + RemoteAddr: req.RemoteAddr, + Timestamp: time.Now().Unix() * 1000, + External: external, + } + + // put r on buffered recordChan to take advantage of batch insertion in DB + recordChan <- r + +} + +// 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, should run an initial prune of old data, and +// sets up the queue/batching channel +func Init() { + store, err := bolt.Open("analytics.db", 0666, nil) + if err != nil { + log.Fatalln(err) + } + + recordChan = make(chan apiRequest, 1024*128) + + go serve() + + err = store.Update(func(tx *bolt.Tx) error { + + return nil + }) +} + +func serve() { + // make timer to notify select to batch request insert from recordChan + // interval: 1 minute + apiRequestTimer := time.NewTicker(time.Minute * 1) + + // make timer to notify select to remove old analytics + // interval: 2 weeks + // TODO: enable analytics backup service to cloud + pruneDBTimer := time.NewTicker(time.Hour * 24 * 14) + + for { + select { + case <-apiRequestTimer.C: + var reqs []apiRequest + batchSize := len(recordChan) + + for i := 0; i < batchSize; i++ { + reqs = append(reqs, <-recordChan) + } + + case <-pruneDBTimer.C: + + default: + } + } +} diff --git a/system/api/external.go b/system/api/external.go index e6e75f0..0da7eac 100644 --- a/system/api/external.go +++ b/system/api/external.go @@ -10,6 +10,7 @@ import ( // Externalable accepts or rejects external POST requests to /external/posts?type=Review type Externalable interface { + // Accepts determines whether a type will allow external submissions Accepts() bool } @@ -21,7 +22,7 @@ func externalPostsHandler(res http.ResponseWriter, req *http.Request) { err := req.ParseMultipartForm(1024 * 1024 * 4) // maxMemory 4MB if err != nil { - log.Println("[External]", err) + log.Println("[External] error:", err) res.WriteHeader(http.StatusInternalServerError) return } @@ -34,7 +35,7 @@ func externalPostsHandler(res http.ResponseWriter, req *http.Request) { p, found := content.Types[t] if !found { - log.Println("[External] Attempt to submit content", t, "by", req.RemoteAddr) + log.Println("[External] attempt to submit unknown type:", t, "from:", req.RemoteAddr) res.WriteHeader(http.StatusNotFound) return } @@ -43,15 +44,15 @@ func externalPostsHandler(res http.ResponseWriter, req *http.Request) { ext, ok := post.(Externalable) if !ok { - log.Println("[External]", err) - res.WriteHeader(http.StatusInternalServerError) + log.Println("[External] rejected non-externalable type:", t, "from:", req.RemoteAddr) + res.WriteHeader(http.StatusBadRequest) return } if ext.Accepts() { _, err := db.SetContent(t+"_external"+":-1", req.Form) if err != nil { - log.Println("[External]", err) + log.Println("[External] error:", err) res.WriteHeader(http.StatusInternalServerError) return } diff --git a/system/api/handlers.go b/system/api/handlers.go index a56a667..8356683 100644 --- a/system/api/handlers.go +++ b/system/api/handlers.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/bosssauce/ponzu/content" + "github.com/bosssauce/ponzu/system/api/analytics" "github.com/bosssauce/ponzu/system/db" ) @@ -210,9 +211,6 @@ func SendJSON(res http.ResponseWriter, j map[string]interface{}) { sendData(res, data, 200) } -// ResponseFunc ... -type ResponseFunc func(http.ResponseWriter, *http.Request) - // CORS wraps a HandleFunc to response to OPTIONS requests properly func CORS(next http.HandlerFunc) http.HandlerFunc { return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { @@ -224,3 +222,12 @@ func CORS(next http.HandlerFunc) http.HandlerFunc { next.ServeHTTP(res, req) }) } + +// Record wraps a HandleFunc to record API requests for analytical purposes +func Record(next http.HandlerFunc) http.HandlerFunc { + return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + go analytics.Record(req) + + next.ServeHTTP(res, req) + }) +} -- cgit v1.2.3 From a4ff81d168e159f18b6d68e2c26ab4416ca66b20 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Fri, 28 Oct 2016 13:07:53 -0700 Subject: moving non-switch code out of switch --- system/admin/handlers.go | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 8cbfe0a..3960eed 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -628,31 +628,32 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { ` if hasExt { created := q.Get("created") - switch created { - q.Set("created", "internal") - intURL := strings.TrimPrefix(req.URL.String(), req.URL.Scheme+req.URL.Host) - q.Set("created", "external") - extURL := strings.TrimPrefix(req.URL.String(), req.URL.Scheme+req.URL.Host) + q.Set("created", "internal") + intURL := strings.TrimPrefix(req.URL.String(), req.URL.Scheme+req.URL.Host) + + q.Set("created", "external") + extURL := strings.TrimPrefix(req.URL.String(), req.URL.Scheme+req.URL.Host) + + switch created { + case "internal": - case "internal": - html += `
    Created by: - Internal + Internal  |  - External + External
    ` - case "external": + case "external": html += `
    Created by: - Internal + Internal  |  - External + External
    ` } - + } html += `
      ` -- cgit v1.2.3 From a10e7f3960bed2a9fec81608d8365005855c113e Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Fri, 28 Oct 2016 13:09:07 -0700 Subject: delete unused --- system/admin/handlers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 3960eed..9f0b81e 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -563,7 +563,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { } var hasExt bool - ext, ok := pt.(api.Externalable) + _, ok = pt.(api.Externalable) if ok { hasExt = true } -- cgit v1.2.3 From 3eb0378414ea769df0724805129dd1028af7abe7 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Fri, 28 Oct 2016 13:14:08 -0700 Subject: attempt fix for bolt err --- system/db/init.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'system') diff --git a/system/db/init.go b/system/db/init.go index e5a588a..39840da 100644 --- a/system/db/init.go +++ b/system/db/init.go @@ -79,11 +79,13 @@ func Init() { } // sort all content into type_sorted buckets - go func() { - for t := range content.Types { - SortContent(t) - } - }() + if SystemInitComplete() { + go func() { + for t := range content.Types { + SortContent(t) + } + }() + } } -- cgit v1.2.3 From 763a6f96821be3c6fc3874f3fd9a5bd0316b2bf4 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Fri, 28 Oct 2016 13:17:17 -0700 Subject: attempt fix for bolt err --- system/db/init.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'system') diff --git a/system/db/init.go b/system/db/init.go index 39840da..7f8bce9 100644 --- a/system/db/init.go +++ b/system/db/init.go @@ -79,13 +79,13 @@ func Init() { } // sort all content into type_sorted buckets - if SystemInitComplete() { - go func() { - for t := range content.Types { - SortContent(t) - } - }() - } + // if SystemInitComplete() { + // go func() { + // for t := range content.Types { + // SortContent(t) + // } + // }() + // } } -- cgit v1.2.3 From c716fb39d8ae2e3d3d767c1419997d2a529329a7 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Fri, 28 Oct 2016 17:06:04 -0700 Subject: code reorg and debugging bolt issues --- system/api/analytics/analytics.go | 97 ----------------------------------- system/api/analytics/init.go | 103 ++++++++++++++++++++++++++++++++++++++ system/db/init.go | 16 +++--- 3 files changed, 111 insertions(+), 105 deletions(-) delete mode 100644 system/api/analytics/analytics.go create mode 100644 system/api/analytics/init.go (limited to 'system') diff --git a/system/api/analytics/analytics.go b/system/api/analytics/analytics.go deleted file mode 100644 index c30ce26..0000000 --- a/system/api/analytics/analytics.go +++ /dev/null @@ -1,97 +0,0 @@ -// Package analytics provides the methods to run an analytics reporting system -// for API requests which may be useful to users for measuring access and -// possibly identifying bad actors abusing requests. -package analytics - -import ( - "log" - "net/http" - "strings" - "time" - - "github.com/boltdb/bolt" -) - -type apiRequest struct { - URL string `json:"url"` - Method string `json:"http_method"` - RemoteAddr string `json:"ip_address"` - Timestamp int64 `json:"timestamp"` - External bool `json:"external"` -} - -var ( - store *bolt.DB - recordChan chan apiRequest -) - -// Record queues an apiRequest for metrics -func Record(req *http.Request) { - external := strings.Contains(req.URL.Path, "/external/") - - r := apiRequest{ - URL: req.URL.String(), - Method: req.Method, - RemoteAddr: req.RemoteAddr, - Timestamp: time.Now().Unix() * 1000, - External: external, - } - - // put r on buffered recordChan to take advantage of batch insertion in DB - recordChan <- r - -} - -// 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, should run an initial prune of old data, and -// sets up the queue/batching channel -func Init() { - store, err := bolt.Open("analytics.db", 0666, nil) - if err != nil { - log.Fatalln(err) - } - - recordChan = make(chan apiRequest, 1024*128) - - go serve() - - err = store.Update(func(tx *bolt.Tx) error { - - return nil - }) -} - -func serve() { - // make timer to notify select to batch request insert from recordChan - // interval: 1 minute - apiRequestTimer := time.NewTicker(time.Minute * 1) - - // make timer to notify select to remove old analytics - // interval: 2 weeks - // TODO: enable analytics backup service to cloud - pruneDBTimer := time.NewTicker(time.Hour * 24 * 14) - - for { - select { - case <-apiRequestTimer.C: - var reqs []apiRequest - batchSize := len(recordChan) - - for i := 0; i < batchSize; i++ { - reqs = append(reqs, <-recordChan) - } - - case <-pruneDBTimer.C: - - default: - } - } -} diff --git a/system/api/analytics/init.go b/system/api/analytics/init.go new file mode 100644 index 0000000..c04a7f2 --- /dev/null +++ b/system/api/analytics/init.go @@ -0,0 +1,103 @@ +// Package analytics provides the methods to run an analytics reporting system +// for API requests which may be useful to users for measuring access and +// possibly identifying bad actors abusing requests. +package analytics + +import ( + "fmt" + "log" + "net/http" + "strings" + "time" + + "github.com/boltdb/bolt" +) + +type apiRequest struct { + URL string `json:"url"` + Method string `json:"http_method"` + RemoteAddr string `json:"ip_address"` + Timestamp int64 `json:"timestamp"` + External bool `json:"external"` +} + +var ( + store *bolt.DB + recordChan chan apiRequest +) + +// Record queues an apiRequest for metrics +func Record(req *http.Request) { + external := strings.Contains(req.URL.Path, "/external/") + + r := apiRequest{ + URL: req.URL.String(), + Method: req.Method, + RemoteAddr: req.RemoteAddr, + Timestamp: time.Now().Unix() * 1000, + External: external, + } + + // put r on buffered recordChan to take advantage of batch insertion in DB + recordChan <- r + +} + +// 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, should run an initial prune of old data, and +// sets up the queue/batching channel +func Init() { + store, err := bolt.Open("analytics.db", 0666, nil) + if err != nil { + log.Fatalln(err) + } + + fmt.Println("analytics", store) + + recordChan = make(chan apiRequest, 1024*128) + + go serve() + + err = store.Update(func(tx *bolt.Tx) error { + + return nil + }) + if err != nil { + log.Fatalln(err) + } +} + +func serve() { + // make timer to notify select to batch request insert from recordChan + // interval: 1 minute + apiRequestTimer := time.NewTicker(time.Minute * 1) + + // make timer to notify select to remove old analytics + // interval: 2 weeks + // TODO: enable analytics backup service to cloud + pruneDBTimer := time.NewTicker(time.Hour * 24 * 14) + + for { + select { + case <-apiRequestTimer.C: + var reqs []apiRequest + batchSize := len(recordChan) + + for i := 0; i < batchSize; i++ { + reqs = append(reqs, <-recordChan) + } + + case <-pruneDBTimer.C: + + default: + } + } +} diff --git a/system/db/init.go b/system/db/init.go index 7f8bce9..423c265 100644 --- a/system/db/init.go +++ b/system/db/init.go @@ -2,6 +2,7 @@ package db import ( "encoding/json" + "fmt" "log" "github.com/bosssauce/ponzu/content" @@ -29,6 +30,8 @@ func Init() { log.Fatalln(err) } + fmt.Println("system", store) + err = store.Update(func(tx *bolt.Tx) error { // initialize db with all content type buckets & sorted bucket for type for t := range content.Types { @@ -78,14 +81,11 @@ func Init() { log.Fatalln("Coudn't initialize db with buckets.", err) } - // sort all content into type_sorted buckets - // if SystemInitComplete() { - // go func() { - // for t := range content.Types { - // SortContent(t) - // } - // }() - // } + go func() { + for t := range content.Types { + SortContent(t) + } + }() } -- cgit v1.2.3 From 58b67b59829235978994b705fe005fc7c9e0e661 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Fri, 28 Oct 2016 17:09:49 -0700 Subject: debugging --- system/db/init.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'system') diff --git a/system/db/init.go b/system/db/init.go index 423c265..0c3c887 100644 --- a/system/db/init.go +++ b/system/db/init.go @@ -81,11 +81,11 @@ func Init() { log.Fatalln("Coudn't initialize db with buckets.", err) } - go func() { - for t := range content.Types { + go func(types map[string]func() interface{}) { + for t := range types { SortContent(t) } - }() + }(content.Types) } -- cgit v1.2.3 From b6eb040045fcfeb39dda4fcd440d2be184c8e715 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 01:33:33 -0700 Subject: adding db/analytics init back in after reverting for debug --- system/api/analytics/init.go | 6 ++---- system/api/external.go | 11 ++++++++++- system/db/content.go | 11 +++-------- system/db/init.go | 6 ++---- 4 files changed, 17 insertions(+), 17 deletions(-) (limited to 'system') diff --git a/system/api/analytics/init.go b/system/api/analytics/init.go index c04a7f2..c351bed 100644 --- a/system/api/analytics/init.go +++ b/system/api/analytics/init.go @@ -4,7 +4,6 @@ package analytics import ( - "fmt" "log" "net/http" "strings" @@ -55,13 +54,12 @@ func Close() { // Init creates a db connection, should run an initial prune of old data, and // sets up the queue/batching channel func Init() { - store, err := bolt.Open("analytics.db", 0666, nil) + var err error + store, err = bolt.Open("analytics.db", 0666, nil) if err != nil { log.Fatalln(err) } - fmt.Println("analytics", store) - recordChan = make(chan apiRequest, 1024*128) go serve() diff --git a/system/api/external.go b/system/api/external.go index 0da7eac..a65618b 100644 --- a/system/api/external.go +++ b/system/api/external.go @@ -8,12 +8,21 @@ import ( "github.com/bosssauce/ponzu/system/db" ) -// Externalable accepts or rejects external POST requests to /external/posts?type=Review +// Externalable accepts or rejects external POST requests to endpoints such as: +// /external/posts?type=Review type Externalable interface { // Accepts determines whether a type will allow external submissions Accepts() bool } +// Mergeable allows external post content to be approved and published through +// the public-facing API +type Mergeable interface { + // Approve copies an external post to the internal collection and triggers + // a re-sort of its content type posts + Approve() error +} + func externalPostsHandler(res http.ResponseWriter, req *http.Request) { if req.Method != http.MethodPost { res.WriteHeader(http.StatusMethodNotAllowed) diff --git a/system/db/content.go b/system/db/content.go index 6e70c1b..8eb42b3 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -202,8 +202,8 @@ 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) + numKeys := b.Stats().KeyN + posts = make([][]byte, 0, numKeys) b.ForEach(func(k, v []byte) error { posts = append(posts, v) @@ -224,7 +224,7 @@ func SortContent(namespace string) { 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]() @@ -243,11 +243,6 @@ func SortContent(namespace string) { // store in _sorted bucket, first delete existing err := store.Update(func(tx *bolt.Tx) error { - err := tx.DeleteBucket([]byte(namespace + "_sorted")) - if err != nil { - return err - } - b, err := tx.CreateBucket([]byte(namespace + "_sorted")) if err != nil { err := tx.Rollback() diff --git a/system/db/init.go b/system/db/init.go index 0c3c887..92fa908 100644 --- a/system/db/init.go +++ b/system/db/init.go @@ -2,7 +2,6 @@ package db import ( "encoding/json" - "fmt" "log" "github.com/bosssauce/ponzu/content" @@ -25,13 +24,12 @@ func Close() { // Init creates a db connection, initializes db with required info, sets secrets func Init() { - store, err := bolt.Open("system.db", 0666, nil) + var err error + store, err = bolt.Open("system.db", 0666, nil) if err != nil { log.Fatalln(err) } - fmt.Println("system", store) - err = store.Update(func(tx *bolt.Tx) error { // initialize db with all content type buckets & sorted bucket for type for t := range content.Types { -- cgit v1.2.3 From 9f831fdf32e75a3a53845f037ada24a759d635c0 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 01:36:33 -0700 Subject: adding db/analytics init back in after reverting for debug --- system/db/content.go | 5 ----- system/db/init.go | 6 +++--- 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'system') diff --git a/system/db/content.go b/system/db/content.go index 8eb42b3..76a54a1 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -263,11 +263,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 } } diff --git a/system/db/init.go b/system/db/init.go index 92fa908..63804e1 100644 --- a/system/db/init.go +++ b/system/db/init.go @@ -79,11 +79,11 @@ func Init() { log.Fatalln("Coudn't initialize db with buckets.", err) } - go func(types map[string]func() interface{}) { - for t := range types { + go func() { + for t := range content.Types { SortContent(t) } - }(content.Types) + }() } -- cgit v1.2.3 From 9f34ec118483fc023026f1b6c8f6c627342279b5 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 01:37:28 -0700 Subject: adding db/analytics init back in after reverting for debug --- system/db/content.go | 5 ----- 1 file changed, 5 deletions(-) (limited to 'system') diff --git a/system/db/content.go b/system/db/content.go index 76a54a1..a83f0f0 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -245,11 +245,6 @@ func SortContent(namespace string) { err := store.Update(func(tx *bolt.Tx) error { b, err := tx.CreateBucket([]byte(namespace + "_sorted")) if err != nil { - err := tx.Rollback() - if err != nil { - return err - } - return err } -- cgit v1.2.3 From e3d9f80a8bbb0dab11259b132976fd9c7a5e2a8f Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 01:38:39 -0700 Subject: bucket create if not exist --- system/db/content.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system') diff --git a/system/db/content.go b/system/db/content.go index a83f0f0..616d75f 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -243,7 +243,7 @@ func SortContent(namespace string) { // store in _sorted bucket, first delete existing err := store.Update(func(tx *bolt.Tx) error { - b, err := tx.CreateBucket([]byte(namespace + "_sorted")) + b, err := tx.CreateBucketIfNotExists([]byte(namespace + "_sorted")) if err != nil { return err } -- cgit v1.2.3 From ec0c753e8386d0dabe6c65ffb9d26484fa361eb0 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 14:02:15 -0700 Subject: initial set up for external/internal toggle view --- system/admin/handlers.go | 8 ++++++-- system/admin/server.go | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 9f0b81e..b511339 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -638,7 +638,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { switch created { case "internal": - html += `
      + html += `
      Created by: Internal  |  @@ -646,7 +646,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) {
      ` case "external": - html += `
      + html += `
      Created by: Internal  |  @@ -753,6 +753,10 @@ func adminPostListItem(p editor.Editable, t string) []byte { return []byte(post) } +func approvePostHandler(res http.ResponseWriter, req *http.Request) { + +} + func editHandler(res http.ResponseWriter, req *http.Request) { switch req.Method { case http.MethodGet: diff --git a/system/admin/server.go b/system/admin/server.go index c22c278..161220e 100644 --- a/system/admin/server.go +++ b/system/admin/server.go @@ -24,6 +24,7 @@ func Run() { http.HandleFunc("/admin/configure/users/delete", user.Auth(configUsersDeleteHandler)) http.HandleFunc("/admin/posts", user.Auth(postsHandler)) + http.HandleFunc("/admin/posts/approve", user.Auth(approvePostHandler)) http.HandleFunc("/admin/posts/search", user.Auth(searchHandler)) http.HandleFunc("/admin/edit", user.Auth(editHandler)) -- cgit v1.2.3 From 631fbefe6166756af7053debee0753a9b435c982 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 14:17:15 -0700 Subject: changing copy and testing fix for public/private listing of content --- system/admin/handlers.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index b511339..a477647 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -627,30 +627,30 @@ func postsHandler(res http.ResponseWriter, req *http.Request) {
      ` if hasExt { - created := q.Get("created") + status := q.Get("status") - q.Set("created", "internal") - intURL := strings.TrimPrefix(req.URL.String(), req.URL.Scheme+req.URL.Host) + req.Form.Set("status", "public") + publicURL := strings.TrimPrefix(req.URL.String(), req.URL.Scheme+req.URL.Host) - q.Set("created", "external") - extURL := strings.TrimPrefix(req.URL.String(), req.URL.Scheme+req.URL.Host) + req.Form.Set("status", "pending") + pendingURL := strings.TrimPrefix(req.URL.String(), req.URL.Scheme+req.URL.Host) - switch created { - case "internal": + switch status { + case "public", "": html += `
      - Created by: - Internal + Status: + Public  |  - External + Pending
      ` - case "external": + case "pending": html += `
      - Created by: - Internal + Status: + Public  |  - External + Pending
      ` } -- cgit v1.2.3 From e3d64b9fdb8f8b2b429254d48e8186712d534c22 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 14:21:45 -0700 Subject: adding defauld status to form map --- system/admin/handlers.go | 3 +++ 1 file changed, 3 insertions(+) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index a477647..fb5a165 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -628,6 +628,9 @@ func postsHandler(res http.ResponseWriter, req *http.Request) {
      ` if hasExt { status := q.Get("status") + if status == "" { + req.Form.Add("status", "") + } req.Form.Set("status", "public") publicURL := strings.TrimPrefix(req.URL.String(), req.URL.Scheme+req.URL.Host) -- cgit v1.2.3 From ed4726b10562102dbe399ed0467c95fc786ff3b0 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 14:26:56 -0700 Subject: adding defauld status to form map --- system/admin/handlers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index fb5a165..55e9e94 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -629,7 +629,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { if hasExt { status := q.Get("status") if status == "" { - req.Form.Add("status", "") + req.Form.Add("status", "public") } req.Form.Set("status", "public") -- cgit v1.2.3 From 4730ba0b7f465dc001327ba560c058c90812c3c6 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 14:37:04 -0700 Subject: adding defauld status to form map --- system/admin/handlers.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 55e9e94..96530fd 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -629,14 +629,14 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { if hasExt { status := q.Get("status") if status == "" { - req.Form.Add("status", "public") + q.Add("status", "public") } - req.Form.Set("status", "public") - publicURL := strings.TrimPrefix(req.URL.String(), req.URL.Scheme+req.URL.Host) + q.Set("status", "public") + publicURL := req.URL.Path + q.Encode() - req.Form.Set("status", "pending") - pendingURL := strings.TrimPrefix(req.URL.String(), req.URL.Scheme+req.URL.Host) + q.Set("status", "pending") + pendingURL := req.URL.Path + q.Encode() switch status { case "public", "": -- cgit v1.2.3 From 0be1959e0e19bf77c24ddd49e0ad9ccea0e3b31a Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 14:38:39 -0700 Subject: adding defauld status to form map --- system/admin/handlers.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 96530fd..9414fba 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -633,10 +633,10 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { } q.Set("status", "public") - publicURL := req.URL.Path + q.Encode() + publicURL := req.URL.Path + "?" + q.Encode() q.Set("status", "pending") - pendingURL := req.URL.Path + q.Encode() + pendingURL := req.URL.Path + "?" + q.Encode() switch status { case "public", "": -- cgit v1.2.3 From b1212fa6f48da1d539a73e1bd5a0bf6894b97d7d Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 17:36:47 -0700 Subject: adding db procedures and updating handler for external submissions / pending content --- system/admin/handlers.go | 12 ++++--- system/api/external.go | 2 +- system/db/content.go | 83 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 65 insertions(+), 32 deletions(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 9414fba..181478a 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -642,7 +642,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { case "public", "": html += `
      - Status: + Status: Public  |  Pending @@ -650,17 +650,21 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { case "pending": html += `
      - Status: + Status: Public  |  Pending
      ` } + // get _pending posts of type t from the db + posts = db.ContentAll(t + "_pending") + } html += `
        ` - if order == "desc" || order == "" { + switch order { + case "desc", "": // keep natural order of posts slice, as returned from sorted bucket for i := range posts { err := json.Unmarshal(posts[i], &p) @@ -676,7 +680,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { b.Write(post) } - } else if order == "asc" { + case "asc": // reverse the order of posts slice for i := len(posts) - 1; i >= 0; i-- { err := json.Unmarshal(posts[i], &p) diff --git a/system/api/external.go b/system/api/external.go index a65618b..f9f2538 100644 --- a/system/api/external.go +++ b/system/api/external.go @@ -59,7 +59,7 @@ func externalPostsHandler(res http.ResponseWriter, req *http.Request) { } if ext.Accepts() { - _, err := db.SetContent(t+"_external"+":-1", req.Form) + err := db.SetPendingContent(t+"_pending", req.Form) if err != nil { log.Println("[External] error:", err) res.WriteHeader(http.StatusInternalServerError) diff --git a/system/db/content.go b/system/db/content.go index 616d75f..0b486ba 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -3,12 +3,14 @@ package db import ( "bytes" "encoding/json" + "errors" "fmt" "log" "net/url" "sort" "strconv" "strings" + "time" "github.com/bosssauce/ponzu/content" "github.com/bosssauce/ponzu/management/editor" @@ -108,44 +110,39 @@ func insert(ns string, data url.Values) (int, error) { return 0, err } - // since sorting can be expensive, limit sort to non-externally created posts - if !strings.Contains(ns, "_external") { - go SortContent(ns) - } + go SortContent(ns) return effectedID, nil } -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) +// SetPendingContent inserts submitted content for pending approval +func SetPendingContent(target string, data url.Values) error { + if !strings.Contains(target, "_pending") { + return errors.New("Only set items into _pending bucket using SetPendingContent. Namespace should be _pending") } - 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 - } + ns := strings.Split(target, "_")[0] - slug, err := manager.Slug(post.(editor.Editable)) - if err != nil { - return nil, err - } - post.(editor.Editable).SetSlug(slug) + err := store.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte(target)) + if err != nil { + return err + } - // marshall content struct to json for db storage - j, err := json.Marshal(post) + key := fmt.Sprintf("%d", time.Now().UTC().Unix()) + j, err := postToJSON(ns, data) + if err != nil { + return err + } + b.Put([]byte(key), j) + + return nil + }) if err != nil { - return nil, err + return err } - return j, nil + return nil } // DeleteContent removes an item from the database. Deleting a non-existent item @@ -283,3 +280,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 +} -- cgit v1.2.3 From ffa19ffc49ac11c426d29b543e3df26d3de61ec8 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 17:39:55 -0700 Subject: adding db procedures and updating handler for external submissions / pending content --- system/db/content.go | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'system') diff --git a/system/db/content.go b/system/db/content.go index 0b486ba..f3397ba 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -199,6 +199,10 @@ func ContentAll(namespace string) [][]byte { store.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte(namespace)) + if b == nil { + return nil + } + numKeys := b.Stats().KeyN posts = make([][]byte, 0, numKeys) -- cgit v1.2.3 From ca6c0ad73b37a1e77fafc0a8dede5207fed504d1 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 17:41:43 -0700 Subject: adding db procedures and updating handler for external submissions / pending content --- system/admin/handlers.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 181478a..8e52e91 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -640,7 +640,6 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { switch status { case "public", "": - html += `
        Status: Public @@ -649,6 +648,9 @@ func postsHandler(res http.ResponseWriter, req *http.Request) {
        ` case "pending": + // get _pending posts of type t from the db + posts = db.ContentAll(t + "_pending") + html += `
        Status: Public @@ -657,9 +659,6 @@ func postsHandler(res http.ResponseWriter, req *http.Request) {
        ` } - // get _pending posts of type t from the db - posts = db.ContentAll(t + "_pending") - } html += `
          ` -- cgit v1.2.3 From 391229f645225d958dda3c6d7846443ee27511b6 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 17:52:26 -0700 Subject: renaming and exporting upload file func --- system/admin/upload.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'system') diff --git a/system/admin/upload.go b/system/admin/upload.go index 7f2a4fa..3f61765 100644 --- a/system/admin/upload.go +++ b/system/admin/upload.go @@ -10,7 +10,8 @@ import ( "time" ) -func storeFileUploads(req *http.Request) (map[string]string, error) { +// StoreFileUploads stores file uploads at paths like /YYYY/MM/filename.ext +func StoreFileUploads(req *http.Request) (map[string]string, error) { err := req.ParseMultipartForm(1024 * 1024 * 4) // maxMemory 4MB if err != nil { return nil, fmt.Errorf("%s", err) -- cgit v1.2.3 From ed4c47babef56f18df0a5b393b0c0fe79e659105 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 17:52:56 -0700 Subject: adding db procedures and updating handler for external submissions / pending content --- system/admin/handlers.go | 4 ++-- system/api/external.go | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 3 deletions(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 8e52e91..ce07c4c 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -869,7 +869,7 @@ func editHandler(res http.ResponseWriter, req *http.Request) { req.PostForm.Set("updated", ts) } - urlPaths, err := storeFileUploads(req) + urlPaths, err := StoreFileUploads(req) if err != nil { log.Println(err) res.WriteHeader(http.StatusInternalServerError) @@ -971,7 +971,7 @@ func editUploadHandler(res http.ResponseWriter, req *http.Request) { return } - urlPaths, err := storeFileUploads(req) + urlPaths, err := StoreFileUploads(req) if err != nil { log.Println("Couldn't store file uploads.", err) res.WriteHeader(http.StatusInternalServerError) diff --git a/system/api/external.go b/system/api/external.go index f9f2538..1c69afb 100644 --- a/system/api/external.go +++ b/system/api/external.go @@ -1,10 +1,14 @@ package api import ( + "fmt" "log" "net/http" + "strings" + "time" "github.com/bosssauce/ponzu/content" + "github.com/bosssauce/ponzu/system/admin" "github.com/bosssauce/ponzu/system/db" ) @@ -59,7 +63,44 @@ func externalPostsHandler(res http.ResponseWriter, req *http.Request) { } if ext.Accepts() { - err := db.SetPendingContent(t+"_pending", req.Form) + ts := fmt.Sprintf("%d", time.Now().Unix()*1000) + req.PostForm.Set("timestamp", ts) + req.PostForm.Set("updated", ts) + req.PostForm.Set("id", ts) + + urlPaths, err := admin.storeFileUploads(req) + if err != nil { + log.Println(err) + res.WriteHeader(http.StatusInternalServerError) + return + } + + for name, urlPath := range urlPaths { + req.PostForm.Add(name, urlPath) + } + + // 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 req.PostForm { + if strings.Contains(k, ".") { + key := strings.Split(k, ".")[0] + + if req.PostForm.Get(key) == "" { + req.PostForm.Set(key, v[0]) + discardKeys = append(discardKeys, k) + } else { + req.PostForm.Add(key, v[0]) + } + } + } + + for _, discardKey := range discardKeys { + req.PostForm.Del(discardKey) + } + + err = db.SetPendingContent(t+"_pending", req.PostForm) if err != nil { log.Println("[External] error:", err) res.WriteHeader(http.StatusInternalServerError) -- cgit v1.2.3 From c930db63601095ce386413b3eb764b71ee71fe2c Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 17:56:46 -0700 Subject: renaming and moving File upload logic into own package --- system/admin/handlers.go | 5 ++- system/admin/upload.go | 90 ------------------------------------------- system/admin/upload/upload.go | 90 +++++++++++++++++++++++++++++++++++++++++++ system/api/external.go | 4 +- 4 files changed, 95 insertions(+), 94 deletions(-) delete mode 100644 system/admin/upload.go create mode 100644 system/admin/upload/upload.go (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index ce07c4c..6f23683 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -14,6 +14,7 @@ import ( "github.com/bosssauce/ponzu/management/editor" "github.com/bosssauce/ponzu/management/manager" "github.com/bosssauce/ponzu/system/admin/config" + "github.com/bosssauce/ponzu/system/admin/upload" "github.com/bosssauce/ponzu/system/admin/user" "github.com/bosssauce/ponzu/system/api" "github.com/bosssauce/ponzu/system/db" @@ -869,7 +870,7 @@ func editHandler(res http.ResponseWriter, req *http.Request) { req.PostForm.Set("updated", ts) } - urlPaths, err := StoreFileUploads(req) + urlPaths, err := upload.StoreFiles(req) if err != nil { log.Println(err) res.WriteHeader(http.StatusInternalServerError) @@ -971,7 +972,7 @@ func editUploadHandler(res http.ResponseWriter, req *http.Request) { return } - urlPaths, err := StoreFileUploads(req) + urlPaths, err := upload.StoreFiles(req) if err != nil { log.Println("Couldn't store file uploads.", err) res.WriteHeader(http.StatusInternalServerError) diff --git a/system/admin/upload.go b/system/admin/upload.go deleted file mode 100644 index 3f61765..0000000 --- a/system/admin/upload.go +++ /dev/null @@ -1,90 +0,0 @@ -package admin - -import ( - "fmt" - "io" - "net/http" - "os" - "path/filepath" - "strconv" - "time" -) - -// StoreFileUploads stores file uploads at paths like /YYYY/MM/filename.ext -func StoreFileUploads(req *http.Request) (map[string]string, error) { - err := req.ParseMultipartForm(1024 * 1024 * 4) // maxMemory 4MB - if err != nil { - return nil, fmt.Errorf("%s", err) - } - - ts := req.FormValue("timestamp") // timestamp in milliseconds since unix epoch - - if ts == "" { - ts = fmt.Sprintf("%d", time.Now().Unix()*1000) // Unix() returns seconds since unix epoch - } - - req.Form.Set("timestamp", ts) - - // To use for FormValue name:urlPath - urlPaths := make(map[string]string) - - // get or create upload directory to save files from request - pwd, err := os.Getwd() - if err != nil { - err := fmt.Errorf("Failed to locate current directory: %s", err) - return nil, err - } - - i, err := strconv.ParseInt(ts, 10, 64) - if err != nil { - return nil, err - } - - tm := time.Unix(int64(i/1000), int64(i%1000)) - - urlPathPrefix := "api" - uploadDirName := "uploads" - - uploadDir := filepath.Join(pwd, uploadDirName, fmt.Sprintf("%d", tm.Year()), fmt.Sprintf("%d", tm.Month())) - err = os.MkdirAll(uploadDir, os.ModeDir|os.ModePerm) - - // loop over all files and save them to disk - for name, fds := range req.MultipartForm.File { - filename := fds[0].Filename - src, err := fds[0].Open() - if err != nil { - err := fmt.Errorf("Couldn't open uploaded file: %s", err) - return nil, err - - } - defer src.Close() - - // check if file at path exists, if so, add timestamp to file - absPath := filepath.Join(uploadDir, filename) - - if _, err := os.Stat(absPath); !os.IsNotExist(err) { - filename = fmt.Sprintf("%d-%s", time.Now().Unix(), filename) - absPath = filepath.Join(uploadDir, filename) - } - - // save to disk (TODO: or check if S3 credentials exist, & save to cloud) - dst, err := os.Create(absPath) - if err != nil { - err := fmt.Errorf("Failed to create destination file for upload: %s", err) - return nil, err - } - - // copy file from src to dst on disk - if _, err = io.Copy(dst, src); err != nil { - err := fmt.Errorf("Failed to copy uploaded file to destination: %s", err) - return nil, err - } - - // add name:urlPath to req.PostForm to be inserted into db - urlPath := fmt.Sprintf("/%s/%s/%d/%d/%s", urlPathPrefix, uploadDirName, tm.Year(), tm.Month(), filename) - - urlPaths[name] = urlPath - } - - return urlPaths, nil -} diff --git a/system/admin/upload/upload.go b/system/admin/upload/upload.go new file mode 100644 index 0000000..169bffe --- /dev/null +++ b/system/admin/upload/upload.go @@ -0,0 +1,90 @@ +package upload + +import ( + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "strconv" + "time" +) + +// StoreFiles stores file uploads at paths like /YYYY/MM/filename.ext +func StoreFiles(req *http.Request) (map[string]string, error) { + err := req.ParseMultipartForm(1024 * 1024 * 4) // maxMemory 4MB + if err != nil { + return nil, fmt.Errorf("%s", err) + } + + ts := req.FormValue("timestamp") // timestamp in milliseconds since unix epoch + + if ts == "" { + ts = fmt.Sprintf("%d", time.Now().Unix()*1000) // Unix() returns seconds since unix epoch + } + + req.Form.Set("timestamp", ts) + + // To use for FormValue name:urlPath + urlPaths := make(map[string]string) + + // get or create upload directory to save files from request + pwd, err := os.Getwd() + if err != nil { + err := fmt.Errorf("Failed to locate current directory: %s", err) + return nil, err + } + + i, err := strconv.ParseInt(ts, 10, 64) + if err != nil { + return nil, err + } + + tm := time.Unix(int64(i/1000), int64(i%1000)) + + urlPathPrefix := "api" + uploadDirName := "uploads" + + uploadDir := filepath.Join(pwd, uploadDirName, fmt.Sprintf("%d", tm.Year()), fmt.Sprintf("%d", tm.Month())) + err = os.MkdirAll(uploadDir, os.ModeDir|os.ModePerm) + + // loop over all files and save them to disk + for name, fds := range req.MultipartForm.File { + filename := fds[0].Filename + src, err := fds[0].Open() + if err != nil { + err := fmt.Errorf("Couldn't open uploaded file: %s", err) + return nil, err + + } + defer src.Close() + + // check if file at path exists, if so, add timestamp to file + absPath := filepath.Join(uploadDir, filename) + + if _, err := os.Stat(absPath); !os.IsNotExist(err) { + filename = fmt.Sprintf("%d-%s", time.Now().Unix(), filename) + absPath = filepath.Join(uploadDir, filename) + } + + // save to disk (TODO: or check if S3 credentials exist, & save to cloud) + dst, err := os.Create(absPath) + if err != nil { + err := fmt.Errorf("Failed to create destination file for upload: %s", err) + return nil, err + } + + // copy file from src to dst on disk + if _, err = io.Copy(dst, src); err != nil { + err := fmt.Errorf("Failed to copy uploaded file to destination: %s", err) + return nil, err + } + + // add name:urlPath to req.PostForm to be inserted into db + urlPath := fmt.Sprintf("/%s/%s/%d/%d/%s", urlPathPrefix, uploadDirName, tm.Year(), tm.Month(), filename) + + urlPaths[name] = urlPath + } + + return urlPaths, nil +} diff --git a/system/api/external.go b/system/api/external.go index 1c69afb..52240d5 100644 --- a/system/api/external.go +++ b/system/api/external.go @@ -8,7 +8,7 @@ import ( "time" "github.com/bosssauce/ponzu/content" - "github.com/bosssauce/ponzu/system/admin" + "github.com/bosssauce/ponzu/system/admin/upload" "github.com/bosssauce/ponzu/system/db" ) @@ -68,7 +68,7 @@ func externalPostsHandler(res http.ResponseWriter, req *http.Request) { req.PostForm.Set("updated", ts) req.PostForm.Set("id", ts) - urlPaths, err := admin.storeFileUploads(req) + urlPaths, err := upload.StoreFiles(req) if err != nil { log.Println(err) res.WriteHeader(http.StatusInternalServerError) -- cgit v1.2.3 From 12987a604581836f669f579afede891a9fe22c1e Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 19:55:37 -0700 Subject: adding rough sort ordering for pending content, based on reversing the natural order of key-based sort from Bolt bucket --- system/admin/handlers.go | 74 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 20 deletions(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 6f23683..2b38e16 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -665,35 +665,69 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { switch order { case "desc", "": - // keep natural order of posts slice, as returned from sorted bucket - for i := range posts { - err := json.Unmarshal(posts[i], &p) - if err != nil { - log.Println("Error unmarshal json into", t, err, posts[i]) + if hasExt { + // reverse the order of posts slice + for i := len(posts) - 1; i >= 0; i-- { + err := json.Unmarshal(posts[i], &p) + if err != nil { + log.Println("Error unmarshal json into", t, err, posts[i]) - post := `
        • Error decoding data. Possible file corruption.
        • ` - b.Write([]byte(post)) - continue + post := `
        • Error decoding data. Possible file corruption.
        • ` + b.Write([]byte(post)) + continue + } + + post := adminPostListItem(p, t) + b.Write(post) } + } else { + // keep natural order of posts slice, as returned from sorted bucket + for i := range posts { + err := json.Unmarshal(posts[i], &p) + if err != nil { + log.Println("Error unmarshal json into", t, err, posts[i]) + + post := `
        • Error decoding data. Possible file corruption.
        • ` + b.Write([]byte(post)) + continue + } - post := adminPostListItem(p, t) - b.Write(post) + post := adminPostListItem(p, t) + b.Write(post) + } } case "asc": - // reverse the order of posts slice - for i := len(posts) - 1; i >= 0; i-- { - err := json.Unmarshal(posts[i], &p) - if err != nil { - log.Println("Error unmarshal json into", t, err, posts[i]) + if hasExt { + // keep natural order of posts slice, as returned from sorted bucket + for i := range posts { + err := json.Unmarshal(posts[i], &p) + if err != nil { + log.Println("Error unmarshal json into", t, err, posts[i]) - post := `
        • Error decoding data. Possible file corruption.
        • ` - b.Write([]byte(post)) - continue + post := `
        • Error decoding data. Possible file corruption.
        • ` + b.Write([]byte(post)) + continue + } + + post := adminPostListItem(p, t) + b.Write(post) } + } else { + // reverse the order of posts slice + for i := len(posts) - 1; i >= 0; i-- { + err := json.Unmarshal(posts[i], &p) + if err != nil { + log.Println("Error unmarshal json into", t, err, posts[i]) + + post := `
        • Error decoding data. Possible file corruption.
        • ` + b.Write([]byte(post)) + continue + } - post := adminPostListItem(p, t) - b.Write(post) + post := adminPostListItem(p, t) + b.Write(post) + } } } -- cgit v1.2.3 From dbbadadec8ebd20c55230c14b28ae729b19bc551 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 19:59:10 -0700 Subject: adding check for pending content request to update namespace in db.Content call --- system/admin/handlers.go | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 2b38e16..661ede3 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -804,6 +804,8 @@ func editHandler(res http.ResponseWriter, req *http.Request) { q := req.URL.Query() i := q.Get("id") t := q.Get("type") + status := q.Get("status") + contentType, ok := content.Types[t] if !ok { fmt.Fprintf(res, content.ErrTypeNotRegistered, t) @@ -812,6 +814,9 @@ func editHandler(res http.ResponseWriter, req *http.Request) { post := contentType() if i != "" { + if status == "pending" { + t = t + "_pending" + } data, err := db.Content(t + ":" + i) if err != nil { log.Println(err) -- cgit v1.2.3 From 894968232241a50df69817ebea2c0576ce8f65db Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 20:05:11 -0700 Subject: debugging --- system/admin/handlers.go | 1 + 1 file changed, 1 insertion(+) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 661ede3..9caa231 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -831,6 +831,7 @@ func editHandler(res http.ResponseWriter, req *http.Request) { } if len(data) < 1 || data == nil { + fmt.Println(string(data)) res.WriteHeader(http.StatusNotFound) errView, err := Error404() if err != nil { -- cgit v1.2.3 From 5737f4f300dfd624bdef292bd6e467ec2cbb6037 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 20:08:17 -0700 Subject: debugging --- system/admin/admin.go | 2 +- system/admin/handlers.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'system') diff --git a/system/admin/admin.go b/system/admin/admin.go index 824edc8..9ee86c3 100644 --- a/system/admin/admin.go +++ b/system/admin/admin.go @@ -414,7 +414,7 @@ var err405HTML = `
          405 Error: Method Not Allowed
          -
          Sorry, the page you requested could not be found.
          +
          Sorry, the method of your request is not allowed.
      diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 9caa231..94ce74b 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -817,6 +817,7 @@ func editHandler(res http.ResponseWriter, req *http.Request) { if status == "pending" { t = t + "_pending" } + fmt.Println(t, i, status) data, err := db.Content(t + ":" + i) if err != nil { log.Println(err) -- cgit v1.2.3 From 17bf0b7f04e599e1da010b7312141650a5d21bc7 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 20:15:06 -0700 Subject: testing fix for _pending content retrieval --- system/admin/handlers.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 94ce74b..314ecba 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -677,7 +677,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { continue } - post := adminPostListItem(p, t) + post := adminPostListItem(p, t, "_pending") b.Write(post) } } else { @@ -692,7 +692,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { continue } - post := adminPostListItem(p, t) + post := adminPostListItem(p, t, "") b.Write(post) } } @@ -710,7 +710,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { continue } - post := adminPostListItem(p, t) + post := adminPostListItem(p, t, "_pending") b.Write(post) } } else { @@ -725,7 +725,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { continue } - post := adminPostListItem(p, t) + post := adminPostListItem(p, t, "") b.Write(post) } } @@ -762,7 +762,8 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { // adminPostListItem is a helper to create the li containing a post. // p is the asserted post as an Editable, t is the Type of the post. -func adminPostListItem(p editor.Editable, t string) []byte { +// specifier is passed to append a name to a namespace like _pending +func adminPostListItem(p editor.Editable, t, specifier string) []byte { s, ok := p.(editor.Sortable) if !ok { log.Println("Content type", t, "doesn't implement editor.Sortable") @@ -780,14 +781,14 @@ func adminPostListItem(p editor.Editable, t string) []byte { post := `
    • - ` + p.ContentName() + ` + ` + p.ContentName() + ` Updated: ` + updatedTime + ` ` + publishTime + `
      Delete - +
    • ` @@ -817,7 +818,7 @@ func editHandler(res http.ResponseWriter, req *http.Request) { if status == "pending" { t = t + "_pending" } - fmt.Println(t, i, status) + data, err := db.Content(t + ":" + i) if err != nil { log.Println(err) -- cgit v1.2.3 From 3bdb6bbe79c848ff86664a26e99b0a2f95b83f7d Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 20:16:33 -0700 Subject: testing fix for _pending content retrieval --- system/admin/handlers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 314ecba..9eeb1b2 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -1070,7 +1070,7 @@ func searchHandler(res http.ResponseWriter, req *http.Request) { continue } - post := adminPostListItem(p, t) + post := adminPostListItem(p, t, "") b.Write([]byte(post)) } -- cgit v1.2.3 From 83e0095de7091816080a9b7e70ef09c84cdbbb42 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sat, 29 Oct 2016 20:22:18 -0700 Subject: support to delete _pending content items --- system/admin/handlers.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 9eeb1b2..f7460a3 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -677,7 +677,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { continue } - post := adminPostListItem(p, t, "_pending") + post := adminPostListItem(p, t, "pending") b.Write(post) } } else { @@ -710,7 +710,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { continue } - post := adminPostListItem(p, t, "_pending") + post := adminPostListItem(p, t, "pending") b.Write(post) } } else { @@ -763,7 +763,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { // adminPostListItem is a helper to create the li containing a post. // p is the asserted post as an Editable, t is the Type of the post. // specifier is passed to append a name to a namespace like _pending -func adminPostListItem(p editor.Editable, t, specifier string) []byte { +func adminPostListItem(p editor.Editable, t, status string) []byte { s, ok := p.(editor.Sortable) if !ok { log.Println("Content type", t, "doesn't implement editor.Sortable") @@ -781,14 +781,14 @@ func adminPostListItem(p editor.Editable, t, specifier string) []byte { post := `
    • - ` + p.ContentName() + ` + ` + p.ContentName() + ` Updated: ` + updatedTime + ` ` + publishTime + `
      Delete - +
    • ` -- cgit v1.2.3 From 3ba9236ae25cdf4a2b80b7a1f860edbf2e749e39 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sun, 30 Oct 2016 21:42:51 -0700 Subject: slight refactor of pending content code & reimplementing where needed --- system/api/external.go | 3 +-- system/db/content.go | 32 +++++++++++++++++++------------- 2 files changed, 20 insertions(+), 15 deletions(-) (limited to 'system') diff --git a/system/api/external.go b/system/api/external.go index 52240d5..6489c68 100644 --- a/system/api/external.go +++ b/system/api/external.go @@ -66,7 +66,6 @@ func externalPostsHandler(res http.ResponseWriter, req *http.Request) { ts := fmt.Sprintf("%d", time.Now().Unix()*1000) req.PostForm.Set("timestamp", ts) req.PostForm.Set("updated", ts) - req.PostForm.Set("id", ts) urlPaths, err := upload.StoreFiles(req) if err != nil { @@ -100,7 +99,7 @@ func externalPostsHandler(res http.ResponseWriter, req *http.Request) { req.PostForm.Del(discardKey) } - err = db.SetPendingContent(t+"_pending", req.PostForm) + _, err = db.SetPendingContent(t, req.PostForm) if err != nil { log.Println("[External] error:", err) res.WriteHeader(http.StatusInternalServerError) diff --git a/system/db/content.go b/system/db/content.go index f3397ba..2f6fb90 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -3,14 +3,12 @@ package db import ( "bytes" "encoding/json" - "errors" "fmt" "log" "net/url" "sort" "strconv" "strings" - "time" "github.com/bosssauce/ponzu/content" "github.com/bosssauce/ponzu/management/editor" @@ -116,33 +114,41 @@ func insert(ns string, data url.Values) (int, error) { } // SetPendingContent inserts submitted content for pending approval -func SetPendingContent(target string, data url.Values) error { - if !strings.Contains(target, "_pending") { - return errors.New("Only set items into _pending bucket using SetPendingContent. Namespace should be _pending") - } - - ns := strings.Split(target, "_")[0] +func SetPendingContent(ns string, data url.Values) (int, error) { + var effectedID int err := store.Update(func(tx *bolt.Tx) error { - b, err := tx.CreateBucketIfNotExists([]byte(target)) + b, err := tx.CreateBucketIfNotExists([]byte(ns + "_pending")) + if err != nil { + return err + } + + // get the next available ID and convert to string + // also set effectedID to int of ID + id, err := b.NextSequence() if err != nil { return err } + cid := strconv.FormatUint(id, 10) + effectedID, err = strconv.Atoi(cid) + if err != nil { + return err + } + data.Set("id", cid) - key := fmt.Sprintf("%d", time.Now().UTC().Unix()) j, err := postToJSON(ns, data) if err != nil { return err } - b.Put([]byte(key), j) + b.Put([]byte(cid), j) return nil }) if err != nil { - return err + return 0, err } - return nil + return effectedID, nil } // DeleteContent removes an item from the database. Deleting a non-existent item -- cgit v1.2.3 From dd0fd60357e8a8dcaf3732947a35e5072eeefaf7 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sun, 30 Oct 2016 22:35:47 -0700 Subject: refactor some db code and update how status vars interpolate throughour UI code --- system/admin/handlers.go | 18 +++++++++----- system/api/external.go | 2 +- system/db/content.go | 61 ++++++++++++++++-------------------------------- 3 files changed, 33 insertions(+), 48 deletions(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index f7460a3..dbeefd2 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -534,6 +534,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { } order := strings.ToLower(q.Get("order")) + status := q.Get("status") posts := db.ContentAll(t + "_sorted") b := &bytes.Buffer{} @@ -628,7 +629,6 @@ func postsHandler(res http.ResponseWriter, req *http.Request) {
      ` if hasExt { - status := q.Get("status") if status == "" { q.Add("status", "public") } @@ -677,7 +677,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { continue } - post := adminPostListItem(p, t, "pending") + post := adminPostListItem(p, t, status) b.Write(post) } } else { @@ -692,7 +692,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { continue } - post := adminPostListItem(p, t, "") + post := adminPostListItem(p, t, status) b.Write(post) } } @@ -710,7 +710,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { continue } - post := adminPostListItem(p, t, "pending") + post := adminPostListItem(p, t, status) b.Write(post) } } else { @@ -725,7 +725,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) { continue } - post := adminPostListItem(p, t, "") + post := adminPostListItem(p, t, status) b.Write(post) } } @@ -779,6 +779,12 @@ func adminPostListItem(p editor.Editable, t, status string) []byte { cid := fmt.Sprintf("%d", p.ContentID()) + if status == "public" { + status = "" + } else { + status = "_" + status + } + post := `
    • ` + p.ContentName() + ` @@ -788,7 +794,7 @@ func adminPostListItem(p editor.Editable, t, status string) []byte {
      Delete - +
    • ` diff --git a/system/api/external.go b/system/api/external.go index 6489c68..7426272 100644 --- a/system/api/external.go +++ b/system/api/external.go @@ -99,7 +99,7 @@ func externalPostsHandler(res http.ResponseWriter, req *http.Request) { req.PostForm.Del(discardKey) } - _, err = db.SetPendingContent(t, req.PostForm) + _, err = db.SetContent(t+":-1", req.PostForm) if err != nil { log.Println("[External] error:", err) res.WriteHeader(http.StatusInternalServerError) diff --git a/system/db/content.go b/system/db/content.go index 2f6fb90..2c49e77 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,16 +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 } @@ -108,44 +123,8 @@ func insert(ns string, data url.Values) (int, error) { return 0, err } - go SortContent(ns) - - return effectedID, nil -} - -// SetPendingContent inserts submitted content for pending approval -func SetPendingContent(ns string, data url.Values) (int, error) { - var effectedID int - - err := store.Update(func(tx *bolt.Tx) error { - b, err := tx.CreateBucketIfNotExists([]byte(ns + "_pending")) - if err != nil { - return err - } - - // get the next available ID and convert to string - // also set effectedID to int of ID - id, err := b.NextSequence() - if err != nil { - return err - } - cid := strconv.FormatUint(id, 10) - effectedID, err = strconv.Atoi(cid) - if err != nil { - return err - } - data.Set("id", cid) - - j, err := postToJSON(ns, data) - if err != nil { - return err - } - b.Put([]byte(cid), j) - - return nil - }) - if err != nil { - return 0, err + if specifier == "" { + go SortContent(ns) } return effectedID, nil -- cgit v1.2.3 From 38d6462f5a40317f8c2fdfbd5528b554e3611191 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sun, 30 Oct 2016 22:40:08 -0700 Subject: fixing previously removed specifier for pending in refactored db set content --- system/api/external.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system') diff --git a/system/api/external.go b/system/api/external.go index 7426272..4d52f48 100644 --- a/system/api/external.go +++ b/system/api/external.go @@ -99,7 +99,7 @@ func externalPostsHandler(res http.ResponseWriter, req *http.Request) { req.PostForm.Del(discardKey) } - _, err = db.SetContent(t+":-1", req.PostForm) + _, err = db.SetContent(t+"_pending:-1", req.PostForm) if err != nil { log.Println("[External] error:", err) res.WriteHeader(http.StatusInternalServerError) -- cgit v1.2.3 From 61444e3c7b145527a84a93665704762d70644f19 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sun, 30 Oct 2016 22:45:01 -0700 Subject: left out _ separator from ns+specifier in db call --- system/db/content.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'system') diff --git a/system/db/content.go b/system/db/content.go index 2c49e77..7e804d2 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -51,7 +51,7 @@ func update(ns, id string, data url.Values) (int, error) { } err = store.Update(func(tx *bolt.Tx) error { - b, err := tx.CreateBucketIfNotExists([]byte(ns + specifier)) + b, err := tx.CreateBucketIfNotExists([]byte(ns + "_" + specifier)) if err != nil { return err } @@ -89,7 +89,7 @@ func insert(ns string, data url.Values) (int, error) { } err := store.Update(func(tx *bolt.Tx) error { - b, err := tx.CreateBucketIfNotExists([]byte(ns + specifier)) + b, err := tx.CreateBucketIfNotExists([]byte(ns + "_" + specifier)) if err != nil { return err } -- cgit v1.2.3 From 3f5fefd80ace18f95ec80001cf71af5d2f426c15 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sun, 30 Oct 2016 22:47:50 -0700 Subject: fixing _ specifier location --- system/db/content.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'system') diff --git a/system/db/content.go b/system/db/content.go index 7e804d2..283851c 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -42,7 +42,7 @@ func update(ns, id string, data url.Values) (int, error) { if strings.Contains(ns, "_") { spec := strings.Split(ns, "_") ns = spec[0] - specifier = spec[1] + specifier = "_" + spec[1] } cid, err := strconv.Atoi(id) @@ -51,7 +51,7 @@ func update(ns, id string, data url.Values) (int, error) { } err = store.Update(func(tx *bolt.Tx) error { - b, err := tx.CreateBucketIfNotExists([]byte(ns + "_" + specifier)) + b, err := tx.CreateBucketIfNotExists([]byte(ns + specifier)) if err != nil { return err } @@ -85,11 +85,11 @@ func insert(ns string, data url.Values) (int, error) { if strings.Contains(ns, "_") { spec := strings.Split(ns, "_") ns = spec[0] - specifier = spec[1] + specifier = "_" + spec[1] } err := store.Update(func(tx *bolt.Tx) error { - b, err := tx.CreateBucketIfNotExists([]byte(ns + "_" + specifier)) + b, err := tx.CreateBucketIfNotExists([]byte(ns + specifier)) if err != nil { return err } -- cgit v1.2.3 From f787a4787cd7aed1b8556874967ce407e255c57e Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sun, 30 Oct 2016 22:51:51 -0700 Subject: identified another bug related to _ specifier in UI code --- system/admin/handlers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index dbeefd2..d6c3baa 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -787,7 +787,7 @@ func adminPostListItem(p editor.Editable, t, status string) []byte { post := `
    • - ` + p.ContentName() + ` + ` + p.ContentName() + ` Updated: ` + updatedTime + ` ` + publishTime + ` -- cgit v1.2.3 From 4442aa7afbb15f7c52942f4461eaa5a9c78b5718 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sun, 30 Oct 2016 23:01:33 -0700 Subject: need to delete _sorted bucket before re-sorting on delete --- system/db/content.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'system') diff --git a/system/db/content.go b/system/db/content.go index 283851c..1d4c59e 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -229,7 +229,13 @@ func SortContent(namespace string) { // store in _sorted bucket, first delete existing err := store.Update(func(tx *bolt.Tx) error { - b, err := tx.CreateBucketIfNotExists([]byte(namespace + "_sorted")) + bname := []byte(namespace + "_sorted") + err := tx.DeleteBucket(bname) + if err != nil { + return err + } + + b, err := tx.CreateBucketIfNotExists(bname) if err != nil { return err } -- cgit v1.2.3 From 3016c1e6b38ea845b15571c36257c3137d334d07 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sun, 30 Oct 2016 23:07:12 -0700 Subject: dont allow non main content types to be sorted --- system/db/content.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'system') diff --git a/system/db/content.go b/system/db/content.go index 1d4c59e..bd1ee4b 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -140,7 +140,6 @@ func DeleteContent(target string) error { tx.Bucket([]byte(ns)).Delete([]byte(id)) return nil }) - if err != nil { return err } @@ -207,6 +206,11 @@ 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 -- cgit v1.2.3 From b1dd82806b8e31ff62d5cbb0612998411a8a1259 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sun, 30 Oct 2016 23:14:12 -0700 Subject: fixing delete routine when specifier is in the type name --- system/admin/handlers.go | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index d6c3baa..4a0453d 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -1009,6 +1009,12 @@ func deleteHandler(res http.ResponseWriter, req *http.Request) { return } + // catch specifier suffix from delete form value + if strings.Contains(t, "_") { + spec := strings.Split(t, "_") + t = spec[0] + } + redir := strings.TrimSuffix(req.URL.Scheme+req.URL.Host+req.URL.Path, "/edit/delete") redir = redir + "/posts?type=" + t http.Redirect(res, req, redir, http.StatusFound) -- cgit v1.2.3 From dd4a88bed52b6127503824218fb97645d44e1a7d Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sun, 30 Oct 2016 23:31:37 -0700 Subject: adding initial code for merging pending to private content --- system/admin/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system') diff --git a/system/admin/server.go b/system/admin/server.go index 161220e..5d93d84 100644 --- a/system/admin/server.go +++ b/system/admin/server.go @@ -24,11 +24,11 @@ func Run() { http.HandleFunc("/admin/configure/users/delete", user.Auth(configUsersDeleteHandler)) http.HandleFunc("/admin/posts", user.Auth(postsHandler)) - http.HandleFunc("/admin/posts/approve", user.Auth(approvePostHandler)) http.HandleFunc("/admin/posts/search", user.Auth(searchHandler)) http.HandleFunc("/admin/edit", user.Auth(editHandler)) http.HandleFunc("/admin/edit/delete", user.Auth(deleteHandler)) + http.HandleFunc("/admin/edit/approve", user.Auth(approvePostHandler)) http.HandleFunc("/admin/edit/upload", user.Auth(editUploadHandler)) pwd, err := os.Getwd() -- cgit v1.2.3 From e747830167e22d97ea34969fab3cfe1c71c35f75 Mon Sep 17 00:00:00 2001 From: Steve Manuel Date: Sun, 30 Oct 2016 23:38:11 -0700 Subject: pulling getParam into utils file --- system/admin/handlers.go | 15 --------------- system/admin/static/common/js/util.js | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) (limited to 'system') diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 4a0453d..84f047c 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -585,21 +585,6 @@ func postsHandler(res http.ResponseWriter, req *http.Request) {