Skip to content

Commit 297ccf7

Browse files
committed
Add some rules and can add custom validation function
1 parent dc461b0 commit 297ccf7

File tree

5 files changed

+116
-9
lines changed

5 files changed

+116
-9
lines changed

Diff for: go.mod

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ module github.com/debug-ing/validation-go
22

33
go 1.22.3
44

5-
require github.com/google/uuid v1.6.0
5+
require (
6+
github.com/google/uuid v1.6.0
7+
github.com/oklog/ulid/v2 v2.1.0
8+
)

Diff for: go.sum

+3
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
22
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
3+
github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU=
4+
github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
5+
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=

Diff for: main.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"errors"
45
"fmt"
56

67
"github.com/debug-ing/validation-go/pkg/validation"
@@ -12,6 +13,7 @@ type UpdateIAMUserRequest struct {
1213
LName string `validate:"required,minlength=10"`
1314
Age int `validate:"required,numeric,minmax=18-100"`
1415
Nike string `validate:"required,between=1-10"`
16+
Test string `validate:"contains=hello"`
1517
}
1618

1719
func main() {
@@ -21,12 +23,22 @@ func main() {
2123
LName: "ddsffddddd",
2224
Age: 29,
2325
Nike: "sdfkjdf",
26+
Test: "hell1o",
2427
}
25-
//
28+
validation.AddCustomValidator("test", "%s vard kon", validateRequired)
2629
err := validation.ValidateStruct(req)
2730
if err != nil {
2831
fmt.Println("Validation error:", err)
2932
} else {
3033
fmt.Println("Validation passed")
3134
}
35+
//
36+
}
37+
38+
func validateRequired(value string, errorMsg string) error {
39+
if value == "" {
40+
fmt.Println(errorMsg)
41+
return errors.New(errorMsg)
42+
}
43+
return nil
3244
}

Diff for: pkg/validation/rules.go

+62
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package validation
22

33
import (
44
"errors"
5+
"regexp"
56
"strconv"
67
"strings"
78

89
"github.com/google/uuid"
10+
"github.com/oklog/ulid/v2"
911
)
1012

