package main import ( "net/http" "time" ) // Take `creationDate` as a param because comment import (from Disqus, for // example) will require a custom time. func commentNew(commenterHex string, domain string, path string, parentHex string, markdown string, state string, creationDate time.Time) (string, error) { // path is allowed to be empty if commenterHex == "" || domain == "" || parentHex == "" || markdown == "" || state == "" { return "", errorMissingField } commentHex, err := randomHex(32) if err != nil { return "", err } html := markdownToHtml(markdown) statement := ` INSERT INTO comments (commentHex, domain, path, commenterHex, parentHex, markdown, html, creationDate, state) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9 ); ` _, err = db.Exec(statement, commentHex, domain, path, commenterHex, parentHex, markdown, html, creationDate, state) if err != nil { logger.Errorf("cannot insert comment: %v", err) return "", errorInternal } if err = commentVote(commenterHex, commentHex, 1); err != nil { logger.Warningf("error: cannot upvote new comment automatically: %v", err) } return commentHex, nil } func commentNewHandler(w http.ResponseWriter, r *http.Request) { type request struct { Session *string `json:"session"` Domain *string `json:"domain"` Path *string `json:"path"` ParentHex *string `json:"parentHex"` Markdown *string `json:"markdown"` } var x request if err := unmarshalBody(r, &x); err != nil { writeBody(w, response{"success": false, "message": err.Error()}) return } domain := stripDomain(*x.Domain) path := *x.Path d, err := domainGet(domain) if err != nil { writeBody(w, response{"success": false, "message": err.Error()}) return } if d.State == "frozen" { writeBody(w, response{"success": false, "message": errorDomainFrozen.Error()}) return } // logic: (empty column indicates the value doesn't matter) // | anonymous | moderator | requireIdentification | requireModeration | approved? | // |-----------+-----------+-----------------------+-------------------+-----------| // | yes | | | | no | // | no | yes | | | yes | // | no | no | | yes | yes | // | no | no | | no | no | var commenterHex string var state string if *x.Session == "anonymous" { state = "unapproved" commenterHex = "anonymous" } else { c, err := commenterGetBySession(*x.Session) if err != nil { writeBody(w, response{"success": false, "message": err.Error()}) return } // cheaper than a SQL query as we already have this information isModerator := false for _, mod := range d.Moderators { if mod.Email == c.Email { isModerator = true break } } commenterHex = c.CommenterHex if isModerator { state = "approved" } else { if d.RequireModeration { state = "unapproved" } else { state = "approved" } } } commentHex, err := commentNew(commenterHex, domain, path, *x.ParentHex, *x.Markdown, state, time.Now().UTC()) if err != nil { writeBody(w, response{"success": false, "message": err.Error()}) return } writeBody(w, response{"success": true, "commentHex": commentHex}) }