|
9 | 9 | "fmt" |
10 | 10 | "io/fs" |
11 | 11 | "net" |
| 12 | + "net/mail" |
12 | 13 | "net/url" |
13 | 14 | "os" |
14 | 15 | "reflect" |
|
50 | 51 | keysTag: {}, |
51 | 52 | endKeysTag: {}, |
52 | 53 | structOnlyTag: {}, |
| 54 | + omitzero: {}, |
53 | 55 | omitempty: {}, |
54 | 56 | omitnil: {}, |
55 | 57 | skipValidationTag: {}, |
@@ -242,6 +244,7 @@ var ( |
242 | 244 | "cron": isCron, |
243 | 245 | "spicedb": isSpiceDB, |
244 | 246 | "oci_tag": isOciTag, |
| 247 | + "ein": isEIN, |
245 | 248 | } |
246 | 249 | ) |
247 | 250 |
|
@@ -1376,7 +1379,6 @@ func isEqIgnoreCase(fl FieldLevel) bool { |
1376 | 1379 | param := fl.Param() |
1377 | 1380 |
|
1378 | 1381 | switch field.Kind() { |
1379 | | - |
1380 | 1382 | case reflect.String: |
1381 | 1383 | return strings.EqualFold(field.String(), param) |
1382 | 1384 | } |
@@ -1606,7 +1608,6 @@ func isImage(fl FieldLevel) bool { |
1606 | 1608 | case reflect.String: |
1607 | 1609 | filePath := field.String() |
1608 | 1610 | fileInfo, err := os.Stat(filePath) |
1609 | | - |
1610 | 1611 | if err != nil { |
1611 | 1612 | return false |
1612 | 1613 | } |
@@ -1635,7 +1636,6 @@ func isImage(fl FieldLevel) bool { |
1635 | 1636 |
|
1636 | 1637 | // isFilePath is the validation function for validating if the current field's value is a valid file path. |
1637 | 1638 | func isFilePath(fl FieldLevel) bool { |
1638 | | - |
1639 | 1639 | var exists bool |
1640 | 1640 | var err error |
1641 | 1641 |
|
@@ -1695,6 +1695,10 @@ func isE164(fl FieldLevel) bool { |
1695 | 1695 |
|
1696 | 1696 | // isEmail is the validation function for validating if the current field's value is a valid email address. |
1697 | 1697 | func isEmail(fl FieldLevel) bool { |
| 1698 | + _, err := mail.ParseAddress(fl.Field().String()) |
| 1699 | + if err != nil { |
| 1700 | + return false |
| 1701 | + } |
1698 | 1702 | return emailRegex().MatchString(fl.Field().String()) |
1699 | 1703 | } |
1700 | 1704 |
|
@@ -1798,6 +1802,20 @@ func hasValue(fl FieldLevel) bool { |
1798 | 1802 | } |
1799 | 1803 | } |
1800 | 1804 |
|
| 1805 | +// hasNotZeroValue is the validation function for validating if the current field's value is not the zero value for its type. |
| 1806 | +func hasNotZeroValue(fl FieldLevel) bool { |
| 1807 | + field := fl.Field() |
| 1808 | + switch field.Kind() { |
| 1809 | + case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func: |
| 1810 | + return !field.IsNil() |
| 1811 | + default: |
| 1812 | + if fl.(*validate).fldIsPointer && field.Interface() != nil { |
| 1813 | + return !field.IsZero() |
| 1814 | + } |
| 1815 | + return field.IsValid() && !field.IsZero() |
| 1816 | + } |
| 1817 | +} |
| 1818 | + |
1801 | 1819 | // requireCheckFieldKind is a func for check field kind |
1802 | 1820 | func requireCheckFieldKind(fl FieldLevel, param string, defaultNotFoundValue bool) bool { |
1803 | 1821 | field := fl.Field() |
@@ -2213,7 +2231,6 @@ func isGt(fl FieldLevel) bool { |
2213 | 2231 | case reflect.Struct: |
2214 | 2232 |
|
2215 | 2233 | if field.Type().ConvertibleTo(timeType) { |
2216 | | - |
2217 | 2234 | return field.Convert(timeType).Interface().(time.Time).After(time.Now().UTC()) |
2218 | 2235 | } |
2219 | 2236 | } |
@@ -2450,7 +2467,6 @@ func isLt(fl FieldLevel) bool { |
2450 | 2467 | case reflect.Struct: |
2451 | 2468 |
|
2452 | 2469 | if field.Type().ConvertibleTo(timeType) { |
2453 | | - |
2454 | 2470 | return field.Convert(timeType).Interface().(time.Time).Before(time.Now().UTC()) |
2455 | 2471 | } |
2456 | 2472 | } |
@@ -2630,7 +2646,6 @@ func isDir(fl FieldLevel) bool { |
2630 | 2646 |
|
2631 | 2647 | // isDirPath is the validation function for validating if the current field's value is a valid directory. |
2632 | 2648 | func isDirPath(fl FieldLevel) bool { |
2633 | | - |
2634 | 2649 | var exists bool |
2635 | 2650 | var err error |
2636 | 2651 |
|
@@ -2943,6 +2958,12 @@ func isCveFormat(fl FieldLevel) bool { |
2943 | 2958 | // a valid dns RFC 1035 label, defined in RFC 1035. |
2944 | 2959 | func isDnsRFC1035LabelFormat(fl FieldLevel) bool { |
2945 | 2960 | val := fl.Field().String() |
| 2961 | + |
| 2962 | + size := len(val) |
| 2963 | + if size > 63 { |
| 2964 | + return false |
| 2965 | + } |
| 2966 | + |
2946 | 2967 | return dnsRegexRFC1035Label().MatchString(val) |
2947 | 2968 | } |
2948 | 2969 |
|
@@ -3050,4 +3071,14 @@ func isCron(fl FieldLevel) bool { |
3050 | 3071 | // isOciTag is the validation function for validating if the current field's value is a valid OCI tag, as described in the OCI Distribution Specification: https://github.com/opencontainers/distribution-spec/blob/main/spec.md |
3051 | 3072 | func isOciTag(fl FieldLevel) bool { |
3052 | 3073 | return ociTagRegex().MatchString(fl.Field().String()) |
| 3074 | + |
| 3075 | +// isEIN is the validation function for validating if the current field's value is a valid U.S. Employer Identification Number (EIN) |
| 3076 | +func isEIN(fl FieldLevel) bool { |
| 3077 | + field := fl.Field() |
| 3078 | + |
| 3079 | + if field.Len() != 10 { |
| 3080 | + return false |
| 3081 | + } |
| 3082 | + |
| 3083 | + return einRegex().MatchString(field.String()) |
3053 | 3084 | } |
0 commit comments