-
Notifications
You must be signed in to change notification settings - Fork 0
/
guestbook.go
215 lines (176 loc) · 5.97 KB
/
guestbook.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
package main
import (
"bytes"
"fmt"
"log"
"net/http"
"strings"
"time"
"html/template"
"guestbook/constants"
"github.com/go-chi/chi/v5"
)
var guestbookTemplate *template.Template = loadGuestbookTemplate()
func formatDate(t time.Time) string {
return t.Format("Jan 2, 2006")
}
func loadGuestbookTemplate() *template.Template {
tmpl, err := template.New("guestbook_page.html").Funcs(template.FuncMap{
"formatDate": formatDate,
}).ParseFiles("templates/guestbook_page.html")
if err != nil {
log.Fatal(err)
}
return tmpl
}
func GuestbookPage(w http.ResponseWriter, r *http.Request) {
guestbookID := chi.URLParam(r, "guestbookID")
type GuestbookPageData struct {
WebsiteURL string
CustomPageCSS string
}
var guestbookData GuestbookPageData
result := db.Model(&Guestbook{}).
Select("website_url, custom_page_css").
Where("id = ?", guestbookID).
Scan(&guestbookData)
if result.Error != nil {
http.Error(w, "Error querying the database", http.StatusInternalServerError)
return
}
if result.RowsAffected == 0 {
http.Error(w, "Guestbook not found. It may have been deleted or the URL is incorrect.", http.StatusNotFound)
return
}
if constants.DEBUG_MODE {
guestbookTemplate = loadGuestbookTemplate()
}
selectedBuiltInTheme := ""
if strings.HasPrefix(guestbookData.CustomPageCSS, "<<built__in>>") {
selectedBuiltInTheme = strings.TrimPrefix(guestbookData.CustomPageCSS, "<<built__in>>")
selectedBuiltInTheme = strings.TrimSuffix(selectedBuiltInTheme, "<</built__in>>")
}
data := struct {
ID string
WebsiteURL string
CustomPageCSS template.CSS
SelectedBuiltInTheme string
}{
ID: guestbookID,
WebsiteURL: guestbookData.WebsiteURL,
CustomPageCSS: template.CSS(guestbookData.CustomPageCSS),
SelectedBuiltInTheme: selectedBuiltInTheme,
}
err := guestbookTemplate.Execute(w, data)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func GuestbookSubmit(w http.ResponseWriter, r *http.Request) {
guestbookID := chi.URLParam(r, "guestbookID")
var guestbook Guestbook
result := db.First(&guestbook, guestbookID)
if result.Error != nil {
http.Error(w, "Guestbook not found", http.StatusNotFound)
return
}
// check that the form has the expected challenge if necesary
if strings.TrimSpace(guestbook.ChallengeQuestion) != "" {
challengeQuestionAnswer := strings.TrimSpace(r.FormValue("challengeQuestionAnswer"))
challengeQuestionAnswer = strings.ToLower(challengeQuestionAnswer)
expectedChallengeAnswer := strings.TrimSpace(guestbook.ChallengeAnswer)
expectedChallengeAnswer = strings.ToLower(expectedChallengeAnswer)
if expectedChallengeAnswer != "" && expectedChallengeAnswer != challengeQuestionAnswer {
http.Error(w, "The provided answer to the challenge question is invalid!", http.StatusUnauthorized)
return
}
}
name := strings.TrimSpace(r.FormValue("name"))
text := strings.TrimSpace(r.FormValue("text"))
website := strings.TrimSpace(r.FormValue("website"))
var websitePtr *string
if website != "" {
websitePtr = &website
}
if len(text) > constants.MAX_MESSAGE_LENGTH {
http.Error(w, "Message is too long, maximum length is "+fmt.Sprint(constants.MAX_MESSAGE_LENGTH)+" characters", http.StatusBadRequest)
return
}
message := Message{
Name: name,
Text: text,
Website: websitePtr,
GuestbookID: guestbook.ID,
Approved: !guestbook.RequiresApproval,
}
result = db.Create(&message)
if result.Error != nil {
http.Error(w, "Error submitting message", http.StatusInternalServerError)
return
}
// now send an email to the user if necessary
var adminUser AdminUser
result = db.First(&adminUser, "id = ?", guestbook.AdminUserID)
if result.Error != nil {
http.Error(w, "Guestbook not found", http.StatusNotFound)
return
}
if adminUser.EmailNotifications && adminUser.EmailVerified && adminUser.Email != "" {
submitterText := ""
if website != "" {
submitterText = "[Website: " + website + "]"
}
data := struct {
ApplicationURL string
GuestbookID string
GuestbookURL string
MessageID uint
MessageName string
MessageNeedsApproval bool
MessageText string
SubmitterText string
}{
ApplicationURL: constants.PUBLIC_URL,
GuestbookID: guestbookID,
GuestbookURL: guestbook.WebsiteURL,
MessageID: message.ID,
MessageName: message.Name,
MessageNeedsApproval: guestbook.RequiresApproval && !message.Approved,
MessageText: message.Text,
SubmitterText: submitterText,
}
// Define your template string
tmpl := `
Hi! Someone has just submitted a new message on your guestbook '{{.GuestbookURL}}'.
From: {{.MessageName}} {{.SubmitterText}}
===BEGIN MESSAGE===
{{.MessageText}}
===END MESSAGE===
You can view the messages on your guestbook here {{.ApplicationURL}}/admin/guestbook/{{.GuestbookID}}
{{if .MessageNeedsApproval}}
This message needs approval before it is shown on your guestbook.
Please go here to approve or reject the message: {{.ApplicationURL}}/admin/guestbook/{{.GuestbookID}}/message/{{.MessageID}}/edit
{{end}}
This is an autogenerated message from {{.ApplicationURL}} . Please don't answer since this mailbox is not monitored.
If you do need some help then please reach out through here https://meadow.cafe/mailbox/
`
// Parse and execute the template
t, err := template.New("email").Parse(tmpl)
if err != nil {
fmt.Println("Error parsing template:", err)
return
}
var tpl bytes.Buffer
if err := t.Execute(&tpl, data); err != nil {
fmt.Println("Error executing template:", err)
return
}
if constants.DEBUG_MODE {
fmt.Println("In debug mode, not sending email:")
fmt.Println(tpl.String())
} else {
go SendMail([]string{adminUser.Email}, "[Guestbooks] New message on guestbook '"+guestbook.WebsiteURL+"'", tpl.String())
}
}
http.Redirect(w, r, "/guestbook/"+guestbookID, http.StatusSeeOther)
}