feat: add image validation

pull/982/head
Fanan Dala 2 years ago
parent 9e2ea40380
commit bc7329ef0f
  1. 1
      .gitignore
  2. 1
      README.md
  3. 71
      baked_in.go
  4. 8
      doc.go
  5. 2
      go.mod
  6. 10
      go.sum
  7. BIN
      testdata/music.mp3
  8. 5
      translations/ar/ar.go
  9. 5
      translations/ar/ar_test.go
  10. 5
      translations/en/en.go
  11. 5
      translations/en/en_test.go
  12. 5
      translations/es/es.go
  13. 5
      translations/es/es_test.go
  14. 5
      translations/fa/fa.go
  15. 7
      translations/fa/fa_test.go
  16. 5
      translations/fr/fr.go
  17. 5
      translations/fr/fr_test.go
  18. 5
      translations/id/id.go
  19. 5
      translations/id/id_test.go
  20. 5
      translations/it/it.go
  21. 5
      translations/it/it_test.go
  22. 5
      translations/ja/ja.go
  23. 5
      translations/ja/ja_test.go
  24. 5
      translations/nl/nl.go
  25. 5
      translations/nl/nl_test.go
  26. 5
      translations/pt/pt.go
  27. 5
      translations/pt/pt_test.go
  28. 5
      translations/pt_BR/pt_BR.go
  29. 5
      translations/pt_BR/pt_BR_test.go
  30. 5
      translations/ru/ru.go
  31. 5
      translations/ru/ru_test.go
  32. 5
      translations/tr/tr.go
  33. 5
      translations/tr/tr_test.go
  34. 5
      translations/vi/vi.go
  35. 5
      translations/vi/vi_test.go
  36. 5
      translations/zh/zh.go
  37. 5
      translations/zh/zh_test.go
  38. 5
      translations/zh_tw/zh_tw.go
  39. 5
      translations/zh_tw/zh_tw_test.go
  40. 106
      validator_test.go

1
.gitignore vendored

@ -26,5 +26,6 @@ _testmain.go
*.test *.test
*.out *.out
*.txt *.txt
/**/*.DS_Store
cover.html cover.html
README.html README.html

@ -218,6 +218,7 @@ Baked-in Validations
| - | - | | - | - |
| dir | Directory | | dir | Directory |
| file | File path | | file | File path |
| image | Image |
| isdefault | Is Default | | isdefault | Is Default |
| len | Length | | len | Length |
| max | Maximum | | max | Maximum |

