-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathvalidators.go
230 lines (195 loc) · 5.52 KB
/
validators.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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
package main
import (
"fmt"
"net/mail"
"time"
)
// ValidateServiceNames checks for reserved service names
func ValidateServiceNames(names []string) error {
reservedNames := map[string]bool{
"metrics": true,
"log_level": true,
}
for _, name := range names {
_, found := reservedNames[name]
if found {
return fmt.Errorf("could not use reserved serice name: %q", name)
}
}
return nil
}
func Validate(field FieldConfig, value interface{}, valueSet bool) error {
// field required, not set
if field.Required != nil && *field.Required && !valueSet {
return fmt.Errorf("field %q: required", field.Name)
}
// field not required, not set
if field.Required == nil && !valueSet {
return nil
}
// field not required, not set
if field.Required != nil && !*field.Required && !valueSet {
return nil
}
var err error
fieldType, err := field.GetType()
if err != nil {
return fmt.Errorf("filed %q: unknown type", field.Name)
}
switch fieldType {
case FieldTypeObject:
v, converted := value.(map[string]interface{})
if !converted {
return fmt.Errorf("field %q: could not expand object", field.Name)
}
for n, f := range *field.Fields {
if err := Validate(*f, v[n], v[n] != nil); err != nil {
return err
}
}
return nil
case FieldTypeArray:
v, converted := value.([]interface{})
if !converted {
return fmt.Errorf("field %q: could not expand array", field.Name)
}
if err = validateArray(field, v); err != nil {
return err
}
for _, item := range v {
if err = Validate(*field.Items, item, true); err != nil {
return fmt.Errorf("field %q: %w", field.Name, err)
}
}
return nil
case FieldTypeString:
strValue, converted := value.(string)
if !converted {
return fmt.Errorf("field %q: could not convert to string", field.Name)
}
return validateString(field, strValue)
case FieldTypeDate:
strValue, converted := value.(string)
if !converted {
return fmt.Errorf("field %q: could not convert to date", field.Name)
}
return validateDate(field, strValue)
case FieldTypeInt:
floatValue, converted := value.(float64)
if !converted {
return fmt.Errorf("field %q: could not convert to int", field.Name)
}
return validateInt(field, floatValue)
case FieldTypeFloat:
floatValue, converted := value.(float64)
if !converted {
return fmt.Errorf("field %q: could not convert to float", field.Name)
}
return validateFloat(field, floatValue)
}
panic(fmt.Sprintf("should never happen; field: %s", field.Name))
}
func validateArray(field FieldConfig, value []interface{}) error {
if field.Items == nil {
return fmt.Errorf("field %q: array items are not defined", field.Name)
}
// if required, at least one = min 1
if field.Required != nil && *field.Required && field.Min == nil {
onePtr := 1
field.Min = &onePtr
}
if field.Required != nil && *field.Required && field.Min != nil && *field.Min < 1 {
onePtr := 1
field.Min = &onePtr
}
length := len(value)
if field.Min != nil {
if length < *field.Min {
return fmt.Errorf("field %q: at least %d items required", field.Name, *field.Min)
}
}
if field.Max != nil {
if length > *field.Max {
return fmt.Errorf("field %q: at most %d items allowed", field.Name, *field.Max)
}
}
return nil
}
func validateString(field FieldConfig, value string) error {
length := len(value)
// check rules
if field.Rule != nil && len(*field.Rule) > 0 {
// email rule
if field.GetRule() == FieldRuleEmail {
_, err := mail.ParseAddress(value)
if err != nil {
return fmt.Errorf("field %q: valid email address required", field.Name)
}
}
}
// required field
if field.Required != nil && *field.Required {
if length == 0 {
return fmt.Errorf("field %q: required", field.Name)
}
}
// min length field
if field.Min != nil && *field.Min > 0 {
if length < *field.Min {
return fmt.Errorf("field %q: min '%d' lenght required", field.Name, *field.Min)
}
}
// max length field
if field.Max != nil && *field.Max > 0 {
if length > *field.Max {
return fmt.Errorf("field %q: max '%d' lenght required", field.Name, *field.Max)
}
}
return nil
}
func validateDate(field FieldConfig, value string) error {
length := len(value)
// required field
if field.Required != nil && *field.Required {
if length == 0 {
return fmt.Errorf("field %q required", field.Name)
}
}
// format
if field.Format != nil && *field.Format == "" {
return fmt.Errorf("field %q: format is required for date type", field.Name)
}
if field.Format != nil && length > 0 {
_, err := time.Parse(*field.Format, value)
if err != nil {
return fmt.Errorf("field %q: could not parse date %q using format %q", field.Name, value, *field.Format)
}
}
return nil
}
func validateInt(field FieldConfig, value float64) error {
if value != float64(int(value)) {
return fmt.Errorf("field %q: could not convert float %f to int", field.Name, value)
}
intValue := int(value)
// check min value
if field.Min != nil && intValue < *field.Min {
return fmt.Errorf("field %q: minimum is %d", field.Name, *field.Min)
}
// check max value
if field.Max != nil && intValue > *field.Max {
return fmt.Errorf("field %q: maximum is %d", field.Name, *field.Max)
}
return nil
}
func validateFloat(field FieldConfig, value float64) error {
// check min value
if field.Min != nil && value < float64(*field.Min) {
return fmt.Errorf("field %q: minimum is %d", field.Name, *field.Min)
}
// check max value
if field.Max != nil && value > float64(*field.Max) {
return fmt.Errorf("field %q: maximum is %d", field.Name, *field.Max)
}
return nil
}