main
1package main
2
3import (
4 "html/template"
5 "log"
6 "net/http"
7 "regexp"
8)
9
10// PageData holds common data passed to templates
11type PageData struct {
12 Title string
13 ServiceName string
14 Content interface{}
15}
16
17// home displays the buylater.email landing page
18func home(w http.ResponseWriter, r *http.Request) {
19 w.Header().Add("Server", "buylater.email")
20
21 // Parse templates with inheritance
22 ts, err := template.ParseFiles(
23 "./ui/html/layouts/base.tmpl",
24 "./ui/html/pages/home.tmpl",
25 )
26 if err != nil {
27 log.Println(err.Error())
28 http.Error(w, "Internal Server Error", 500)
29 return
30 }
31
32 // Prepare template data
33 data := PageData{
34 Title: "Home",
35 ServiceName: "buylater.email",
36 Content: nil,
37 }
38
39 // Execute template - specify the base template name
40 err = ts.ExecuteTemplate(w, "base", data)
41 if err != nil {
42 log.Println(err.Error())
43 http.Error(w, "Internal Server Error", 500)
44 }
45}
46
47// submitForm displays the email submission form for scheduling purchase reminders
48func submitForm(w http.ResponseWriter, r *http.Request) {
49 w.Header().Add("Server", "buylater.email")
50
51 // Parse templates with inheritance
52 ts, err := template.ParseFiles(
53 "./ui/html/layouts/base.tmpl",
54 "./ui/html/pages/submit.tmpl",
55 )
56 if err != nil {
57 log.Println(err.Error())
58 http.Error(w, "Internal Server Error", 500)
59 return
60 }
61
62 // Prepare template data
63 data := PageData{
64 Title: "Submit",
65 ServiceName: "buylater.email",
66 Content: nil,
67 }
68
69 // Execute template - specify the base template name
70 err = ts.ExecuteTemplate(w, "base", data)
71 if err != nil {
72 log.Println(err.Error())
73 http.Error(w, "Internal Server Error", 500)
74 }
75}
76
77// processSubmit handles the form submission and schedules the email reminder
78func processSubmit(w http.ResponseWriter, r *http.Request) {
79 w.Header().Add("Server", "buylater.email")
80
81 // Parse templates with inheritance
82 ts, err := template.ParseFiles(
83 "./ui/html/layouts/base.tmpl",
84 "./ui/html/pages/complete.tmpl",
85 )
86 if err != nil {
87 log.Println(err.Error())
88 http.Error(w, "Internal Server Error", 500)
89 return
90 }
91
92 // Prepare template data
93 data := PageData{
94 Title: "Submission Complete",
95 ServiceName: "buylater.email",
96 Content: nil,
97 }
98
99 // Execute template
100 err = ts.ExecuteTemplate(w, "base", data)
101 if err != nil {
102 log.Println(err.Error())
103 http.Error(w, "Internal Server Error", 500)
104 }
105}
106
107// confirmWithToken handles magic link confirmation with token validation
108func confirmWithToken(w http.ResponseWriter, r *http.Request) {
109 token := r.PathValue("token")
110
111 if !isValidToken(token) {
112 w.Header().Add("Server", "buylater.email")
113 http.NotFound(w, r)
114 return
115 }
116
117 w.Header().Add("Server", "buylater.email")
118 w.WriteHeader(http.StatusOK)
119 w.Write([]byte("Email Confirmed! Your purchase reminder has been activated via magic link."))
120}
121
122// isValidToken validates that the token is alphanumeric and at least 32 characters
123func isValidToken(token string) bool {
124 if len(token) < 32 {
125 return false
126 }
127
128 // Check if token contains only alphanumeric characters
129 matched, _ := regexp.MatchString("^[a-zA-Z0-9]+$", token)
130 return matched
131}
132
133// about displays information about the buylater.email service
134func about(w http.ResponseWriter, r *http.Request) {
135 w.Header().Add("Server", "buylater.email")
136
137 // Parse templates with inheritance
138 ts, err := template.ParseFiles(
139 "./ui/html/layouts/base.tmpl",
140 "./ui/html/pages/about.tmpl",
141 )
142 if err != nil {
143 log.Println(err.Error())
144 http.Error(w, "Internal Server Error", 500)
145 return
146 }
147
148 // Prepare template data
149 data := PageData{
150 Title: "About",
151 ServiceName: "buylater.email",
152 Content: nil,
153 }
154
155 // Execute template
156 err = ts.ExecuteTemplate(w, "base", data)
157 if err != nil {
158 log.Println(err.Error())
159 http.Error(w, "Internal Server Error", 500)
160 }
161}