diff --git a/Changes b/Changes index d39deb0cb..15800b01b 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,21 @@ Changes v2 has many incompatibilities with v1. To see the full list of differences between v1 and v2, please read the Changes-v2.md file (https://github.com/lestrrat-go/jwx/blob/develop/v2/Changes-v2.md) +v2.0.0 - 24 Apr 2022 + * This i the first v2 release, which represents a set of design changes + that were learnt over the previous 2 years. As a result the v2 API + should be much more consistent and uniform across packages, and + should be much more flexible to accomodate real-world needs. + + For a complete list of changes, please see the Changes-v2.md file, + or check the diff at https://github.com/lestrrat-go/jwx/compare/v1...v2 + +[Miscellaneous] + * Minor house cleaning on code generation tools + +[jwt] + * `jwt.ErrMissingRequiredClaim()` has been added + v2.0.0-beta2 - 16 Apr 2022 [jwk] * Updated `jwk.Set` API and reflected pending changes from v1 which were diff --git a/README.md b/README.md index 07cf0f5f7..537ae313b 100644 --- a/README.md +++ b/README.md @@ -188,7 +188,7 @@ That is, if you need to not only parse JWTs, but also to control JWKs, or if you need to handle payloads that are NOT JWTs, you should probably consider using this module. You should also note that JWT is built _on top_ of those other technologies. You simply cannot have a complete JWT package without -implementing the entirety of JWS/JWS/JWK, which this library does. +implementing the entirety of JWS/JWE/JWK, which this library does. Next, from an implementation perspective, this module differs significantly from others in that it tries very hard to expose only the APIs, and not the diff --git a/bench/performance/go.sum b/bench/performance/go.sum index 14f9533d4..c627099fd 100644 --- a/bench/performance/go.sum +++ b/bench/performance/go.sum @@ -3,8 +3,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/goccy/go-json v0.9.6 h1:5/4CtRQdtsX0sal8fdVhTaiMN01Ri8BExZZ8iRmHQ6E= -github.com/goccy/go-json v0.9.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80= github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= diff --git a/cmd/jwx/go.mod b/cmd/jwx/go.mod index d47545185..18eac6932 100644 --- a/cmd/jwx/go.mod +++ b/cmd/jwx/go.mod @@ -11,7 +11,7 @@ require ( require ( github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect - github.com/goccy/go-json v0.9.6 // indirect + github.com/goccy/go-json v0.9.7 // indirect github.com/lestrrat-go/blackmagic v1.0.1 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/httprc v1.0.1 // indirect diff --git a/cmd/jwx/go.sum b/cmd/jwx/go.sum index 49849fd7c..7d8654fcf 100644 --- a/cmd/jwx/go.sum +++ b/cmd/jwx/go.sum @@ -7,8 +7,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/goccy/go-json v0.9.6 h1:5/4CtRQdtsX0sal8fdVhTaiMN01Ri8BExZZ8iRmHQ6E= -github.com/goccy/go-json v0.9.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80= github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= diff --git a/examples/go.sum b/examples/go.sum index e0c4f5f4e..ebbd452ca 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -6,8 +6,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/goccy/go-json v0.9.6 h1:5/4CtRQdtsX0sal8fdVhTaiMN01Ri8BExZZ8iRmHQ6E= -github.com/goccy/go-json v0.9.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80= github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= diff --git a/go.mod b/go.mod index cc0a3b7e4..13e060745 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 - github.com/goccy/go-json v0.9.6 + github.com/goccy/go-json v0.9.7 github.com/lestrrat-go/blackmagic v1.0.1 github.com/lestrrat-go/httprc v1.0.1 github.com/lestrrat-go/iter v1.0.2 @@ -12,10 +12,3 @@ require ( github.com/stretchr/testify v1.7.1 golang.org/x/crypto v0.0.0-20220214200702-86341886e292 ) - -require ( - github.com/davecgh/go-spew v1.1.0 // indirect - github.com/lestrrat-go/httpcc v1.0.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect -) diff --git a/go.sum b/go.sum index 14f9533d4..c627099fd 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/goccy/go-json v0.9.6 h1:5/4CtRQdtsX0sal8fdVhTaiMN01Ri8BExZZ8iRmHQ6E= -github.com/goccy/go-json v0.9.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80= github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= diff --git a/jwk/ecdsa_gen.go b/jwk/ecdsa_gen.go index 3b83e0914..92f56f5a6 100644 --- a/jwk/ecdsa_gen.go +++ b/jwk/ecdsa_gen.go @@ -400,6 +400,8 @@ func (k *ecdsaPublicKey) SetDecodeCtx(dc json.DecodeCtx) { } func (h *ecdsaPublicKey) UnmarshalJSON(buf []byte) error { + h.mu.Lock() + defer h.mu.Unlock() h.algorithm = nil h.crv = nil h.keyID = nil @@ -982,6 +984,8 @@ func (k *ecdsaPrivateKey) SetDecodeCtx(dc json.DecodeCtx) { } func (h *ecdsaPrivateKey) UnmarshalJSON(buf []byte) error { + h.mu.Lock() + defer h.mu.Unlock() h.algorithm = nil h.crv = nil h.d = nil diff --git a/jwk/okp_gen.go b/jwk/okp_gen.go index 8be029702..ccad6775b 100644 --- a/jwk/okp_gen.go +++ b/jwk/okp_gen.go @@ -376,6 +376,8 @@ func (k *okpPublicKey) SetDecodeCtx(dc json.DecodeCtx) { } func (h *okpPublicKey) UnmarshalJSON(buf []byte) error { + h.mu.Lock() + defer h.mu.Unlock() h.algorithm = nil h.crv = nil h.keyID = nil @@ -928,6 +930,8 @@ func (k *okpPrivateKey) SetDecodeCtx(dc json.DecodeCtx) { } func (h *okpPrivateKey) UnmarshalJSON(buf []byte) error { + h.mu.Lock() + defer h.mu.Unlock() h.algorithm = nil h.crv = nil h.d = nil diff --git a/jwk/rsa_gen.go b/jwk/rsa_gen.go index 60837290f..ce4e400ff 100644 --- a/jwk/rsa_gen.go +++ b/jwk/rsa_gen.go @@ -379,6 +379,8 @@ func (k *rsaPublicKey) SetDecodeCtx(dc json.DecodeCtx) { } func (h *rsaPublicKey) UnmarshalJSON(buf []byte) error { + h.mu.Lock() + defer h.mu.Unlock() h.algorithm = nil h.e = nil h.keyID = nil @@ -1036,6 +1038,8 @@ func (k *rsaPrivateKey) SetDecodeCtx(dc json.DecodeCtx) { } func (h *rsaPrivateKey) UnmarshalJSON(buf []byte) error { + h.mu.Lock() + defer h.mu.Unlock() h.algorithm = nil h.d = nil h.dp = nil diff --git a/jwk/symmetric_gen.go b/jwk/symmetric_gen.go index 7be6d5f29..6a965193c 100644 --- a/jwk/symmetric_gen.go +++ b/jwk/symmetric_gen.go @@ -349,6 +349,8 @@ func (k *symmetricKey) SetDecodeCtx(dc json.DecodeCtx) { } func (h *symmetricKey) UnmarshalJSON(buf []byte) error { + h.mu.Lock() + defer h.mu.Unlock() h.algorithm = nil h.keyID = nil h.keyOps = nil diff --git a/jws/headers_gen.go b/jws/headers_gen.go index c3436b35d..fd892e2c4 100644 --- a/jws/headers_gen.go +++ b/jws/headers_gen.go @@ -175,6 +175,22 @@ func (h *stdHeaders) X509URL() string { return *(h.x509URL) } +func (h *stdHeaders) clear() { + h.algorithm = nil + h.contentType = nil + h.critical = nil + h.jwk = nil + h.jwkSetURL = nil + h.keyID = nil + h.typ = nil + h.x509CertChain = nil + h.x509CertThumbprint = nil + h.x509CertThumbprintS256 = nil + h.x509URL = nil + h.privateParams = nil + h.raw = nil +} + func (h *stdHeaders) DecodeCtx() DecodeCtx { h.mu.RLock() defer h.mu.RUnlock() @@ -425,17 +441,9 @@ func (h *stdHeaders) Remove(key string) error { } func (h *stdHeaders) UnmarshalJSON(buf []byte) error { - h.algorithm = nil - h.contentType = nil - h.critical = nil - h.jwk = nil - h.jwkSetURL = nil - h.keyID = nil - h.typ = nil - h.x509CertChain = nil - h.x509CertThumbprint = nil - h.x509CertThumbprintS256 = nil - h.x509URL = nil + h.mu.Lock() + defer h.mu.Unlock() + h.clear() dec := json.NewDecoder(bytes.NewReader(buf)) LOOP: for { diff --git a/jwt/jwt_test.go b/jwt/jwt_test.go index c02d8f9c3..eff8cdd3f 100644 --- a/jwt/jwt_test.go +++ b/jwt/jwt_test.go @@ -1291,6 +1291,13 @@ func TestGH430(t *testing.T) { } } +func TestGH706(t *testing.T) { + tok := jwt.New() + if !assert.ErrorIs(t, jwt.ErrMissingRequiredClaim(""), jwt.Validate(tok, jwt.WithRequiredClaim("foo")), `jwt.Validate should fail`) { + return + } +} + func TestBenHigginsByPassRegression(t *testing.T) { key, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { diff --git a/jwt/openid/token_gen.go b/jwt/openid/token_gen.go index 607314a1c..81c40055b 100644 --- a/jwt/openid/token_gen.go +++ b/jwt/openid/token_gen.go @@ -1161,8 +1161,6 @@ LOOP: } func (t stdToken) MarshalJSON() ([]byte, error) { - t.mu.RLock() - defer t.mu.RUnlock() buf := pool.GetBytesBuffer() defer pool.ReleaseBytesBuffer(buf) buf.WriteByte('{') diff --git a/jwt/token_gen.go b/jwt/token_gen.go index 03c7caa54..4a09a3b64 100644 --- a/jwt/token_gen.go +++ b/jwt/token_gen.go @@ -462,8 +462,6 @@ LOOP: } func (t stdToken) MarshalJSON() ([]byte, error) { - t.mu.RLock() - defer t.mu.RUnlock() buf := pool.GetBytesBuffer() defer pool.ReleaseBytesBuffer(buf) buf.WriteByte('{') diff --git a/jwt/validate.go b/jwt/validate.go index d8148d5e8..f4a4aa672 100644 --- a/jwt/validate.go +++ b/jwt/validate.go @@ -159,6 +159,22 @@ func (err *validationError) Unwrap() error { return err.error } +type missingRequiredClaimError struct { + claim string +} + +func (err *missingRequiredClaimError) Error() string { + return fmt.Sprintf("%q not satisfied: required claim not found", err.claim) +} + +func (err *missingRequiredClaimError) Is(target error) bool { + _, ok := target.(*missingRequiredClaimError) + return ok +} + +func (err *missingRequiredClaimError) isValidationError() {} +func (*missingRequiredClaimError) Unwrap() error { return nil } + var errTokenExpired = NewValidationError(fmt.Errorf(`"exp" not satisfied`)) var errInvalidIssuedAt = NewValidationError(fmt.Errorf(`"iat" not satisfied`)) var errTokenNotYetValid = NewValidationError(fmt.Errorf(`"nbf" not satisfied`)) @@ -179,6 +195,11 @@ func ErrTokenNotYetValid() ValidationError { return errTokenNotYetValid } +// ErrMissingRequiredClaim creates a new error for missing required claims. +func ErrMissingRequiredClaim(name string) ValidationError { + return &missingRequiredClaimError{claim: name} +} + // Validator describes interface to validate a Token. type Validator interface { // Validate should return an error if a required conditions is not met. @@ -377,9 +398,10 @@ func IsRequired(name string) Validator { type isRequired string func (ir isRequired) Validate(_ context.Context, t Token) ValidationError { - _, ok := t.Get(string(ir)) + name := string(ir) + _, ok := t.Get(name) if !ok { - return NewValidationError(fmt.Errorf(`%q not satisfied: required claim not found`, string(ir))) + return ErrMissingRequiredClaim(name) } return nil } diff --git a/tools/cmd/genjwe/go.mod b/tools/cmd/genjwe/go.mod index 5b1226bd2..7ee8345df 100644 --- a/tools/cmd/genjwe/go.mod +++ b/tools/cmd/genjwe/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( github.com/goccy/go-yaml v1.9.4 - github.com/lestrrat-go/codegen v1.0.4-0.20220329032654-7b542c9fb49b + github.com/lestrrat-go/codegen v1.0.4-0.20220422093832-3f381ea644e3 github.com/stretchr/testify v1.7.1 // indirect golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect ) diff --git a/tools/cmd/genjwe/go.sum b/tools/cmd/genjwe/go.sum index 952c1ee24..026adac42 100644 --- a/tools/cmd/genjwe/go.sum +++ b/tools/cmd/genjwe/go.sum @@ -13,8 +13,8 @@ github.com/goccy/go-yaml v1.9.4 h1:S0GCYjwHKVI6IHqio7QWNKNThUl6NLzFd/g8Z65Axw8= github.com/goccy/go-yaml v1.9.4/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/lestrrat-go/codegen v1.0.4-0.20220329032654-7b542c9fb49b h1:PQ+SVFMytiSbfozcIQbp4Kb7/xe6NPiHdFNVQxnynlk= -github.com/lestrrat-go/codegen v1.0.4-0.20220329032654-7b542c9fb49b/go.mod h1:B5zvyPBGsMtVrUaM9q0doiP+oyw05CI/dpFU9T1TUFo= +github.com/lestrrat-go/codegen v1.0.4-0.20220422093832-3f381ea644e3 h1:ePhghrkFCIQH5Wnq5R5H5iw+RXdYkc53M/bcc7ylqpQ= +github.com/lestrrat-go/codegen v1.0.4-0.20220422093832-3f381ea644e3/go.mod h1:B5zvyPBGsMtVrUaM9q0doiP+oyw05CI/dpFU9T1TUFo= github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4= github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/lestrrat-go/xstrings v0.0.0-20210804220435-4dd8b234342b h1:3laG8JWIeDGb7lf00nMRznLdCHy0aZPd/CGz7Okn1SY= diff --git a/tools/cmd/genjwe/main.go b/tools/cmd/genjwe/main.go index 9f3677586..054209ebf 100644 --- a/tools/cmd/genjwe/main.go +++ b/tools/cmd/genjwe/main.go @@ -55,24 +55,6 @@ func yaml2json(fn string) ([]byte, error) { return json.Marshal(v) } -func boolFromField(f codegen.Field, field string) (bool, error) { - v, ok := f.Extra(field) - if !ok { - return false, fmt.Errorf("%q does not exist in %q", field, f.Name(true)) - } - - b, ok := v.(bool) - if !ok { - return false, fmt.Errorf("%q should be a bool in %q", field, f.Name(true)) - } - return b, nil -} - -func fieldHasAccept(f codegen.Field) bool { - v, _ := boolFromField(f, "hasAccept") - return v -} - func IsPointer(f codegen.Field) bool { return strings.HasPrefix(f.Type(), `*`) } @@ -234,7 +216,7 @@ func generateHeaders(obj *codegen.Object) error { o.L("switch name {") for _, f := range obj.Fields() { o.L("case %sKey:", f.Name(true)) - if fieldHasAccept(f) { + if f.Bool(`hasAccept`) { o.L("var acceptor %s", PointerElem(f)) o.L("if err := acceptor.Accept(value); err != nil {") o.L("return fmt.Errorf(`invalid value for %%s key: %%w`, %sKey, err)", f.Name(true)) diff --git a/tools/cmd/genjwk/go.mod b/tools/cmd/genjwk/go.mod index 79da8af7d..510ec12b5 100644 --- a/tools/cmd/genjwk/go.mod +++ b/tools/cmd/genjwk/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( github.com/goccy/go-yaml v1.9.4 - github.com/lestrrat-go/codegen v1.0.4-0.20220329032654-7b542c9fb49b + github.com/lestrrat-go/codegen v1.0.4-0.20220422093832-3f381ea644e3 github.com/stretchr/testify v1.7.1 // indirect golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect ) diff --git a/tools/cmd/genjwk/go.sum b/tools/cmd/genjwk/go.sum index 952c1ee24..026adac42 100644 --- a/tools/cmd/genjwk/go.sum +++ b/tools/cmd/genjwk/go.sum @@ -13,8 +13,8 @@ github.com/goccy/go-yaml v1.9.4 h1:S0GCYjwHKVI6IHqio7QWNKNThUl6NLzFd/g8Z65Axw8= github.com/goccy/go-yaml v1.9.4/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/lestrrat-go/codegen v1.0.4-0.20220329032654-7b542c9fb49b h1:PQ+SVFMytiSbfozcIQbp4Kb7/xe6NPiHdFNVQxnynlk= -github.com/lestrrat-go/codegen v1.0.4-0.20220329032654-7b542c9fb49b/go.mod h1:B5zvyPBGsMtVrUaM9q0doiP+oyw05CI/dpFU9T1TUFo= +github.com/lestrrat-go/codegen v1.0.4-0.20220422093832-3f381ea644e3 h1:ePhghrkFCIQH5Wnq5R5H5iw+RXdYkc53M/bcc7ylqpQ= +github.com/lestrrat-go/codegen v1.0.4-0.20220422093832-3f381ea644e3/go.mod h1:B5zvyPBGsMtVrUaM9q0doiP+oyw05CI/dpFU9T1TUFo= github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4= github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/lestrrat-go/xstrings v0.0.0-20210804220435-4dd8b234342b h1:3laG8JWIeDGb7lf00nMRznLdCHy0aZPd/CGz7Okn1SY= diff --git a/tools/cmd/genjwk/main.go b/tools/cmd/genjwk/main.go index 5790be04c..d0d4b77a4 100644 --- a/tools/cmd/genjwk/main.go +++ b/tools/cmd/genjwk/main.go @@ -92,60 +92,6 @@ func _main() error { return nil } -func boolFromField(f codegen.Field, field string) (bool, error) { - v, ok := f.Extra(field) - if !ok { - return false, fmt.Errorf("%q does not exist in %q", field, f.Name(true)) - } - - b, ok := v.(bool) - if !ok { - return false, fmt.Errorf("%q should be a bool in %q", field, f.Name(true)) - } - return b, nil -} - -func stringFromField(f codegen.Field, field string) (string, error) { - v, ok := f.Extra(field) - if !ok { - return "", fmt.Errorf("%q does not exist in %q", field, f.Name(true)) - } - - s, ok := v.(string) - if !ok { - return "", fmt.Errorf("%q should be a string in %q", field, f.Name(true)) - } - return s, nil -} - -func fieldIsStd(f codegen.Field) bool { - v, _ := boolFromField(f, `is_std`) - return v -} - -func fieldNoDeref(f codegen.Field) bool { - v, _ := boolFromField(f, "noDeref") - return v -} - -func fieldHasGet(f codegen.Field) bool { - v, _ := boolFromField(f, "hasGet") - return v -} - -func fieldHasAccept(f codegen.Field) bool { - v, _ := boolFromField(f, "hasAccept") - return v -} - -func fieldGetterReturnValue(f codegen.Field) string { - if v, err := stringFromField(f, `getter_return_value`); err == nil { - return v - } - - return f.Type() -} - func IsPointer(f codegen.Field) bool { return strings.HasPrefix(f.Type(), `*`) } @@ -164,43 +110,6 @@ func fieldStorageTypeIsIndirect(s string) bool { return s == "KeyOperationList" || !(strings.HasPrefix(s, `*`) || strings.HasPrefix(s, `[]`) || strings.HasSuffix(s, `List`)) } -func stringFromObject(o *codegen.Object, field string) (string, error) { - v, ok := o.Extra(field) - if !ok { - return "", fmt.Errorf("%q does not exist in %q", field, o.Name(true)) - } - - s, ok := v.(string) - if !ok { - return "", fmt.Errorf("%q should be a string in %q", field, o.Name(true)) - } - return s, nil -} - -func objectRawKeyType(obj *codegen.Object) string { - v, err := stringFromObject(obj, "raw_key_type") - if err != nil { - panic(err.Error()) - } - return v -} - -func objectStructName(o *codegen.Object) string { - v, err := stringFromObject(o, `struct_name`) - if err != nil { - return "" - } - return v -} - -func objectInterface(o *codegen.Object) string { - v, err := stringFromObject(o, `interface`) - if err != nil { - return "" - } - return v -} - type Constant struct { Name string Value string @@ -217,7 +126,7 @@ func generateKeyType(kt *KeyType) error { seen := make(map[string]struct{}) for _, obj := range kt.Objects { for _, f := range obj.Fields() { - if fieldIsStd(f) { + if f.Bool(`is_std`) { continue } n := f.Name(true) @@ -241,7 +150,7 @@ func generateKeyType(kt *KeyType) error { for _, obj := range kt.Objects { if err := generateObject(o, kt, obj); err != nil { - return fmt.Errorf(`failed to generate object %s: %w`, obj.Name(true)) + return fmt.Errorf(`failed to generate object %s: %w`, obj.Name(true), err) } } @@ -256,19 +165,19 @@ func generateKeyType(kt *KeyType) error { func generateObject(o *codegen.Output, kt *KeyType, obj *codegen.Object) error { ifName := kt.Prefix + obj.Name(true) - if v := objectInterface(obj); v != "" { + if v := obj.String(`interface`); v != "" { ifName = v } structName := strings.ToLower(kt.Prefix) + obj.Name(true) - if v := objectStructName(obj); v != "" { + if v := obj.String(`struct_name`); v != "" { structName = v } o.LL("type %s interface {", ifName) o.L("Key") - o.L("FromRaw(%s) error", objectRawKeyType(obj)) + o.L("FromRaw(%s) error", obj.MustString(`raw_key_type`)) for _, f := range obj.Fields() { - if fieldIsStd(f) { + if f.Bool(`is_std`) { continue } o.L("%s() %s", f.GetterMethod(true), f.Type()) @@ -303,16 +212,16 @@ func generateObject(o *codegen.Output, kt *KeyType, obj *codegen.Object) error { for _, f := range obj.Fields() { o.LL("func (h *%s) %s() ", structName, f.GetterMethod(true)) - if v := fieldGetterReturnValue(f); v != "" { + if v := f.String(`getter_return_value`); v != "" { o.R("%s", v) - } else if IsPointer(f) && fieldNoDeref(f) { + } else if IsPointer(f) && f.Bool(`noDeref`) { o.R("%s", f.Type()) } else { o.R("%s", PointerElem(f)) } o.R(" {") - if fieldHasGet(f) { + if f.Bool(`hasGet`) { o.L("if h.%s != nil {", f.Name(false)) o.L("return h.%s.Get()", f.Name(false)) o.L("}") @@ -341,7 +250,7 @@ func generateObject(o *codegen.Output, kt *KeyType, obj *codegen.Object) error { o.L("pairs = append(pairs, &HeaderPair{Key: \"kty\", Value: %s})", kt.KeyType) for _, f := range obj.Fields() { var keyName string - if fieldIsStd(f) { + if f.Bool(`is_std`) { keyName = f.Name(true) + "Key" } else { keyName = kt.Prefix + f.Name(true) + "Key" @@ -371,7 +280,7 @@ func generateObject(o *codegen.Output, kt *KeyType, obj *codegen.Object) error { o.L("case KeyTypeKey:") o.L("return h.KeyType(), true") for _, f := range obj.Fields() { - if fieldIsStd(f) { + if f.Bool(`is_std`) { o.L("case %sKey:", f.Name(true)) } else { o.L("case %s%sKey:", kt.Prefix, f.Name(true)) @@ -380,7 +289,7 @@ func generateObject(o *codegen.Output, kt *KeyType, obj *codegen.Object) error { o.L("if h.%s == nil {", f.Name(false)) o.L("return nil, false") o.L("}") - if fieldHasGet(f) { + if f.Bool(`hasGet`) { o.L("return h.%s.Get(), true", f.Name(false)) } else if fieldStorageTypeIsIndirect(f.Type()) { o.L("return *(h.%s), true", f.Name(false)) @@ -406,7 +315,7 @@ func generateObject(o *codegen.Output, kt *KeyType, obj *codegen.Object) error { o.L("return nil") // This is not great, but we just ignore it for _, f := range obj.Fields() { var keyName string - if fieldIsStd(f) { + if f.Bool(`is_std`) { keyName = f.Name(true) + "Key" } else { keyName = kt.Prefix + f.Name(true) + "Key" @@ -440,7 +349,7 @@ func generateObject(o *codegen.Output, kt *KeyType, obj *codegen.Object) error { o.L("default:") o.L("return fmt.Errorf(`invalid key usage type %%s`, v)") o.L("}") - } else if fieldHasAccept(f) { + } else if f.Bool(`hasAccept`) { o.L("var acceptor %s", f.Type()) o.L("if err := acceptor.Accept(value); err != nil {") o.L("return fmt.Errorf(`invalid value for %%s key: %%w`, %s, err)", keyName) @@ -478,7 +387,7 @@ func generateObject(o *codegen.Output, kt *KeyType, obj *codegen.Object) error { o.L("switch key {") for _, f := range obj.Fields() { var keyName string - if fieldIsStd(f) { + if f.Bool(`is_std`) { keyName = f.Name(true) + "Key" } else { keyName = kt.Prefix + f.Name(true) + "Key" @@ -509,6 +418,8 @@ func generateObject(o *codegen.Output, kt *KeyType, obj *codegen.Object) error { o.L("}") o.LL("func (h *%s) UnmarshalJSON(buf []byte) error {", structName) + o.L(`h.mu.Lock()`) + o.L(`defer h.mu.Unlock()`) for _, f := range obj.Fields() { o.L("h.%s = nil", f.Name(false)) } @@ -769,9 +680,9 @@ func generateGenericHeaders(fields codegen.FieldList) error { o.L("// This is why there exists a `jwa.KeyAlgorithm` type that encompases both types.") } o.L("%s() ", f.GetterMethod(true)) - if v := fieldGetterReturnValue(f); v != "" { + if v := f.String(`getter_return_value`); v != "" { o.R("%s", v) - } else if IsPointer(f) && fieldNoDeref(f) { + } else if IsPointer(f) && f.Bool(`noDeref`) { o.R("%s", f.Type()) } else { o.R("%s", PointerElem(f)) diff --git a/tools/cmd/genjws/go.mod b/tools/cmd/genjws/go.mod index 71e3fd500..3464df01f 100644 --- a/tools/cmd/genjws/go.mod +++ b/tools/cmd/genjws/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( github.com/goccy/go-yaml v1.9.4 - github.com/lestrrat-go/codegen v1.0.4-0.20220329032654-7b542c9fb49b + github.com/lestrrat-go/codegen v1.0.4-0.20220422093832-3f381ea644e3 github.com/stretchr/testify v1.7.1 // indirect golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect ) diff --git a/tools/cmd/genjws/go.sum b/tools/cmd/genjws/go.sum index 952c1ee24..026adac42 100644 --- a/tools/cmd/genjws/go.sum +++ b/tools/cmd/genjws/go.sum @@ -13,8 +13,8 @@ github.com/goccy/go-yaml v1.9.4 h1:S0GCYjwHKVI6IHqio7QWNKNThUl6NLzFd/g8Z65Axw8= github.com/goccy/go-yaml v1.9.4/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/lestrrat-go/codegen v1.0.4-0.20220329032654-7b542c9fb49b h1:PQ+SVFMytiSbfozcIQbp4Kb7/xe6NPiHdFNVQxnynlk= -github.com/lestrrat-go/codegen v1.0.4-0.20220329032654-7b542c9fb49b/go.mod h1:B5zvyPBGsMtVrUaM9q0doiP+oyw05CI/dpFU9T1TUFo= +github.com/lestrrat-go/codegen v1.0.4-0.20220422093832-3f381ea644e3 h1:ePhghrkFCIQH5Wnq5R5H5iw+RXdYkc53M/bcc7ylqpQ= +github.com/lestrrat-go/codegen v1.0.4-0.20220422093832-3f381ea644e3/go.mod h1:B5zvyPBGsMtVrUaM9q0doiP+oyw05CI/dpFU9T1TUFo= github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4= github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/lestrrat-go/xstrings v0.0.0-20210804220435-4dd8b234342b h1:3laG8JWIeDGb7lf00nMRznLdCHy0aZPd/CGz7Okn1SY= diff --git a/tools/cmd/genjws/main.go b/tools/cmd/genjws/main.go index 049beb28e..bf6521138 100644 --- a/tools/cmd/genjws/main.go +++ b/tools/cmd/genjws/main.go @@ -54,29 +54,6 @@ func yaml2json(fn string) ([]byte, error) { return json.Marshal(v) } -func boolFromField(f codegen.Field, field string) (bool, error) { - v, ok := f.Extra(field) - if !ok { - return false, fmt.Errorf("%q does not exist in %q", field, f.Name(true)) - } - - b, ok := v.(bool) - if !ok { - return false, fmt.Errorf("%q should be a bool in %q", field, f.Name(true)) - } - return b, nil -} - -func fieldNoDeref(f codegen.Field) bool { - v, _ := boolFromField(f, "noDeref") - return v -} - -func fieldHasAccept(f codegen.Field) bool { - v, _ := boolFromField(f, "hasAccept") - return v -} - func IsPointer(f codegen.Field) bool { return strings.HasPrefix(f.Type(), `*`) } @@ -115,7 +92,7 @@ func generateHeaders(obj *codegen.Object) error { o.L("json.Unmarshaler") // These are the basic values that most jws have for _, f := range obj.Fields() { - if fieldNoDeref(f) { + if f.Bool(`noDeref`) { o.L("%s() %s", f.GetterMethod(true), f.Type()) } else { o.L("%s() %s", f.GetterMethod(true), PointerElem(f)) @@ -176,6 +153,14 @@ func generateHeaders(obj *codegen.Object) error { o.L("}") // func (h *stdHeaders) %s() %s } + o.LL("func (h *stdHeaders) clear() {") + for _, f := range obj.Fields() { + o.L("h.%s = nil", f.Name(false)) + } + o.L("h.privateParams = nil") + o.L("h.raw = nil") + o.L("}") + o.LL("func (h *stdHeaders) DecodeCtx() DecodeCtx{") o.L("h.mu.RLock()") o.L("defer h.mu.RUnlock()") @@ -254,7 +239,7 @@ func generateHeaders(obj *codegen.Object) error { o.L("switch name {") for _, f := range obj.Fields() { o.L("case %sKey:", f.Name(true)) - if fieldHasAccept(f) { + if f.Bool(`hasAccept`) { o.L("var acceptor %s", PointerElem(f)) o.L("if err := acceptor.Accept(value); err != nil {") o.L("return fmt.Errorf(`invalid value for %%s key: %%w`, %sKey, err)", f.Name(true)) @@ -297,10 +282,9 @@ func generateHeaders(obj *codegen.Object) error { o.L("}") o.LL("func (h *stdHeaders) UnmarshalJSON(buf []byte) error {") - for _, f := range obj.Fields() { - o.L("h.%s = nil", f.Name(false)) - } - + o.L("h.mu.Lock()") + o.L("defer h.mu.Unlock()") + o.L("h.clear()") o.L("dec := json.NewDecoder(bytes.NewReader(buf))") o.L("LOOP:") o.L("for {") @@ -349,7 +333,7 @@ func generateHeaders(obj *codegen.Object) error { o.L("return fmt.Errorf(`failed to decode value for key %%s: %%w`, %sKey, err)", f.Name(true)) o.L("}") o.L("h.%s = decoded", f.Name(false)) - } else if fieldNoDeref(f) { + } else if f.Bool(`noDeref`) { o.L("case %sKey:", f.Name(true)) o.L("var decoded %s", PointerElem(f)) o.L("if err := dec.Decode(&decoded); err != nil {") diff --git a/tools/cmd/genjwt/go.mod b/tools/cmd/genjwt/go.mod index 2cf74ff11..a509e63fb 100644 --- a/tools/cmd/genjwt/go.mod +++ b/tools/cmd/genjwt/go.mod @@ -5,7 +5,7 @@ go 1.16 require ( github.com/goccy/go-json v0.9.6 github.com/goccy/go-yaml v1.9.4 - github.com/lestrrat-go/codegen v1.0.4-0.20220329032654-7b542c9fb49b + github.com/lestrrat-go/codegen v1.0.4-0.20220422093832-3f381ea644e3 github.com/stretchr/testify v1.7.1 // indirect golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect ) diff --git a/tools/cmd/genjwt/go.sum b/tools/cmd/genjwt/go.sum index 817208841..2661b17eb 100644 --- a/tools/cmd/genjwt/go.sum +++ b/tools/cmd/genjwt/go.sum @@ -15,8 +15,8 @@ github.com/goccy/go-yaml v1.9.4 h1:S0GCYjwHKVI6IHqio7QWNKNThUl6NLzFd/g8Z65Axw8= github.com/goccy/go-yaml v1.9.4/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/lestrrat-go/codegen v1.0.4-0.20220329032654-7b542c9fb49b h1:PQ+SVFMytiSbfozcIQbp4Kb7/xe6NPiHdFNVQxnynlk= -github.com/lestrrat-go/codegen v1.0.4-0.20220329032654-7b542c9fb49b/go.mod h1:B5zvyPBGsMtVrUaM9q0doiP+oyw05CI/dpFU9T1TUFo= +github.com/lestrrat-go/codegen v1.0.4-0.20220422093832-3f381ea644e3 h1:ePhghrkFCIQH5Wnq5R5H5iw+RXdYkc53M/bcc7ylqpQ= +github.com/lestrrat-go/codegen v1.0.4-0.20220422093832-3f381ea644e3/go.mod h1:B5zvyPBGsMtVrUaM9q0doiP+oyw05CI/dpFU9T1TUFo= github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4= github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/lestrrat-go/xstrings v0.0.0-20210804220435-4dd8b234342b h1:3laG8JWIeDGb7lf00nMRznLdCHy0aZPd/CGz7Okn1SY= diff --git a/tools/cmd/genjwt/main.go b/tools/cmd/genjwt/main.go index b1dbafe37..4c52fe3c6 100644 --- a/tools/cmd/genjwt/main.go +++ b/tools/cmd/genjwt/main.go @@ -51,105 +51,19 @@ func _main() error { for _, object := range def.Objects { if err := generateToken(object); err != nil { - return fmt.Errorf(`failed to generate token file %s: %w`, objectFilename(object), err) + return fmt.Errorf(`failed to generate token file %s: %w`, object.MustString(`filename`), err) } } for _, object := range def.Objects { if err := genBuilder(object); err != nil { - return fmt.Errorf(`failed to generate builder for package %q: %w`, objectPackage(object), err) + return fmt.Errorf(`failed to generate builder for package %q: %w`, object.MustString(`package`), err) } } return nil } -func boolFromField(f codegen.Field, field string) (bool, error) { - v, ok := f.Extra(field) - if !ok { - return false, fmt.Errorf("%q does not exist in %q", field, f.Name(true)) - } - - b, ok := v.(bool) - if !ok { - return false, fmt.Errorf("%q should be a bool in %q", field, f.Name(true)) - } - return b, nil -} - -func stringFromField(f codegen.Field, field string) (string, error) { - v, ok := f.Extra(field) - if !ok { - return "", fmt.Errorf("%q does not exist in %q", field, f.Name(true)) - } - - s, ok := v.(string) - if !ok { - return "", fmt.Errorf("%q should be a string in %q", field, f.Name(true)) - } - return s, nil -} - -func fieldNoDeref(f codegen.Field) bool { - v, _ := boolFromField(f, "noDeref") - return v -} - -func fieldHasGet(f codegen.Field) bool { - v, _ := boolFromField(f, "hasGet") - return v -} - -func fieldHasAccept(f codegen.Field) bool { - v, _ := boolFromField(f, "hasAccept") - return v -} - -func fieldGetterReturnValue(f codegen.Field) string { - if v, err := stringFromField(f, `getter_return_value`); err == nil { - return v - } - - return f.Type() -} - -func stringFromObject(o *codegen.Object, field string) (string, error) { - v, ok := o.Extra(field) - if !ok { - return "", fmt.Errorf("%q does not exist in %q", field, o.Name(true)) - } - - s, ok := v.(string) - if !ok { - return "", fmt.Errorf("%q should be a string in %q", field, o.Name(true)) - } - return s, nil -} - -func objectFilename(o *codegen.Object) string { - v, err := stringFromObject(o, `filename`) - if err != nil { - panic(err.Error()) - } - return v -} - -func objectPackage(o *codegen.Object) string { - v, err := stringFromObject(o, `package`) - if err != nil { - panic(err.Error()) - } - return v -} - -func objectInterface(o *codegen.Object) string { - v, err := stringFromObject(o, `interface`) - if err != nil { - panic(err.Error()) - } - return v -} - func yaml2json(fn string) ([]byte, error) { in, err := os.Open(fn) if err != nil { @@ -189,7 +103,7 @@ func generateToken(obj *codegen.Object) error { o := codegen.NewOutput(&buf) o.L("// This file is auto-generated by jwt/internal/cmd/gentoken/main.go. DO NOT EDIT") - o.LL("package %s", objectPackage(obj)) + o.LL("package %s", obj.String(`package`)) var fields = obj.Fields() @@ -199,7 +113,7 @@ func generateToken(obj *codegen.Object) error { } o.L(")") // end const - if objectPackage(obj) == "jwt" && obj.Name(false) == "stdToken" { + if obj.String(`package`) == "jwt" && obj.Name(false) == "stdToken" { o.LL("// Token represents a generic JWT token.") o.L("// which are type-aware (to an extent). Other claims may be accessed via the `Get`/`Set`") o.L("// methods but their types are not taken into consideration at all. If you have non-standard") @@ -212,10 +126,15 @@ func generateToken(obj *codegen.Object) error { o.L("// work well when it is embedded in other structure") } - o.L("type %s interface {", objectInterface(obj)) + o.L("type %s interface {", obj.String(`interface`)) for _, field := range fields { o.LL("// %s returns the value for %q field of the token", field.GetterMethod(true), field.JSON()) - o.L("%s() %s", field.GetterMethod(true), fieldGetterReturnValue(field)) + + rv := field.String(`getter_return_value`) + if rv == "" { + rv = field.Type() + } + o.L("%s() %s", field.GetterMethod(true), rv) } o.LL("// PrivateClaims return the entire set of fields (claims) in the token") o.L("// *other* than the pre-defined fields such as `iss`, `nbf`, `iat`, etc.") @@ -236,7 +155,7 @@ func generateToken(obj *codegen.Object) error { o.L("// for the types of each of these fields") o.L("Set(string, interface{}) error") o.L("Remove(string) error") - if objectPackage(obj) != "jwt" { + if obj.String(`package`) != "jwt" { o.L("Clone() (jwt.Token, error)") } else { o.L("Clone() (Token, error)") @@ -272,7 +191,7 @@ func generateToken(obj *codegen.Object) error { } o.R(".\n// Convenience accessors are provided for these standard claims") - o.L("func New() %s {", objectInterface(obj)) + o.L("func New() %s {", obj.String(`interface`)) o.L("return &%s{", obj.Name(false)) o.L("mu: &sync.RWMutex{},") o.L("privateClaims: make(map[string]interface{}),") @@ -288,7 +207,7 @@ func generateToken(obj *codegen.Object) error { o.L("if t.%s == nil {", f.Name(false)) o.L("return nil, false") o.L("}") - if fieldHasGet(f) { + if f.Bool(`hasGet`) { o.L("v := t.%s.Get()", f.Name(false)) } else { if fieldStorageTypeIsIndirect(f.Type()) { @@ -353,7 +272,7 @@ func generateToken(obj *codegen.Object) error { o.L("return fmt.Errorf(`invalid type for %%s key: %%T`, %s, value)", keyName) o.L("}") o.L("return nil") - } else if fieldHasAccept(f) { + } else if f.Bool(`hasAccept`) { if IsPointer(f) { o.L("var acceptor %s", strings.TrimPrefix(f.Type(), "*")) } else { @@ -391,10 +310,14 @@ func generateToken(obj *codegen.Object) error { o.L("}") // end func (t *%s) Set(name string, value interface{}) for _, f := range fields { + rv := f.String(`getter_return_value`) + if rv == "" { + rv = f.Type() + } o.LL("func (t *%s) %s() ", obj.Name(false), f.GetterMethod(true)) - if rv := fieldGetterReturnValue(f); rv != "" { + if rv != "" { o.R("%s", rv) - } else if IsPointer(f) && fieldNoDeref(f) { + } else if IsPointer(f) && f.Bool(`noDeref`) { o.R("%s", f.Type()) } else { o.R("%s", PointerElem(f)) @@ -403,17 +326,17 @@ func generateToken(obj *codegen.Object) error { o.L("t.mu.RLock()") o.L("defer t.mu.RUnlock()") - if fieldHasGet(f) { + if f.Bool(`hasGet`) { o.L("if t.%s != nil {", f.Name(false)) o.L("return t.%s.Get()", f.Name(false)) o.L("}") - o.L("return %s", codegen.ZeroVal(fieldGetterReturnValue(f))) + o.L("return %s", codegen.ZeroVal(rv)) } else if !IsPointer(f) { if fieldStorageTypeIsIndirect(f.Type()) { o.L("if t.%s != nil {", f.Name(false)) o.L("return *(t.%s)", f.Name(false)) o.L("}") - o.L("return %s", codegen.ZeroVal(fieldGetterReturnValue(f))) + o.L("return %s", codegen.ZeroVal(rv)) } else { o.L("return t.%s", f.Name(false)) } @@ -440,7 +363,7 @@ func generateToken(obj *codegen.Object) error { for _, f := range fields { keyName := f.Name(true) + "Key" o.L("if t.%s != nil {", f.Name(false)) - if fieldHasGet(f) { + if f.Bool(`hasGet`) { o.L("v := t.%s.Get()", f.Name(false)) } else { if fieldStorageTypeIsIndirect(f.Type()) { @@ -554,8 +477,6 @@ func generateToken(obj *codegen.Object) error { } o.LL("func (t %s) MarshalJSON() ([]byte, error) {", obj.Name(false)) - o.L("t.mu.RLock()") - o.L("defer t.mu.RUnlock()") o.L("buf := pool.GetBytesBuffer()") o.L("defer pool.ReleaseBytesBuffer(buf)") o.L("buf.WriteByte('{')") @@ -632,18 +553,18 @@ func generateToken(obj *codegen.Object) error { o.L("return iter.AsMap(ctx, t)") o.L("}") - if err := o.WriteFile(objectFilename(obj), codegen.WithFormatCode(true)); err != nil { + if err := o.WriteFile(obj.MustString(`filename`), codegen.WithFormatCode(true)); err != nil { if cfe, ok := err.(codegen.CodeFormatError); ok { fmt.Fprint(os.Stderr, cfe.Source()) } - return fmt.Errorf(`failed to write to %s: %w`, objectFilename(obj), err) + return fmt.Errorf(`failed to write to %s: %w`, obj.MustString(`filename`), err) } return nil } func genBuilder(obj *codegen.Object) error { var buf bytes.Buffer - pkg := objectPackage(obj) + pkg := obj.MustString(`package`) o := codegen.NewOutput(&buf) o.L("// This file is auto-generated by jwt/internal/cmd/gentoken/main.go. DO NOT EDIT") o.LL("package %s", pkg)