1113
func validateRequired(value string, errorMsg string) error {
@@ -23,6 +25,38 @@ func validationIsUUID(value string, errorMsg string) error {
2325
return nil
2426
}
2527

28+
func validationIsULID(value string, errorMsg string) error {
29+
_, err := ulid.Parse(value)
30+
if err != nil {
31+
return errors.New(errorMsg)
32+
}
33+
return nil
34+
}
35+
36+
func validationIsBIC(value string, errorMsg string) error {
37+
bicRegex := `^[A-Za-z]{4}[A-Za-z]{2}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$`
38+
if matched, _ := regexp.MatchString(bicRegex, value); !matched {
39+
return errors.New(errorMsg)
40+
}
41+
return nil
42+
}
43+
44+
func validationIsEthereumAddress(value string, errorMsg string) error {
45+
ethRegex := `^0x[a-fA-F0-9]{40}$`
46+
if matched, _ := regexp.MatchString(ethRegex, value); !matched {
47+
return errors.New(errorMsg)
48+
}
49+
return nil
50+
}
51+
52+
func validationIsBtcAddress(value string, errorMsg string) error {
53+
btcRegex := `^(1|3|bc1)[a-zA-HJ-NP-Z0-9]{25,39}$`
54+
if matched, _ := regexp.MatchString(btcRegex, value); !matched {
55+
return errors.New(errorMsg)
56+
}
57+
return nil
58+
}
59+
2660
func validateMinLength(value string, min int, errorMsg string) error {
2761
if len(value) < min {
2862
return errors.New(errorMsg)
@@ -41,6 +75,12 @@ func validateIsNumber(value string, errorMsg string) error {
4175
}
4276
return nil
4377
}
78+
func validateIsBoolean(value string, errorMsg string) error {
79+
if _, err := strconv.ParseBool(value); err != nil {
80+
return errors.New(errorMsg)
81+
}
82+
return nil
83+
}
4484

4585
func validationBetween(value string, min, max int, errorMsg string) error {
4686
if len(value) < min || len(value) > max {
@@ -60,3 +100,25 @@ func validationMinMaxNumber(value string, min, max int, errorMsg string) error {
60100
}
61101
return nil
62102
}
103+
104+
func validationIsContains(value string, contains string, errorMsg string) error {
105+
if !strings.Contains(value, contains) {
106+
return errors.New(errorMsg)
107+
}
108+
return nil
109+
}
110+
111+
func validationIsNotContains(value string, contains string, errorMsg string) error {
112+
if strings.Contains(value, contains) {
113+
return errors.New(errorMsg)
114+
}
115+
return nil
116+
}
117+
118+
func validationIsMongoID(value string, errorMsg string) error {
119+
mongoIDRegex := `^[0-9a-fA-F]{24}$`
120+
if matched, _ := regexp.MatchString(mongoIDRegex, value); !matched {
121+
return errors.New(errorMsg)
122+
}
123+
return nil
124+
}

Diff for: pkg/validation/validator.go

+34-7
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,21 @@ import (
88
)
99

1010
var validators = map[string]interface{}{
11-
"required": validateRequired,
12-
"minlength": validateMinLength,
13-
"uuid": validationIsUUID,
14-
"email": validateIsEmail,
15-
"numeric": validateIsNumber,
16-
"between": validationBetween,
17-
"minmax": validationMinMaxNumber,
11+
"required": validateRequired,
12+
"minlength": validateMinLength,
13+
"uuid": validationIsUUID,
14+
"ulid": validationIsULID,
15+
"bic": validationIsBIC,
16+
"ethaddress": validationIsEthereumAddress,
17+
"btcaddress": validationIsBtcAddress,
18+
"mongoID": validationIsMongoID,
19+
"email": validateIsEmail,
20+
"numeric": validateIsNumber,
21+
"boolean": validateIsBoolean,
22+
"contains": validationIsContains,
23+
"notcontains": validationIsNotContains,
24+
"between": validationBetween,
25+
"minmax": validationMinMaxNumber,
1826
}
1927

2028
var data = map[string]map[string]string{
@@ -39,6 +47,12 @@ var data = map[string]map[string]string{
3947
"minmax": {
4048
"error_msg": "%s must be between %d and %d.",
4149
},
50+
"contains": {
51+
"error_msg": "%s must contain.",
52+
},
53+
"notcontains": {
54+
"error_msg": "%s must not contain.",
55+
},
4256
}
4357

4458
func ValidateStruct(s interface{}) error {
@@ -73,6 +87,11 @@ func ValidateStruct(s interface{}) error {
7387
} else {
7488
return fmt.Errorf("invalid parameter for tag %s", tagName)
7589
}
90+
case func(string, string, string) error:
91+
errorMsg := getMessage(tagName, fieldName)
92+
if err := validator(fmt.Sprint(value), tagParam, errorMsg); err != nil {
93+
return err
94+
}
7695
case func(string, int, int, string) error:
7796
params := strings.Split(tagParam, "-")
7897
if len(params) != 2 {
@@ -101,6 +120,14 @@ func ValidateStruct(s interface{}) error {
101120
return nil
102121
}
103122

123+
func AddCustomValidator(tagName, message string, fn interface{}) {
124+
validators[tagName] = fn
125+
data[tagName] = map[string]string{
126+
"error_msg": message,
127+
}
128+
fmt.Println(data)
129+
}
130+
104131
func getMessage(tagName, fieldName string, args ...interface{}) string {
105132
errorMsgTemplate := data[tagName]["error_msg"]
106133
return fmt.Sprintf(errorMsgTemplate, append([]interface{}{fieldName}, args...)...)

0 commit comments

Comments
 (0)