Skip to content

Commit 79c42ad

Browse files
authored
Feat: add EIN validation (#1384)
## Fixes Or Enhances The Employeer Identification Number for USA **Make sure that you've checked the boxes below before you submit PR:** - [x] Tests exist or have been written that cover this particular change. @go-playground/validator-maintainers
1 parent 2cadaff commit 79c42ad

File tree

5 files changed

+60
-13
lines changed

5 files changed

+60
-13
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ validate := validator.New(validator.WithRequiredStructEnabled())
172172
| spicedb | SpiceDb ObjectID/Permission/Type |
173173
| datetime | Datetime |
174174
| e164 | e164 formatted phone number |
175+
| ein | U.S. Employeer Identification Number |
175176
| email | E-mail String
176177
| eth_addr | Ethereum Address |
177178
| hexadecimal | Hexadecimal String |

baked_in.go

+12
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ var (
242242
"mongodb_connection_string": isMongoDBConnectionString,
243243
"cron": isCron,
244244
"spicedb": isSpiceDB,
245+
"ein": isEIN,
245246
}
246247
)
247248

@@ -3060,3 +3061,14 @@ func isCron(fl FieldLevel) bool {
30603061
cronString := fl.Field().String()
30613062
return cronRegex().MatchString(cronString)
30623063
}
3064+
3065+
// isEIN is the validation function for validating if the current field's value is a valid U.S. Employer Identification Number (EIN)
3066+
func isEIN(fl FieldLevel) bool {
3067+
field := fl.Field()
3068+
3069+
if field.Len() != 10 {
3070+
return false
3071+
}
3072+
3073+
return einRegex().MatchString(field.String())
3074+
}

doc.go

+6
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,12 @@ This validates that a string value contains a valid longitude.
11341134
11351135
Usage: longitude
11361136
1137+
# Employeer Identification Number EIN
1138+
1139+
This validates that a string value contains a valid U.S. Employer Identification Number.
1140+
1141+
Usage: ein
1142+
11371143
# Social Security Number SSN
11381144
11391145
This validates that a string value contains a valid U.S. Social Security Number.

regexes.go

+2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ const (
7777
spicedbIDRegexString = `^(([a-zA-Z0-9/_|\-=+]{1,})|\*)$`
7878
spicedbPermissionRegexString = "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$"
7979
spicedbTypeRegexString = "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$"
80+
einRegexString = "^(\\d{2}-\\d{7})$"
8081
)
8182

