add cpf validation

pull/851/head
marcelobiao 3 years ago
parent 9e2ea40380
commit e0e8fed530
  1. 1
      README.md
  2. 37
      baked_in.go
  3. 6
      doc.go
  4. 5
      translations/en/en.go
  5. 5
      translations/en/en_test.go
  6. 21
      util.go
  7. 49
      validator_test.go

@ -202,6 +202,7 @@ Baked-in Validations
| tiger192 | TIGER192 hash |
| semver | Semantic Versioning 2.0.0 |
| ulid | Universally Unique Lexicographically Sortable Identifier ULID |
| cpf | Registration of Individuals |
### Comparisons:
| Tag | Description |

@ -214,6 +214,7 @@ var (
"semver": isSemverFormat,
"dns_rfc1035_label": isDnsRFC1035LabelFormat,
"credit_card": isCreditCard,
"cpf": isCPFFormat,
}
)
@ -2519,3 +2520,39 @@ func isCreditCard(fl FieldLevel) bool {
}
return (sum % 10) == 0
}
// isCPFFormat is the validation function for validating if the current field's value is a valid CPF, defined by Federal Revenue of Brazil
func isCPFFormat(fl FieldLevel) bool {
cpfFirstDigitTable := []int{10, 9, 8, 7, 6, 5, 4, 3, 2}
cpfSecondDigitTable := []int{11, 10, 9, 8, 7, 6, 5, 4, 3, 2}
cpf := fl.Field().String()
if len(cpf) != 11 {
return false
}
firstPart := cpf[0:9]
sum := sumDigit(firstPart, cpfFirstDigitTable)
r1 := sum % 11
d1 := 0
if r1 >= 2 {
d1 = 11 - r1
}
secondPart := firstPart + strconv.Itoa(d1)
dsum := sumDigit(secondPart, cpfSecondDigitTable)
r2 := dsum % 11
d2 := 0
if r2 >= 2 {
d2 = 11 - r2
}
finalPart := fmt.Sprintf("%s%d%d", firstPart, d1, d2)
return finalPart == cpf
}

@ -1047,6 +1047,12 @@ This validates that a string value contains a valid ULID value.
Usage: ulid
Registration of Individuals (CPF)
This validates that a string value contains a valid CPF.
Usage: cpf
ASCII
This validates that a string value contains only ASCII characters.

@ -1146,6 +1146,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
translation: "{0} must be a valid ULID",
override: false,
},
{
tag: "cpf",
translation: "{0} must be a valid CPF",
override: false,
},
{
tag: "ascii",
translation: "{0} must contain only ascii characters",

@ -106,6 +106,7 @@ func TestTranslations(t *testing.T) {
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
CPF string `validate:"cpf"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
@ -334,6 +335,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.ULID",
expected: "ULID must be a valid ULID",
},
{
ns: "Test.CPF",
expected: "CPF must be a valid CPF",
},
{
ns: "Test.ISBN",
expected: "ISBN must be a valid ISBN number",

@ -286,3 +286,24 @@ func panicIf(err error) {
panic(err.Error())
}
}
// Receive a sequence of integers and an array of index. Returns the sum of index values
// Used for CPF/CNPJ validation
func sumDigit(s string, table []int) int {
if len(s) != len(table) {
return 0
}
sum := 0
for i, v := range table {
c := string(s[i])
d, err := strconv.Atoi(c)
if err == nil {
sum += v * d
}
}
return sum
}

@ -12286,3 +12286,52 @@ func TestMultiOrOperatorGroup(t *testing.T) {
}
}
}
func TestCPFField(t *testing.T) {
tests := []struct {
Value string `validate:"cpf"`
expected bool
}{
{"33888222044", true}, //249//293
{"16814496097", true}, //233 290
{"37919050073", true},
{"338.882.220-44", false},
{"02588789854INVALID", false},
{"33888222042", false},
}
validate := New()
for i, test := range tests {
errs := validate.Struct(test)
if test.expected {
if !IsEqual(errs, nil) {
t.Fatalf("Index: %d cpf failed Error: %s", i, errs)
}
} else {
if IsEqual(errs, nil) {
t.Fatalf("Index: %d cpf failed Error: %s", i, errs)
}
}
}
}
func TestSumDigit(t *testing.T) {
tests := []struct {
sequence string `validate:"cpf"`
indexs []int
expected int
}{
{"338882220", []int{10, 9, 8, 7, 6, 5, 4, 3, 2}, 249},
{"3388822204", []int{11, 10, 9, 8, 7, 6, 5, 4, 3, 2}, 293},
{"168144960", []int{10, 9, 8, 7, 6, 5, 4, 3, 2}, 233},
{"1681449609", []int{11, 10, 9, 8, 7, 6, 5, 4, 3, 2}, 290},
}
for i, test := range tests {
result := sumDigit(test.sequence, test.indexs)
if !IsEqual(result, test.expected) {
t.Fatalf("Index: %d cpf failed. Expected: %d, received: %d", i, test.expected, result)
}
}
}

Loading…
Cancel
Save