diff --git a/baked_in.go b/baked_in.go index 0fae541..186c6da 100644 --- a/baked_in.go +++ b/baked_in.go @@ -158,6 +158,7 @@ var ( "html": isHTML, "html_encoded": isHTMLEncoded, "url_encoded": isURLEncoded, + "dir": isDir, } ) @@ -1845,3 +1846,19 @@ func isFQDN(fl FieldLevel) bool { return strings.ContainsAny(val, ".") && hostnameRegexRFC952.MatchString(val) } + +// IsDir is the validation function for validating if the current field's value is a valid directory. +func isDir(fl FieldLevel) bool { + field := fl.Field() + + if field.Kind() == 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())) +} diff --git a/doc.go b/doc.go index 64cbcdf..17ab625 100644 --- a/doc.go +++ b/doc.go @@ -947,6 +947,14 @@ to https://tools.ietf.org/html/rfc3986#section-2.1 Usage: url_encoded +Directory + +This validates that a string value contains a valid directory and that +it exists on the machine. +This is done using os.Stat, which is a platform independent function. + + Usage: dir + Alias Validators and Tags NOTE: When returning an error, the tag returned in "FieldError" will be diff --git a/validator_test.go b/validator_test.go index 5534aa5..88ad55b 100644 --- a/validator_test.go +++ b/validator_test.go @@ -8508,3 +8508,38 @@ func TestStructLevelValidationsPointerPassing(t *testing.T) { NotEqual(t, errs, nil) AssertError(t, errs, "TestStruct.StringVal", "TestStruct.String", "StringVal", "String", "badvalueteststruct") } + +func TestDirValidation(t *testing.T) { + validate := New() + + tests := []struct { + title string + param string + expected bool + }{ + {"existing dir", "testdata", true}, + {"existing self dir", ".", true}, + {"existing parent dir", "..", true}, + {"empty dir", "", false}, + {"missing dir", "non_existing_testdata", false}, + {"a file not a directory", filepath.Join("testdata", "a.go"), false}, + } + + for _, test := range tests { + errs := validate.Var(test.param, "dir") + + 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(2, "dir") + }, "Bad field type int") +}