From 69880643092feafde7d3ba0f60388dbdfcde9aa4 Mon Sep 17 00:00:00 2001 From: Chris Sexton Date: Thu, 23 Jul 2020 12:13:58 -0400 Subject: [PATCH] adoc support * These changes are unverified and I don't know what they're really for * Ref #7 --- auth/auth.go | 2 +- entry/entry.go | 31 ++++++++++++++- web/entry.go | 103 ++++++++++++++++++++++--------------------------- web/routes.go | 5 ++- 4 files changed, 81 insertions(+), 60 deletions(-) diff --git a/auth/auth.go b/auth/auth.go index 2739a8f..9eac86d 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -49,7 +49,7 @@ func makeKey() (string, error) { } func New(db *db.Database, name, password string) (*User, error) { - q := `insert into users values (null, ?, ?, ?, ?)` + q := `insert or replace into users values (null, ?, ?, ?, ?)` key, err := makeKey() if err != nil { diff --git a/entry/entry.go b/entry/entry.go index 5c18704..1dd32a4 100644 --- a/entry/entry.go +++ b/entry/entry.go @@ -2,6 +2,8 @@ package entry import ( "fmt" + "io" + "os/exec" "regexp" "strings" "time" @@ -53,7 +55,7 @@ func PrepareTable(tx *sqlx.Tx) error { return nil } -func NewFromMd(db *db.Database, body string) *Entry { +func NewFromAdoc(db *db.Database, body string) *Entry { e := New(db) e.Content = body e.Title = e.GenerateTitle() @@ -61,6 +63,33 @@ func NewFromMd(db *db.Database, body string) *Entry { return e } +func pandocMdToAdoc(body string) string { + log.Debug().Str("input", body).Msgf("converting md->adoc") + cmd := exec.Command("pandoc", "-f", "commonmark", "-t", "asciidoctor") + stdin, err := cmd.StdinPipe() + if err != nil { + log.Error().Err(err).Msgf("could not get stdin") + } + + go func() { + defer stdin.Close() + io.WriteString(stdin, body) + }() + + out, err := cmd.CombinedOutput() + if err != nil { + log.Error().Err(err).Msgf("could not get stdout") + } + + log.Debug().Msgf("md->adoc: %s", out) + return string(out) +} + +func NewFromMd(db *db.Database, body string) *Entry { + body = pandocMdToAdoc(body) + return NewFromAdoc(db, body) +} + func New(db *db.Database) *Entry { e := Entry{ db: db, diff --git a/web/entry.go b/web/entry.go index 85f58f4..0cd4f0a 100644 --- a/web/entry.go +++ b/web/entry.go @@ -13,6 +13,18 @@ import ( "github.com/gorilla/mux" ) +func (web *Web) writeJSON(w http.ResponseWriter, code int, data interface{}) error { + w.Header().Set("content-type", "application/json") + resp, err := json.Marshal(data) + if err != nil { + w.WriteHeader(500) + return err + } + w.WriteHeader(code) + w.Write(resp) + return nil +} + func (web *Web) editEntry(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) slug := vars["slug"] @@ -43,70 +55,67 @@ func (web *Web) editEntry(w http.ResponseWriter, r *http.Request) { err = oldEntry.Update() if err != nil { - w.WriteHeader(500) - fmt.Fprint(w, err) + web.writeJSON(w, 500, err) return } - resp, err := json.Marshal(oldEntry) + web.writeJSON(w, 200, oldEntry) +} + +func (web *Web) newAdocEntry(w http.ResponseWriter, r *http.Request) { + body, err := ioutil.ReadAll(r.Body) if err != nil { - w.WriteHeader(500) - fmt.Fprint(w, err) + web.writeJSON(w, 500, err) + return + } + newEntry := entry.NewFromAdoc(web.db, string(body)) + err = newEntry.Create() + if err != nil { + web.writeJSON(w, 500, err) return } - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, string(resp)) + web.writeJSON(w, 200, newEntry) } func (web *Web) newMarkdownEntry(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { - w.WriteHeader(500) - fmt.Fprint(w, err) + log.Error().Err(err).Msgf("could not read message body") + web.writeJSON(w, 500, err) return } newEntry := entry.NewFromMd(web.db, string(body)) err = newEntry.Create() if err != nil { - w.WriteHeader(500) - fmt.Fprint(w, err) + log.Error().Err(err).Msgf("could not create entry") + web.writeJSON(w, 500, err) return } - resp, err := json.Marshal(newEntry) - if err != nil { - w.WriteHeader(500) - fmt.Fprint(w, err) - return - } - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, string(resp)) + web.writeJSON(w, 200, newEntry) } func (web *Web) newEntry(w http.ResponseWriter, r *http.Request) { + log.Debug(). + Str("content-type", r.Header.Get("Content-Type")). + Msgf("newEntry") dec := json.NewDecoder(r.Body) newEntry := entry.New(web.db) err := dec.Decode(&newEntry) if err != nil { - w.WriteHeader(500) - fmt.Fprint(w, err) + log.Error().Err(err).Msgf("could not decode entry") + web.writeJSON(w, 500, err) return } err = newEntry.Create() if err != nil { - w.WriteHeader(500) - fmt.Fprint(w, err) + log.Error().Err(err).Msgf("could not create raw entry") + web.writeJSON(w, 500, err) return } - resp, err := json.Marshal(newEntry) - if err != nil { - w.WriteHeader(500) - fmt.Fprint(w, err) - return - } - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, string(resp)) + + web.writeJSON(w, 200, newEntry) } func (web *Web) allEntries(w http.ResponseWriter, r *http.Request) { @@ -122,19 +131,11 @@ func (web *Web) allEntries(w http.ResponseWriter, r *http.Request) { entries, err := entry.SearchByTag(web.db, query, tags) if err != nil { log.Error().Msgf("Error querying: %w", err) - w.WriteHeader(500) - fmt.Fprint(w, err) + web.writeJSON(w, 500, err) return } - resp, err := json.Marshal(entries) - if err != nil { - w.WriteHeader(500) - fmt.Fprint(w, err) - return - } - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, string(resp)) + web.writeJSON(w, 200, entries) } func (web *Web) getEntry(w http.ResponseWriter, r *http.Request) { @@ -143,25 +144,16 @@ func (web *Web) getEntry(w http.ResponseWriter, r *http.Request) { entry, err := entry.GetBySlug(web.db, slug) if err != nil { - w.WriteHeader(500) - fmt.Fprint(w, err) + web.writeJSON(w, 500, err) return } if !web.AuthCheck(r) && !entry.HasTag("public") { - w.WriteHeader(401) - fmt.Fprint(w, "not allowed") + web.writeJSON(w, 401, "not authorized") return } - resp, err := json.Marshal(entry) - if err != nil { - w.WriteHeader(500) - fmt.Fprint(w, err) - return - } - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, string(resp)) + web.writeJSON(w, 200, entry) } func (web *Web) removeEntry(w http.ResponseWriter, r *http.Request) { @@ -171,9 +163,8 @@ func (web *Web) removeEntry(w http.ResponseWriter, r *http.Request) { err := entry.RemoveBySlug(web.db, slug) if err != nil { log.Error().Msgf("Error deleting: %s", err) - w.WriteHeader(500) - fmt.Fprint(w, err) + web.writeJSON(w, 500, err) return } - w.WriteHeader(200) + web.writeJSON(w, 200, "success") } diff --git a/web/routes.go b/web/routes.go index 0cf18c6..35aa3ed 100644 --- a/web/routes.go +++ b/web/routes.go @@ -88,11 +88,12 @@ func (web *Web) routeSetup() http.Handler { // curl 'http://127.0.0.1:8080/v1/test' -X POST -H 'Accept: application/json, text/plain, */*' --compressed -H 'Content-Type: application/json;charset=utf-8' --data '{ "test": 1 }' - authedApi.HandleFunc("/entries", web.newEntry).Methods(http.MethodPost) authedApi.HandleFunc("/entries", web.newEntry).Methods(http.MethodPost). HeadersRegexp("Content-Type", "application/(text|json).*") authedApi.HandleFunc("/entries", web.newMarkdownEntry).Methods(http.MethodPost). - HeadersRegexp("Content-Type", "application/markdown.*") + HeadersRegexp("Content-Type", "application/markdown") + authedApi.HandleFunc("/entries", web.newAdocEntry).Methods(http.MethodPost). + HeadersRegexp("Content-Type", "application/asciidoc") authedApi.HandleFunc("/entries/{slug}", web.removeEntry).Methods(http.MethodDelete) authedApi.HandleFunc("/entries/{slug}", web.editEntry).Methods(http.MethodPut)