diff options
Diffstat (limited to 'system/api/delete.go')
-rw-r--r-- | system/api/delete.go | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/system/api/delete.go b/system/api/delete.go new file mode 100644 index 0000000..68b5f35 --- /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, req.PostForm) + 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 + } + +} |