Skip to content

Commit

Permalink
date validation
Browse files Browse the repository at this point in the history
  • Loading branch information
iesreza committed Jul 22, 2024
1 parent 786dbce commit 8b33984
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 19 deletions.
26 changes: 11 additions & 15 deletions lib/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,31 @@ import (
"fmt"
"github.com/getevo/evo/v2/lib/db"
"github.com/getevo/evo/v2/lib/generic"
"reflect"
"gorm.io/gorm/schema"
)

func Struct(input interface{}, fields ...string) []error {
var errors []error
var g = generic.Parse(input)
if len(fields) == 0 {
fields = g.FieldNames()
}

for _, field := range g.Props() {
for _, f := range fields {
if field.Name == f {
if field.Tag.Get("validation") != "" {
var stmt = db.Model(input).Statement
_ = stmt.Parse(input)

var err = validateField(&g, &field)
if err != nil {
errors = append(errors, err)
}
}
break
for idx, _ := range stmt.Schema.Fields {
field := stmt.Schema.Fields[idx]
if field.Tag.Get("validation") != "" {
var err = validateField(&g, field)
if err != nil {
errors = append(errors, err)
}
}

}

return errors
}

func validateField(g *generic.Value, field *reflect.StructField) error {
func validateField(g *generic.Value, field *schema.Field) error {
var value = g.Prop(field.Name)
validators := parseValidators(field.Tag.Get("validation"))
for _, validator := range validators {
Expand Down
59 changes: 55 additions & 4 deletions lib/validation/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ import (
)

var DBValidators = map[*regexp.Regexp]func(match []string, value *generic.Value, stmt *gorm.Statement, field *schema.Field) error{
regexp.MustCompile("^unique$"): uniqueValidator,
regexp.MustCompile("^fk$"): foreignKeyValidator,
regexp.MustCompile("^enum$"): enumValidator,
regexp.MustCompile("^unique$"): uniqueValidator,
regexp.MustCompile("^fk$"): foreignKeyValidator,
regexp.MustCompile("^enum$"): enumValidator,
regexp.MustCompile(`^before\((\w+)\)$`): beforeValidator,
regexp.MustCompile(`^after\((\w+)\)$`): afterValidator,
}

var Validators = map[*regexp.Regexp]func(match []string, value *generic.Value) error{
Expand Down Expand Up @@ -68,6 +70,55 @@ func enumValidator(match []string, value *generic.Value, stmt *gorm.Statement, f
return fmt.Errorf("invalid value, expected values are: %s", strings.TrimLeft(expected, ","))
}

func afterValidator(match []string, value *generic.Value, stmt *gorm.Statement, field *schema.Field) error {
var srcVal, err = value.Time()
if err != nil {
return fmt.Errorf("invalid date, date expected be in RFC3339 format")
}
var f, ok = stmt.Schema.FieldsByName[match[1]]
if !ok {
return fmt.Errorf("field %s not found", match[1])
}
dst, zero := f.ValueOf(context.Background(), reflect.ValueOf(stmt.Model))
v := reflect.ValueOf(dst)
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
if !zero {
if dstVal, ok := v.Interface().(time.Time); ok {
if !srcVal.After(dstVal) {
return fmt.Errorf("%s must be before %s", field.Name, match[1])
}
}
}
return nil
}

func beforeValidator(match []string, value *generic.Value, stmt *gorm.Statement, field *schema.Field) error {
var srcVal, err = value.Time()
if err != nil {
return fmt.Errorf("invalid date, date expected be in RFC3339 format")
}
var f, ok = stmt.Schema.FieldsByName[match[1]]
if !ok {
return fmt.Errorf("field %s not found", match[1])
}
dst, zero := f.ValueOf(context.Background(), reflect.ValueOf(stmt.Model))
v := reflect.ValueOf(dst)
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
if !zero {
if dstVal, ok := v.Interface().(time.Time); ok {
if !srcVal.Before(dstVal) {
return fmt.Errorf("%s must be before %s", field.Name, match[1])
}
}
}

return nil
}

func uniqueValidator(match []string, value *generic.Value, stmt *gorm.Statement, field *schema.Field) error {
if field.StructField.Type.Kind() == reflect.Ptr && value.String() == "<nil>" {
return nil
Expand Down Expand Up @@ -403,7 +454,7 @@ func regexValidator(match []string, value *generic.Value) error {
}

func dateValidator(match []string, value *generic.Value) error {
_, err := time.Parse(time.RFC3339, value.String())
_, err := value.Time()
if err != nil {
return fmt.Errorf("invalid date, date expected be in RFC3339 format")
}
Expand Down

0 comments on commit 8b33984

Please sign in to comment.