github.com/duskeagle/pop@v4.10.1-0.20190417200916-92f2b794aab5+incompatible/validations.go (about)

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