github.com/hyperledger/aries-framework-go@v0.3.2/pkg/store/did/store.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  SPDX-License-Identifier: Apache-2.0
     4  */
     5  
     6  package did
     7  
     8  import (
     9  	"errors"
    10  	"fmt"
    11  
    12  	"github.com/hyperledger/aries-framework-go/pkg/common/log"
    13  	"github.com/hyperledger/aries-framework-go/pkg/doc/did"
    14  	"github.com/hyperledger/aries-framework-go/spi/storage"
    15  )
    16  
    17  const (
    18  	// NameSpace for did store.
    19  	NameSpace = "didstore"
    20  
    21  	didNameKey        = "didname_"
    22  	didNameKeyPattern = didNameKey + "%s"
    23  )
    24  
    25  var logger = log.New("aries-framework/store/did")
    26  
    27  // Store stores did doc.
    28  type Store struct {
    29  	store storage.Store
    30  }
    31  
    32  type provider interface {
    33  	StorageProvider() storage.Provider
    34  }
    35  
    36  // New returns a new did store.
    37  func New(ctx provider) (*Store, error) {
    38  	store, err := ctx.StorageProvider().OpenStore(NameSpace)
    39  	if err != nil {
    40  		return nil, fmt.Errorf("failed to open did store: %w", err)
    41  	}
    42  
    43  	err = ctx.StorageProvider().SetStoreConfig(NameSpace, storage.StoreConfiguration{TagNames: []string{didNameKey}})
    44  	if err != nil {
    45  		return nil, fmt.Errorf("failed to set store configuration: %w", err)
    46  	}
    47  
    48  	return &Store{store: store}, nil
    49  }
    50  
    51  // SaveDID saves a did doc.
    52  func (s *Store) SaveDID(name string, didDoc *did.Doc) error {
    53  	if name == "" {
    54  		return errors.New("did name is mandatory")
    55  	}
    56  
    57  	id, err := s.GetDIDByName(name)
    58  	if err != nil && !errors.Is(err, storage.ErrDataNotFound) {
    59  		return fmt.Errorf("get did using name : %w", err)
    60  	}
    61  
    62  	if id != "" {
    63  		return errors.New("did name already exists")
    64  	}
    65  
    66  	docBytes, err := didDoc.JSONBytes()
    67  	if err != nil {
    68  		return fmt.Errorf("failed to marshal didDoc: %w", err)
    69  	}
    70  
    71  	if err := s.store.Put(didDoc.ID, docBytes); err != nil {
    72  		return fmt.Errorf("failed to put didDoc: %w", err)
    73  	}
    74  
    75  	if err := s.store.Put(didNameDataKey(name), []byte(didDoc.ID), storage.Tag{Name: didNameKey}); err != nil {
    76  		return fmt.Errorf("store did name to id map : %w", err)
    77  	}
    78  
    79  	return nil
    80  }
    81  
    82  // GetDID retrieves a didDoc based on ID.
    83  func (s *Store) GetDID(id string) (*did.Doc, error) {
    84  	docBytes, err := s.store.Get(id)
    85  	if err != nil {
    86  		return nil, fmt.Errorf("failed to get did doc: %w", err)
    87  	}
    88  
    89  	didDoc, err := did.ParseDocument(docBytes)
    90  	if err != nil {
    91  		return nil, fmt.Errorf("umarshalling didDoc failed: %w", err)
    92  	}
    93  
    94  	return didDoc, nil
    95  }
    96  
    97  // GetDIDByName retrieves did id based on name.
    98  func (s *Store) GetDIDByName(name string) (string, error) {
    99  	idBytes, err := s.store.Get(didNameDataKey(name))
   100  	if err != nil {
   101  		return "", fmt.Errorf("fetch did doc id based on name : %w", err)
   102  	}
   103  
   104  	return string(idBytes), nil
   105  }
   106  
   107  // GetDIDRecords retrieves the didDoc records containing name and didID.
   108  func (s *Store) GetDIDRecords() []*Record {
   109  	itr, err := s.store.Query(didNameKey)
   110  	if err != nil {
   111  		return nil
   112  	}
   113  
   114  	defer func() {
   115  		errClose := itr.Close()
   116  		if errClose != nil {
   117  			logger.Errorf("failed to close iterator: %s", errClose.Error())
   118  		}
   119  	}()
   120  
   121  	var records []*Record
   122  
   123  	more, err := itr.Next()
   124  	if err != nil {
   125  		return nil
   126  	}
   127  
   128  	for more {
   129  		name, err := itr.Key()
   130  		if err != nil {
   131  			return nil
   132  		}
   133  
   134  		id, err := itr.Value()
   135  		if err != nil {
   136  			return nil
   137  		}
   138  
   139  		record := &Record{
   140  			Name: getDIDName(name),
   141  			ID:   string(id),
   142  		}
   143  
   144  		records = append(records, record)
   145  
   146  		more, err = itr.Next()
   147  		if err != nil {
   148  			return nil
   149  		}
   150  	}
   151  
   152  	return records
   153  }
   154  
   155  func didNameDataKey(name string) string {
   156  	return fmt.Sprintf(didNameKeyPattern, name)
   157  }
   158  
   159  func getDIDName(dataKey string) string {
   160  	return dataKey[len(didNameKey):]
   161  }