summaryrefslogtreecommitdiff
path: root/system/api
diff options
context:
space:
mode:
Diffstat (limited to 'system/api')
-rw-r--r--system/api/create.go (renamed from system/api/external.go)48
-rw-r--r--system/api/delete.go140
-rw-r--r--system/api/handlers.go4
-rw-r--r--system/api/server.go4
-rw-r--r--system/api/update.go29
5 files changed, 184 insertions, 41 deletions
diff --git a/system/api/external.go b/system/api/create.go
index 7f13917..3328bd6 100644
--- a/system/api/external.go
+++ b/system/api/create.go
@@ -14,20 +14,20 @@ import (
"github.com/ponzu-cms/ponzu/system/item"
)
-// Externalable accepts or rejects external POST requests to endpoints such as:
-// /api/content/external?type=Review
-type Externalable interface {
- // Accept allows external content submissions of a specific type
- Accept(http.ResponseWriter, *http.Request) error
+// Createable accepts or rejects external POST requests to endpoints such as:
+// /api/content/create?type=Review
+type Createable interface {
+ // Create enables external clients to submit content of a specific type
+ Create(http.ResponseWriter, *http.Request) error
}
// Trustable allows external content to be auto-approved, meaning content sent
-// as an Externalable will be stored in the public content bucket
+// as an Createable will be stored in the public content bucket
type Trustable interface {
AutoApprove(http.ResponseWriter, *http.Request) error
}
-func externalContentHandler(res http.ResponseWriter, req *http.Request) {
+func createContentHandler(res http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodPost {
res.WriteHeader(http.StatusMethodNotAllowed)
return
@@ -35,7 +35,7 @@ func externalContentHandler(res http.ResponseWriter, req *http.Request) {
err := req.ParseMultipartForm(1024 * 1024 * 4) // maxMemory 4MB
if err != nil {
- log.Println("[External] error:", err)
+ log.Println("[Create] error:", err)
res.WriteHeader(http.StatusInternalServerError)
return
}
@@ -48,16 +48,16 @@ func externalContentHandler(res http.ResponseWriter, req *http.Request) {
p, found := item.Types[t]
if !found {
- log.Println("[External] attempt to submit unknown type:", t, "from:", req.RemoteAddr)
+ log.Println("[Create] attempt to submit unknown type:", t, "from:", req.RemoteAddr)
res.WriteHeader(http.StatusNotFound)
return
}
post := p()
- ext, ok := post.(Externalable)
+ ext, ok := post.(Createable)
if !ok {
- log.Println("[External] rejected non-externalable type:", t, "from:", req.RemoteAddr)
+ log.Println("[Create] rejected non-createable type:", t, "from:", req.RemoteAddr)
res.WriteHeader(http.StatusBadRequest)
return
}
@@ -126,26 +126,26 @@ func externalContentHandler(res http.ResponseWriter, req *http.Request) {
hook, ok := post.(item.Hookable)
if !ok {
- log.Println("[External] error: Type", t, "does not implement item.Hookable or embed item.Item.")
+ log.Println("[Create] error: Type", t, "does not implement item.Hookable or embed item.Item.")
res.WriteHeader(http.StatusBadRequest)
return
}
- err = hook.BeforeAccept(res, req)
+ err = hook.BeforeAPICreate(res, req)
if err != nil {
- log.Println("[External] error calling BeforeAccept:", err)
+ log.Println("[Create] error calling BeforeAccept:", err)
return
}
- err = ext.Accept(res, req)
+ err = ext.Create(res, req)
if err != nil {
- log.Println("[External] error calling Accept:", err)
+ log.Println("[Create] error calling Accept:", err)
return
}
err = hook.BeforeSave(res, req)
if err != nil {
- log.Println("[External] error calling BeforeSave:", err)
+ log.Println("[Create] error calling BeforeSave:", err)
return
}
@@ -160,7 +160,7 @@ func externalContentHandler(res http.ResponseWriter, req *http.Request) {
if ok {
err := trusted.AutoApprove(res, req)
if err != nil {
- log.Println("[External] error calling AutoApprove:", err)
+ log.Println("[Create] error calling AutoApprove:", err)
return
}
} else {
@@ -169,7 +169,7 @@ func externalContentHandler(res http.ResponseWriter, req *http.Request) {
id, err := db.SetContent(t+spec+":-1", req.PostForm)
if err != nil {
- log.Println("[External] error calling SetContent:", err)
+ log.Println("[Create] error calling SetContent:", err)
res.WriteHeader(http.StatusInternalServerError)
return
}
@@ -180,13 +180,13 @@ func externalContentHandler(res http.ResponseWriter, req *http.Request) {
err = hook.AfterSave(res, req)
if err != nil {
- log.Println("[External] error calling AfterSave:", err)
+ log.Println("[Create] error calling AfterSave:", err)
return
}
- err = hook.AfterAccept(res, req)
+ err = hook.AfterAPICreate(res, req)
if err != nil {
- log.Println("[External] error calling AfterAccept:", err)
+ log.Println("[Create] error calling AfterAccept:", err)
return
}
@@ -215,7 +215,7 @@ func externalContentHandler(res http.ResponseWriter, req *http.Request) {
j, err := json.Marshal(resp)
if err != nil {
- log.Println("[External] error marshalling response to JSON:", err)
+ log.Println("[Create] error marshalling response to JSON:", err)
res.WriteHeader(http.StatusInternalServerError)
return
}
@@ -223,7 +223,7 @@ func externalContentHandler(res http.ResponseWriter, req *http.Request) {
res.Header().Set("Content-Type", "application/json")
_, err = res.Write(j)
if err != nil {
- log.Println("[External] error writing response:", err)
+ log.Println("[Create] error writing response:", err)
return
}
diff --git a/system/api/delete.go b/system/api/delete.go
new file mode 100644
index 0000000..36f2b1b
--- /dev/null
+++ b/system/api/delete.go
@@ -0,0 +1,140 @@
+package api
+
+import (
+ "encoding/json"
+ "log"
+ "net/http"
+
+ "github.com/ponzu-cms/ponzu/system/db"
+ "github.com/ponzu-cms/ponzu/system/item"
+)
+
+// Deleteable accepts or rejects update POST requests to endpoints such as:
+// /api/content/delete?type=Review&id=1
+type Deleteable interface {
+ // Delete enables external clients to delete content of a specific type
+ Delete(http.ResponseWriter, *http.Request) error
+}
+
+func deleteContentHandler(res http.ResponseWriter, req *http.Request) {
+ if req.Method != http.MethodPost {
+ res.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+
+ err := req.ParseMultipartForm(1024 * 1024 * 4) // maxMemory 4MB
+ if err != nil {
+ log.Println("[Delete] error:", err)
+ res.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
+ t := req.URL.Query().Get("type")
+ if t == "" {
+ res.WriteHeader(http.StatusBadRequest)
+ return
+ }
+
+ p, found := item.Types[t]
+ if !found {
+ log.Println("[Delete] attempt to delete content of unknown type:", t, "from:", req.RemoteAddr)
+ res.WriteHeader(http.StatusNotFound)
+ return
+ }
+
+ id := req.URL.Query().Get("id")
+ if !db.IsValidID(id) {
+ log.Println("[Delete] attempt to delete content with missing or invalid id from:", req.RemoteAddr)
+ res.WriteHeader(http.StatusBadRequest)
+ return
+ }
+
+ post := p()
+
+ ext, ok := post.(Deleteable)
+ if !ok {
+ log.Println("[Delete] rejected non-deleteable type:", t, "from:", req.RemoteAddr)
+ res.WriteHeader(http.StatusBadRequest)
+ return
+ }
+
+ hook, ok := post.(item.Hookable)
+ if !ok {
+ log.Println("[Delete] error: Type", t, "does not implement item.Hookable or embed item.Item.")
+ res.WriteHeader(http.StatusBadRequest)
+ return
+ }
+
+ err = hook.BeforeAPIDelete(res, req)
+ if err != nil {
+ log.Println("[Delete] error calling BeforeAPIDelete:", err)
+ if err == ErrNoAuth {
+ // BeforeAPIDelete can check user.IsValid(req) for auth
+ res.WriteHeader(http.StatusUnauthorized)
+ }
+ return
+ }
+
+ err = ext.Delete(res, req)
+ if err != nil {
+ log.Println("[Delete] error calling Delete:", err)
+ if err == ErrNoAuth {
+ // Delete can check user.IsValid(req) or other forms of validation for auth
+ res.WriteHeader(http.StatusUnauthorized)
+ }
+ return
+ }
+
+ err = hook.BeforeDelete(res, req)
+ if err != nil {
+ log.Println("[Delete] error calling BeforeSave:", err)
+ return
+ }
+
+ err = db.DeleteContent(t + ":" + id)
+ if err != nil {
+ log.Println("[Delete] error calling DeleteContent:", err)
+ res.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
+ err = hook.AfterDelete(res, req)
+ if err != nil {
+ log.Println("[Delete] error calling AfterDelete:", err)
+ return
+ }
+
+ err = hook.AfterAPIDelete(res, req)
+ if err != nil {
+ log.Println("[Delete] error calling AfterAPIDelete:", err)
+ return
+ }
+
+ // create JSON response to send data back to client
+ var data = map[string]interface{}{
+ "id": id,
+ "status": "deleted",
+ "type": t,
+ }
+
+ resp := map[string]interface{}{
+ "data": []map[string]interface{}{
+ data,
+ },
+ }
+
+ j, err := json.Marshal(resp)
+ if err != nil {
+ log.Println("[Delete] error marshalling response to JSON:", err)
+ res.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
+ res.Header().Set("Content-Type", "application/json")
+ _, err = res.Write(j)
+ if err != nil {
+ log.Println("[Delete] error writing response:", err)
+ return
+ }
+
+}
diff --git a/system/api/handlers.go b/system/api/handlers.go
index 4a9eaff..83bbe43 100644
--- a/system/api/handlers.go
+++ b/system/api/handlers.go
@@ -2,6 +2,7 @@ package api
import (
"encoding/json"
+ "errors"
"log"
"net/http"
"strconv"
@@ -11,6 +12,9 @@ import (
"github.com/ponzu-cms/ponzu/system/item"
)
+// ErrNoAuth should be used to report failed auth requests
+var ErrNoAuth = errors.New("Auth failed for request")
+
// deprecating from API, but going to provide code here in case someone wants it
func typesHandler(res http.ResponseWriter, req *http.Request) {
var types = []string{}
diff --git a/system/api/server.go b/system/api/server.go
index 6a848dd..c568877 100644
--- a/system/api/server.go
+++ b/system/api/server.go
@@ -8,7 +8,9 @@ func Run() {
http.HandleFunc("/api/content", Record(CORS(Gzip(contentHandler))))
- http.HandleFunc("/api/content/external", Record(CORS(externalContentHandler)))
+ http.HandleFunc("/api/content/create", Record(CORS(createContentHandler)))
http.HandleFunc("/api/content/update", Record(CORS(updateContentHandler)))
+
+ http.HandleFunc("/api/content/delete", Record(CORS(deleteContentHandler)))
}
diff --git a/system/api/update.go b/system/api/update.go
index 3a92a84..f7f7346 100644
--- a/system/api/update.go
+++ b/system/api/update.go
@@ -3,7 +3,6 @@ package api
import (
"context"
"encoding/json"
- "errors"
"fmt"
"log"
"net/http"
@@ -15,13 +14,11 @@ import (
"github.com/ponzu-cms/ponzu/system/item"
)
-var ErrNoAuth = errors.New("Auth failed for update request.")
-
// Updateable accepts or rejects update POST requests to endpoints such as:
// /api/content/update?type=Review&id=1
type Updateable interface {
- // AcceptUpdate allows external content update submissions of a specific type
- AcceptUpdate(http.ResponseWriter, *http.Request) error
+ // Update enabled external clients to update content of a specific type
+ Update(http.ResponseWriter, *http.Request) error
}
func updateContentHandler(res http.ResponseWriter, req *http.Request) {
@@ -45,14 +42,14 @@ func updateContentHandler(res http.ResponseWriter, req *http.Request) {
p, found := item.Types[t]
if !found {
- log.Println("[Update] attempt to submit unknown type:", t, "from:", req.RemoteAddr)
+ log.Println("[Update] attempt to update content unknown type:", t, "from:", req.RemoteAddr)
res.WriteHeader(http.StatusNotFound)
return
}
id := req.URL.Query().Get("id")
if !db.IsValidID(id) {
- log.Println("[Update] attempt to submit update with missing or invalid id from:", req.RemoteAddr)
+ log.Println("[Update] attempt to update content with missing or invalid id from:", req.RemoteAddr)
res.WriteHeader(http.StatusBadRequest)
return
}
@@ -135,21 +132,21 @@ func updateContentHandler(res http.ResponseWriter, req *http.Request) {
return
}
- err = hook.BeforeAcceptUpdate(res, req)
+ err = hook.BeforeAPIUpdate(res, req)
if err != nil {
- log.Println("[Update] error calling BeforeAcceptUpdate:", err)
+ log.Println("[Update] error calling BeforeAPIUpdate:", err)
if err == ErrNoAuth {
- // BeforeAcceptUpdate can check user.IsValid(req) for auth
+ // BeforeAPIUpdate can check user.IsValid(req) for auth
res.WriteHeader(http.StatusUnauthorized)
}
return
}
- err = ext.AcceptUpdate(res, req)
+ err = ext.Update(res, req)
if err != nil {
- log.Println("[Update] error calling AcceptUpdate:", err)
+ log.Println("[Update] error calling Update:", err)
if err == ErrNoAuth {
- // AcceptUpdate can check user.IsValid(req) for auth
+ // Update can check user.IsValid(req) or other forms of validation for auth
res.WriteHeader(http.StatusUnauthorized)
}
return
@@ -172,7 +169,7 @@ func updateContentHandler(res http.ResponseWriter, req *http.Request) {
}
// set the target in the context so user can get saved value from db in hook
- ctx := context.WithValue(req.Context(), "target", fmt.Sprintf("%s:%d", t, id))
+ ctx := context.WithValue(req.Context(), "target", fmt.Sprintf("%s:%s", t, id))
req = req.WithContext(ctx)
err = hook.AfterSave(res, req)
@@ -181,9 +178,9 @@ func updateContentHandler(res http.ResponseWriter, req *http.Request) {
return
}
- err = hook.AfterAcceptUpdate(res, req)
+ err = hook.AfterAPIUpdate(res, req)
if err != nil {
- log.Println("[Update] error calling AfterAcceptUpdate:", err)
+ log.Println("[Update] error calling AfterAPIUpdate:", err)
return
}