github.com/hyperledger/aries-framework-go@v0.3.2/pkg/store/did/didconnection.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package did 8 9 import ( 10 "encoding/json" 11 "errors" 12 "fmt" 13 14 "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service" 15 diddoc "github.com/hyperledger/aries-framework-go/pkg/doc/did" 16 "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr" 17 "github.com/hyperledger/aries-framework-go/spi/storage" 18 ) 19 20 // StoreName DID connection store name. 21 const StoreName = "didconnection" 22 23 // ErrNotFound signals that the entry for the given DID and key is not present in the store. 24 var ErrNotFound = errors.New("did not found under given key") 25 26 // ConnectionStore provides interface for storing and retrieving DIDs. 27 type ConnectionStore interface { 28 GetDID(key string) (string, error) 29 SaveDID(did string, keys ...string) error 30 SaveDIDFromDoc(doc *diddoc.Doc) error 31 SaveDIDByResolving(did string, keys ...string) error 32 } 33 34 // ConnectionStoreImpl stores DIDs indexed by key. 35 type ConnectionStoreImpl struct { 36 store storage.Store 37 vdr vdr.Registry 38 } 39 40 type didRecord struct { 41 DID string `json:"did,omitempty"` 42 } 43 44 type connectionProvider interface { 45 StorageProvider() storage.Provider 46 VDRegistry() vdr.Registry 47 } 48 49 // NewConnectionStore returns a new ConnectionStore backed by provided storage and VDR. 50 func NewConnectionStore(ctx connectionProvider) (*ConnectionStoreImpl, error) { 51 store, err := ctx.StorageProvider().OpenStore(StoreName) 52 if err != nil { 53 return nil, err 54 } 55 56 return &ConnectionStoreImpl{store: store, vdr: ctx.VDRegistry()}, nil 57 } 58 59 // saveDID saves a DID, indexed using the given public key. 60 func (c *ConnectionStoreImpl) saveDID(did, key string) error { 61 data := didRecord{ 62 DID: did, 63 } 64 65 bytes, err := json.Marshal(data) 66 if err != nil { 67 return err 68 } 69 70 return c.store.Put(key, bytes) 71 } 72 73 // SaveDID saves a DID, indexed using the given public keys. 74 func (c *ConnectionStoreImpl) SaveDID(did string, keys ...string) error { 75 for _, key := range keys { 76 err := c.saveDID(did, key) 77 if err != nil { 78 return fmt.Errorf("saving DID in did map: %w", err) 79 } 80 } 81 82 return nil 83 } 84 85 // SaveDIDFromDoc saves a map from a did doc's keys to the did. 86 func (c *ConnectionStoreImpl) SaveDIDFromDoc(doc *diddoc.Doc) error { 87 var keys []string 88 89 // save recipientKeys from didcomm-enabled service entries 90 // an error is returned only if the doc does not have a valid didcomm service entry, so we ignore it 91 svc, err := service.CreateDestination(doc) 92 if err == nil { 93 keys = append(keys, svc.RecipientKeys...) 94 } else { 95 logger.Debugf("saveDIDFromDoc: CreateDestination of DID Document returned error [%v], no keys will be "+ 96 "linked for this DID '%s' in the connection store", err, doc.ID) 97 } 98 99 return c.SaveDID(doc.ID, keys...) 100 } 101 102 // SaveDIDByResolving resolves a DID using the VDR then saves the map from keys -> did 103 // keys: fallback keys in case the DID can't be resolved 104 func (c *ConnectionStoreImpl) SaveDIDByResolving(did string, keys ...string) error { 105 docResolution, err := c.vdr.Resolve(did) 106 if errors.Is(err, vdr.ErrNotFound) { 107 return c.SaveDID(did, keys...) 108 } else if err != nil { 109 return fmt.Errorf("failed to read from vdr store : %w", err) 110 } 111 112 return c.SaveDIDFromDoc(docResolution.DIDDocument) 113 } 114 115 // GetDID gets the DID stored under the given key. 116 func (c *ConnectionStoreImpl) GetDID(key string) (string, error) { 117 bytes, err := c.store.Get(key) 118 if errors.Is(err, storage.ErrDataNotFound) { 119 return "", ErrNotFound 120 } else if err != nil { 121 return "", err 122 } 123 124 var record didRecord 125 126 err = json.Unmarshal(bytes, &record) 127 if err != nil { 128 return "", err 129 } 130 131 return record.DID, nil 132 }