forked from astaxie/build-web-application-with-golang
/
main.go
175 lines (162 loc) · 4.14 KB
/
main.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
// This file contains all the validators to validate the profile page.
package validator
import (
"errors"
"fmt"
"net/url"
"regexp"
"strconv"
"strings"
"time"
)
type ProfilePage struct {
Form *url.Values
}
type Errors struct {
Errors []error
}
// Goes through the form object and validates each element.
// Attachs an error to the output if validation fails.
func (p *ProfilePage) GetErrors() Errors {
errs := make([]error, 0, 10)
if *p.Form == nil || len(*p.Form) < 1 {
errs = append(errs, errors.New("No data was received. Please submit from the profile page."))
}
for name, val := range *p.Form {
if fn, ok := stringValidator[name]; ok {
if err := fn(strings.Join(val, "")); err != nil {
errs = append(errs, err)
}
} else {
if fn, ok := stringsValidator[name]; ok {
if err := fn(val); err != nil {
errs = append(errs, err)
}
}
}
}
return Errors{errs}
}
const (
// Used for parsing the time
mmddyyyyForm = "01/02/2006" // we want the date sent in this format
yyyymmddForm = "2006-01-02" // However, HTML5 pages send the date in this format
)
var stringValidator map[string]func(string) error = map[string]func(string) error{
// parameter name : validator reference
"age": checkAge,
"birthday": checkDate,
"chineseName": checkChineseName,
"email": checkEmail,
"gender": checkGender,
"shirtsize": checkShirtSize,
"username": checkUsername,
}
var stringsValidator map[string]func([]string) error = map[string]func([]string) error{
// parameter name : validator reference
"sibling": checkSibling,
}
// Returns true if slices have a common element
func doSlicesIntersect(s1, s2 []string) bool {
if s1 == nil || s2 == nil {
return false
}
for _, str := range s1 {
if isElementInSlice(str, s2) {
return true
}
}
return false
}
func isElementInSlice(str string, sl []string) bool {
if sl == nil || str == "" {
return false
}
for _, v := range sl {
if v == str {
return true
}
}
return false
}
// Checks if all the characters are chinese characters. Won't check if empty.'
func checkChineseName(str string) error {
if str != "" {
if m, _ := regexp.MatchString("^[\\x{4e00}-\\x{9fa5}]+$", strings.Trim(str, " ")); !m {
return errors.New("Please make sure that the chinese name only contains chinese characters.")
}
}
return nil
}
// Checks if a user name exist.
func checkUsername(str string) error {
if strings.Trim(str, " ") == "" {
return errors.New("Please enter a username.")
}
return nil
}
// Check if age is a number and between 13 and 130
func checkAge(str string) error {
age, err := strconv.Atoi(str)
if str == "" || err != nil {
return errors.New("Please enter a valid age.")
}
if age < 13 {
return errors.New("You must be at least 13 years of age to submit.")
}
if age > 130 {
return errors.New("You're too old to register, grandpa.")
}
return nil
}
func checkEmail(str string) error {
if m, err := regexp.MatchString(`^[^@]+@[^@]+$`, str); !m {
fmt.Println("err = ", err)
return errors.New("Please enter a valid email address.")
}
return nil
}
// Checks if a valid date was passed.
func checkDate(str string) error {
_, err := time.Parse(mmddyyyyForm, str)
if err != nil {
_, err = time.Parse(yyyymmddForm, str)
}
if str == "" || err != nil {
return errors.New("Please enter a valid Date.")
}
return nil
}
// Checks if the passed input is a known gender option
func checkGender(str string) error {
if str == "" {
return nil
}
siblings := []string{"m", "f", "na"}
if !isElementInSlice(str, siblings) {
return errors.New("Please select a valid gender.")
}
return nil
}
// Check if all the values are known options.
func checkSibling(strs []string) error {
if strs == nil || len(strs) < 1 {
return nil
}
siblings := []string{"m", "f"}
if siblings != nil && !doSlicesIntersect(siblings, strs) {
return errors.New("Please select a valid sibling")
}
return nil
}
// Checks if the shirt size is a known option.
func checkShirtSize(str string) error {
if str == "" {
return nil
}
shirts := []string{"s", "m", "l", "xl", "xxl"}
if !isElementInSlice(str, shirts) {
return errors.New("Please select a valid shirt size")
}
return nil
}