GoBlog/comments.go

154 lines
4.3 KiB
Go
Raw Normal View History

2021-01-23 16:24:47 +00:00
package main
import (
"database/sql"
"fmt"
"net/http"
2021-02-14 13:15:01 +00:00
"net/url"
2021-01-23 16:24:47 +00:00
"strconv"
2021-02-14 13:15:01 +00:00
"strings"
2021-01-23 16:24:47 +00:00
"github.com/go-chi/chi"
"github.com/microcosm-cc/bluemonday"
)
type comment struct {
ID int
Target string
Name string
Website string
Comment string
}
func serveComment(blog string) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
id, err := strconv.Atoi(chi.URLParam(r, "id"))
if err != nil {
serveError(w, r, err.Error(), http.StatusBadRequest)
return
}
row, err := appDbQueryRow("select id, target, name, website, comment from comments where id = @id", sql.Named("id", id))
if err != nil {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
comment := &comment{}
if err = row.Scan(&comment.ID, &comment.Target, &comment.Name, &comment.Website, &comment.Comment); err == sql.ErrNoRows {
serve404(w, r)
return
} else if err != nil {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
2021-01-23 16:44:40 +00:00
w.Header().Set("X-Robots-Tag", "noindex")
2021-01-23 16:24:47 +00:00
render(w, templateComment, &renderData{
BlogString: blog,
2021-02-14 13:15:01 +00:00
Canonical: appConfig.Server.PublicAddress + appConfig.Blogs[blog].getRelativePath(fmt.Sprintf("/comment/%d", id)),
2021-01-23 16:24:47 +00:00
Data: comment,
})
}
}
func createComment(blog, commentsPath string) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
// Check target
target := checkCommentTarget(w, r)
if target == "" {
return
}
2021-02-15 17:58:45 +00:00
// Check and clean comment
strict := bluemonday.StrictPolicy()
comment := strings.TrimSpace(strict.Sanitize(r.FormValue("comment")))
2021-01-23 16:24:47 +00:00
if comment == "" {
serveError(w, r, "Comment is empty", http.StatusBadRequest)
return
}
2021-02-15 17:58:45 +00:00
name := strings.TrimSpace(strict.Sanitize(r.FormValue("name")))
2021-01-23 16:24:47 +00:00
if name == "" {
name = "Anonymous"
}
2021-02-15 17:58:45 +00:00
website := strings.TrimSpace(strict.Sanitize(r.FormValue("website")))
2021-01-23 16:24:47 +00:00
// Insert
result, err := appDbExec("insert into comments (target, comment, name, website) values (@target, @comment, @name, @website)", sql.Named("target", target), sql.Named("comment", comment), sql.Named("name", name), sql.Named("website", website))
if err != nil {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
2021-02-08 17:51:07 +00:00
if commentID, err := result.LastInsertId(); err != nil {
// Serve error
serveError(w, r, err.Error(), http.StatusInternalServerError)
} else {
commentAddress := fmt.Sprintf("%s/%d", commentsPath, commentID)
// Send webmention
_ = createWebmention(appConfig.Server.PublicAddress+commentAddress, appConfig.Server.PublicAddress+target)
// Redirect to comment
http.Redirect(w, r, commentAddress, http.StatusFound)
}
2021-01-23 16:24:47 +00:00
}
}
func checkCommentTarget(w http.ResponseWriter, r *http.Request) string {
target := r.FormValue("target")
if target == "" {
serveError(w, r, "No target specified", http.StatusBadRequest)
return ""
2021-02-14 13:15:01 +00:00
} else if !strings.HasPrefix(target, appConfig.Server.PublicAddress) {
serveError(w, r, "Bad target", http.StatusBadRequest)
2021-01-23 16:24:47 +00:00
return ""
}
2021-02-14 13:15:01 +00:00
targetURL, err := url.Parse(target)
if err != nil {
serveError(w, r, err.Error(), http.StatusBadRequest)
2021-01-23 16:24:47 +00:00
return ""
}
2021-02-14 13:15:01 +00:00
return targetURL.Path
2021-01-23 16:24:47 +00:00
}
func commentsAdmin(w http.ResponseWriter, r *http.Request) {
comments, err := getComments()
if err != nil {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
render(w, templateCommentsAdmin, &renderData{
Data: comments,
})
}
func getComments() ([]*comment, error) {
comments := []*comment{}
2021-01-23 19:32:42 +00:00
rows, err := appDbQuery("select id, target, name, website, comment from comments order by id desc")
2021-01-23 16:24:47 +00:00
if err != nil {
return nil, err
}
for rows.Next() {
c := &comment{}
err = rows.Scan(&c.ID, &c.Target, &c.Name, &c.Website, &c.Comment)
if err != nil {
return nil, err
}
comments = append(comments, c)
}
return comments, nil
}
func commentsAdminDelete(w http.ResponseWriter, r *http.Request) {
id, err := strconv.Atoi(r.FormValue("commentid"))
if err != nil {
serveError(w, r, err.Error(), http.StatusBadRequest)
return
}
err = deleteComment(id)
if err != nil {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
purgeCache()
http.Redirect(w, r, ".", http.StatusFound)
}
func deleteComment(id int) error {
_, err := appDbExec("delete from comments where id = @id", sql.Named("id", id))
return err
}