mirror of
https://github.com/astaxie/beego.git
synced 2024-11-26 05:11:31 +00:00
add validation funcs
This commit is contained in:
parent
a41cd17092
commit
6d05163c9f
177
validation/validation.go
Normal file
177
validation/validation.go
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
package validation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ValidationError struct {
|
||||||
|
Message, Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the Message.
|
||||||
|
func (e *ValidationError) String() string {
|
||||||
|
if e == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return e.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Validation context manages data validation and error messages.
|
||||||
|
type Validation struct {
|
||||||
|
Errors []*ValidationError
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Clear() {
|
||||||
|
v.Errors = []*ValidationError{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) HasErrors() bool {
|
||||||
|
return len(v.Errors) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the errors mapped by key.
|
||||||
|
// If there are multiple validation errors associated with a single key, the
|
||||||
|
// first one "wins". (Typically the first validation will be the more basic).
|
||||||
|
func (v *Validation) ErrorMap() map[string]*ValidationError {
|
||||||
|
m := map[string]*ValidationError{}
|
||||||
|
for _, e := range v.Errors {
|
||||||
|
if _, ok := m[e.Key]; !ok {
|
||||||
|
m[e.Key] = e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an error to the validation context.
|
||||||
|
func (v *Validation) Error(message string, args ...interface{}) *ValidationResult {
|
||||||
|
result := (&ValidationResult{
|
||||||
|
Ok: false,
|
||||||
|
Error: &ValidationError{},
|
||||||
|
}).Message(message, args...)
|
||||||
|
v.Errors = append(v.Errors, result.Error)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ValidationResult is returned from every validation method.
|
||||||
|
// It provides an indication of success, and a pointer to the Error (if any).
|
||||||
|
type ValidationResult struct {
|
||||||
|
Error *ValidationError
|
||||||
|
Ok bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ValidationResult) Key(key string) *ValidationResult {
|
||||||
|
if r.Error != nil {
|
||||||
|
r.Error.Key = key
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ValidationResult) Message(message string, args ...interface{}) *ValidationResult {
|
||||||
|
if r.Error != nil {
|
||||||
|
if len(args) == 0 {
|
||||||
|
r.Error.Message = message
|
||||||
|
} else {
|
||||||
|
r.Error.Message = fmt.Sprintf(message, args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that the argument is non-nil and non-empty (if string or list)
|
||||||
|
func (v *Validation) Required(obj interface{}, key string) *ValidationResult {
|
||||||
|
return v.apply(Required{key}, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Min(n int, min int, key string) *ValidationResult {
|
||||||
|
return v.apply(Min{min, key}, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Max(n int, max int, key string) *ValidationResult {
|
||||||
|
return v.apply(Max{max, key}, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Range(n, min, max int, key string) *ValidationResult {
|
||||||
|
return v.apply(Range{Min{Min: min}, Max{Max: max}, key}, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) MinSize(obj interface{}, min int, key string) *ValidationResult {
|
||||||
|
return v.apply(MinSize{min, key}, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) MaxSize(obj interface{}, max int, key string) *ValidationResult {
|
||||||
|
return v.apply(MaxSize{max, key}, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Length(obj interface{}, n int, key string) *ValidationResult {
|
||||||
|
return v.apply(Length{n, key}, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Alpha(obj interface{}, n int, key string) *ValidationResult {
|
||||||
|
return v.apply(Alpha{key}, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Numeric(obj interface{}, n int, key string) *ValidationResult {
|
||||||
|
return v.apply(Numeric{key}, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) AlphaNumeric(obj interface{}, n int, key string) *ValidationResult {
|
||||||
|
return v.apply(AlphaNumeric{key}, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Match(str string, regex *regexp.Regexp, key string) *ValidationResult {
|
||||||
|
return v.apply(Match{regex, key}, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) NoMatch(str string, regex *regexp.Regexp, key string) *ValidationResult {
|
||||||
|
return v.apply(NoMatch{Match{Regexp: regex}, key}, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) AlphaDash(str string, key string) *ValidationResult {
|
||||||
|
return v.apply(AlphaDash{NoMatch{Match: Match{Regexp: alphaDashPattern}}, key}, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Email(str string, key string) *ValidationResult {
|
||||||
|
return v.apply(Email{Match{Regexp: emailPattern}, key}, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) IP(str string, key string) *ValidationResult {
|
||||||
|
return v.apply(IP{Match{Regexp: ipPattern}, key}, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) Base64(str string, key string) *ValidationResult {
|
||||||
|
return v.apply(Base64{Match{Regexp: base64Pattern}, key}, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validation) apply(chk Validator, obj interface{}) *ValidationResult {
|
||||||
|
if chk.IsSatisfied(obj) {
|
||||||
|
return &ValidationResult{Ok: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the error to the validation context.
|
||||||
|
err := &ValidationError{
|
||||||
|
Message: chk.DefaultMessage(),
|
||||||
|
Key: chk.GetKey(),
|
||||||
|
}
|
||||||
|
v.Errors = append(v.Errors, err)
|
||||||
|
|
||||||
|
// Also return it in the result.
|
||||||
|
return &ValidationResult{
|
||||||
|
Ok: false,
|
||||||
|
Error: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply a group of validators to a field, in order, and return the
|
||||||
|
// ValidationResult from the first one that fails, or the last one that
|
||||||
|
// succeeds.
|
||||||
|
func (v *Validation) Check(obj interface{}, checks ...Validator) *ValidationResult {
|
||||||
|
var result *ValidationResult
|
||||||
|
for _, check := range checks {
|
||||||
|
result = v.apply(check, obj)
|
||||||
|
if !result.Ok {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package revel
|
package validation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -10,9 +10,12 @@ import (
|
|||||||
type Validator interface {
|
type Validator interface {
|
||||||
IsSatisfied(interface{}) bool
|
IsSatisfied(interface{}) bool
|
||||||
DefaultMessage() string
|
DefaultMessage() string
|
||||||
|
GetKey() string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Required struct{}
|
type Required struct {
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
func (r Required) IsSatisfied(obj interface{}) bool {
|
func (r Required) IsSatisfied(obj interface{}) bool {
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
@ -42,11 +45,13 @@ func (r Required) DefaultMessage() string {
|
|||||||
return "Required"
|
return "Required"
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
func (r Required) GetKey() string {
|
||||||
// type Unique struct {}
|
return r.Key
|
||||||
|
}
|
||||||
|
|
||||||
type Min struct {
|
type Min struct {
|
||||||
Min int
|
Min int
|
||||||
|
Key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Min) IsSatisfied(obj interface{}) bool {
|
func (m Min) IsSatisfied(obj interface{}) bool {
|
||||||
@ -61,8 +66,13 @@ func (m Min) DefaultMessage() string {
|
|||||||
return fmt.Sprintln("Minimum is", m.Min)
|
return fmt.Sprintln("Minimum is", m.Min)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m Min) GetKey() string {
|
||||||
|
return m.Key
|
||||||
|
}
|
||||||
|
|
||||||
type Max struct {
|
type Max struct {
|
||||||
Max int
|
Max int
|
||||||
|
Key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Max) IsSatisfied(obj interface{}) bool {
|
func (m Max) IsSatisfied(obj interface{}) bool {
|
||||||
@ -77,10 +87,15 @@ func (m Max) DefaultMessage() string {
|
|||||||
return fmt.Sprintln("Maximum is", m.Max)
|
return fmt.Sprintln("Maximum is", m.Max)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m Max) GetKey() string {
|
||||||
|
return m.Key
|
||||||
|
}
|
||||||
|
|
||||||
// Requires an integer to be within Min, Max inclusive.
|
// Requires an integer to be within Min, Max inclusive.
|
||||||
type Range struct {
|
type Range struct {
|
||||||
Min
|
Min
|
||||||
Max
|
Max
|
||||||
|
Key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Range) IsSatisfied(obj interface{}) bool {
|
func (r Range) IsSatisfied(obj interface{}) bool {
|
||||||
@ -91,9 +106,14 @@ func (r Range) DefaultMessage() string {
|
|||||||
return fmt.Sprintln("Range is", r.Min.Min, "to", r.Max.Max)
|
return fmt.Sprintln("Range is", r.Min.Min, "to", r.Max.Max)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r Range) GetKey() string {
|
||||||
|
return r.Key
|
||||||
|
}
|
||||||
|
|
||||||
// Requires an array or string to be at least a given length.
|
// Requires an array or string to be at least a given length.
|
||||||
type MinSize struct {
|
type MinSize struct {
|
||||||
Min int
|
Min int
|
||||||
|
Key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m MinSize) IsSatisfied(obj interface{}) bool {
|
func (m MinSize) IsSatisfied(obj interface{}) bool {
|
||||||
@ -111,9 +131,14 @@ func (m MinSize) DefaultMessage() string {
|
|||||||
return fmt.Sprintln("Minimum size is", m.Min)
|
return fmt.Sprintln("Minimum size is", m.Min)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m MinSize) GetKey() string {
|
||||||
|
return m.Key
|
||||||
|
}
|
||||||
|
|
||||||
// Requires an array or string to be at most a given length.
|
// Requires an array or string to be at most a given length.
|
||||||
type MaxSize struct {
|
type MaxSize struct {
|
||||||
Max int
|
Max int
|
||||||
|
Key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m MaxSize) IsSatisfied(obj interface{}) bool {
|
func (m MaxSize) IsSatisfied(obj interface{}) bool {
|
||||||
@ -131,27 +156,38 @@ func (m MaxSize) DefaultMessage() string {
|
|||||||
return fmt.Sprintln("Maximum size is", m.Max)
|
return fmt.Sprintln("Maximum size is", m.Max)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m MaxSize) GetKey() string {
|
||||||
|
return m.Key
|
||||||
|
}
|
||||||
|
|
||||||
// Requires an array or string to be exactly a given length.
|
// Requires an array or string to be exactly a given length.
|
||||||
type Length struct {
|
type Length struct {
|
||||||
N int
|
N int
|
||||||
|
Key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Length) IsSatisfied(obj interface{}) bool {
|
func (l Length) IsSatisfied(obj interface{}) bool {
|
||||||
if str, ok := obj.(string); ok {
|
if str, ok := obj.(string); ok {
|
||||||
return len(str) == s.N
|
return len(str) == l.N
|
||||||
}
|
}
|
||||||
v := reflect.ValueOf(obj)
|
v := reflect.ValueOf(obj)
|
||||||
if v.Kind() == reflect.Slice {
|
if v.Kind() == reflect.Slice {
|
||||||
return v.Len() == s.N
|
return v.Len() == l.N
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Length) DefaultMessage() string {
|
func (l Length) DefaultMessage() string {
|
||||||
return fmt.Sprintln("Required length is", s.N)
|
return fmt.Sprintln("Required length is", l.N)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Alpha struct{}
|
func (l Length) GetKey() string {
|
||||||
|
return l.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
type Alpha struct {
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
func (a Alpha) IsSatisfied(obj interface{}) bool {
|
func (a Alpha) IsSatisfied(obj interface{}) bool {
|
||||||
if str, ok := obj.(string); ok {
|
if str, ok := obj.(string); ok {
|
||||||
@ -168,7 +204,13 @@ func (a Alpha) DefaultMessage() string {
|
|||||||
return fmt.Sprintln("Must be valid alpha characters")
|
return fmt.Sprintln("Must be valid alpha characters")
|
||||||
}
|
}
|
||||||
|
|
||||||
type Numeric struct{}
|
func (a Alpha) GetKey() string {
|
||||||
|
return a.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
type Numeric struct {
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
func (n Numeric) IsSatisfied(obj interface{}) bool {
|
func (n Numeric) IsSatisfied(obj interface{}) bool {
|
||||||
if str, ok := obj.(string); ok {
|
if str, ok := obj.(string); ok {
|
||||||
@ -185,7 +227,13 @@ func (n Numeric) DefaultMessage() string {
|
|||||||
return fmt.Sprintln("Must be valid numeric characters")
|
return fmt.Sprintln("Must be valid numeric characters")
|
||||||
}
|
}
|
||||||
|
|
||||||
type AlphaNumeric struct{}
|
func (n Numeric) GetKey() string {
|
||||||
|
return n.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
type AlphaNumeric struct {
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
func (a AlphaNumeric) IsSatisfied(obj interface{}) bool {
|
func (a AlphaNumeric) IsSatisfied(obj interface{}) bool {
|
||||||
if str, ok := obj.(string); ok {
|
if str, ok := obj.(string); ok {
|
||||||
@ -202,9 +250,14 @@ func (a AlphaNumeric) DefaultMessage() string {
|
|||||||
return fmt.Sprintln("Must be valid alpha or numeric characters")
|
return fmt.Sprintln("Must be valid alpha or numeric characters")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a AlphaNumeric) GetKey() string {
|
||||||
|
return a.Key
|
||||||
|
}
|
||||||
|
|
||||||
// Requires a string to match a given regex.
|
// Requires a string to match a given regex.
|
||||||
type Match struct {
|
type Match struct {
|
||||||
Regexp *regexp.Regexp
|
Regexp *regexp.Regexp
|
||||||
|
Key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Match) IsSatisfied(obj interface{}) bool {
|
func (m Match) IsSatisfied(obj interface{}) bool {
|
||||||
@ -216,55 +269,84 @@ func (m Match) DefaultMessage() string {
|
|||||||
return fmt.Sprintln("Must match", m.Regexp)
|
return fmt.Sprintln("Must match", m.Regexp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m Match) GetKey() string {
|
||||||
|
return m.Key
|
||||||
|
}
|
||||||
|
|
||||||
// Requires a string to not match a given regex.
|
// Requires a string to not match a given regex.
|
||||||
type NoMatch struct {
|
type NoMatch struct {
|
||||||
Match
|
Match
|
||||||
|
Key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m NoMatch) IsSatisfied(obj interface{}) bool {
|
func (n NoMatch) IsSatisfied(obj interface{}) bool {
|
||||||
return !m.Match.IsSatisfied(obj)
|
return !n.Match.IsSatisfied(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m NoMatch) DefaultMessage() string {
|
func (n NoMatch) DefaultMessage() string {
|
||||||
return fmt.Sprintln("Must no match", m.Regexp)
|
return fmt.Sprintln("Must no match", n.Regexp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n NoMatch) GetKey() string {
|
||||||
|
return n.Key
|
||||||
}
|
}
|
||||||
|
|
||||||
var alphaDashPattern = regexp.MustCompile("[^\\d\\w-_]")
|
var alphaDashPattern = regexp.MustCompile("[^\\d\\w-_]")
|
||||||
|
|
||||||
type AlphaDash struct {
|
type AlphaDash struct {
|
||||||
NoMatch
|
NoMatch
|
||||||
|
Key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AlphaDash) DefaultMessage() string {
|
func (a AlphaDash) DefaultMessage() string {
|
||||||
return fmt.Sprintln("Must be valid characters")
|
return fmt.Sprintln("Must be valid characters")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a AlphaDash) GetKey() string {
|
||||||
|
return a.Key
|
||||||
|
}
|
||||||
|
|
||||||
var emailPattern = regexp.MustCompile("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[a-zA-Z0-9](?:[\\w-]*[\\w])?")
|
var emailPattern = regexp.MustCompile("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[a-zA-Z0-9](?:[\\w-]*[\\w])?")
|
||||||
|
|
||||||
type Email struct {
|
type Email struct {
|
||||||
Match
|
Match
|
||||||
|
Key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e Email) DefaultMessage() string {
|
func (e Email) DefaultMessage() string {
|
||||||
return fmt.Sprintln("Must be a valid email address")
|
return fmt.Sprintln("Must be a valid email address")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e Email) GetKey() string {
|
||||||
|
return e.Key
|
||||||
|
}
|
||||||
|
|
||||||
var ipPattern = regexp.MustCompile("((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)")
|
var ipPattern = regexp.MustCompile("((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)")
|
||||||
|
|
||||||
type IP struct {
|
type IP struct {
|
||||||
Match
|
Match
|
||||||
|
Key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i IP) DefaultMessage() string {
|
func (i IP) DefaultMessage() string {
|
||||||
return fmt.Sprintln("Must be a valid ip address")
|
return fmt.Sprintln("Must be a valid ip address")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i IP) GetKey() string {
|
||||||
|
return i.Key
|
||||||
|
}
|
||||||
|
|
||||||
var base64Pattern = regexp.MustCompile("^(?:[A-Za-z0-99+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")
|
var base64Pattern = regexp.MustCompile("^(?:[A-Za-z0-99+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$")
|
||||||
|
|
||||||
type Base64 struct {
|
type Base64 struct {
|
||||||
Match
|
Match
|
||||||
|
Key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Base64) DefaultMessage() string {
|
func (b Base64) DefaultMessage() string {
|
||||||
return fmt.Sprintln("Must be valid base64 characters")
|
return fmt.Sprintln("Must be valid base64 characters")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b Base64) GetKey() string {
|
||||||
|
return b.Key
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user