From 8ec7bd065b96b9cd25ffe5ee81be5a954167d77b Mon Sep 17 00:00:00 2001 From: Firas Qutishat Date: Thu, 21 Jan 2021 03:36:51 -0500 Subject: [PATCH] refactor: VDR support for deactivate/update closes #2423 Signed-off-by: Firas Qutishat --- pkg/framework/aries/api/vdr/vdr.go | 5 ++ pkg/mock/vdr/mock_registry.go | 32 +++++++-- pkg/mock/vdr/mock_vdr.go | 25 ++++++- pkg/vdr/httpbinding/vdr.go | 10 +++ pkg/vdr/httpbinding/vdr_test.go | 22 +++++++ pkg/vdr/key/vdr.go | 17 +++++ pkg/vdr/key/vdr_test.go | 18 +++++ pkg/vdr/peer/vdr.go | 12 ++++ pkg/vdr/peer/vdr_test.go | 37 +++++++++++ pkg/vdr/registry.go | 32 +++++++++ pkg/vdr/registry_test.go | 102 +++++++++++++++++++++++++++++ pkg/vdr/web/vdr.go | 17 +++++ pkg/vdr/web/vdr_test.go | 18 +++++ 13 files changed, 339 insertions(+), 8 deletions(-) create mode 100644 pkg/vdr/peer/vdr_test.go diff --git a/pkg/framework/aries/api/vdr/vdr.go b/pkg/framework/aries/api/vdr/vdr.go index b45e2fe8a..f7a7c29f2 100644 --- a/pkg/framework/aries/api/vdr/vdr.go +++ b/pkg/framework/aries/api/vdr/vdr.go @@ -25,14 +25,19 @@ const DIDCommServiceType = "did-communication" type Registry interface { Resolve(did string, opts ...ResolveOption) (*did.DocResolution, error) Create(method string, did *did.Doc, opts ...DIDMethodOption) (*did.DocResolution, error) + Update(did *did.Doc, opts ...DIDMethodOption) error + Deactivate(did string, opts ...DIDMethodOption) error Close() error } // VDR verifiable data registry interface. +// TODO https://github.com/hyperledger/aries-framework-go/issues/2475 type VDR interface { Read(did string, opts ...ResolveOption) (*did.DocResolution, error) Create(keyManager kms.KeyManager, did *did.Doc, opts ...DIDMethodOption) (*did.DocResolution, error) Accept(method string) bool + Update(did *did.Doc, opts ...DIDMethodOption) error + Deactivate(did string, opts ...DIDMethodOption) error Close() error } diff --git a/pkg/mock/vdr/mock_registry.go b/pkg/mock/vdr/mock_registry.go index 34c8bdd12..d361d64d4 100644 --- a/pkg/mock/vdr/mock_registry.go +++ b/pkg/mock/vdr/mock_registry.go @@ -18,12 +18,14 @@ import ( // MockVDRegistry mock implementation of vdr // to be used only for unit tests. type MockVDRegistry struct { - CreateErr error - CreateValue *did.Doc - CreateFunc func(string, *did.Doc, ...vdrapi.DIDMethodOption) (*did.DocResolution, error) - ResolveErr error - ResolveValue *did.Doc - ResolveFunc func(didID string, opts ...vdrapi.ResolveOption) (*did.DocResolution, error) + CreateErr error + CreateValue *did.Doc + CreateFunc func(string, *did.Doc, ...vdrapi.DIDMethodOption) (*did.DocResolution, error) + UpdateFunc func(didDoc *did.Doc, opts ...vdrapi.DIDMethodOption) error + DeactivateFunc func(did string, opts ...vdrapi.DIDMethodOption) error + ResolveErr error + ResolveValue *did.Doc + ResolveFunc func(didID string, opts ...vdrapi.ResolveOption) (*did.DocResolution, error) } // Create mock implementation of create DID. @@ -62,6 +64,24 @@ func (m *MockVDRegistry) Resolve(didID string, opts ...vdrapi.ResolveOption) (*d return &did.DocResolution{DIDDocument: m.ResolveValue}, nil } +// Update did. +func (m *MockVDRegistry) Update(didDoc *did.Doc, opts ...vdrapi.DIDMethodOption) error { + if m.UpdateFunc != nil { + return m.UpdateFunc(didDoc, opts...) + } + + return nil +} + +// Deactivate did. +func (m *MockVDRegistry) Deactivate(didID string, opts ...vdrapi.DIDMethodOption) error { + if m.DeactivateFunc != nil { + return m.DeactivateFunc(didID, opts...) + } + + return nil +} + // Close frees resources being maintained by vdr. func (m *MockVDRegistry) Close() error { return nil diff --git a/pkg/mock/vdr/mock_vdr.go b/pkg/mock/vdr/mock_vdr.go index 1b2d47a12..d4f41bf23 100644 --- a/pkg/mock/vdr/mock_vdr.go +++ b/pkg/mock/vdr/mock_vdr.go @@ -18,8 +18,11 @@ type MockVDR struct { AcceptValue bool StoreErr error ReadFunc func(didID string, opts ...vdrapi.ResolveOption) (*did.DocResolution, error) - CreateFunc func(keyManager kms.KeyManager, did *did.Doc, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) - CloseErr error + CreateFunc func(keyManager kms.KeyManager, did *did.Doc, + opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) + UpdateFunc func(didDoc *did.Doc, opts ...vdrapi.DIDMethodOption) error + DeactivateFunc func(did string, opts ...vdrapi.DIDMethodOption) error + CloseErr error } // Read did. @@ -41,6 +44,24 @@ func (m *MockVDR) Create(keyManager kms.KeyManager, didDoc *did.Doc, return nil, nil } +// Update did. +func (m *MockVDR) Update(didDoc *did.Doc, opts ...vdrapi.DIDMethodOption) error { + if m.UpdateFunc != nil { + return m.UpdateFunc(didDoc, opts...) + } + + return nil +} + +// Deactivate did. +func (m *MockVDR) Deactivate(didID string, opts ...vdrapi.DIDMethodOption) error { + if m.DeactivateFunc != nil { + return m.DeactivateFunc(didID, opts...) + } + + return nil +} + // Accept did. func (m *MockVDR) Accept(method string) bool { return m.AcceptValue diff --git a/pkg/vdr/httpbinding/vdr.go b/pkg/vdr/httpbinding/vdr.go index 704a48795..9a0bdc421 100644 --- a/pkg/vdr/httpbinding/vdr.go +++ b/pkg/vdr/httpbinding/vdr.go @@ -68,6 +68,16 @@ func (v *VDR) Close() error { return nil } +// Update did doc. +func (v *VDR) Update(didDoc *did.Doc, opts ...vdrapi.DIDMethodOption) error { + return fmt.Errorf("not supported") +} + +// Deactivate did doc. +func (v *VDR) Deactivate(didID string, opts ...vdrapi.DIDMethodOption) error { + return fmt.Errorf("not supported") +} + // Option configures the peer vdr. type Option func(opts *VDR) diff --git a/pkg/vdr/httpbinding/vdr_test.go b/pkg/vdr/httpbinding/vdr_test.go index 884578b81..d2fc1e497 100644 --- a/pkg/vdr/httpbinding/vdr_test.go +++ b/pkg/vdr/httpbinding/vdr_test.go @@ -32,3 +32,25 @@ func TestVDR_Build(t *testing.T) { require.Nil(t, result) }) } + +func TestUpdate(t *testing.T) { + t.Run("test update", func(t *testing.T) { + v, err := New("/did:example:334455") + require.NoError(t, err) + + err = v.Update(nil) + require.Error(t, err) + require.Contains(t, err.Error(), "not supported") + }) +} + +func TestDeactivate(t *testing.T) { + t.Run("test deactivate", func(t *testing.T) { + v, err := New("/did:example:334455") + require.NoError(t, err) + + err = v.Deactivate("") + require.Error(t, err) + require.Contains(t, err.Error(), "not supported") + }) +} diff --git a/pkg/vdr/key/vdr.go b/pkg/vdr/key/vdr.go index 703068aeb..5cbde3c10 100644 --- a/pkg/vdr/key/vdr.go +++ b/pkg/vdr/key/vdr.go @@ -6,6 +6,13 @@ SPDX-License-Identifier: Apache-2.0 package key +import ( + "fmt" + + diddoc "github.com/hyperledger/aries-framework-go/pkg/doc/did" + vdrapi "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr" +) + const ( // DIDMethod did method. @@ -32,3 +39,13 @@ func (v *VDR) Accept(method string) bool { func (v *VDR) Close() error { return nil } + +// Update did doc. +func (v *VDR) Update(didDoc *diddoc.Doc, opts ...vdrapi.DIDMethodOption) error { + return fmt.Errorf("not supported") +} + +// Deactivate did doc. +func (v *VDR) Deactivate(didID string, opts ...vdrapi.DIDMethodOption) error { + return fmt.Errorf("not supported") +} diff --git a/pkg/vdr/key/vdr_test.go b/pkg/vdr/key/vdr_test.go index ff4d0ed5c..9b5b166e5 100644 --- a/pkg/vdr/key/vdr_test.go +++ b/pkg/vdr/key/vdr_test.go @@ -34,6 +34,24 @@ func TestAccept(t *testing.T) { }) } +func TestUpdate(t *testing.T) { + t.Run("test update", func(t *testing.T) { + v := New() + err := v.Update(nil) + require.Error(t, err) + require.Contains(t, err.Error(), "not supported") + }) +} + +func TestDeactivate(t *testing.T) { + t.Run("test deactivate", func(t *testing.T) { + v := New() + err := v.Deactivate("") + require.Error(t, err) + require.Contains(t, err.Error(), "not supported") + }) +} + func TestClose(t *testing.T) { t.Run("test success", func(t *testing.T) { v := New() diff --git a/pkg/vdr/peer/vdr.go b/pkg/vdr/peer/vdr.go index 67f59ada4..6e385df91 100644 --- a/pkg/vdr/peer/vdr.go +++ b/pkg/vdr/peer/vdr.go @@ -9,6 +9,8 @@ package peer import ( "fmt" + diddoc "github.com/hyperledger/aries-framework-go/pkg/doc/did" + vdrapi "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr" "github.com/hyperledger/aries-framework-go/pkg/storage" ) @@ -36,6 +38,16 @@ func New(s storage.Provider) (*VDR, error) { return &VDR{store: didDBStore}, nil } +// Update did doc. +func (v *VDR) Update(didDoc *diddoc.Doc, opts ...vdrapi.DIDMethodOption) error { + return fmt.Errorf("not supported") +} + +// Deactivate did doc. +func (v *VDR) Deactivate(did string, opts ...vdrapi.DIDMethodOption) error { + return fmt.Errorf("not supported") +} + // Accept did method. func (v *VDR) Accept(method string) bool { return method == DIDMethod diff --git a/pkg/vdr/peer/vdr_test.go b/pkg/vdr/peer/vdr_test.go new file mode 100644 index 000000000..0e34f880f --- /dev/null +++ b/pkg/vdr/peer/vdr_test.go @@ -0,0 +1,37 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package peer + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/hyperledger/aries-framework-go/pkg/mock/storage" +) + +func TestUpdate(t *testing.T) { + t.Run("test update", func(t *testing.T) { + v, err := New(&storage.MockStoreProvider{}) + require.NoError(t, err) + + err = v.Update(nil) + require.Error(t, err) + require.Contains(t, err.Error(), "not supported") + }) +} + +func TestDeactivate(t *testing.T) { + t.Run("test deactivate", func(t *testing.T) { + v, err := New(&storage.MockStoreProvider{}) + require.NoError(t, err) + + err = v.Deactivate("") + require.Error(t, err) + require.Contains(t, err.Error(), "not supported") + }) +} diff --git a/pkg/vdr/registry.go b/pkg/vdr/registry.go index 3349f579d..7a574099e 100644 --- a/pkg/vdr/registry.go +++ b/pkg/vdr/registry.go @@ -71,6 +71,38 @@ func (r *Registry) Resolve(did string, opts ...vdrapi.ResolveOption) (*diddoc.Do return didDocResolution, nil } +// Update did document. +func (r *Registry) Update(didDoc *diddoc.Doc, opts ...vdrapi.DIDMethodOption) error { + didMethod, err := GetDidMethod(didDoc.ID) + if err != nil { + return err + } + + // resolve did method + method, err := r.resolveVDR(didMethod) + if err != nil { + return err + } + + return method.Update(didDoc, opts...) +} + +// Deactivate did document. +func (r *Registry) Deactivate(did string, opts ...vdrapi.DIDMethodOption) error { + didMethod, err := GetDidMethod(did) + if err != nil { + return err + } + + // resolve did method + method, err := r.resolveVDR(didMethod) + if err != nil { + return err + } + + return method.Deactivate(did, opts...) +} + // Create a new DID Document and store it in this registry. func (r *Registry) Create(didMethod string, did *diddoc.Doc, opts ...vdrapi.DIDMethodOption) (*diddoc.DocResolution, error) { diff --git a/pkg/vdr/registry_test.go b/pkg/vdr/registry_test.go index a770bdcea..a4e4bf5d7 100644 --- a/pkg/vdr/registry_test.go +++ b/pkg/vdr/registry_test.go @@ -115,6 +115,108 @@ func TestRegistry_Resolve(t *testing.T) { }) } +func TestRegistry_Update(t *testing.T) { + t.Run("test invalid did input", func(t *testing.T) { + registry := New(&mockprovider.Provider{}) + err := registry.Update(&did.Doc{ID: "id"}) + require.Error(t, err) + require.Contains(t, err.Error(), "wrong format did input") + }) + + t.Run("test did method not supported", func(t *testing.T) { + registry := New(&mockprovider.Provider{}, WithVDR(&mockvdr.MockVDR{AcceptValue: false})) + err := registry.Update(&did.Doc{ID: "1:id:123"}) + require.Error(t, err) + require.Contains(t, err.Error(), "did method id not supported for vdr") + }) + + t.Run("test error from update did", func(t *testing.T) { + registry := New(&mockprovider.Provider{}, WithVDR(&mockvdr.MockVDR{ + AcceptValue: true, UpdateFunc: func(didDoc *did.Doc, opts ...vdrapi.DIDMethodOption) error { + return fmt.Errorf("update error") + }, + })) + err := registry.Update(&did.Doc{ID: "1:id:123"}) + require.Error(t, err) + require.Contains(t, err.Error(), "update error") + }) + + t.Run("test opts passed", func(t *testing.T) { + registry := New(&mockprovider.Provider{}, WithVDR(&mockvdr.MockVDR{ + AcceptValue: true, UpdateFunc: func(didDoc *did.Doc, opts ...vdrapi.DIDMethodOption) error { + didOpts := &vdrapi.DIDMethodOpts{Values: make(map[string]interface{})} + // Apply options + for _, opt := range opts { + opt(didOpts) + } + + require.NotNil(t, didOpts.Values["k1"]) + return nil + }, + })) + + err := registry.Update(&did.Doc{ID: "1:id:123"}, vdrapi.WithOption("k1", "v1")) + require.NoError(t, err) + }) + + t.Run("test success", func(t *testing.T) { + registry := New(&mockprovider.Provider{}, WithVDR(&mockvdr.MockVDR{AcceptValue: true})) + err := registry.Update(&did.Doc{ID: "1:id:123"}) + require.NoError(t, err) + }) +} + +func TestRegistry_Deactivate(t *testing.T) { + t.Run("test invalid did input", func(t *testing.T) { + registry := New(&mockprovider.Provider{}) + err := registry.Deactivate("id") + require.Error(t, err) + require.Contains(t, err.Error(), "wrong format did input") + }) + + t.Run("test did method not supported", func(t *testing.T) { + registry := New(&mockprovider.Provider{}, WithVDR(&mockvdr.MockVDR{AcceptValue: false})) + err := registry.Deactivate("1:id:123") + require.Error(t, err) + require.Contains(t, err.Error(), "did method id not supported for vdr") + }) + + t.Run("test error from deactivate did", func(t *testing.T) { + registry := New(&mockprovider.Provider{}, WithVDR(&mockvdr.MockVDR{ + AcceptValue: true, DeactivateFunc: func(didID string, opts ...vdrapi.DIDMethodOption) error { + return fmt.Errorf("deactivate error") + }, + })) + err := registry.Deactivate("1:id:123") + require.Error(t, err) + require.Contains(t, err.Error(), "deactivate error") + }) + + t.Run("test opts passed", func(t *testing.T) { + registry := New(&mockprovider.Provider{}, WithVDR(&mockvdr.MockVDR{ + AcceptValue: true, DeactivateFunc: func(didID string, opts ...vdrapi.DIDMethodOption) error { + didOpts := &vdrapi.DIDMethodOpts{Values: make(map[string]interface{})} + // Apply options + for _, opt := range opts { + opt(didOpts) + } + + require.NotNil(t, didOpts.Values["k1"]) + return nil + }, + })) + + err := registry.Deactivate("1:id:123", vdrapi.WithOption("k1", "v1")) + require.NoError(t, err) + }) + + t.Run("test success", func(t *testing.T) { + registry := New(&mockprovider.Provider{}, WithVDR(&mockvdr.MockVDR{AcceptValue: true})) + err := registry.Deactivate("1:id:123") + require.NoError(t, err) + }) +} + func TestRegistry_Create(t *testing.T) { t.Run("test did method not supported", func(t *testing.T) { registry := New(&mockprovider.Provider{KMSValue: &mockkms.KeyManager{}}, diff --git a/pkg/vdr/web/vdr.go b/pkg/vdr/web/vdr.go index 2b91c4266..fda05b326 100644 --- a/pkg/vdr/web/vdr.go +++ b/pkg/vdr/web/vdr.go @@ -6,6 +6,13 @@ SPDX-License-Identifier: Apache-2.0 package web +import ( + "fmt" + + diddoc "github.com/hyperledger/aries-framework-go/pkg/doc/did" + vdrapi "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr" +) + const ( namespace = "web" ) @@ -23,6 +30,16 @@ func (v *VDR) Accept(method string) bool { return method == namespace } +// Update did doc. +func (v *VDR) Update(didDoc *diddoc.Doc, opts ...vdrapi.DIDMethodOption) error { + return fmt.Errorf("not supported") +} + +// Deactivate did doc. +func (v *VDR) Deactivate(did string, opts ...vdrapi.DIDMethodOption) error { + return fmt.Errorf("not supported") +} + // Close method of the VDR interface. func (v *VDR) Close() error { return nil diff --git a/pkg/vdr/web/vdr_test.go b/pkg/vdr/web/vdr_test.go index 3423a8f7e..24ccaca76 100644 --- a/pkg/vdr/web/vdr_test.go +++ b/pkg/vdr/web/vdr_test.go @@ -21,3 +21,21 @@ func TestVDRMethods(t *testing.T) { require.Nil(t, err) }) } + +func TestUpdate(t *testing.T) { + t.Run("test update", func(t *testing.T) { + v := New() + err := v.Update(nil) + require.Error(t, err) + require.Contains(t, err.Error(), "not supported") + }) +} + +func TestDeactivate(t *testing.T) { + t.Run("test deactivate", func(t *testing.T) { + v := New() + err := v.Deactivate("") + require.Error(t, err) + require.Contains(t, err.Error(), "not supported") + }) +}