From 659f834360c7db3a1e849f0dbf44e1d49c2a3d84 Mon Sep 17 00:00:00 2001 From: Lyuben Penkovski <lyuben.penkovski@vereign.com> Date: Wed, 1 Nov 2023 10:01:40 +0200 Subject: [PATCH] Dependency injection for jsonld document loader Some unit tests start clean and create new signer service instance for every test case. In order for all test cases to reuse a common caching document loader, it's injected as dependency to the signer. All this is needed because recently W3C introduced a rate limiter on their web site and JSONLD context pages, and unit tests fail if too many requests for resolving contexts are made in short periods of time. --- cmd/signer/main.go | 5 +++- internal/service/signer/service.go | 17 ++---------- internal/service/signer/service_test.go | 37 +++++++++++++++---------- 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/cmd/signer/main.go b/cmd/signer/main.go index 887a1d4..c3369de 100644 --- a/cmd/signer/main.go +++ b/cmd/signer/main.go @@ -10,6 +10,7 @@ import ( "time" "github.com/kelseyhightower/envconfig" + "github.com/piprate/json-gold/ld" "github.com/prometheus/client_golang/prometheus/promhttp" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -64,7 +65,9 @@ func main() { healthSvc goahealth.Service ) { - signerSvc = signer.New(vault, cfg.Vault.SupportedKeys, httpClient, logger) + // create jsonld document loader which the signer uses to resolve jsonld contexts + docLoader := ld.NewCachingDocumentLoader(ld.NewDefaultDocumentLoader(httpClient)) + signerSvc = signer.New(vault, cfg.Vault.SupportedKeys, docLoader, logger) healthSvc = health.New(Version) } diff --git a/internal/service/signer/service.go b/internal/service/signer/service.go index 10a175c..bd9789d 100644 --- a/internal/service/signer/service.go +++ b/internal/service/signer/service.go @@ -7,9 +7,7 @@ import ( "encoding/json" "encoding/pem" "fmt" - "net/http" "strings" - "sync" "time" "github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite" @@ -35,11 +33,6 @@ var defaultJSONLDContexts = []string{ "https://schema.org", } -var ( - initDefaultCachingLoader sync.Once - defaultCachingLoader *ld.CachingDocumentLoader -) - type VaultKey struct { Name string `json:"name"` Type string `json:"type"` @@ -65,13 +58,7 @@ type Service struct { logger *zap.Logger } -func New(vault Vault, supportedKeys []string, httpClient *http.Client, logger *zap.Logger) *Service { - // create document loader only once - initDefaultCachingLoader.Do(func() { - loader := ld.NewDefaultDocumentLoader(httpClient) - defaultCachingLoader = ld.NewCachingDocumentLoader(loader) - }) - +func New(vault Vault, supportedKeys []string, docLoader *ld.CachingDocumentLoader, logger *zap.Logger) *Service { // only DID:WEB and DID:KEY methods are supported currently webVDR := web.New() keyVDR := key.New() @@ -84,7 +71,7 @@ func New(vault Vault, supportedKeys []string, httpClient *http.Client, logger *z return &Service{ vault: vault, supportedKeys: supportedKeys, - docLoader: defaultCachingLoader, + docLoader: docLoader, keyFetcher: keyResolver.PublicKeyFetcher(), logger: logger, } diff --git a/internal/service/signer/service_test.go b/internal/service/signer/service_test.go index e7f724b..be27a0c 100644 --- a/internal/service/signer/service_test.go +++ b/internal/service/signer/service_test.go @@ -11,6 +11,7 @@ import ( "testing" "github.com/hyperledger/aries-framework-go/pkg/doc/verifiable" + "github.com/piprate/json-gold/ld" "github.com/square/go-jose/v3" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -22,6 +23,14 @@ import ( "gitlab.eclipse.org/eclipse/xfsc/tsa/signer/internal/service/signer/signerfakes" ) +var docLoader *ld.CachingDocumentLoader + +func init() { + if docLoader == nil { + docLoader = ld.NewCachingDocumentLoader(ld.NewDefaultDocumentLoader(http.DefaultClient)) + } +} + func TestService_Namespaces(t *testing.T) { t.Run("vault client fails to return namespaces", func(t *testing.T) { vault := &signerfakes.FakeVault{ @@ -30,7 +39,7 @@ func TestService_Namespaces(t *testing.T) { }, } - svc := signer.New(vault, []string{}, http.DefaultClient, zap.NewNop()) + svc := signer.New(vault, []string{}, docLoader, zap.NewNop()) namespaces, err := svc.Namespaces(context.Background()) assert.Nil(t, namespaces) assert.NotNil(t, err) @@ -44,7 +53,7 @@ func TestService_Namespaces(t *testing.T) { }, } - svc := signer.New(vault, []string{}, http.DefaultClient, zap.NewNop()) + svc := signer.New(vault, []string{}, docLoader, zap.NewNop()) namespaces, err := svc.Namespaces(context.Background()) assert.NoError(t, err) assert.NotNil(t, namespaces) @@ -59,7 +68,7 @@ func TestService_NamespaceKeys(t *testing.T) { return nil, errors.New(errors.Internal, "some error") }, } - svc := signer.New(vault, []string{}, http.DefaultClient, zap.NewNop()) + svc := signer.New(vault, []string{}, docLoader, zap.NewNop()) keys, err := svc.NamespaceKeys(context.Background(), &goasigner.NamespaceKeysRequest{}) assert.Nil(t, keys) assert.NotNil(t, err) @@ -73,7 +82,7 @@ func TestService_NamespaceKeys(t *testing.T) { }, } - svc := signer.New(vault, []string{}, http.DefaultClient, zap.NewNop()) + svc := signer.New(vault, []string{}, docLoader, zap.NewNop()) keys, err := svc.NamespaceKeys(context.Background(), &goasigner.NamespaceKeysRequest{}) assert.Nil(t, keys) assert.NotNil(t, err) @@ -87,7 +96,7 @@ func TestService_NamespaceKeys(t *testing.T) { }, } - svc := signer.New(vault, []string{}, http.DefaultClient, zap.NewNop()) + svc := signer.New(vault, []string{}, docLoader, zap.NewNop()) keys, err := svc.NamespaceKeys(context.Background(), &goasigner.NamespaceKeysRequest{}) assert.NoError(t, err) assert.Equal(t, keys, []string{"key1", "key3"}) @@ -102,7 +111,7 @@ func TestService_VerificationMethod(t *testing.T) { }, } - svc := signer.New(vaultError, []string{}, http.DefaultClient, zap.NewNop()) + svc := signer.New(vaultError, []string{}, docLoader, zap.NewNop()) result, err := svc.VerificationMethod(context.Background(), &goasigner.VerificationMethodRequest{Key: "key1"}) assert.Nil(t, result) assert.Error(t, err) @@ -122,7 +131,7 @@ func TestService_VerificationMethod(t *testing.T) { }, } - svc := signer.New(signerOK, []string{"ecdsa-p256"}, http.DefaultClient, zap.NewNop()) + svc := signer.New(signerOK, []string{"ecdsa-p256"}, docLoader, zap.NewNop()) result, err := svc.VerificationMethod(context.Background(), &goasigner.VerificationMethodRequest{Did: "did:web:example.com", Key: "key1"}) assert.NotNil(t, result) assert.NoError(t, err) @@ -147,7 +156,7 @@ func TestService_VerificationMethods(t *testing.T) { }, } - svc := signer.New(vaultError, []string{}, http.DefaultClient, zap.NewNop()) + svc := signer.New(vaultError, []string{}, docLoader, zap.NewNop()) result, err := svc.VerificationMethods(context.Background(), &goasigner.VerificationMethodsRequest{Namespace: "unknown"}) assert.Nil(t, result) assert.Error(t, err) @@ -162,7 +171,7 @@ func TestService_VerificationMethods(t *testing.T) { return nil, errors.New(errors.NotFound, "no keys") }, } - svc := signer.New(vaultErrorEmptyList, []string{}, http.DefaultClient, zap.NewNop()) + svc := signer.New(vaultErrorEmptyList, []string{}, docLoader, zap.NewNop()) result, err := svc.VerificationMethods(context.Background(), &goasigner.VerificationMethodsRequest{ Did: "did:web:example.com", Namespace: "nm", @@ -184,7 +193,7 @@ func TestService_VerificationMethods(t *testing.T) { }, } - svc := signer.New(signerOK, []string{"ecdsa-p256"}, http.DefaultClient, zap.NewNop()) + svc := signer.New(signerOK, []string{"ecdsa-p256"}, docLoader, zap.NewNop()) result, err := svc.VerificationMethods(context.Background(), &goasigner.VerificationMethodsRequest{ Did: "did:web:example.com", Namespace: "nm", @@ -222,7 +231,7 @@ func TestService_VerificationMethods(t *testing.T) { }, } - svc := signer.New(signerOK, []string{"ecdsa-p256"}, http.DefaultClient, zap.NewNop()) + svc := signer.New(signerOK, []string{"ecdsa-p256"}, docLoader, zap.NewNop()) result, err := svc.VerificationMethods(context.Background(), &goasigner.VerificationMethodsRequest{ Did: "did:web:example.com", Namespace: "nm", @@ -405,7 +414,7 @@ func TestService_CredentialProof(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - svc := signer.New(test.signer, test.supportedKeys, http.DefaultClient, zap.NewNop()) + svc := signer.New(test.signer, test.supportedKeys, docLoader, zap.NewNop()) var cred interface{} err := json.Unmarshal(test.credential, &cred) @@ -606,7 +615,7 @@ func TestService_PresentationProof(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - svc := signer.New(test.signer, test.supportedKeys, http.DefaultClient, zap.NewNop()) + svc := signer.New(test.signer, test.supportedKeys, docLoader, zap.NewNop()) var pres interface{} err := json.Unmarshal(test.presentation, &pres) @@ -769,7 +778,7 @@ func TestService_CreateCredential(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - signer := signer.New(test.signer, test.supportedKeys, http.DefaultClient, zap.NewNop()) + signer := signer.New(test.signer, test.supportedKeys, docLoader, zap.NewNop()) req := &goasigner.CreateCredentialRequest{ Issuer: test.issuer, -- GitLab