Add editor to create, update or delete posts

This commit is contained in:
Jan-Lukas Else 2020-12-12 23:44:03 +01:00
parent 366514699d
commit eeb68dbba9
8 changed files with 156 additions and 4 deletions

85
editor.go Normal file
View File

@ -0,0 +1,85 @@
package main
import (
"bytes"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
)
const editorPath = "/editor"
func serveEditor(w http.ResponseWriter, r *http.Request) {
render(w, templateEditor, &renderData{})
}
func serveEditorPost(w http.ResponseWriter, r *http.Request) {
if action := r.FormValue("editoraction"); action != "" {
if action == "loadupdate" {
parsedURL, err := url.Parse(r.FormValue("url"))
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
post, err := getPost(parsedURL.Path)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
mf := post.toMfItem()
render(w, templateEditor, &renderData{
Data: map[string]interface{}{
"UpdatePostURL": parsedURL.String(),
"UpdatePostContent": mf.Properties.Content[0],
},
})
return
} else if action == "updatepost" {
urlValue := r.FormValue("url")
content := r.FormValue("content")
mf := map[string]interface{}{
"action": actionUpdate,
"url": urlValue,
"replace": map[string][]string{
"content": {
content,
},
},
}
jsonBytes, err := json.Marshal(mf)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
req, err := http.NewRequest(http.MethodPost, "", bytes.NewReader(jsonBytes))
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
req.Header.Set(contentType, contentTypeJSON)
editorMicropubPost(w, req)
return
}
http.Error(w, "unknown editoraction", http.StatusBadRequest)
return
}
editorMicropubPost(w, r)
}
func editorMicropubPost(w http.ResponseWriter, r *http.Request) {
recorder := httptest.NewRecorder()
addAllScopes(http.HandlerFunc(serveMicropubPost)).ServeHTTP(recorder, r)
result := recorder.Result()
if location := result.Header.Get("Location"); location != "" {
http.Redirect(w, r, result.Header.Get("Location"), http.StatusFound)
return
}
if result.StatusCode >= 200 && result.StatusCode <= 400 {
http.Redirect(w, r, editorPath, http.StatusFound)
return
}
w.WriteHeader(result.StatusCode)
body, _ := ioutil.ReadAll(result.Body)
w.Write(body)
}

View File

@ -106,6 +106,13 @@ func buildHandler() (http.Handler, error) {
}
})
// Editor
r.Route("/editor", func(mpRouter chi.Router) {
mpRouter.Use(authMiddleware)
mpRouter.Get("/", serveEditor)
mpRouter.Post("/", serveEditorPost)
})
// IndieAuth
r.Route("/indieauth", func(indieauthRouter chi.Router) {
indieauthRouter.Use(middleware.NoCache)

View File

@ -21,3 +21,10 @@ func checkIndieAuth(next http.Handler) http.Handler {
return
})
}
func addAllScopes(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
next.ServeHTTP(rw, r.WithContext(context.WithValue(r.Context(), "scope", "create update delete media")))
return
})
}

View File

@ -90,6 +90,8 @@ func (p *post) toMfItem() *microformatItem {
params["path"] = []string{p.Path}
params["section"] = []string{p.Section}
params["blog"] = []string{p.Blog}
params["published"] = []string{p.Published}
params["updated"] = []string{p.Updated}
pb, _ := yaml.Marshal(p.Parameters)
content := fmt.Sprintf("---\n%s---\n%s", string(pb), p.Content)
return &microformatItem{
@ -185,8 +187,7 @@ func serveMicropubPost(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Add("Location", p.fullURL())
w.WriteHeader(http.StatusAccepted)
http.Redirect(w, r, p.fullURL(), http.StatusAccepted)
return
}
@ -424,7 +425,7 @@ func micropubDelete(w http.ResponseWriter, r *http.Request, u *url.URL) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
w.WriteHeader(http.StatusNoContent)
http.Redirect(w, r, u.String(), http.StatusNoContent)
return
}
@ -557,4 +558,5 @@ func micropubUpdate(w http.ResponseWriter, r *http.Request, u *url.URL, mf *micr
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
http.Redirect(w, r, p.fullURL(), http.StatusNoContent)
}

View File

@ -56,6 +56,13 @@ func (p *post) checkPost() error {
if p.Blog == "" {
p.Blog = appConfig.DefaultBlog
}
if _, ok := appConfig.Blogs[p.Blog]; !ok {
return errors.New("blog doesn't exist")
}
// Check if section exists
if _, ok := appConfig.Blogs[p.Blog].Sections[p.Section]; p.Section != "" && !ok {
return errors.New("section doesn't exist")
}
// Check path
p.Path = strings.TrimSuffix(p.Path, "/")
if p.Path == "" {

View File

@ -30,6 +30,7 @@ const templateTaxonomy = "taxonomy"
const templateSearch = "search"
const templateSummary = "summary"
const templatePhotosSummary = "photosummary"
const templateEditor = "editor"
var templates map[string]*template.Template
var templateFunctions template.FuncMap
@ -229,6 +230,9 @@ func render(w http.ResponseWriter, template string, data *renderData) {
}
data.Blog = appConfig.Blogs[data.blogString]
}
if data.Data == nil {
data.Data = map[string]interface{}{}
}
// We need to use a buffer here to enable minification
var buffer bytes.Buffer
err := templates[template].ExecuteTemplate(&buffer, template, data)

37
templates/editor.gohtml Normal file
View File

@ -0,0 +1,37 @@
{{ define "title" }}
<title>{{ string .Blog.Lang "editor" }} - {{ .Blog.Title }}</title>
{{ end }}
{{ define "main" }}
<main>
<h1>{{ string .Blog.Lang "editor" }}</h1>
<h2>{{ string .Blog.Lang "create" }}</h2>
<form class="fw-form p" method="post">
<input type="hidden" name="h" value="entry">
<textarea class="fw" name="content"></textarea>
<input class="fw" type="submit" value="{{ string .Blog.Lang "create" }}">
</form>
<h2>{{ string .Blog.Lang "update" }}</h2>
<form class="fw-form p" method="post">
{{ if .Data.UpdatePostURL }}
<input type="hidden" name="editoraction" value="updatepost">
<input type="hidden" name="url" value="{{ .Data.UpdatePostURL }}">
<textarea class="fw" name="content">{{ .Data.UpdatePostContent }}</textarea>
{{ else }}
<input type="hidden" name="editoraction" value="loadupdate">
<input class="fw" type="text" style="margin-bottom: 5px" name="url" placeholder="URL">
{{ end }}
<input class="fw" type="submit" value="{{ string .Blog.Lang "update" }}">
</form>
<h2>{{ string .Blog.Lang "delete" }}</h2>
<form class="fw-form p" method="post">
<input type="hidden" name="action" value="delete">
<input class="fw" type="text" style="margin-bottom: 5px" name="url" placeholder="URL">
<input class="fw" type="submit" value="{{ string .Blog.Lang "delete" }}">
</form>
</main>
{{ end }}
{{ define "editor" }}
{{ template "base" . }}
{{ end }}

View File

@ -22,4 +22,7 @@ anoncomment: "You can also create an anonymous comment."
interactions: "Interactions"
send: "Send"
interactionslabel: "Have you published a response to this? Paste the URL here."
search: "Search"
search: "Search"
editor: "Editor"
create: "Create"
update: "Update"