Skip to content

Commit 5ac1643

Browse files
authored
feat: add image validation (#982)
1 parent cc45daf commit 5ac1643

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+357
-19
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ _testmain.go
2626
*.test
2727
*.out
2828
*.txt
29+
/**/*.DS_Store
2930
cover.html
3031
README.html
3132
.idea

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ Baked-in Validations
228228
| dirpath | Directory Path |
229229
| file | Existing File |
230230
| filepath | File Path |
231+
| image | Image |
231232
| isdefault | Is Default |
232233
| len | Length |
233234
| max | Maximum |

baked_in.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"golang.org/x/crypto/sha3"
2323
"golang.org/x/text/language"
2424

25+
"github.com/gabriel-vasile/mimetype"
2526
"github.com/leodido/go-urn"
2627
)
2728

@@ -144,6 +145,7 @@ var (
144145
"endswith": endsWith,
145146
"startsnotwith": startsNotWith,
146147
"endsnotwith": endsNotWith,
148+
"image": isImage,
147149
"isbn": isISBN,
148150
"isbn10": isISBN10,
149151
"isbn13": isISBN13,
@@ -1488,6 +1490,67 @@ func isFile(fl FieldLevel) bool {
14881490
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
14891491
}
14901492

1493+
// isImage is the validation function for validating if the current field's value contains the path to a valid image file
1494+
func isImage(fl FieldLevel) bool {
1495+
mimetypes := map[string]bool{
1496+
"image/bmp": true,
1497+
"image/cis-cod": true,
1498+
"image/gif": true,
1499+
"image/ief": true,
1500+
"image/jpeg": true,
1501+
"image/jp2": true,
1502+
"image/jpx": true,
1503+
"image/jpm": true,
1504+
"image/pipeg": true,
1505+
"image/png": true,
1506+
"image/svg+xml": true,
1507+
"image/tiff": true,
1508+
"image/webp": true,
1509+
"image/x-cmu-raster": true,
1510+
"image/x-cmx": true,
1511+
"image/x-icon": true,
1512+
"image/x-portable-anymap": true,
1513+
"image/x-portable-bitmap": true,
1514+
"image/x-portable-graymap": true,
1515+
"image/x-portable-pixmap": true,
1516+
"image/x-rgb": true,
1517+
"image/x-xbitmap": true,
1518+
"image/x-xpixmap": true,
1519+
"image/x-xwindowdump": true,
1520+
}
1521+
field := fl.Field()
1522+
1523+
switch field.Kind() {
1524+
case reflect.String:
1525+
filePath := field.String()
1526+
fileInfo, err := os.Stat(filePath)
1527+
1528+
if err != nil {
1529+
return false
1530+
}
1531+
1532+
if fileInfo.IsDir() {
1533+
return false
1534+
}
1535+
1536+
file, err := os.Open(filePath)
1537+
if err != nil {
1538+
return false
1539+
}
1540+
defer file.Close()
1541+
1542+
mime, err := mimetype.DetectReader(file)
1543+
if err != nil {
1544+
return false
1545+
}
1546+
1547+
if _, ok := mimetypes[mime.String()]; ok {
1548+
return true
1549+
}
1550+
}
1551+
return false
1552+
}
1553+
14911554
// isFilePath is the validation function for validating if the current field's value is a valid file path.
14921555
func isFilePath(fl FieldLevel) bool {
14931556

country_codes.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1135,7 +1135,7 @@ var iso3166_2 = map[string]bool{
11351135
"VN-69": true, "VN-70": true, "VN-71": true, "VN-72": true, "VN-73": true,
11361136
"VN-CT": true, "VN-DN": true, "VN-HN": true, "VN-HP": true, "VN-SG": true,
11371137
"VU-MAP": true, "VU-PAM": true, "VU-SAM": true, "VU-SEE": true, "VU-TAE": true,
1138-
"VU-TOB": true, "WF-SG": true,"WF-UV": true, "WS-AA": true, "WS-AL": true, "WS-AT": true, "WS-FA": true,
1138+
"VU-TOB": true, "WF-SG": true, "WF-UV": true, "WS-AA": true, "WS-AL": true, "WS-AT": true, "WS-FA": true,
11391139
"WS-GE": true, "WS-GI": true, "WS-PA": true, "WS-SA": true, "WS-TU": true,
11401140
"WS-VF": true, "WS-VS": true, "YE-AB": true, "YE-AD": true, "YE-AM": true,
11411141
"YE-BA": true, "YE-DA": true, "YE-DH": true, "YE-HD": true, "YE-HJ": true, "YE-HU": true,

doc.go

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -863,7 +863,6 @@ This validates that a string value is a valid JWT
863863
864864
Usage: jwt
865865
866-
867866
# File
868867
869868
This validates that a string value contains a valid file path and that
@@ -872,6 +871,15 @@ This is done using os.Stat, which is a platform independent function.
872871
873872
Usage: file
874873
874+
# Image path
875+
876+
This validates that a string value contains a valid file path and that
877+
the file exists on the machine and is an image.
878+
This is done using os.Stat and github.com/gabriel-vasile/mimetype
879+
880+
Usage: image
881+
882+
# URL String
875883
876884
# File Path
877885
@@ -881,7 +889,6 @@ This is done using os.Stat, which is a platform independent function.
881889
882890
Usage: filepath
883891
884-
885892
# URL String
886893
887894
This validates that a string value contains a valid url
@@ -923,7 +930,6 @@ you can use this with the omitempty tag.
923930
924931
Usage: base64url
925932
926-
927933
# Base64RawURL String
928934
929935
This validates that a string value contains a valid base64 URL safe value,
@@ -934,7 +940,6 @@ you can use this with the omitempty tag.
934940
935941
Usage: base64url
936942
937-
938943
# Bitcoin Address
939944
940945
This validates that a string value contains a valid bitcoin address.
@@ -1267,7 +1272,6 @@ This is done using os.Stat, which is a platform independent function.
12671272
12681273
Usage: dir
12691274
1270-
12711275
# Directory Path
12721276
12731277
This validates that a string value contains a valid directory but does
@@ -1278,7 +1282,6 @@ may not exist at the time of validation.
12781282
12791283
Usage: dirpath
12801284
1281-
12821285
# HostPort
12831286
12841287
This validates that a string value contains a valid DNS hostname and port that
@@ -1350,42 +1353,38 @@ More information on https://semver.org/
13501353
13511354
Usage: semver
13521355
1353-
13541356
# CVE Identifier
13551357
13561358
This validates that a string value is a valid cve id, defined in cve mitre.
13571359
More information on https://cve.mitre.org/
13581360
13591361
Usage: cve
13601362
1361-
13621363
# Credit Card
13631364
13641365
This validates that a string value contains a valid credit card number using Luhn algorithm.
13651366
13661367
Usage: credit_card
13671368
1368-
13691369
# Luhn Checksum
13701370
1371-
Usage: luhn_checksum
1371+
Usage: luhn_checksum
13721372
13731373
This validates that a string or (u)int value contains a valid checksum using the Luhn algorithm.
13741374
13751375
# MongoDb ObjectID
13761376
13771377
This validates that a string is a valid 24 character hexadecimal string.
13781378
1379-
Usage: mongodb
1380-
1379+
Usage: mongodb
13811380
13821381
# Cron
13831382
13841383
This validates that a string value contains a valid cron expression.
13851384
13861385
Usage: cron
13871386
1388-
Alias Validators and Tags
1387+
# Alias Validators and Tags
13891388
13901389
Alias Validators and Tags
13911390
NOTE: When returning an error, the tag returned in "FieldError" will be

go.mod

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ module github.com/go-playground/validator/v10
33
go 1.18
44

55
require (
6+
github.com/gabriel-vasile/mimetype v1.4.2
67
github.com/go-playground/assert/v2 v2.2.0
78
github.com/go-playground/locales v0.14.1
89
github.com/go-playground/universal-translator v0.18.1
9-
github.com/leodido/go-urn v1.2.3
10+
github.com/leodido/go-urn v1.2.4
1011
golang.org/x/crypto v0.7.0
1112
golang.org/x/text v0.8.0
1213
)
1314

14-
require golang.org/x/sys v0.6.0 // indirect
15+
require (
16+
golang.org/x/net v0.8.0 // indirect
17+
golang.org/x/sys v0.6.0 // indirect
18+
)

go.sum

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
22
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
33
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4+
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
5+
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
46
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
57
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
68
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
79
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
810
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
911
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
10-
github.com/leodido/go-urn v1.2.3 h1:6BE2vPT0lqoz3fmOesHZiaiFh7889ssCo2GMvLCfiuA=
11-
github.com/leodido/go-urn v1.2.3/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
12+
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
13+
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
1214
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1315
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
1416
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -20,6 +22,8 @@ github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ
2022
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
2123
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
2224
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
25+
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
26+
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
2327
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
2428
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
2529
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=

testdata/music.mp3

5.07 KB
Binary file not shown.

translations/ar/ar.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,6 +1346,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
13461346
return t
13471347
},
13481348
},
1349+
{
1350+
tag: "image",
1351+
translation: "يجب أن تكون {0} صورة صالحة",
1352+
override: false,
1353+
},
13491354
}
13501355

13511356
for _, t := range translations {

translations/ar/ar_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ func TestTranslations(t *testing.T) {
149149
PostCode string `validate:"postcode_iso3166_alpha2=SG"`
150150
PostCodeCountry string
151151
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"`
152+
Image string `validate:"image"`
152153
}
153154

154155
var test Test
@@ -676,6 +677,10 @@ func TestTranslations(t *testing.T) {
676677
ns: "Test.PostCodeByField",
677678
expected: "لا يتطابق PostCodeByField مع تنسيق الرمز البريدي للبلد في حقل PostCodeCountry",
678679
},
680+
{
681+
ns: "Test.Image",
682+
expected: "يجب أن تكون Image صورة صالحة",
683+
},
679684
}
680685

681686
for _, tt := range tests {

0 commit comments

Comments
 (0)