diff --git a/baked_in.go b/baked_in.go index 3f87da4..17fc6c3 100644 --- a/baked_in.go +++ b/baked_in.go @@ -7,6 +7,7 @@ import ( "fmt" "net" "net/url" + "os" "reflect" "strconv" "strings" @@ -97,6 +98,7 @@ var ( "email": isEmail, "url": isURL, "uri": isURI, + "file": isFile, "base64": isBase64, "base64url": isBase64URL, "contains": contains, @@ -1060,6 +1062,23 @@ func isURL(fl FieldLevel) bool { panic(fmt.Sprintf("Bad field type %T", field.Interface())) } +// IsFile is the validation function for validating if the current field's value is a valid file path. +func isFile(fl FieldLevel) bool { + field := fl.Field() + + switch field.Kind() { + case reflect.String: + fileInfo, err := os.Stat(field.String()) + if err != nil { + return false + } + + return !fileInfo.IsDir() + } + + panic(fmt.Sprintf("Bad field type %T", field.Interface())) +} + // IsEmail is the validation function for validating if the current field's value is a valid email address. func isEmail(fl FieldLevel) bool { return emailRegex.MatchString(fl.Field().String()) diff --git a/testdata/a.go b/testdata/a.go new file mode 100644 index 0000000..69d29d3 --- /dev/null +++ b/testdata/a.go @@ -0,0 +1 @@ +package testdata diff --git a/validator_test.go b/validator_test.go index 0823812..36c61fa 100644 --- a/validator_test.go +++ b/validator_test.go @@ -8,6 +8,7 @@ import ( "encoding/base64" "encoding/json" "fmt" + "path/filepath" "reflect" "strings" "testing" @@ -4446,6 +4447,39 @@ func TestBase64URLValidation(t *testing.T) { } } +func TestFileValidation(t *testing.T) { + validate := New() + + tests := []struct { + title string + param string + expected bool + }{ + {"empty path", "", false}, + {"regular file", filepath.Join("testdata", "a.go"), true}, + {"missing file", filepath.Join("testdata", "no.go"), false}, + {"directory, not a file", "testdata", false}, + } + + for _, test := range tests { + errs := validate.Var(test.param, "file") + + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Test: '%s' failed Error: %s", test.title, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Test: '%s' failed Error: %s", test.title, errs) + } + } + } + + PanicMatches(t, func() { + validate.Var(6, "file") + }, "Bad field type int") +} + func TestEthereumAddressValidation(t *testing.T) { validate := New()