Skip to content

Commit

Permalink
fixes jakecoffman#9 implement pattern validation on strings (jakecoff…
Browse files Browse the repository at this point in the history
…man#11)

Co-authored-by: Matthew Wood <[email protected]>
  • Loading branch information
matthewtylerwood and matthewtylerwood authored Dec 3, 2021
1 parent 4210fb7 commit db56162
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 0 deletions.
18 changes: 18 additions & 0 deletions field.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package crud
import (
"fmt"
"reflect"
"regexp"
"strings"
"time"
)
Expand All @@ -14,6 +15,7 @@ type Field struct {
obj map[string]Field
max *float64
min *float64
pattern *regexp.Regexp
required *bool
example interface{}
description string
Expand Down Expand Up @@ -64,6 +66,7 @@ var (
errMinimum = fmt.Errorf("minimum exceeded")
errEnumNotFound = fmt.Errorf("value not in enum")
errUnknown = fmt.Errorf("unknown value")
errPattern = fmt.Errorf("value does not match pattern")
)

// Validate is used in the validation middleware to tell if the value passed
Expand Down Expand Up @@ -115,6 +118,9 @@ func (f *Field) Validate(value interface{}) error {
if f.min != nil && len(v) < int(*f.min) {
return errMinimum
}
if f.pattern != nil && !f.pattern.MatchString(v) {
return errPattern
}
switch f.format {
case FormatDateTime:
_, err := time.Parse(time.RFC3339, v)
Expand Down Expand Up @@ -328,6 +334,12 @@ func (f Field) Max(max float64) Field {
return f
}

// Pattern specifies a regex pattern value for this field
func (f Field) Pattern(pattern string) Field {
f.pattern = regexp.MustCompile(pattern)
return f
}

// Required specifies the field must be provided. Can't be used with Default.
func (f Field) Required() Field {
if f._default != nil {
Expand Down Expand Up @@ -460,6 +472,9 @@ func (f *Field) ToSwaggerParameters(in string) (parameters []Parameter) {
Minimum: field.min,
Maximum: field.max,
}
if field.pattern != nil {
param.Pattern = field.pattern.String()
}
if field.kind == KindArray {
if field.arr != nil {
temp := field.arr.ToJsonSchema()
Expand Down Expand Up @@ -518,6 +533,9 @@ func (f *Field) ToJsonSchema() JsonSchema {
if field.max != nil {
prop.Maximum = *field.max
}
if field.pattern != nil {
prop.Pattern = field.pattern.String()
}
if prop.Type == KindArray {
if field.arr != nil {
items := field.arr.ToJsonSchema()
Expand Down
20 changes: 20 additions & 0 deletions field_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ func TestField_Min_Panic(t *testing.T) {
String().Max(1).Min(2)
}

func TestField_Pattern_Panic(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Errorf("The code did not panic")
}
}()

String().Pattern("[")
}

func TestField_String(t *testing.T) {
table := []struct {
Field Field
Expand Down Expand Up @@ -93,6 +103,16 @@ func TestField_String(t *testing.T) {
Input: "hi",
Expected: nil,
},
{
Field: String().Pattern("[a-c]"),
Input: "abc",
Expected: nil,
},
{
Field: String().Pattern("[a-c]"),
Input: "def",
Expected: errPattern,
},
}

for i, test := range table {
Expand Down
2 changes: 2 additions & 0 deletions swagger.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type JsonSchema struct {
Maximum float64 `json:"maximum,omitempty"`
Enum []interface{} `json:"enum,omitempty"`
Default interface{} `json:"default,omitempty"`
Pattern string `json:"pattern,omitempty"`
}

type Path struct {
Expand Down Expand Up @@ -58,6 +59,7 @@ type Parameter struct {
Minimum *float64 `json:"minimum,omitempty"`
Maximum *float64 `json:"maximum,omitempty"`
Enum []interface{} `json:"enum,omitempty"`
Pattern string `json:"pattern,omitempty"`
Default interface{} `json:"default,omitempty"`
Items *JsonSchema `json:"items,omitempty"`
CollectionFormat string `json:"collectionFormat,omitempty"`
Expand Down

0 comments on commit db56162

Please sign in to comment.