-
Notifications
You must be signed in to change notification settings - Fork 0
/
comment_new.go
130 lines (110 loc) · 3.69 KB
/
comment_new.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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
}
p, err := pageGet(domain, path)
if err != nil {
logger.Errorf("cannot get page attributes: %v", err)
return "", errorInternal
}
if p.IsLocked {
return "", errorThreadLocked
}
commentHex, err := randomHex(32)
if err != nil {
return "", err
}
html := markdownToHtml(markdown)
if err = pageNew(domain, path); err != nil {
return "", err
}
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
}
return commentHex, nil
}
func commentNewHandler(w http.ResponseWriter, r *http.Request) {
type request struct {
CommenterToken *string `json:"commenterToken"`
Domain *string `json:"domain"`
Path *string `json:"path"`
ParentHex *string `json:"parentHex"`
Markdown *string `json:"markdown"`
}
var x request
if err := bodyUnmarshal(r, &x); err != nil {
bodyMarshal(w, response{"success": false, "message": err.Error()})
return
}
domain := domainStrip(*x.Domain)
path := *x.Path
d, err := domainGet(domain)
if err != nil {
bodyMarshal(w, response{"success": false, "message": err.Error()})
return
}
if d.State == "frozen" {
bodyMarshal(w, response{"success": false, "message": errorDomainFrozen.Error()})
return
}
if d.RequireIdentification && *x.CommenterToken == "anonymous" {
bodyMarshal(w, response{"success": false, "message": errorNotAuthorised.Error()})
return
}
var commenterHex, commenterName, commenterEmail, commenterLink string
var isModerator bool
if *x.CommenterToken == "anonymous" {
commenterHex, commenterName, commenterEmail, commenterLink = "anonymous", "Anonymous", "", ""
} else {
c, err := commenterGetByCommenterToken(*x.CommenterToken)
if err != nil {
bodyMarshal(w, response{"success": false, "message": err.Error()})
return
}
commenterHex, commenterName, commenterEmail, commenterLink = c.CommenterHex, c.Name, c.Email, c.Link
for _, mod := range d.Moderators {
if mod.Email == c.Email {
isModerator = true
break
}
}
}
var state string
if isModerator {
state = "approved"
} else if d.RequireModeration {
state = "unapproved"
} else if commenterHex == "anonymous" && d.ModerateAllAnonymous {
state = "unapproved"
} else if d.AutoSpamFilter && isSpam(*x.Domain, getIp(r), getUserAgent(r), commenterName, commenterEmail, commenterLink, *x.Markdown) {
state = "flagged"
} else {
state = "approved"
}
commentHex, err := commentNew(commenterHex, domain, path, *x.ParentHex, *x.Markdown, state, time.Now().UTC())
if err != nil {
bodyMarshal(w, response{"success": false, "message": err.Error()})
return
}
// TODO: reuse html in commentNew and do only one markdown to HTML conversion?
html := markdownToHtml(*x.Markdown)
bodyMarshal(w, response{"success": true, "commentHex": commentHex, "state": state, "html": html})
if smtpConfigured {
go emailNotificationNew(d, path, commenterHex, commentHex, html, *x.ParentHex, state)
}
}