diff --git a/baked_in.go b/baked_in.go index 9bbf399..95a7431 100644 --- a/baked_in.go +++ b/baked_in.go @@ -2,6 +2,7 @@ package validator import ( "fmt" + "net" "net/url" "reflect" "strconv" @@ -64,6 +65,29 @@ var BakedInValidators = map[string]Func{ "latitude": isLatitude, "longitude": isLongitude, "ssn": isSSN, + "ipv4": isIPv4, + "ipv6": isIPv6, + "ip": isIP, +} + +func isIPv4(topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { + + ip := net.ParseIP(field.String()) + + return ip != nil && ip.To4() != nil +} + +func isIPv6(topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { + ip := net.ParseIP(field.String()) + + return ip != nil && ip.To4() == nil +} + +func isIP(topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { + + ip := net.ParseIP(field.String()) + + return ip != nil } func isSSN(topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool { diff --git a/doc.go b/doc.go index 82804b8..e81d6c2 100644 --- a/doc.go +++ b/doc.go @@ -372,6 +372,18 @@ Here is a list of the current built in validators: This validates that a string value contains a valid U.S. Social Security Number. (Usage: ssn) + ip + This validates that a string value contains a valid IP Adress. + (Usage: ip) + + ipv4 + This validates that a string value contains a valid v4 IP Adress. + (Usage: ipv4) + + ipv6 + This validates that a string value contains a valid v6 IP Adress. + (Usage: ipv6) + Validator notes: regex diff --git a/validator_test.go b/validator_test.go index 6048606..87e0716 100644 --- a/validator_test.go +++ b/validator_test.go @@ -119,6 +119,120 @@ func AssertError(t *testing.T, errs ValidationErrors, key, field, expectedTag st EqualSkip(t, 2, val.Tag, expectedTag) } +func TestIPValidation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"10.0.0.1", true}, + {"172.16.0.1", true}, + {"192.168.0.1", true}, + {"192.168.255.254", true}, + {"192.168.255.256", false}, + {"172.16.255.254", true}, + {"172.16.256.255", false}, + {"2001:cdba:0000:0000:0000:0000:3257:9652", true}, + {"2001:cdba:0:0:0:0:3257:9652", true}, + {"2001:cdba::3257:9652", true}, + } + + for i, test := range tests { + + errs := validate.Field(test.param, "ip") + + if test.expected == true { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d ip failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d ip failed Error: %s", i, errs) + } else { + val := errs[""] + if val.Tag != "ip" { + t.Fatalf("Index: %d ip failed Error: %s", i, errs) + } + } + } + } +} + +func TestIPv6Validation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"10.0.0.1", false}, + {"172.16.0.1", false}, + {"192.168.0.1", false}, + {"192.168.255.254", false}, + {"192.168.255.256", false}, + {"172.16.255.254", false}, + {"172.16.256.255", false}, + {"2001:cdba:0000:0000:0000:0000:3257:9652", true}, + {"2001:cdba:0:0:0:0:3257:9652", true}, + {"2001:cdba::3257:9652", true}, + } + + for i, test := range tests { + + errs := validate.Field(test.param, "ipv6") + + if test.expected == true { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs) + } else { + val := errs[""] + if val.Tag != "ipv6" { + t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs) + } + } + } + } +} + +func TestIPv4Validation(t *testing.T) { + tests := []struct { + param string + expected bool + }{ + {"10.0.0.1", true}, + {"172.16.0.1", true}, + {"192.168.0.1", true}, + {"192.168.255.254", true}, + {"192.168.255.256", false}, + {"172.16.255.254", true}, + {"172.16.256.255", false}, + {"2001:cdba:0000:0000:0000:0000:3257:9652", false}, + {"2001:cdba:0:0:0:0:3257:9652", false}, + {"2001:cdba::3257:9652", false}, + } + + for i, test := range tests { + + errs := validate.Field(test.param, "ipv4") + + if test.expected == true { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs) + } else { + val := errs[""] + if val.Tag != "ipv4" { + t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs) + } + } + } + } +} + func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) { var m map[string]string