8283
func lazyRegexCompile(str string) func() *regexp.Regexp {
@@ -160,4 +161,5 @@ var (
160161
spicedbIDRegex = lazyRegexCompile(spicedbIDRegexString)
161162
spicedbPermissionRegex = lazyRegexCompile(spicedbPermissionRegexString)
162163
spicedbTypeRegex = lazyRegexCompile(spicedbTypeRegexString)
164+
einRegex = lazyRegexCompile(einRegexString)
163165
)

validator_test.go

+39-13
Original file line numberDiff line numberDiff line change
@@ -746,11 +746,9 @@ func TestStructPartial(t *testing.T) {
746746

747747
SubSlice: []*SubTest{
748748
{
749-
750749
Test: "Required",
751750
},
752751
{
753-
754752
Test: "Required",
755753
},
756754
},
@@ -4002,7 +4000,6 @@ func TestUUID5Validation(t *testing.T) {
40024000
param string
40034001
expected bool
40044002
}{
4005-
40064003
{"", false},
40074004
{"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
40084005
{"9c858901-8a57-4791-81fe-4c455b099bc9", false},
@@ -4119,8 +4116,10 @@ func (u uuidAlias) String() string {
41194116
return "This is a UUID " + string(u)
41204117
}
41214118

4122-
var _ fmt.Stringer = uuidTestType{}
4123-
var _ fmt.Stringer = uuidAlias("")
4119+
var (
4120+
_ fmt.Stringer = uuidTestType{}
4121+
_ fmt.Stringer = uuidAlias("")
4122+
)
41244123

41254124
func TestUUIDValidation(t *testing.T) {
41264125
tests := []struct {
@@ -4190,7 +4189,6 @@ func TestUUID5RFC4122Validation(t *testing.T) {
41904189
param string
41914190
expected bool
41924191
}{
4193-
41944192
{"", false},
41954193
{"xxxa987Fbc9-4bed-3078-cf07-9141ba07c9f3", false},
41964194
{"9c858901-8a57-4791-81Fe-4c455b099bc9", false},
@@ -8903,6 +8901,7 @@ func TestNumeric(t *testing.T) {
89038901
errs = validate.Var(i, "numeric")
89048902
Equal(t, errs, nil)
89058903
}
8904+
89068905
func TestBoolean(t *testing.T) {
89078906
validate := New()
89088907

@@ -9628,11 +9627,9 @@ func TestStructFiltered(t *testing.T) {
96289627

96299628
SubSlice: []*SubTest{
96309629
{
9631-
96329630
Test: "Required",
96339631
},
96349632
{
9635-
96369633
Test: "Required",
96379634
},
96389635
},
@@ -12080,7 +12077,7 @@ func TestExcludedIf(t *testing.T) {
1208012077

1208112078
test11 := struct {
1208212079
Field1 bool
12083-
Field2 *string `validate:"excluded_if=Field1 false"`
12080+
Field2 *string `validate:"excluded_if=Field1 false"`
1208412081
}{
1208512082
Field1: false,
1208612083
Field2: nil,
@@ -12788,7 +12785,7 @@ func TestIsIso3166AlphaNumericEUValidation(t *testing.T) {
1278812785
value interface{}
1278912786
expected bool
1279012787
}{
12791-
{752, true}, //Sweden
12788+
{752, true}, // Sweden
1279212789
{"752", true},
1279312790
{826, false}, // UK
1279412791
{"826", false},
@@ -13185,7 +13182,6 @@ func TestSemverFormatValidation(t *testing.T) {
1318513182
}
1318613183

1318713184
func TestCveFormatValidation(t *testing.T) {
13188-
1318913185
tests := []struct {
1319013186
value string `validate:"cve"`
1319113187
tag string
@@ -13384,7 +13380,6 @@ func TestPostCodeByIso3166Alpha2Field_InvalidKind(t *testing.T) {
1338413380
}
1338513381

1338613382
func TestValidate_ValidateMapCtx(t *testing.T) {
13387-
1338813383
type args struct {
1338913384
data map[string]interface{}
1339013385
rules map[string]interface{}
@@ -13509,6 +13504,7 @@ func TestMongoDBObjectIDFormatValidation(t *testing.T) {
1350913504
}
1351013505
}
1351113506
}
13507+
1351213508
func TestMongoDBConnectionStringFormatValidation(t *testing.T) {
1351313509
tests := []struct {
1351413510
value string `validate:"mongodb_connection_string"`
@@ -13919,7 +13915,7 @@ func TestNestedStructValidation(t *testing.T) {
1391913915
},
1392013916
}
1392113917

13922-
var evaluateTest = func(tt test, errs error) {
13918+
evaluateTest := func(tt test, errs error) {
1392313919
if tt.err != (testErr{}) && errs != nil {
1392413920
Equal(t, len(errs.(ValidationErrors)), 1)
1392513921

@@ -14075,6 +14071,36 @@ func TestOmitZero(t *testing.T) {
1407514071
})
1407614072
}
1407714073

14074+
func TestEINStringValidation(t *testing.T) {
14075+
tests := []struct {
14076+
value string `validate:"ein"`
14077+
expected bool
14078+
}{
14079+
{"01-2564282", true},
14080+
{"25-4573894", true},
14081+
{"63-236", false},
14082+
{"3-5738294", false},
14083+
{"4235-48", false},
14084+
{"0.-47829", false},
14085+
{"23-", false},
14086+
}
14087+
validate := New()
14088+
14089+
for i, test := range tests {
14090+
errs := validate.Var(test.value, "ein")
14091+
14092+
if test.expected {
14093+
if !IsEqual(errs, nil) {
14094+
t.Fatalf("Index: %d ein failed Error: %s", i, errs)
14095+
}
14096+
} else {
14097+
if IsEqual(errs, nil) {
14098+
t.Fatalf("Index: %d ein failed Error: %s", i, errs)
14099+
}
14100+
}
14101+
}
14102+
}
14103+
1407814104
func TestPrivateFieldsStruct(t *testing.T) {
1407914105
type tc struct {
1408014106
stct interface{}

0 commit comments

Comments
 (0)