Skip to content

Commit

Permalink
Add UUID-Validator (#70)
Browse files Browse the repository at this point in the history
- new uuid validator
- add testcases
- print warning message if uuid and regex validator is set for a field
- ignore the regex and uuid validator if both are set for a field.
- adding the string_not_empty validator to the example, makes it clearer that uuid_ver otherwise allows empty string
  • Loading branch information
fho authored and Helcaraxan committed Aug 8, 2019
1 parent c00cd28 commit 710a5f4
Show file tree
Hide file tree
Showing 11 changed files with 548 additions and 161 deletions.
2 changes: 1 addition & 1 deletion examples/nested.proto
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ message OuterMessage {
string important_string = 1 [(validator.field) = {regex: "^[a-z]{2,5}$"}];
// proto3 doesn't have `required`, the `msg_exist` enforces presence of InnerMessage.
InnerMessage inner = 2 [(validator.field) = {msg_exists : true}];
}
}
81 changes: 81 additions & 0 deletions examples/uuid.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions examples/uuid.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
syntax = "proto3";
package validator.examples;
import "github.com/mwitkow/go-proto-validators/validator.proto";

message UUIDMsg {
// user_id must be a valid version 4 UUID.
string user_id = 1 [(validator.field) = {uuid_ver: 4, string_not_empty: true}];
}
30 changes: 30 additions & 0 deletions examples/uuid.validator.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 46 additions & 4 deletions plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,18 @@ import (

"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
"github.com/gogo/protobuf/vanity"
validator "github.com/mwitkow/go-proto-validators"
)

const uuidPattern = "^([a-fA-F0-9]{8}-" +
"[a-fA-F0-9]{4}-" +
"[%s][a-fA-F0-9]{3}-" +
"[8|9|aA|bB][a-fA-F0-9]{3}-" +
"[a-fA-F0-9]{12})?$"

type plugin struct {
*generator.Generator
generator.PluginImports
Expand Down Expand Up @@ -154,9 +160,21 @@ func (p *plugin) generateRegexVars(file *generator.FileDescriptor, message *gene
ccTypeName := generator.CamelCaseSlice(message.TypeName())
for _, field := range message.Field {
validator := getFieldValidatorIfAny(field)
if validator != nil && validator.Regex != nil {
if validator != nil {
fieldName := p.GetOneOfFieldName(message, field)
p.P(`var `, p.regexName(ccTypeName, fieldName), ` = `, p.regexPkg.Use(), `.MustCompile(`, "`", *validator.Regex, "`", `)`)
if validator.Regex != nil && validator.UuidVer != nil {
fmt.Fprintf(os.Stderr, "WARNING: regex and uuid validator is set for field %v.%v, only one of them can be set. Regex and UUID validator is ignored for this field.", ccTypeName, fieldName)
} else if validator.UuidVer != nil {
uuid, err := getUUIDRegex(validator.UuidVer)
if err != nil {
fmt.Fprintf(os.Stderr, "WARNING: field %v.%v error %s.\n", ccTypeName, fieldName, err)
} else {
validator.Regex = &uuid
p.P(`var `, p.regexName(ccTypeName, fieldName), ` = `, p.regexPkg.Use(), `.MustCompile(`, "`", *validator.Regex, "`", `)`)
}
} else if validator.Regex != nil {
p.P(`var `, p.regexName(ccTypeName, fieldName), ` = `, p.regexPkg.Use(), `.MustCompile(`, "`", *validator.Regex, "`", `)`)
}
}
}
}
Expand Down Expand Up @@ -500,8 +518,32 @@ func (p *plugin) generateFloatValidator(variableName string, ccTypeName string,
}
}

// getUUIDRegex returns a regex to validate that a string is in UUID
// format. The version parameter specified the UUID version. If version is 0,
// the returned regex is valid for any UUID version
func getUUIDRegex(version *int32) (string, error) {
if version == nil {
return "", nil
} else if *version < 0 || *version > 5 {
return "", fmt.Errorf("UUID version should be between 0-5, Got %d", *version)
} else if *version == 0 {
return fmt.Sprintf(uuidPattern, "1-5"), nil
} else {
return fmt.Sprintf(uuidPattern, strconv.Itoa(int(*version))), nil
}
}

func (p *plugin) generateStringValidator(variableName string, ccTypeName string, fieldName string, fv *validator.FieldValidator) {
if fv.Regex != nil {
if fv.Regex != nil || fv.UuidVer != nil {
if fv.UuidVer != nil {
uuid, err := getUUIDRegex(fv.UuidVer)
if err != nil {
fmt.Fprintf(os.Stderr, "WARNING: field %v.%v error %s.\n", ccTypeName, fieldName, err)
} else {
fv.Regex = &uuid
}
}

p.P(`if !`, p.regexName(ccTypeName, fieldName), `.MatchString(`, variableName, `) {`)
p.In()
errorStr := "be a string conforming to regex " + strconv.Quote(fv.GetRegex())
Expand Down
Loading

0 comments on commit 710a5f4

Please sign in to comment.