Skip to content

Commit

Permalink
Rekeying and Disallow Fields (#175)
Browse files Browse the repository at this point in the history
  • Loading branch information
bbengfort authored Sep 4, 2024
1 parent 9c6fb9f commit f74c234
Show file tree
Hide file tree
Showing 9 changed files with 1,101 additions and 265 deletions.
25 changes: 5 additions & 20 deletions pkg/ivms101/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,9 @@ import (
)

func (i *IdentityPayload) Scan(src interface{}) error {
p := IdentityPayload{}
if err := ScanJSON(src, &p); err != nil {
if err := ScanJSON(src, i); err != nil {
return err
}

*i = p
return nil
}

Expand All @@ -21,12 +18,9 @@ func (i *IdentityPayload) Value() (_ driver.Value, err error) {
}

func (p *Person) Scan(src interface{}) error {
o := Person{}
if err := ScanJSON(src, &o); err != nil {
if err := ScanJSON(src, p); err != nil {
return err
}

*p = o
return nil
}

Expand All @@ -35,12 +29,9 @@ func (p *Person) Value() (_ driver.Value, err error) {
}

func (p *NaturalPerson) Scan(src interface{}) error {
o := NaturalPerson{}
if err := ScanJSON(src, &o); err != nil {
if err := ScanJSON(src, p); err != nil {
return err
}

*p = o
return nil
}

Expand All @@ -49,12 +40,9 @@ func (p *NaturalPerson) Value() (_ driver.Value, err error) {
}

func (p *LegalPerson) Scan(src interface{}) error {
o := LegalPerson{}
if err := ScanJSON(src, &o); err != nil {
if err := ScanJSON(src, p); err != nil {
return err
}

*p = o
return nil
}

Expand All @@ -63,12 +51,9 @@ func (p *LegalPerson) Value() (_ driver.Value, err error) {
}

func (a *Address) Scan(src interface{}) error {
o := Address{}
if err := ScanJSON(src, &o); err != nil {
if err := ScanJSON(src, a); err != nil {
return err
}

*a = o
return nil
}

Expand Down
139 changes: 128 additions & 11 deletions pkg/ivms101/errors.go
Original file line number Diff line number Diff line change
@@ -1,39 +1,156 @@
package ivms101

import "errors"
import (
"errors"
"fmt"
"strings"
)

// Standard error values for error type checking
var (
ErrNoNaturalPersonNameIdentifiers = errors.New("one or more natural person name identifiers is required")
ErrInvalidNaturalPersonName = errors.New("natural person name required with max length 100 chars")
ErrInvalidNaturalPersonNameTypeCode = errors.New("invalid natural person name type code")
ErrParseNaturalPersonNameTypeCode = errors.New("could not parse natural person name type code from value")
ErrNoLegalPersonNameIdentifiers = errors.New("one or more legal person name identifiers is required")
ErrInvalidLegalPersonName = errors.New("legal person name required with max length 100 chars")
ErrInvalidLegalPersonNameTypeCode = errors.New("invalid legal person name type code")
ErrParseLegalPersonNameTypeCode = errors.New("could not parse legal person name type code from value")
ErrLegalNamesPresent = errors.New("at least one name identifier must have a LEGL name identifier type")
ErrInvalidCustomerNumber = errors.New("customer number can be at most 50 chars")
ErrInvalidCustomerIdentification = errors.New("customer identification can be at most 50 chars")
ErrInvalidCountryCode = errors.New("invalid ISO-3166-1 alpha-2 country code")
ErrValidNationalIdentifierLegalPerson = errors.New("a legal person must have a national identifier of type RAID, MISC, LEIX, or TXID")
ErrInvalidLEI = errors.New("national identifier required with max length 35")
ErrInvalidNationalIdentifierTypeCode = errors.New("invalid national identifier type code")
ErrParseNationalIdentifierTypeCode = errors.New("could not parse national identifier type code from value")
ErrCompleteNationalIdentifierCountry = errors.New("a legal person must not have a value for country if identifier type is not LEIX")
ErrCompleteNationalIdentifierAuthorityEmpty = errors.New("a legal person must have a value for registration authority if identifier type is not LEIX")
ErrCompleteNationalIdentifierAuthority = errors.New("a legal person must not have a value for registration authority if identifier type is LEIX")
ErrInvalidDateOfBirth = errors.New("date of birth must be a valid date in YYYY-MM-DD format")
ErrInvalidPlaceOfBirth = errors.New("place of birth required with at most 70 characters")
ErrDateInPast = errors.New("date of birth must be a historic date, prior to current date")
ErrValidAddress = errors.New("address must have at least one address line or street name + building name or number")
ErrInvalidAddressTypeCode = errors.New("invalid address type code")
ErrParseAddressTypeCode = errors.New("could not parse address type code from value")
ErrInvalidAddressLines = errors.New("an address can contain at most 7 address lines")
ErrInvalidTransliterationMethodCode = errors.New("invalid transliteration method code")
ErrParseTransliterationMethodCode = errors.New("could not parse transliteration method code from value")
)

// Parsing and JSON Serialization Errors
var (
ErrPersonOneOfViolation = errors.New("ivms101: person must be either a legal person or a natural person not both")
ErrInvalidNaturalPersonNameTypeCode = errors.New("ivms101: invalid natural person name type code")
ErrParseNaturalPersonNameTypeCode = errors.New("ivms101: could not parse natural person name type code from value")
ErrInvalidLegalPersonNameTypeCode = errors.New("ivms101: invalid legal person name type code")
ErrParseLegalPersonNameTypeCode = errors.New("ivms101: could not parse legal person name type code from value")
ErrInvalidNationalIdentifierTypeCode = errors.New("ivms101: invalid national identifier type code")
ErrParseNationalIdentifierTypeCode = errors.New("ivms101: could not parse national identifier type code from value")
ErrInvalidAddressTypeCode = errors.New("ivms101: invalid address type code")
ErrParseAddressTypeCode = errors.New("ivms101: could not parse address type code from value")
ErrInvalidTransliterationMethodCode = errors.New("ivms101: invalid transliteration method code")
ErrParseTransliterationMethodCode = errors.New("ivms101: could not parse transliteration method code from value")
)

//===========================================================================
// Validation Errors
//===========================================================================

func MissingField(field string) *FieldError {
return &FieldError{verb: "missing", field: field, issue: "this field is required"}
}

func IncorrectField(field, issue string) *FieldError {
return &FieldError{verb: "invalid field", field: field, issue: issue}
}

func ReadOnlyField(field string) *FieldError {
return &FieldError{verb: "read-only field", field: field, issue: "this field cannot be written by the user"}
}

func OneOfMissing(fields ...string) *FieldError {
var fieldstr string
switch len(fields) {
case 0:
panic("no fields specified for one of")
case 1:
return MissingField(fields[0])
default:
fieldstr = fieldList(fields...)
}

return &FieldError{verb: "missing one of", field: fieldstr, issue: "at most one of these fields is required"}
}

func OneOfTooMany(fields ...string) *FieldError {
if len(fields) < 2 {
panic("must specify at least two fields for one of too many")
}
return &FieldError{verb: "specify only one of", field: fieldList(fields...), issue: "at most one of these fields may be specified"}
}

func ValidationError(err error, errs ...*FieldError) error {
var verr ValidationErrors
if err == nil {
verr = make(ValidationErrors, 0, len(errs))
} else {
var ok bool
if verr, ok = err.(ValidationErrors); !ok {
verr = make(ValidationErrors, 0, len(errs)+1)
verr = append(verr, &FieldError{verb: "invalid", field: "input", issue: err.Error()})
}
}

for _, e := range errs {
if e != nil {
verr = append(verr, e)
}
}

if len(verr) == 0 {
return nil
}
return verr
}

type ValidationErrors []*FieldError

func (e ValidationErrors) Error() string {
if len(e) == 1 {
return e[0].Error()
}

errs := make([]string, 0, len(e))
for _, err := range e {
errs = append(errs, err.Error())
}

return fmt.Sprintf("%d validation errors occurred:\n %s", len(e), strings.Join(errs, "\n "))
}

type FieldError struct {
verb string
field string
issue string
}

func (e *FieldError) Error() string {
return fmt.Sprintf("ivms101: %s %s: %s", e.verb, e.field, e.issue)
}

func (e *FieldError) Field() string {
return e.field
}

func fieldList(fields ...string) string {
switch len(fields) {
case 0:
return ""
case 1:
return fields[0]
case 2:
return fmt.Sprintf("%s or %s", fields[0], fields[1])
default:
last := len(fields) - 1
return fmt.Sprintf("%s, or %s", strings.Join(fields[0:last], ", "), fields[last])
}
}

//===========================================================================
// Wrapped Error
//===========================================================================

// Wraps one error with another error for better error type checking.
type WrappedError struct {
error error
Expand Down
Loading

0 comments on commit f74c234

Please sign in to comment.