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  }