@ -7,6 +7,7 @@ import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"net" "net"
"net/url" "net/url"
"os" "os"
@ -20,6 +21,7 @@ import (
"golang.org/x/crypto/sha3" "golang.org/x/crypto/sha3"
"golang.org/x/text/language" "golang.org/x/text/language"
"github.com/gabriel-vasile/mimetype"
urn "github.com/leodido/go-urn" urn "github.com/leodido/go-urn"
) )
@ -136,6 +138,7 @@ var (
"endswith": endsWith, "endswith": endsWith,
"startsnotwith": startsNotWith, "startsnotwith": startsNotWith,
"endsnotwith": endsNotWith, "endsnotwith": endsNotWith,
"image": isImage,
"isbn": isISBN, "isbn": isISBN,
"isbn10": isISBN10, "isbn10": isISBN10,
"isbn13": isISBN13, "isbn13": isISBN13,
@ -1404,6 +1407,74 @@ func isFile(fl FieldLevel) bool {
panic(fmt.Sprintf("Bad field type %T", field.Interface())) panic(fmt.Sprintf("Bad field type %T", field.Interface()))
} }
func isImage(fl FieldLevel) bool {
mimetypes := map[string]bool{
"image/bmp": true,
"image/cis-cod": true,
"image/gif": true,
"image/ief": true,
"image/jpeg": true,
"image/jp2": true,
"image/jpx": true,
"image/jpm": true,
"image/pipeg": true,
"image/png": true,
"image/svg+xml": true,
"image/tiff": true,
"image/webp": true,
"image/x-cmu-raster": true,
"image/x-cmx": true,
"image/x-icon": true,
"image/x-portable-anymap": true,
"image/x-portable-bitmap": true,
"image/x-portable-graymap": true,
"image/x-portable-pixmap": true,
"image/x-rgb": true,
"image/x-xbitmap": true,
"image/x-xpixmap": true,
"image/x-xwindowdump": true,
}
field := fl.Field()
switch field.Kind() {
case reflect.String:
filePath := field.String()
fileInfo, err := os.Stat(filePath)
if err != nil {
return false
}
if fileInfo.IsDir() {
return false
}
file, err := os.OpenFile(filePath, os.O_RDWR, 0644)
if err != nil {
return false
}
defer file.Close()
mime, err := mimetype.DetectReader(file)
if err != nil {
return false
}
_, err = file.Seek(0, io.SeekStart)
if err != nil {
panic(fmt.Sprintf("Could not reset seek start for file. Error: %s", err))
}
if _, ok := mimetypes[mime.String()]; ok {
return true
}
return false
}
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
}
// isE164 is the validation function for validating if the current field's value is a valid e.164 formatted phone number. // isE164 is the validation function for validating if the current field's value is a valid e.164 formatted phone number.
func isE164(fl FieldLevel) bool { func isE164(fl FieldLevel) bool {
return e164Regex.MatchString(fl.Field().String()) return e164Regex.MatchString(fl.Field().String())

@ -873,6 +873,14 @@ This is done using os.Stat, which is a platform independent function.
Usage: file Usage: file
Image path
This validates that a string value contains a valid file path and that
the file exists on the machine and is an image.
This is done using os.Stat and github.com/gabriel-vasile/mimetype
Usage: image
URL String URL String
This validates that a string value contains a valid url This validates that a string value contains a valid url

@ -4,6 +4,7 @@ go 1.13
require ( require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.1
github.com/go-playground/assert/v2 v2.0.1 github.com/go-playground/assert/v2 v2.0.1
github.com/go-playground/locales v0.14.0 github.com/go-playground/locales v0.14.0
github.com/go-playground/universal-translator v0.18.0 github.com/go-playground/universal-translator v0.18.0
@ -12,7 +13,6 @@ require (
github.com/rogpeppe/go-internal v1.8.0 // indirect github.com/rogpeppe/go-internal v1.8.0 // indirect
github.com/stretchr/testify v1.7.0 // indirect github.com/stretchr/testify v1.7.0 // indirect
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect
golang.org/x/text v0.3.7 golang.org/x/text v0.3.7
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect

@ -2,6 +2,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gabriel-vasile/mimetype v1.4.1 h1:TRWk7se+TOjCYgRth7+1/OYLNiRNIotknkFtf/dnN7Q=
github.com/gabriel-vasile/mimetype v1.4.1/go.mod h1:05Vi0w3Y9c/lNvJOdmIwvrrAhX3rYhfQQCaf9VJcv7M=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
@ -31,13 +33,15 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=

BIN
testdata/music.mp3 vendored

Binary file not shown.

@ -1346,6 +1346,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return t return t
}, },
}, },
{
tag: "image",
translation: "يجب أن تكون {0} صورة صالحة",
override: false,
},
} }
for _, t := range translations { for _, t := range translations {

@ -149,6 +149,7 @@ func TestTranslations(t *testing.T) {
PostCode string `validate:"postcode_iso3166_alpha2=SG"` PostCode string `validate:"postcode_iso3166_alpha2=SG"`
PostCodeCountry string PostCodeCountry string
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"` PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"`
Image string `validate:"image"`
} }
var test Test var test Test
@ -676,6 +677,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.PostCodeByField", ns: "Test.PostCodeByField",
expected: "لا يتطابق PostCodeByField مع تنسيق الرمز البريدي للبلد في حقل PostCodeCountry", expected: "لا يتطابق PostCodeByField مع تنسيق الرمز البريدي للبلد في حقل PostCodeCountry",
}, },
{
ns: "Test.Image",
expected: "يجب أن تكون Image صورة صالحة",
},
} }
for _, tt := range tests { for _, tt := range tests {

@ -1356,6 +1356,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} must be a valid boolean value", translation: "{0} must be a valid boolean value",
override: false, override: false,
}, },
{
tag: "image",
translation: "{0} must be a valid image",
override: false,
},
} }
for _, t := range translations { for _, t := range translations {

@ -152,6 +152,7 @@ func TestTranslations(t *testing.T) {
PostCodeCountry string PostCodeCountry string
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"` PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"`
BooleanString string `validate:"boolean"` BooleanString string `validate:"boolean"`
Image string `validate:"image"`
} }
var test Test var test Test
@ -690,6 +691,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.BooleanString", ns: "Test.BooleanString",
expected: "BooleanString must be a valid boolean value", expected: "BooleanString must be a valid boolean value",
}, },
{
ns: "Test.Image",
expected: "Image must be a valid image",
},
} }
for _, tt := range tests { for _, tt := range tests {

@ -1326,6 +1326,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return s return s
}, },
}, },
{
tag: "image",
translation: "{0} debe ser una imagen válida",
override: false,
},
} }
for _, t := range translations { for _, t := range translations {

@ -142,6 +142,7 @@ func TestTranslations(t *testing.T) {
UniqueSlice []string `validate:"unique"` UniqueSlice []string `validate:"unique"`
UniqueArray [3]string `validate:"unique"` UniqueArray [3]string `validate:"unique"`
UniqueMap map[string]string `validate:"unique"` UniqueMap map[string]string `validate:"unique"`
Image string `validate:"image"`
} }
var test Test var test Test
@ -637,6 +638,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.UniqueMap", ns: "Test.UniqueMap",
expected: "UniqueMap debe contener valores únicos", expected: "UniqueMap debe contener valores únicos",
}, },
{
ns: "Test.Image",
expected: "Image debe ser una imagen válida",
},
} }
for _, tt := range tests { for _, tt := range tests {

@ -1341,6 +1341,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return t return t
}, },
}, },
{
tag: "image",
translation: "{0} باید یک تصویر معتبر باشد",
override: false,
},
} }
for _, t := range translations { for _, t := range translations {

@ -148,6 +148,7 @@ func TestTranslations(t *testing.T) {
PostCode string `validate:"postcode_iso3166_alpha2=SG"` PostCode string `validate:"postcode_iso3166_alpha2=SG"`
PostCodeCountry string PostCodeCountry string
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"` PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"`
Image string `validate:"image"`
} }
var test Test var test Test
@ -671,8 +672,12 @@ func TestTranslations(t *testing.T) {
ns: "Test.PostCodeByField", ns: "Test.PostCodeByField",
expected: "PostCodeByField یک کدپستی معتبر کشور فیلد PostCodeCountry نیست", expected: "PostCodeByField یک کدپستی معتبر کشور فیلد PostCodeCountry نیست",
}, },
{
ns: "Test.Image",
expected: "Image باید یک تصویر معتبر باشد",
},
} }
for _, tt := range tests { for _, tt := range tests {
var fe validator.FieldError var fe validator.FieldError

@ -1316,6 +1316,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return s return s
}, },
}, },
{
tag: "image",
translation: "{0} doit être une image valide",
override: false,
},
} }
for _, t := range translations { for _, t := range translations {

@ -139,6 +139,7 @@ func TestTranslations(t *testing.T) {
StrPtrGte *string `validate:"gte=10"` StrPtrGte *string `validate:"gte=10"`
OneOfString string `validate:"oneof=red green"` OneOfString string `validate:"oneof=red green"`
OneOfInt int `validate:"oneof=5 63"` OneOfInt int `validate:"oneof=5 63"`
Image string `validate:"image"`
} }
var test Test var test Test
@ -619,6 +620,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.OneOfInt", ns: "Test.OneOfInt",
expected: "OneOfInt doit être l'un des choix suivants [5 63]", expected: "OneOfInt doit être l'un des choix suivants [5 63]",
}, },
{
ns: "Test.Image",
expected: "Image doit être une image valide",
},
} }
for _, tt := range tests { for _, tt := range tests {

@ -1316,6 +1316,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return s return s
}, },
}, },
{
tag: "image",
translation: "{0} harus berupa gambar yang valid",
override: false,
},
} }
for _, t := range translations { for _, t := range translations {

@ -139,6 +139,7 @@ func TestTranslations(t *testing.T) {
StrPtrGte *string `validate:"gte=10"` StrPtrGte *string `validate:"gte=10"`
OneOfString string `validate:"oneof=merah hijau"` OneOfString string `validate:"oneof=merah hijau"`
OneOfInt int `validate:"oneof=5 63"` OneOfInt int `validate:"oneof=5 63"`
Image string `validate:"image"`
} }
var test Test var test Test
@ -619,6 +620,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.OneOfInt", ns: "Test.OneOfInt",
expected: "OneOfInt harus berupa salah satu dari [5 63]", expected: "OneOfInt harus berupa salah satu dari [5 63]",
}, },
{
ns: "Test.Image",
expected: "Image harus berupa gambar yang valid",
},
} }
for _, tt := range tests { for _, tt := range tests {

@ -1205,6 +1205,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
override: false, override: false,
customTransFunc: customTransFuncV1, customTransFunc: customTransFuncV1,
}, },
{
tag: "image",
translation: "{0} deve essere un'immagine valida",
override: false,
},
} }
for _, t := range translations { for _, t := range translations {

@ -154,6 +154,7 @@ func TestTranslations(t *testing.T) {
PostCode string `validate:"postcode_iso3166_alpha2=SG"` PostCode string `validate:"postcode_iso3166_alpha2=SG"`
PostCodeCountry string PostCodeCountry string
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"` PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"`
Image string `validate:"image"`
} }
var test Test var test Test
@ -706,6 +707,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.PostCodeByField", ns: "Test.PostCodeByField",
expected: "PostCodeByField non corrisponde al formato del codice postale dello stato nel campo PostCodeCountry", expected: "PostCodeByField non corrisponde al formato del codice postale dello stato nel campo PostCodeCountry",
}, },
{
ns: "Test.Image",
expected: "Image deve essere un'immagine valida",
},
} }
for _, tt := range tests { for _, tt := range tests {

@ -1372,6 +1372,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return s return s
}, },
}, },
{
tag: "image",
translation: "{0} は有効な画像でなければなりません",
override: false,
},
} }
for _, t := range translations { for _, t := range translations {

@ -139,6 +139,7 @@ func TestTranslations(t *testing.T) {
StrPtrGte *string `validate:"gte=10"` StrPtrGte *string `validate:"gte=10"`
OneOfString string `validate:"oneof=red green"` OneOfString string `validate:"oneof=red green"`
OneOfInt int `validate:"oneof=5 63"` OneOfInt int `validate:"oneof=5 63"`
Image string `validate:"image"`
} }
var test Test var test Test
@ -619,6 +620,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.OneOfInt", ns: "Test.OneOfInt",
expected: "OneOfIntは[5 63]のうちのいずれかでなければなりません", expected: "OneOfIntは[5 63]のうちのいずれかでなければなりません",
}, },
{
ns: "Test.Image",
expected: "Image は有効な画像でなければなりません",
},
} }
for _, tt := range tests { for _, tt := range tests {

@ -1316,6 +1316,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return s return s
}, },
}, },
{
tag: "image",
translation: "{0} moet een geldige afbeelding zijn",
override: false,
},
} }
for _, t := range translations { for _, t := range translations {

@ -139,6 +139,7 @@ func TestTranslations(t *testing.T) {
StrPtrGte *string `validate:"gte=10"` StrPtrGte *string `validate:"gte=10"`
OneOfString string `validate:"oneof=red green"` OneOfString string `validate:"oneof=red green"`
OneOfInt int `validate:"oneof=5 63"` OneOfInt int `validate:"oneof=5 63"`
Image string `validate:"image"`
} }
var test Test var test Test
@ -619,6 +620,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.OneOfInt", ns: "Test.OneOfInt",
expected: "OneOfInt moet een van de volgende zijn [5 63]", expected: "OneOfInt moet een van de volgende zijn [5 63]",
}, },
{
ns: "Test.Image",
expected: "Image moet een geldige afbeelding zijn",
},
} }
for _, tt := range tests { for _, tt := range tests {

@ -1356,6 +1356,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return t return t
}, },
}, },
{
tag: "image",
translation: "{0} deve ser uma imagem válida",
override: false,
},
} }
for _, t := range translations { for _, t := range translations {

@ -147,6 +147,7 @@ func TestTranslations(t *testing.T) {
LowercaseString string `validate:"lowercase"` LowercaseString string `validate:"lowercase"`
UppercaseString string `validate:"uppercase"` UppercaseString string `validate:"uppercase"`
Datetime string `validate:"datetime=2006-01-02"` Datetime string `validate:"datetime=2006-01-02"`
Image string `validate:"image"`
} }
var test Test var test Test
@ -662,6 +663,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.Datetime", ns: "Test.Datetime",
expected: "Datetime não está no formato 2006-01-02", expected: "Datetime não está no formato 2006-01-02",
}, },
{
ns: "Test.Image",
expected: "Image deve ser uma imagem válida",
},
} }
for _, tt := range tests { for _, tt := range tests {

@ -1321,6 +1321,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} deve ser um valor booleano válido", translation: "{0} deve ser um valor booleano válido",
override: false, override: false,
}, },
{
tag: "image",
translation: "{0} deve ser uma imagen válido",
override: false,
},
} }
for _, t := range translations { for _, t := range translations {

@ -140,6 +140,7 @@ func TestTranslations(t *testing.T) {
OneOfString string `validate:"oneof=red green"` OneOfString string `validate:"oneof=red green"`
OneOfInt int `validate:"oneof=5 63"` OneOfInt int `validate:"oneof=5 63"`
BooleanString string `validate:"boolean"` BooleanString string `validate:"boolean"`
Image string `validate:"image"`
} }
var test Test var test Test
@ -625,6 +626,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.BooleanString", ns: "Test.BooleanString",
expected: "BooleanString deve ser um valor booleano válido", expected: "BooleanString deve ser um valor booleano válido",
}, },
{
ns: "Test.Image",
expected: "Image deve ser uma imagen válido",
},
} }
for _, tt := range tests { for _, tt := range tests {

@ -1439,6 +1439,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return s return s
}, },
}, },
{
tag: "image",
translation: "{0} должно быть допустимым изображением",
override: false,
},
} }
for _, t := range translations { for _, t := range translations {

@ -164,6 +164,7 @@ func TestTranslations(t *testing.T) {
UniqueSlice []string `validate:"unique"` UniqueSlice []string `validate:"unique"`
UniqueArray [3]string `validate:"unique"` UniqueArray [3]string `validate:"unique"`
UniqueMap map[string]string `validate:"unique"` UniqueMap map[string]string `validate:"unique"`
Image string `validate:"image"`
} }
var test Test var test Test
@ -745,6 +746,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.UniqueMap", ns: "Test.UniqueMap",
expected: "UniqueMap должен содержать уникальные значения", expected: "UniqueMap должен содержать уникальные значения",
}, },
{
ns: "Test.Image",
expected: "Image должно быть допустимым изображением",
},
} }
for _, tt := range tests { for _, tt := range tests {

@ -1321,6 +1321,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return s return s
}, },
}, },
{
tag: "image",
translation: "{0} geçerli bir resim olmalıdır",
override: false,
},
} }
for _, t := range translations { for _, t := range translations {

@ -142,6 +142,7 @@ func TestTranslations(t *testing.T) {
UniqueSlice []string `validate:"unique"` UniqueSlice []string `validate:"unique"`
UniqueArray [3]string `validate:"unique"` UniqueArray [3]string `validate:"unique"`
UniqueMap map[string]string `validate:"unique"` UniqueMap map[string]string `validate:"unique"`
Image string `validate:"image"`
} }
var test Test var test Test
@ -637,6 +638,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.UniqueMap", ns: "Test.UniqueMap",
expected: "UniqueMap benzersiz değerler içermelidir", expected: "UniqueMap benzersiz değerler içermelidir",
}, },
{
ns: "Test.Image",
expected: "Image geçerli bir resim olmalıdır",
},
} }
for _, tt := range tests { for _, tt := range tests {

@ -1341,6 +1341,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return t return t
}, },
}, },
{
tag: "image",
translation: "{0} phải là một hình ảnh hợp lệ",
override: false,
},
} }
for _, t := range translations { for _, t := range translations {

@ -148,6 +148,7 @@ func TestTranslations(t *testing.T) {
PostCode string `validate:"postcode_iso3166_alpha2=SG"` PostCode string `validate:"postcode_iso3166_alpha2=SG"`
PostCodeCountry string PostCodeCountry string
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"` PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"`
Image string `validate:"image"`
} }
var test Test var test Test
@ -671,6 +672,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.PostCodeByField", ns: "Test.PostCodeByField",
expected: "PostCodeByField sai định dạng postcode của quốc gia tương ứng thuộc trường PostCodeCountry", expected: "PostCodeByField sai định dạng postcode của quốc gia tương ứng thuộc trường PostCodeCountry",
}, },
{
ns: "Test.Image",
expected: "Image phải là một hình ảnh hợp lệ",
},
} }
for _, tt := range tests { for _, tt := range tests {

@ -1428,6 +1428,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return t return t
}, },
}, },
{
tag: "image",
translation: "{0} 必须是有效图像",
override: false,
},
} }
for _, t := range translations { for _, t := range translations {

@ -148,6 +148,7 @@ func TestTranslations(t *testing.T) {
LowercaseString string `validate:"lowercase"` LowercaseString string `validate:"lowercase"`
UppercaseString string `validate:"uppercase"` UppercaseString string `validate:"uppercase"`
Datetime string `validate:"datetime=2006-01-02"` Datetime string `validate:"datetime=2006-01-02"`
Image string `validate:"image"`
} }
var test Test var test Test
@ -676,6 +677,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.Datetime", ns: "Test.Datetime",
expected: "Datetime的格式必须是2006-01-02", expected: "Datetime的格式必须是2006-01-02",
}, },
{
ns: "Test.Image",
expected: "Image 必须是有效图像",
},
} }
for _, tt := range tests { for _, tt := range tests {

@ -1324,6 +1324,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return t return t
}, },
}, },
{
tag: "image",
translation: "{0} 必須是有效圖像",
override: false,
},
} }
for _, t := range translations { for _, t := range translations {

@ -140,6 +140,7 @@ func TestTranslations(t *testing.T) {
OneOfString string `validate:"oneof=red green"` OneOfString string `validate:"oneof=red green"`
OneOfInt int `validate:"oneof=5 63"` OneOfInt int `validate:"oneof=5 63"`
Datetime string `validate:"datetime=2006-01-02"` Datetime string `validate:"datetime=2006-01-02"`
Image string `validate:"image"`
} }
var test Test var test Test
@ -626,6 +627,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.Datetime", ns: "Test.Datetime",
expected: "Datetime與2006-01-02格式不匹配", expected: "Datetime與2006-01-02格式不匹配",
}, },
{
ns: "Test.Image",
expected: "Image 必須是有效圖像",
},
} }
for _, tt := range tests { for _, tt := range tests {

@ -8,6 +8,10 @@ import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"image"
"image/png"
"image/jpeg"
"os"
"path/filepath" "path/filepath"
"reflect" "reflect"
"strings" "strings"
@ -5650,6 +5654,108 @@ func TestFileValidation(t *testing.T) {
}, "Bad field type int") }, "Bad field type int")
} }
func TestImageValidation(t *testing.T) {
validate := New()
paths := map[string]string{
"empty": "",
"directory": "testdata",
"missing": filepath.Join("testdata", "none.png"),
"png": filepath.Join("testdata", "image.png"),
"jpeg": filepath.Join("testdata", "image.jpg"),
"mp3": filepath.Join("testdata", "music.mp3"),
}
tests := []struct {
title string
param string
expected bool
createImage func()
destroyImage func()
}{
{
"empty path",
paths["empty"], false,
func () {},
func () {},
},
{
"directory, not a file",
paths["directory"],
false,
func () {},
func () {},
},
{
"missing file",
paths["missing"],
false,
func () {},
func () {},
},
{
"valid png",
paths["png"],
true,
func () {
img := image.NewRGBA(image.Rectangle{image.Point{0, 0}, image.Point{10, 10}})
f, _ := os.Create(paths["png"])
err := png.Encode(f, img)
if err != nil {
panic(fmt.Sprintf("Could not encode file in PNG. Error: %s", err))
}
},
func () {
os.Remove(paths["png"])
},
},
{
"valid jpeg",
paths["jpeg"],
true,
func () {
var opt jpeg.Options
img := image.NewGray(image.Rect(0, 0, 10, 10))
f, _ := os.Create(paths["jpeg"])
err := jpeg.Encode(f, img, &opt)
if err != nil {
panic(fmt.Sprintf("Could not encode file in JPEG. Error: %s", err))
}
},
func () {
os.Remove(paths["jpeg"])
},
},
{
"valid mp3",
paths["mp3"],
false,
func () {},
func () {},
},
}
for _, test := range tests {
test.createImage()
errs := validate.Var(test.param, "image")
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)
}
}
test.destroyImage()
}
PanicMatches(t, func() {
_ = validate.Var(6, "file")
}, "Bad field type int")
}
func TestEthereumAddressValidation(t *testing.T) { func TestEthereumAddressValidation(t *testing.T) {
validate := New() validate := New()

Loading…
Cancel
Save