github.com/Accefy/pop@v0.0.0-20230428174248-e9f677eab5b9/validations.go (about) 1 package pop 2 3 import ( 4 "reflect" 5 6 "github.com/gobuffalo/validate/v3" 7 ) 8 9 type beforeValidatable interface { 10 BeforeValidations(*Connection) error 11 } 12 13 type validateable interface { 14 Validate(*Connection) (*validate.Errors, error) 15 } 16 17 type modelIterableValidator func(*Model) (*validate.Errors, error) 18 19 func (m *Model) validate(c *Connection) (*validate.Errors, error) { 20 if x, ok := m.Value.(beforeValidatable); ok { 21 if err := x.BeforeValidations(c); err != nil { 22 return validate.NewErrors(), err 23 } 24 } 25 if x, ok := m.Value.(validateable); ok { 26 return x.Validate(c) 27 } 28 return validate.NewErrors(), nil 29 } 30 31 type validateCreateable interface { 32 ValidateCreate(*Connection) (*validate.Errors, error) 33 } 34 35 func (m *Model) validateCreate(c *Connection) (*validate.Errors, error) { 36 return m.iterateAndValidate(func(model *Model) (*validate.Errors, error) { 37 verrs, err := model.validate(c) 38 if err != nil { 39 return verrs, err 40 } 41 if x, ok := model.Value.(validateCreateable); ok { 42 vs, err := x.ValidateCreate(c) 43 if vs != nil { 44 verrs.Append(vs) 45 } 46 if err != nil { 47 return verrs, err 48 } 49 } 50 51 return verrs, err 52 }) 53 } 54 55 func (m *Model) validateAndOnlyCreate(c *Connection) (*validate.Errors, error) { 56 return m.iterateAndValidate(func(model *Model) (*validate.Errors, error) { 57 id, err := model.fieldByName("ID") 58 if err != nil { 59 return nil, err 60 } 61 if !IsZeroOfUnderlyingType(id.Interface()) { 62 return validate.NewErrors(), nil 63 } 64 65 verrs, err := model.validate(c) 66 if err != nil { 67 return verrs, err 68 } 69 if x, ok := model.Value.(validateCreateable); ok { 70 vs, err := x.ValidateCreate(c) 71 if vs != nil { 72 verrs.Append(vs) 73 } 74 if err != nil { 75 return verrs, err 76 } 77 } 78 79 return verrs, err 80 }) 81 } 82 83 type validateSaveable interface { 84 ValidateSave(*Connection) (*validate.Errors, error) 85 } 86 87 func (m *Model) validateSave(c *Connection) (*validate.Errors, error) { 88 return m.iterateAndValidate(func(model *Model) (*validate.Errors, error) { 89 verrs, err := model.validate(c) 90 if err != nil { 91 return verrs, err 92 } 93 if x, ok := model.Value.(validateSaveable); ok { 94 vs, err := x.ValidateSave(c) 95 if vs != nil { 96 verrs.Append(vs) 97 } 98 if err != nil { 99 return verrs, err 100 } 101 } 102 103 return verrs, err 104 }) 105 } 106 107 type validateUpdateable interface { 108 ValidateUpdate(*Connection) (*validate.Errors, error) 109 } 110 111 func (m *Model) validateUpdate(c *Connection) (*validate.Errors, error) { 112 return m.iterateAndValidate(func(model *Model) (*validate.Errors, error) { 113 verrs, err := model.validate(c) 114 if err != nil { 115 return verrs, err 116 } 117 if x, ok := model.Value.(validateUpdateable); ok { 118 vs, err := x.ValidateUpdate(c) 119 if vs != nil { 120 verrs.Append(vs) 121 } 122 if err != nil { 123 return verrs, err 124 } 125 } 126 127 return verrs, err 128 }) 129 } 130 131 func (m *Model) iterateAndValidate(fn modelIterableValidator) (*validate.Errors, error) { 132 v := reflect.Indirect(reflect.ValueOf(m.Value)) 133 if v.Kind() == reflect.Slice || v.Kind() == reflect.Array { 134 for i := 0; i < v.Len(); i++ { 135 val := v.Index(i) 136 newModel := NewModel(val.Addr().Interface(), m.ctx) 137 verrs, err := fn(newModel) 138 139 if err != nil || verrs.HasAny() { 140 return verrs, err 141 } 142 } 143 return validate.NewErrors(), nil 144 } 145 146 return fn(m) 147 }