summaryrefslogtreecommitdiff
path: root/system/admin/handlers.go
diff options
context:
space:
mode:
Diffstat (limited to 'system/admin/handlers.go')
-rw-r--r--system/admin/handlers.go418
1 files changed, 405 insertions, 13 deletions
diff --git a/system/admin/handlers.go b/system/admin/handlers.go
index 1f277e0..38ce41d 100644
--- a/system/admin/handlers.go
+++ b/system/admin/handlers.go
@@ -21,6 +21,7 @@ import (
"github.com/bosssauce/ponzu/system/db"
"github.com/gorilla/schema"
+ emailer "github.com/nilslice/email"
"github.com/nilslice/jwt"
)
@@ -521,12 +522,187 @@ func logoutHandler(res http.ResponseWriter, req *http.Request) {
http.Redirect(res, req, req.URL.Scheme+req.URL.Host+"/admin/login", http.StatusFound)
}
+func forgotPasswordHandler(res http.ResponseWriter, req *http.Request) {
+ switch req.Method {
+ case http.MethodGet:
+ view, err := ForgotPassword()
+ if err != nil {
+ res.WriteHeader(http.StatusInternalServerError)
+ errView, err := Error500()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
+ res.Write(view)
+
+ case http.MethodPost:
+ err := req.ParseMultipartForm(1024 * 1024 * 4) // maxMemory 4MB
+ if err != nil {
+ res.WriteHeader(http.StatusBadRequest)
+ errView, err := Error400()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
+ // check email for user, if no user return Error
+ email := strings.ToLower(req.FormValue("email"))
+ if email == "" {
+ res.WriteHeader(http.StatusBadRequest)
+ errView, err := Error400()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
+ _, err = db.User(email)
+ if err == db.ErrNoUserExists {
+ res.WriteHeader(http.StatusBadRequest)
+ errView, err := Error400()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
+ if err != db.ErrNoUserExists && err != nil {
+ res.WriteHeader(http.StatusInternalServerError)
+ errView, err := Error500()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
+ // create temporary key to verify user
+ key, err := db.SetRecoveryKey(email)
+ if err != nil {
+ res.WriteHeader(http.StatusInternalServerError)
+ errView, err := Error500()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
+ domain := db.ConfigCache("domain")
+ body := fmt.Sprintf(`
+ There has been an account recovery request made for the user with email:
+ %s
+
+ To recover your account, please go to http://%s/admin/recover/key and enter
+ this email address along with the following secret key:
+
+ %s
+
+ If you did not make the request, ignore this message and your password
+ will remain as-is.
+
+
+ Thank you,
+ Ponzu CMS at %s
+
+ `, email, domain, key, domain)
+ msg := emailer.Message{
+ To: email,
+ From: fmt.Sprintf("Ponzu CMS <ponzu-cms@%s", domain),
+ Subject: fmt.Sprintf("Account Recovery [%s]", domain),
+ Body: body,
+ }
+
+ /*
+ err = msg.Send()
+ if err != nil {
+ res.WriteHeader(http.StatusInternalServerError)
+ errView, err := Error500()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+ */
+ fmt.Println(msg)
+
+ // redirect to /admin/recover/key and send email with key and URL
+ http.Redirect(res, req, req.URL.Scheme+req.URL.Host+"/admin/recover/key", http.StatusFound)
+
+ default:
+ res.WriteHeader(http.StatusMethodNotAllowed)
+ errView, err := Error405()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+}
+
+func recoveryKeyHandler(res http.ResponseWriter, req *http.Request) {
+ switch req.Method {
+ case http.MethodGet:
+ view, err := RecoveryKey()
+ if err != nil {
+ res.WriteHeader(http.StatusInternalServerError)
+ errView, err := Error500()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
+ res.Write(view)
+
+ case http.MethodPost:
+
+ // check for email & key match
+
+ // set user with new password
+
+ // redirect to /admin/login
+
+ default:
+ res.WriteHeader(http.StatusMethodNotAllowed)
+ errView, err := Error405()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+}
+
+func recoveryEditHandler(res http.ResponseWriter, req *http.Request) {
+
+}
+
func postsHandler(res http.ResponseWriter, req *http.Request) {
q := req.URL.Query()
t := q.Get("type")
if t == "" {
res.WriteHeader(http.StatusBadRequest)
- errView, err := Error405()
+ errView, err := Error400()
if err != nil {
return
}
@@ -544,7 +720,7 @@ func postsHandler(res http.ResponseWriter, req *http.Request) {
if _, ok := content.Types[t]; !ok {
res.WriteHeader(http.StatusBadRequest)
- errView, err := Error405()
+ errView, err := Error400()
if err != nil {
return
}
@@ -717,7 +893,22 @@ func postsHandler(res http.ResponseWriter, req *http.Request) {
}
}
+ } else {
+ for i := range posts {
+ err := json.Unmarshal(posts[i], &p)
+ if err != nil {
+ log.Println("Error unmarshal json into", t, err, posts[i])
+
+ post := `<li class="col s12">Error decoding data. Possible file corruption.</li>`
+ b.Write([]byte(post))
+ continue
+ }
+
+ post := adminPostListItem(p, t, status)
+ b.Write(post)
+ }
}
+
html += `<ul class="posts row">`
b.Write([]byte(`</ul></div></div>`))
@@ -822,10 +1013,24 @@ func approvePostHandler(res http.ResponseWriter, req *http.Request) {
post := content.Types[t]()
+ // run hooks
+ hook, ok := post.(content.Hookable)
+ if !ok {
+ log.Println("Type", t, "does not implement content.Hookable or embed content.Item.")
+ res.WriteHeader(http.StatusBadRequest)
+ errView, err := Error400()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
// check if we have a Mergeable
- m, ok := post.(api.Mergeable)
+ m, ok := post.(editor.Mergeable)
if !ok {
- log.Println("Content type", t, "must implement api.Mergable before it can bee approved.")
+ log.Println("Content type", t, "must implement editor.Mergable before it can bee approved.")
res.WriteHeader(http.StatusBadRequest)
errView, err := Error400()
if err != nil {
@@ -851,6 +1056,18 @@ func approvePostHandler(res http.ResponseWriter, req *http.Request) {
return
}
+ err = hook.BeforeApprove(req)
+ if err != nil {
+ res.WriteHeader(http.StatusInternalServerError)
+ errView, err := Error500()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
// call its Approve method
err = m.Approve(req)
if err != nil {
@@ -864,6 +1081,30 @@ func approvePostHandler(res http.ResponseWriter, req *http.Request) {
return
}
+ err = hook.AfterApprove(req)
+ if err != nil {
+ res.WriteHeader(http.StatusInternalServerError)
+ errView, err := Error500()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
+ err = hook.BeforeSave(req)
+ if err != nil {
+ res.WriteHeader(http.StatusInternalServerError)
+ errView, err := Error500()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
// Store the content in the bucket t
id, err := db.SetContent(t+":-1", req.Form)
if err != nil {
@@ -877,6 +1118,18 @@ func approvePostHandler(res http.ResponseWriter, req *http.Request) {
return
}
+ err = hook.AfterSave(req)
+ if err != nil {
+ res.WriteHeader(http.StatusInternalServerError)
+ errView, err := Error500()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
// redirect to the new approved content's editor
redir := req.URL.Scheme + req.URL.Host + strings.TrimSuffix(req.URL.Path, "/approve")
redir += fmt.Sprintf("?type=%s&id=%d", t, id)
@@ -946,7 +1199,7 @@ func editHandler(res http.ResponseWriter, req *http.Request) {
log.Println("Content type", t, "doesn't implement editor.Identifiable")
return
}
- s.SetContentID(-1)
+ s.SetItemID(-1)
}
@@ -1040,6 +1293,50 @@ func editHandler(res http.ResponseWriter, req *http.Request) {
req.PostForm.Del(discardKey)
}
+ if strings.Contains(t, "_") {
+ t = strings.Split(t, "_")[0]
+ }
+
+ p, ok := content.Types[t]
+ if !ok {
+ log.Println("Type", t, "is not a content type. Cannot edit or save.")
+ res.WriteHeader(http.StatusBadRequest)
+ errView, err := Error400()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
+ post := p()
+ hook, ok := post.(content.Hookable)
+ if !ok {
+ log.Println("Type", t, "does not implement content.Hookable or embed content.Item.")
+ res.WriteHeader(http.StatusBadRequest)
+ errView, err := Error400()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
+ err = hook.BeforeSave(req)
+ if err != nil {
+ log.Println(err)
+ res.WriteHeader(http.StatusInternalServerError)
+ errView, err := Error500()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
id, err := db.SetContent(t+":"+cid, req.PostForm)
if err != nil {
log.Println(err)
@@ -1053,13 +1350,23 @@ func editHandler(res http.ResponseWriter, req *http.Request) {
return
}
+ err = hook.AfterSave(req)
+ if err != nil {
+ log.Println(err)
+ res.WriteHeader(http.StatusInternalServerError)
+ errView, err := Error500()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
scheme := req.URL.Scheme
host := req.URL.Host
path := req.URL.Path
sid := fmt.Sprintf("%d", id)
- if strings.Contains(t, "_") {
- t = strings.Split(t, "_")[0]
- }
redir := scheme + host + path + "?type=" + t + "&id=" + sid
if req.URL.Query().Get("status") == "pending" {
@@ -1088,12 +1395,75 @@ func deleteHandler(res http.ResponseWriter, req *http.Request) {
id := req.FormValue("id")
t := req.FormValue("type")
+ ct := t
if id == "" || t == "" {
res.WriteHeader(http.StatusBadRequest)
return
}
+ // catch specifier suffix from delete form value
+ if strings.Contains(t, "_") {
+ spec := strings.Split(t, "_")
+ ct = spec[0]
+ }
+
+ p, ok := content.Types[ct]
+ if !ok {
+ log.Println("Type", t, "does not implement content.Hookable or embed content.Item.")
+ res.WriteHeader(http.StatusBadRequest)
+ errView, err := Error400()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
+ post := p()
+ hook, ok := post.(content.Hookable)
+ if !ok {
+ log.Println("Type", t, "does not implement content.Hookable or embed content.Item.")
+ res.WriteHeader(http.StatusBadRequest)
+ errView, err := Error400()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
+ reject := req.URL.Query().Get("reject")
+ if reject == "true" {
+ err = hook.BeforeReject(req)
+ if err != nil {
+ log.Println(err)
+ res.WriteHeader(http.StatusInternalServerError)
+ errView, err := Error500()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+ }
+
+ err = hook.BeforeDelete(req)
+ if err != nil {
+ log.Println(err)
+ res.WriteHeader(http.StatusInternalServerError)
+ errView, err := Error500()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
err = db.DeleteContent(t + ":" + id)
if err != nil {
log.Println(err)
@@ -1101,14 +1471,36 @@ 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]
+ err = hook.AfterDelete(req)
+ if err != nil {
+ log.Println(err)
+ res.WriteHeader(http.StatusInternalServerError)
+ errView, err := Error500()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
+
+ if reject == "true" {
+ err = hook.AfterReject(req)
+ if err != nil {
+ log.Println(err)
+ res.WriteHeader(http.StatusInternalServerError)
+ errView, err := Error500()
+ if err != nil {
+ return
+ }
+
+ res.Write(errView)
+ return
+ }
}
redir := strings.TrimSuffix(req.URL.Scheme+req.URL.Host+req.URL.Path, "/edit/delete")
- redir = redir + "/posts?type=" + t
+ redir = redir + "/posts?type=" + ct
http.Redirect(res, req, redir, http.StatusFound)
}