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 }