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

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package wallet
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/google/uuid"
    16  	"github.com/stretchr/testify/require"
    17  
    18  	"github.com/hyperledger/aries-framework-go/component/storage/edv"
    19  	"github.com/hyperledger/aries-framework-go/internal/testdata"
    20  	"github.com/hyperledger/aries-framework-go/pkg/doc/ld"
    21  	vdrapi "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr"
    22  	"github.com/hyperledger/aries-framework-go/pkg/internal/ldtestutil"
    23  	"github.com/hyperledger/aries-framework-go/pkg/kms"
    24  	mockkms "github.com/hyperledger/aries-framework-go/pkg/mock/kms"
    25  	mockstorage "github.com/hyperledger/aries-framework-go/pkg/mock/storage"
    26  	"github.com/hyperledger/aries-framework-go/pkg/mock/vdr"
    27  	"github.com/hyperledger/aries-framework-go/spi/storage"
    28  )
    29  
    30  const (
    31  	sampleContenttErr  = "sample content err"
    32  	sampleContentValid = `{
    33    			"@context": ["https://w3id.org/wallet/v1"],
    34    		  	"id": "did:example:123456789abcdefghi",
    35      		"type": "Person",
    36      		"name": "John Smith",
    37      		"image": "https://via.placeholder.com/150",
    38      		"description" : "Professional software developer for Acme Corp.",
    39      		"tags": ["professional", "person"],
    40      		"correlation": ["4058a72a-9523-11ea-bb37-0242ac130002"]
    41    		}`
    42  	sampleContentNoID = `{
    43    			"@context": ["https://w3id.org/wallet/v1"],
    44      		"type": "Person",
    45      		"name": "John Smith",
    46      		"image": "https://via.placeholder.com/150",
    47      		"description" : "Professional software developer for Acme Corp.",
    48      		"tags": ["professional", "person"],
    49      		"correlation": ["4058a72a-9523-11ea-bb37-0242ac130002"]
    50    		}`
    51  	sampleContentInvalid = `{
    52    			"@context": ["https://w3id.org/wallet/v1"],
    53      		"type": "Person",
    54      		"name": "John Smith",
    55      		"image": "https://via.placeholder.com/150",
    56      		"description" : "Professional software developer for Acme Corp.",
    57      		"tags": ["professional", "person"],
    58      		"correlation": ["4058a72a-9523-11ea-bb37-0242ac130002"]
    59    		}`
    60  	didResolutionResult = `{
    61              "@context": [
    62                  "https://w3id.org/wallet/v1",
    63                  "https://w3id.org/did-resolution/v1"
    64              ],
    65              "id": "did:example:123",
    66              "type": ["DIDResolutionResponse"],
    67              "name": "Farming Sensor DID Document",
    68              "image": "https://via.placeholder.com/150",
    69              "description": "An IoT device in the middle of a corn field.",
    70              "tags": ["professional"],
    71              "correlation": ["4058a72a-9523-11ea-bb37-0242ac130002"],
    72              "created": "2017-06-18T21:19:10Z",
    73              "expires": "2026-06-18T21:19:10Z",
    74              "didDocument": {
    75                  "@context": [
    76                      "https://www.w3.org/ns/did/v1",
    77                      {
    78                          "@base": "did:key:z6Mks8mvCnVx4HQcoq7ZwvpTbMnoRGudHSiEpXhMf6VW8XMg"
    79                      }
    80                  ],
    81                  "id": "did:key:z6Mks8mvCnVx4HQcoq7ZwvpTbMnoRGudHSiEpXhMf6VW8XMg",
    82                  "verificationMethod": [
    83                      {
    84                          "id": "#z6Mks8mvCnVx4HQcoq7ZwvpTbMnoRGudHSiEpXhMf6VW8XMg",
    85                          "type": "JsonWebKey2020",
    86                          "controller": "did:key:z6Mks8mvCnVx4HQcoq7ZwvpTbMnoRGudHSiEpXhMf6VW8XMg",
    87                          "publicKeyJwk": {
    88                              "crv": "Ed25519",
    89                              "x": "vGur-MEOrN6GDLf4TBGHDYAERxkmWOjTbztvG3xP0I8",
    90                              "kty": "OKP"
    91                          }
    92                      },
    93                      {
    94                          "id": "#z6LScrLMVd9jvbphPeQkGffSeB99EWSYqAnMg8rGiHCgz5ha",
    95                          "type": "JsonWebKey2020",
    96                          "controller": "did:key:z6Mks8mvCnVx4HQcoq7ZwvpTbMnoRGudHSiEpXhMf6VW8XMg",
    97                          "publicKeyJwk": {
    98                              "kty": "OKP",
    99                              "crv": "X25519",
   100                              "x": "EXXinkMxdA4zGmwpOOpbCXt6Ts6CwyXyEKI3jfHkS3k"
   101                          }
   102                      }
   103                  ],
   104                  "authentication": [
   105                      "#z6Mks8mvCnVx4HQcoq7ZwvpTbMnoRGudHSiEpXhMf6VW8XMg"
   106                  ],
   107                  "assertionMethod": [
   108                      "#z6Mks8mvCnVx4HQcoq7ZwvpTbMnoRGudHSiEpXhMf6VW8XMg"
   109                  ],
   110                  "capabilityInvocation": [
   111                      "#z6Mks8mvCnVx4HQcoq7ZwvpTbMnoRGudHSiEpXhMf6VW8XMg"
   112                  ],
   113                  "capabilityDelegation": [
   114                      "#z6Mks8mvCnVx4HQcoq7ZwvpTbMnoRGudHSiEpXhMf6VW8XMg"
   115                  ],
   116                  "keyAgreement": [
   117                      "#z6LScrLMVd9jvbphPeQkGffSeB99EWSYqAnMg8rGiHCgz5ha"
   118                  ]
   119              },
   120              "didDocumentMetadata": {
   121                  "content-type": "application/did+json"
   122              },
   123              "didResolutionMetadata": {}
   124          }`
   125  	sampleKeyContentBase58Valid = `{
   126    			"@context": ["https://w3id.org/wallet/v1"],
   127    		  	"id": "did:example:123456789abcdefghi#key-1",  		  	
   128  			"type": "Ed25519VerificationKey2018",
   129  			"privateKeyBase58":"zJRjGFZydU5DBdS2p5qbiUzDFAxbXTkjiDuGPksMBbY5TNyEsGfK4a4WGKjBCh1zeNryeuKtPotp8W1ESnwP71y"
   130    		}`
   131  	sampleKeyContentBase58WithInvalidField = `{
   132    			"@context": ["https://w3id.org/wallet/v1"],
   133    		  	"id": "did:example:123456789abcdefghi#key-1",
   134  			"controller": "did:example:123456789abcdefghi",
   135  			"type": "Ed25519VerificationKey2018",
   136  			"privateKeyBase58":"zJRjGFZydU5DBdS2p5qbiUzDFAxbXTkjiDuGPksMBbY5TNyEsGfK4a4WGKjBCh1zeNryeuKtPotp8W1ESnwP71y"
   137    		}`
   138  	sampleKeyContentJwkValid = `{
   139    			"@context": ["https://w3id.org/wallet/v1"],
   140    		  	"id": "did:example:123456789abcdefghi#z6MkiEh8RQL83nkPo8ehDeX7",  		  	
   141  			"type": "Ed25519VerificationKey2018",
   142  			"privateKeyJwk": {
   143  				"kty": "OKP",
   144  				"d":"Dq5t2WS3OMzcpkh8AyVxJs5r9v4L39ocIz9CpUOqM40",
   145  				"crv": "Ed25519",
   146  				"x": "ODaPFurJgFcoVCUYEmgOJpWOtPlOYbHSugasscKWqDM",
   147  				"kid":"z6MkiEh8RQL83nkPo8ehDeX7"
   148  			}
   149    		}`
   150  	sampleJWTCredContentValid = "eyJhbGciOiJFZERTQSIsImtpZCI6IiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6M" +
   151  		"TI2MjM3MzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGU" +
   152  		"uZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyNjIzNzM4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2Z" +
   153  		"TEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3c" +
   154  		"udzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFN1YmplY3QiOnsiZGVncmVlIjp7InR5cGUiOiJCY" +
   155  		"WNoZWxvckRlZ3JlZSIsInVuaXZlcnNpdHkiOiJNSVQifSwiaWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjE" +
   156  		"iLCJuYW1lIjoiSmF5ZGVuIERvZSIsInNwb3VzZSI6ImRpZDpleGFtcGxlOmMyNzZlMTJlYzIxZWJmZWIxZjcxMmViYzZmMSJ9LCJpc3N1Z" +
   157  		"XIiOnsibmFtZSI6IkV4YW1wbGUgVW5pdmVyc2l0eSJ9LCJyZWZlcmVuY2VOdW1iZXIiOjguMzI5NDg0N2UrMDcsInR5cGUiOlsiVmVyaWZ" +
   158  		"pYWJsZUNyZWRlbnRpYWwiLCJVbml2ZXJzaXR5RGVncmVlQ3JlZGVudGlhbCJdfX0.a5yKMPmDnEXvM-fG3BaOqfdkqdvU4s2rzeZuOzLmk" +
   159  		"TH1y9sJT-mgTe7map5E9x7abrNVpyYbaH7JaAb9Yhr1DQ"
   160  )
   161  
   162  func TestContentTypes(t *testing.T) {
   163  	t.Run("test content types", func(t *testing.T) {
   164  		tests := []struct {
   165  			name     string
   166  			inputs   []string
   167  			expected []ContentType
   168  			fail     bool
   169  		}{
   170  			{
   171  				name:     "validation success",
   172  				inputs:   []string{"collection", "credential", "didResolutionResponse", "metadata", "connection", "key"},
   173  				expected: []ContentType{Collection, Credential, DIDResolutionResponse, Metadata, Connection, Key},
   174  			},
   175  			{
   176  				name:   "validation error",
   177  				inputs: []string{"collECtion", "CRED", "VC", "DID", ""},
   178  				fail:   true,
   179  			},
   180  		}
   181  
   182  		t.Parallel()
   183  
   184  		for _, test := range tests {
   185  			tc := test
   186  			t.Run(tc.name, func(t *testing.T) {
   187  				for i, input := range tc.inputs {
   188  					ct := ContentType(input)
   189  
   190  					if tc.fail {
   191  						require.Error(t, ct.IsValid())
   192  						return
   193  					}
   194  
   195  					require.NoError(t, ct.IsValid())
   196  					require.Equal(t, tc.expected[i], ct)
   197  					require.Equal(t, ct.Name(), input)
   198  				}
   199  			})
   200  		}
   201  	})
   202  }
   203  
   204  func TestContentStores(t *testing.T) {
   205  	keyMgr := &mockkms.KeyManager{}
   206  
   207  	token, e := sessionManager().createSession(uuid.New().String(), keyMgr, 5*time.Second)
   208  	require.NoError(t, e)
   209  
   210  	t.Run("create new content store - success", func(t *testing.T) {
   211  		sp := getMockStorageProvider()
   212  
   213  		// create new store
   214  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   215  		require.NotEmpty(t, contentStore)
   216  		require.Empty(t, sp.config.TagNames)
   217  
   218  		// open store
   219  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   220  		require.EqualValues(t, sp.config.TagNames,
   221  			[]string{"collection", "credential", "connection", "didResolutionResponse", "connection", "key"})
   222  
   223  		// close store
   224  		require.True(t, contentStore.Close())
   225  		store, err := contentStore.open(token)
   226  		require.Empty(t, store)
   227  		require.True(t, errors.Is(err, ErrWalletLocked))
   228  	})
   229  
   230  	t.Run("create new content store for EDV profile - success", func(t *testing.T) {
   231  		sp := getMockStorageProvider()
   232  
   233  		masterLock, err := getDefaultSecretLock(samplePassPhrase)
   234  		require.NoError(t, err)
   235  
   236  		masterLockCipherText, err := createMasterLock(masterLock)
   237  		require.NoError(t, err)
   238  		require.NotEmpty(t, masterLockCipherText)
   239  
   240  		profileInfo := &profile{
   241  			ID:               uuid.New().String(),
   242  			User:             uuid.New().String(),
   243  			MasterLockCipher: masterLockCipherText,
   244  			EDVConf: &edvConf{
   245  				ServerURL: sampleEDVServerURL,
   246  				VaultID:   sampleEDVVaultID,
   247  			},
   248  		}
   249  
   250  		kmsStore, err := kms.NewAriesProviderWrapper(sp)
   251  		require.NoError(t, err)
   252  
   253  		kmgr, err := keyManager().createKeyManager(profileInfo, kmsStore, &unlockOpts{passphrase: samplePassPhrase})
   254  		require.NotEmpty(t, kmgr)
   255  		require.NoError(t, err)
   256  
   257  		tkn, err := sessionManager().createSession(profileInfo.User, kmgr, 500*time.Millisecond)
   258  
   259  		require.NoError(t, err)
   260  		require.NotEmpty(t, kmgr)
   261  
   262  		err = profileInfo.setupEDVEncryptionKey(kmgr)
   263  		require.NoError(t, err)
   264  
   265  		err = profileInfo.setupEDVMacKey(kmgr)
   266  		require.NoError(t, err)
   267  
   268  		// create new store
   269  		contentStore := newContentStore(sp, createTestDocumentLoader(t), profileInfo)
   270  		require.NotEmpty(t, contentStore)
   271  		require.Empty(t, sp.config.TagNames)
   272  
   273  		// open store
   274  		require.NoError(t, contentStore.Open(kmgr, &unlockOpts{
   275  			edvOpts: []edv.RESTProviderOption{
   276  				edv.WithFullDocumentsReturnedFromQueries(),
   277  				edv.WithBatchEndpointExtension(),
   278  			},
   279  		}))
   280  
   281  		// close store
   282  		require.True(t, contentStore.Close())
   283  		store, err := contentStore.open(tkn)
   284  		require.Empty(t, store)
   285  		require.True(t, errors.Is(err, ErrWalletLocked))
   286  	})
   287  
   288  	t.Run("open store - failure", func(t *testing.T) {
   289  		sp := getMockStorageProvider()
   290  
   291  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   292  
   293  		// open store error
   294  		sp.ErrOpenStoreHandle = errors.New(sampleContenttErr)
   295  		err := contentStore.Open(keyMgr, &unlockOpts{})
   296  		require.Error(t, err)
   297  		require.Contains(t, err.Error(), sampleContenttErr)
   298  		require.Contains(t, err.Error(), "failed to open store")
   299  
   300  		// set store config error
   301  		sp.ErrOpenStoreHandle = nil
   302  		sp.failure = errors.New(sampleContenttErr)
   303  		err = contentStore.Open(keyMgr, &unlockOpts{})
   304  		require.Error(t, err)
   305  		require.Contains(t, err.Error(), sampleContenttErr)
   306  		require.Contains(t, err.Error(), "failed to set store config")
   307  
   308  		sp.ErrOpenStoreHandle = nil
   309  		sp.failure = nil
   310  		sp.Store.ErrClose = errors.New(sampleContenttErr)
   311  		contentStore = newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   312  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   313  
   314  		require.True(t, contentStore.Close())
   315  	})
   316  
   317  	t.Run("save to store - success", func(t *testing.T) {
   318  		sp := getMockStorageProvider()
   319  
   320  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   321  		require.NotEmpty(t, contentStore)
   322  
   323  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   324  
   325  		err := contentStore.Save(token, Collection, []byte(sampleContentValid))
   326  		require.NoError(t, err)
   327  
   328  		// store is open but invalid auth token
   329  		err = contentStore.Save(sampleFakeTkn, Collection, []byte(sampleContentValid))
   330  		require.True(t, errors.Is(err, ErrInvalidAuthToken))
   331  
   332  		err = contentStore.Save(sampleFakeTkn,
   333  			Credential, testdata.SampleUDCVC, AddByCollection("test"))
   334  		require.True(t, errors.Is(err, ErrInvalidAuthToken))
   335  	})
   336  
   337  	t.Run("save content to store without ID - success", func(t *testing.T) {
   338  		sp := getMockStorageProvider()
   339  
   340  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   341  		require.NotEmpty(t, contentStore)
   342  
   343  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   344  
   345  		err := contentStore.Save(token, Collection, []byte(sampleContentNoID))
   346  		require.NoError(t, err)
   347  	})
   348  
   349  	t.Run("save to doc resolution to store - success", func(t *testing.T) {
   350  		sp := getMockStorageProvider()
   351  
   352  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   353  		require.NotEmpty(t, contentStore)
   354  
   355  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   356  
   357  		err := contentStore.Save(token, DIDResolutionResponse, []byte(didResolutionResult))
   358  		require.NoError(t, err)
   359  
   360  		// get by DID ID
   361  		response, err := contentStore.Get(token,
   362  			"did:key:z6Mks8mvCnVx4HQcoq7ZwvpTbMnoRGudHSiEpXhMf6VW8XMg", DIDResolutionResponse)
   363  		require.NoError(t, err)
   364  		require.NotEmpty(t, response)
   365  		require.Equal(t, string(response), didResolutionResult)
   366  
   367  		// store is open but invalid auth token
   368  		response, err = contentStore.Get(sampleFakeTkn,
   369  			"did:key:z6Mks8mvCnVx4HQcoq7ZwvpTbMnoRGudHSiEpXhMf6VW8XMg", DIDResolutionResponse)
   370  		require.True(t, errors.Is(err, ErrInvalidAuthToken))
   371  		require.Empty(t, response)
   372  	})
   373  
   374  	t.Run("save JWTVC to store - success", func(t *testing.T) {
   375  		sp := getMockStorageProvider()
   376  
   377  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   378  		require.NotEmpty(t, contentStore)
   379  
   380  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   381  
   382  		err := contentStore.Save(token, Credential, []byte(sampleJWTCredContentValid))
   383  		require.NoError(t, err)
   384  	})
   385  
   386  	t.Run("save key to store - success", func(t *testing.T) {
   387  		sp := getMockStorageProvider()
   388  		sampleUser := uuid.New().String()
   389  
   390  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: sampleUser})
   391  		require.NotEmpty(t, contentStore)
   392  
   393  		// wallet locked
   394  		err := contentStore.Save(sampleFakeTkn, Key, []byte(sampleKeyContentBase58Valid))
   395  		require.True(t, errors.Is(err, ErrWalletLocked))
   396  
   397  		err = contentStore.Save(sampleFakeTkn, Key, []byte(sampleKeyContentJwkValid))
   398  		require.True(t, errors.Is(err, ErrWalletLocked))
   399  
   400  		// unlock keymanager
   401  		masterLock, err := getDefaultSecretLock(samplePassPhrase)
   402  		require.NoError(t, err)
   403  
   404  		masterLockCipherText, err := createMasterLock(masterLock)
   405  		require.NoError(t, err)
   406  		require.NotEmpty(t, masterLockCipherText)
   407  
   408  		profileInfo := &profile{
   409  			User:             sampleUser,
   410  			MasterLockCipher: masterLockCipherText,
   411  		}
   412  
   413  		kmsStore, err := kms.NewAriesProviderWrapper(mockstorage.NewMockStoreProvider())
   414  		require.NoError(t, err)
   415  
   416  		kmgr, err := keyManager().createKeyManager(profileInfo, kmsStore,
   417  			&unlockOpts{passphrase: samplePassPhrase})
   418  		require.NotEmpty(t, kmgr)
   419  		require.NoError(t, err)
   420  
   421  		tkn, err := sessionManager().createSession(profileInfo.User, kmgr, 500*time.Millisecond)
   422  
   423  		require.NoError(t, err)
   424  		require.NotEmpty(t, tkn)
   425  
   426  		// import base58 private key
   427  		err = contentStore.Save(tkn, Key, []byte(sampleKeyContentBase58Valid), ValidateContent())
   428  		require.NoError(t, err)
   429  
   430  		// import jwk private key
   431  		err = contentStore.Save(tkn, Key, []byte(sampleKeyContentJwkValid), ValidateContent())
   432  		require.NoError(t, err)
   433  
   434  		// import using invalid auth token
   435  		err = contentStore.Save(tkn+"invalid", Key, []byte(sampleKeyContentBase58Valid))
   436  		require.True(t, errors.Is(err, ErrWalletLocked))
   437  	})
   438  
   439  	t.Run("save key to store - invalid jsonld", func(t *testing.T) {
   440  		sp := getMockStorageProvider()
   441  		sampleUser := uuid.New().String()
   442  
   443  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: sampleUser})
   444  		require.NotEmpty(t, contentStore)
   445  
   446  		// unlock keymanager
   447  		masterLock, err := getDefaultSecretLock(samplePassPhrase)
   448  		require.NoError(t, err)
   449  
   450  		masterLockCipherText, err := createMasterLock(masterLock)
   451  		require.NoError(t, err)
   452  		require.NotEmpty(t, masterLockCipherText)
   453  
   454  		profileInfo := &profile{
   455  			User:             sampleUser,
   456  			MasterLockCipher: masterLockCipherText,
   457  		}
   458  
   459  		kmsStore, err := kms.NewAriesProviderWrapper(mockstorage.NewMockStoreProvider())
   460  		require.NoError(t, err)
   461  
   462  		kmgr, err := keyManager().createKeyManager(profileInfo, kmsStore,
   463  			&unlockOpts{passphrase: samplePassPhrase})
   464  		require.NotEmpty(t, kmgr)
   465  		require.NoError(t, err)
   466  
   467  		tkn, err := sessionManager().createSession(profileInfo.User, kmgr, 500*time.Millisecond)
   468  
   469  		require.NoError(t, err)
   470  		require.NotEmpty(t, tkn)
   471  
   472  		// import base58 private key
   473  		err = contentStore.Save(tkn, Key, []byte(sampleKeyContentBase58WithInvalidField), ValidateContent())
   474  		require.Contains(t, err.Error(), "JSON-LD doc has different structure after compaction")
   475  	})
   476  
   477  	t.Run("save JWTVC to store - failures", func(t *testing.T) {
   478  		sp := getMockStorageProvider()
   479  
   480  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   481  		require.NotEmpty(t, contentStore)
   482  
   483  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   484  
   485  		// assumes bad data is not JWT, fails to parse as JSON
   486  		err := contentStore.Save(token, Credential, []byte("f"))
   487  		require.Error(t, err)
   488  		require.Contains(t, err.Error(), "failed to read content to be saved")
   489  
   490  		// fail to decode payload that isn't base64
   491  		err = contentStore.Save(token, Credential, []byte("!!!!.!!!!.!!!!"))
   492  		require.Error(t, err)
   493  		require.Contains(t, err.Error(), "decode base64 JWT data")
   494  
   495  		// YWJjZGVm is abcdef in base64, so this isn't valid JSON
   496  		err = contentStore.Save(token, Credential, []byte("YWJjZGVm.YWJjZGVm.YWJjZGVm"))
   497  		require.Error(t, err)
   498  		require.Contains(t, err.Error(), "failed to unmarshal JWT data")
   499  
   500  		// e30 is {} in base64, so jwt is empty
   501  		err = contentStore.Save(token, Credential, []byte("e30.e30.signature"))
   502  		require.Error(t, err)
   503  		require.Contains(t, err.Error(), "JWT data has no ID")
   504  	})
   505  
   506  	t.Run("save key to store - failure", func(t *testing.T) {
   507  		sp := getMockStorageProvider()
   508  		sampleUser := uuid.New().String()
   509  
   510  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: sampleUser})
   511  		require.NotEmpty(t, contentStore)
   512  
   513  		// wallet locked
   514  		err := contentStore.Save(token, Key, []byte(""))
   515  		require.Error(t, err)
   516  		require.Contains(t, err.Error(), "failed to read key contents")
   517  	})
   518  
   519  	t.Run("save to doc resolution to store - failure", func(t *testing.T) {
   520  		sp := getMockStorageProvider()
   521  
   522  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   523  		require.NotEmpty(t, contentStore)
   524  
   525  		err := contentStore.Save(token, DIDResolutionResponse, []byte(sampleContentInvalid))
   526  		require.Error(t, err)
   527  		require.Contains(t, err.Error(), "invalid DID resolution response model")
   528  	})
   529  
   530  	t.Run("save to store - failures", func(t *testing.T) {
   531  		sp := getMockStorageProvider()
   532  
   533  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   534  		require.NotEmpty(t, contentStore)
   535  
   536  		// invalid content type
   537  		err := contentStore.Save(token, ContentType("invalid"), []byte(sampleContentValid))
   538  		require.Error(t, err)
   539  		require.Contains(t, err.Error(), "invalid content type 'invalid'")
   540  
   541  		// invalid content
   542  		err = contentStore.Save(token, Credential, []byte("--"))
   543  		require.Error(t, err)
   544  		require.Contains(t, err.Error(), "failed to read content to be saved")
   545  
   546  		// store errors
   547  		sp.Store.ErrPut = errors.New(sampleContenttErr)
   548  
   549  		contentStore = newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   550  		require.NotEmpty(t, contentStore)
   551  
   552  		// wallet locked
   553  		err = contentStore.Save(token, Credential, []byte(sampleContentValid))
   554  		require.True(t, errors.Is(err, ErrWalletLocked))
   555  
   556  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   557  
   558  		err = contentStore.Save(token, Credential, []byte(sampleContentValid))
   559  		require.Error(t, err)
   560  		require.Contains(t, err.Error(), sampleContenttErr)
   561  
   562  		sp.Store.ErrGet = errors.New(sampleContenttErr)
   563  		err = contentStore.Save(token, Credential, []byte(sampleContentValid))
   564  		require.Error(t, err)
   565  		require.Contains(t, err.Error(), sampleContenttErr)
   566  	})
   567  
   568  	t.Run("save to invalid content type - validation", func(t *testing.T) {
   569  		sp := getMockStorageProvider()
   570  
   571  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   572  		require.NotEmpty(t, contentStore)
   573  
   574  		err := contentStore.Save(token, "Test", []byte("{}"))
   575  		require.Error(t, err)
   576  		require.Contains(t, err.Error(), "invalid content type")
   577  	})
   578  
   579  	t.Run("save duplicate items - validation", func(t *testing.T) {
   580  		sp := getMockStorageProvider()
   581  
   582  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   583  		require.NotEmpty(t, contentStore)
   584  
   585  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   586  
   587  		err := contentStore.Save(token, Collection, []byte(sampleContentValid))
   588  		require.NoError(t, err)
   589  
   590  		// save again
   591  		err = contentStore.Save(token, Collection, []byte(sampleContentValid))
   592  		require.Error(t, err)
   593  		require.Contains(t, err.Error(), "content with same type and id already exists in this wallet")
   594  	})
   595  
   596  	t.Run("get from store - success", func(t *testing.T) {
   597  		sp := getMockStorageProvider()
   598  
   599  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   600  		require.NotEmpty(t, contentStore)
   601  
   602  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   603  
   604  		// save
   605  		err := contentStore.Save(token, Collection, []byte(sampleContentValid))
   606  		require.NoError(t, err)
   607  
   608  		// get
   609  		content, err := contentStore.Get(token, "did:example:123456789abcdefghi", Collection)
   610  		require.NoError(t, err)
   611  		require.Equal(t, sampleContentValid, string(content))
   612  	})
   613  
   614  	t.Run("get from store - failure", func(t *testing.T) {
   615  		sp := getMockStorageProvider()
   616  		sp.Store.ErrGet = errors.New(sampleContenttErr)
   617  
   618  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   619  		require.NotEmpty(t, contentStore)
   620  
   621  		content, err := contentStore.Get(token, "did:example:123456789abcdefghi", Collection)
   622  		require.Empty(t, content)
   623  		require.True(t, errors.Is(err, ErrWalletLocked))
   624  
   625  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   626  
   627  		// get
   628  		content, err = contentStore.Get(token, "did:example:123456789abcdefghi", Collection)
   629  		require.Empty(t, content)
   630  		require.Error(t, err)
   631  		require.Contains(t, err.Error(), sampleContenttErr)
   632  	})
   633  
   634  	t.Run("remove from store - success", func(t *testing.T) {
   635  		sp := getMockStorageProvider()
   636  
   637  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   638  		require.NotEmpty(t, contentStore)
   639  
   640  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   641  
   642  		// save
   643  		err := contentStore.Save(token, Collection, []byte(sampleContentValid))
   644  		require.NoError(t, err)
   645  
   646  		// get
   647  		content, err := contentStore.Get(token, "did:example:123456789abcdefghi", Collection)
   648  		require.NoError(t, err)
   649  		require.Equal(t, sampleContentValid, string(content))
   650  
   651  		// remove
   652  		err = contentStore.Remove(token, "did:example:123456789abcdefghi", Collection)
   653  		require.NoError(t, err)
   654  
   655  		// get
   656  		content, err = contentStore.Get(token, "did:example:123456789abcdefghi", Collection)
   657  		require.Empty(t, content)
   658  		require.Error(t, err)
   659  		require.True(t, errors.Is(err, storage.ErrDataNotFound))
   660  	})
   661  
   662  	t.Run("remove from store - failure", func(t *testing.T) {
   663  		sp := getMockStorageProvider()
   664  		sp.Store.ErrDelete = errors.New(sampleContenttErr)
   665  
   666  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   667  		require.NotEmpty(t, contentStore)
   668  
   669  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   670  
   671  		// save
   672  		err := contentStore.Save(token, Collection, []byte(sampleContentValid))
   673  		require.NoError(t, err)
   674  
   675  		// remove
   676  		err = contentStore.Remove(token, "did:example:123456789abcdefghi", Collection)
   677  		require.Error(t, err)
   678  		require.Contains(t, err.Error(), sampleContenttErr)
   679  
   680  		require.True(t, contentStore.Close())
   681  		err = contentStore.Remove(token, "did:example:123456789abcdefghi", Collection)
   682  		require.True(t, errors.Is(err, ErrWalletLocked))
   683  	})
   684  }
   685  
   686  func TestContentStore_GetAll(t *testing.T) {
   687  	const vcContent = `{
   688        "@context": [
   689          "https://www.w3.org/2018/credentials/v1",
   690          "https://www.w3.org/2018/credentials/examples/v1"
   691        ],
   692        "credentialSchema": [],
   693        "credentialSubject": {
   694          "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   695          "name": "Jayden Doe"
   696        },
   697        "id": "%s",
   698        "issuanceDate": "2010-01-01T19:23:24Z",
   699        "issuer": {
   700          "id": "did:example:76e12ec712ebc6f1c221ebfeb1f",
   701          "name": "Example University"
   702        },
   703        "type": [
   704          "VerifiableCredential",
   705          "UniversityDegreeCredential"
   706        ]
   707      }`
   708  
   709  	const testMetadata = `{
   710    			"@context": ["https://w3id.org/wallet/v1"],
   711    		  	"id": "%s",
   712      		"type": "Person",
   713      		"name": "John Smith",
   714      		"image": "https://via.placeholder.com/150",
   715      		"description" : "Professional software developer for Acme Corp."
   716    		}`
   717  
   718  	keyMgr := &mockkms.KeyManager{}
   719  
   720  	token, err := sessionManager().createSession(uuid.New().String(), keyMgr, 500*time.Millisecond)
   721  	require.NoError(t, err)
   722  
   723  	t.Run("get all content from store for credential type - success", func(t *testing.T) {
   724  		sp := getMockStorageProvider()
   725  
   726  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   727  		require.NotEmpty(t, contentStore)
   728  
   729  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   730  
   731  		// save test data
   732  		const count = 5
   733  
   734  		for i := 0; i < count; i++ {
   735  			require.NoError(t, contentStore.Save(token,
   736  				Credential, []byte(fmt.Sprintf(vcContent, uuid.New().String()))))
   737  			require.NoError(t, contentStore.Save(token,
   738  				Metadata, []byte(fmt.Sprintf(testMetadata, uuid.New().String()))))
   739  		}
   740  
   741  		allVcs, err := contentStore.GetAll(token, Credential)
   742  		require.NoError(t, err)
   743  		require.Len(t, allVcs, count)
   744  
   745  		allMetadata, err := contentStore.GetAll(token, Metadata)
   746  		require.NoError(t, err)
   747  		require.Len(t, allMetadata, count)
   748  
   749  		allDIDs, err := contentStore.GetAll(token, DIDResolutionResponse)
   750  		require.NoError(t, err)
   751  		require.Empty(t, allDIDs)
   752  
   753  		// store is open but invalid auth token
   754  		allMetadata, err = contentStore.GetAll(sampleFakeTkn, DIDResolutionResponse)
   755  		require.True(t, errors.Is(err, ErrInvalidAuthToken))
   756  		require.Empty(t, allMetadata)
   757  	})
   758  
   759  	t.Run("get all content from store for credential type - errors", func(t *testing.T) {
   760  		sp := getMockStorageProvider()
   761  
   762  		// wallet locked
   763  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   764  
   765  		allVcs, err := contentStore.GetAll(token, Credential)
   766  		require.True(t, errors.Is(err, ErrWalletLocked))
   767  		require.Empty(t, allVcs)
   768  
   769  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   770  		require.NoError(t, contentStore.Save(token, Credential, []byte(fmt.Sprintf(vcContent, uuid.New().String()))))
   771  
   772  		// iterator value error
   773  		sp.MockStoreProvider.Store.ErrValue = errors.New(sampleContenttErr + uuid.New().String())
   774  
   775  		allVcs, err = contentStore.GetAll(token, Credential)
   776  		require.True(t, errors.Is(err, sp.MockStoreProvider.Store.ErrValue))
   777  		require.Empty(t, allVcs)
   778  
   779  		// iterator value error
   780  		sp.MockStoreProvider.Store.ErrKey = errors.New(sampleContenttErr + uuid.New().String())
   781  
   782  		contentStore = newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   783  		require.NotEmpty(t, contentStore)
   784  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   785  
   786  		allVcs, err = contentStore.GetAll(token, Credential)
   787  		require.True(t, errors.Is(err, sp.MockStoreProvider.Store.ErrKey))
   788  		require.Empty(t, allVcs)
   789  
   790  		// iterator next error
   791  		sp.MockStoreProvider.Store.ErrNext = errors.New(sampleContenttErr + uuid.New().String())
   792  
   793  		contentStore = newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   794  		require.NotEmpty(t, contentStore)
   795  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   796  
   797  		require.NoError(t, contentStore.Save(token, Credential, []byte(fmt.Sprintf(vcContent, uuid.New().String()))))
   798  
   799  		allVcs, err = contentStore.GetAll(token, Credential)
   800  		require.True(t, errors.Is(err, sp.MockStoreProvider.Store.ErrNext))
   801  		require.Empty(t, allVcs)
   802  
   803  		// iterator next error
   804  		sp.MockStoreProvider.Store.ErrQuery = errors.New(sampleContenttErr + uuid.New().String())
   805  
   806  		contentStore = newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   807  		require.NotEmpty(t, contentStore)
   808  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   809  
   810  		allVcs, err = contentStore.GetAll(token, Credential)
   811  		require.True(t, errors.Is(err, sp.MockStoreProvider.Store.ErrQuery))
   812  		require.Empty(t, allVcs)
   813  	})
   814  }
   815  
   816  func TestContentDIDResolver(t *testing.T) {
   817  	keyMgr := &mockkms.KeyManager{}
   818  
   819  	token, err := sessionManager().createSession(uuid.New().String(), keyMgr, 500*time.Millisecond)
   820  	require.NoError(t, err)
   821  
   822  	t.Run("create new content store - success", func(t *testing.T) {
   823  		sp := getMockStorageProvider()
   824  
   825  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   826  		require.NotEmpty(t, contentStore)
   827  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   828  
   829  		// save custom DID
   830  		err := contentStore.Save(token, DIDResolutionResponse, testdata.SampleDocResolutionResponse)
   831  		require.NoError(t, err)
   832  
   833  		contentVDR := newContentBasedVDR(token, &vdr.MockVDRegistry{}, contentStore)
   834  		require.NotEmpty(t, contentVDR)
   835  
   836  		didDoc, err := contentVDR.Resolve("did:key:z6MknC1wwS6DEYwtGbZZo2QvjQjkh2qSBjb4GYmbye8dv4S5")
   837  		require.NoError(t, err)
   838  		require.NotEmpty(t, didDoc)
   839  		require.Equal(t, "did:key:z6MknC1wwS6DEYwtGbZZo2QvjQjkh2qSBjb4GYmbye8dv4S5", didDoc.DIDDocument.ID)
   840  		require.NotEmpty(t, didDoc.DIDDocument.Authentication)
   841  
   842  		didDoc, err = contentVDR.Resolve("did:key:invalid")
   843  		require.Error(t, err)
   844  		require.Equal(t, vdrapi.ErrNotFound, err)
   845  		require.Empty(t, didDoc)
   846  	})
   847  
   848  	t.Run("create new content store - errors", func(t *testing.T) {
   849  		sp := getMockStorageProvider()
   850  
   851  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   852  		require.NotEmpty(t, contentStore)
   853  
   854  		contentVDR := newContentBasedVDR(token, &vdr.MockVDRegistry{}, contentStore)
   855  		require.NotEmpty(t, contentVDR)
   856  
   857  		// wallet locked
   858  		didDoc, err := contentVDR.Resolve("did:key:invalid")
   859  		require.True(t, errors.Is(err, ErrWalletLocked))
   860  		require.Empty(t, didDoc)
   861  
   862  		// open store
   863  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   864  
   865  		// DID not found
   866  		didDoc, err = contentVDR.Resolve("did:key:invalid")
   867  		require.Error(t, err)
   868  		require.Equal(t, vdrapi.ErrNotFound, err)
   869  		require.Empty(t, didDoc)
   870  
   871  		// parse error
   872  		st, err := contentStore.open(token)
   873  		require.NoError(t, err)
   874  		err = st.Put(getContentKeyPrefix(DIDResolutionResponse,
   875  			"did:key:z6MknC1wwS6DEYwtGbZZo2QvjQjkh2qSBjb4GYmbye8dv4S5"), []byte(sampleInvalidDIDContent))
   876  		require.NoError(t, err)
   877  
   878  		didDoc, err = contentVDR.Resolve("did:key:z6MknC1wwS6DEYwtGbZZo2QvjQjkh2qSBjb4GYmbye8dv4S5")
   879  		require.Error(t, err)
   880  		require.Contains(t, err.Error(), "failed to parse stored DID")
   881  		require.Empty(t, didDoc)
   882  	})
   883  }
   884  
   885  func TestContentStore_Collections(t *testing.T) {
   886  	const vcContent = `{
   887        "@context": [
   888          "https://www.w3.org/2018/credentials/v1",
   889          "https://www.w3.org/2018/credentials/examples/v1"
   890        ],
   891        "credentialSchema": [],
   892        "credentialSubject": {
   893          "id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
   894          "name": "Jayden Doe"
   895        },
   896        "id": "%s",
   897        "issuanceDate": "2010-01-01T19:23:24Z",
   898        "issuer": {
   899          "id": "did:example:76e12ec712ebc6f1c221ebfeb1f",
   900          "name": "Example University"
   901        },
   902        "type": [
   903          "VerifiableCredential",
   904          "UniversityDegreeCredential"
   905        ]
   906      }`
   907  
   908  	const testMetadata = `{
   909    			"@context": ["https://w3id.org/wallet/v1"],
   910    		  	"id": "%s",
   911      		"type": "Person",
   912      		"name": "John Smith",
   913      		"image": "https://via.placeholder.com/150",
   914      		"description" : "Professional software developer for Acme Corp."
   915    		}`
   916  
   917  	const connection = `{
   918                      "@context": ["https://w3id.org/wallet/v1"],
   919                      "id": "%s",
   920                      "name": "My Health Record Certifier",
   921                      "image": "https://via.placeholder.com/150",
   922                      "description" : "The identifier that issues health record credentials.",
   923                      "tags": ["professional"],
   924                      "correlation": ["4058a72a-9523-11ea-bb37-0242ac130002"],
   925                      "type": "Connection"
   926                  }`
   927  
   928  	const orgCollection = `{
   929                      "@context": ["https://w3id.org/wallet/v1"],
   930                      "id": "did:example:acme123456789abcdefghi",
   931                      "type": "Organization",
   932                      "name": "Acme Corp.",
   933                      "image": "https://via.placeholder.com/150",
   934                      "description" : "A software company.",
   935                      "tags": ["professional", "organization"],
   936                      "correlation": ["4058a72a-9523-11ea-bb37-0242ac130002"]
   937                  }`
   938  
   939  	const collectionID = "did:example:acme123456789abcdefghi"
   940  
   941  	keyMgr := &mockkms.KeyManager{}
   942  
   943  	token, err := sessionManager().createSession(uuid.New().String(), keyMgr, 500*time.Millisecond)
   944  	require.NoError(t, err)
   945  
   946  	t.Run("contents by collection - success", func(t *testing.T) {
   947  		sp := getMockStorageProvider()
   948  
   949  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
   950  		require.NotEmpty(t, contentStore)
   951  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
   952  
   953  		// save a collection
   954  		require.NoError(t, contentStore.Save(token, Collection, []byte(orgCollection)))
   955  
   956  		const addedWithoutCollection = 4
   957  		const addedToCollection = 3
   958  
   959  		// save test data
   960  		for i := 0; i < addedToCollection; i++ {
   961  			require.NoError(t, contentStore.Save(token,
   962  				Credential, []byte(fmt.Sprintf(vcContent, uuid.New().String())), AddByCollection(collectionID)))
   963  			require.NoError(t, contentStore.Save(token,
   964  				Metadata, []byte(fmt.Sprintf(testMetadata, uuid.New().String())), AddByCollection(collectionID)))
   965  		}
   966  
   967  		require.NoError(t, contentStore.Save(token,
   968  			DIDResolutionResponse, []byte(didResolutionResult), AddByCollection(collectionID)))
   969  
   970  		for i := 0; i < addedWithoutCollection; i++ {
   971  			require.NoError(t, contentStore.Save(token,
   972  				Credential, []byte(fmt.Sprintf(vcContent, uuid.New().String()))))
   973  			require.NoError(t, contentStore.Save(token,
   974  				Metadata, []byte(fmt.Sprintf(testMetadata, uuid.New().String()))))
   975  			require.NoError(t, contentStore.Save(token,
   976  				Connection, []byte(fmt.Sprintf(connection, uuid.New().String()))))
   977  		}
   978  
   979  		allVcs, err := contentStore.GetAll(token, Credential)
   980  		require.NoError(t, err)
   981  		require.Len(t, allVcs, addedWithoutCollection+addedToCollection)
   982  
   983  		allVcs, err = contentStore.GetAllByCollection(token, collectionID, Credential)
   984  		require.NoError(t, err)
   985  		require.Len(t, allVcs, addedToCollection)
   986  
   987  		allMetadata, err := contentStore.GetAll(token, Metadata)
   988  		require.NoError(t, err)
   989  		require.Len(t, allMetadata, addedWithoutCollection+addedToCollection)
   990  
   991  		allMetadata, err = contentStore.GetAllByCollection(token, collectionID, Metadata)
   992  		require.NoError(t, err)
   993  		require.Len(t, allMetadata, addedToCollection)
   994  
   995  		allDIDs, err := contentStore.GetAll(token, DIDResolutionResponse)
   996  		require.NoError(t, err)
   997  		require.Len(t, allDIDs, 1)
   998  
   999  		allDIDs, err = contentStore.GetAllByCollection(token, collectionID, DIDResolutionResponse)
  1000  		require.NoError(t, err)
  1001  		require.Len(t, allDIDs, 1)
  1002  
  1003  		allConns, err := contentStore.GetAll(token, Connection)
  1004  		require.NoError(t, err)
  1005  		require.Len(t, allConns, addedWithoutCollection)
  1006  
  1007  		allConns, err = contentStore.GetAllByCollection(token, collectionID, Connection)
  1008  		require.NoError(t, err)
  1009  		require.Empty(t, allConns)
  1010  	})
  1011  
  1012  	t.Run("contents by collection - failure", func(t *testing.T) {
  1013  		sp := getMockStorageProvider()
  1014  
  1015  		contentStore := newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
  1016  		require.NotEmpty(t, contentStore)
  1017  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
  1018  
  1019  		err := contentStore.Save(token,
  1020  			DIDResolutionResponse, []byte(didResolutionResult), AddByCollection(collectionID+"invalid"))
  1021  		require.Error(t, err)
  1022  		require.Contains(t, err.Error(), "failed to find existing collection")
  1023  
  1024  		err = contentStore.Save(token,
  1025  			Credential, []byte(fmt.Sprintf(vcContent, uuid.New().String())), AddByCollection(collectionID+"invalid"))
  1026  		require.Error(t, err)
  1027  		require.Contains(t, err.Error(), "failed to find existing collection")
  1028  
  1029  		// save a collection
  1030  		require.NoError(t, contentStore.Save(token, Collection, []byte(orgCollection)))
  1031  		require.NoError(t, contentStore.Save(token, Credential, []byte(fmt.Sprintf(vcContent, uuid.New().String())),
  1032  			AddByCollection(collectionID)))
  1033  
  1034  		// get content error
  1035  		sp.MockStoreProvider.Store.ErrGet = errors.New(sampleContenttErr + uuid.New().String())
  1036  
  1037  		contentStore = newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
  1038  		require.NotEmpty(t, contentStore)
  1039  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
  1040  
  1041  		allVcs, err := contentStore.GetAllByCollection(token, collectionID, Credential)
  1042  		require.True(t, errors.Is(err, sp.MockStoreProvider.Store.ErrGet))
  1043  		require.Empty(t, allVcs)
  1044  
  1045  		// iterator value error
  1046  		sp.MockStoreProvider.Store.ErrValue = errors.New(sampleContenttErr + uuid.New().String())
  1047  
  1048  		contentStore = newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
  1049  		require.NotEmpty(t, contentStore)
  1050  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
  1051  
  1052  		allVcs, err = contentStore.GetAllByCollection(token, collectionID, Credential)
  1053  		require.True(t, errors.Is(err, sp.MockStoreProvider.Store.ErrValue))
  1054  		require.Empty(t, allVcs)
  1055  
  1056  		// iterator value error
  1057  		sp.MockStoreProvider.Store.ErrKey = errors.New(sampleContenttErr + uuid.New().String())
  1058  
  1059  		contentStore = newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
  1060  		require.NotEmpty(t, contentStore)
  1061  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
  1062  
  1063  		allVcs, err = contentStore.GetAllByCollection(token, collectionID, Credential)
  1064  		require.True(t, errors.Is(err, sp.MockStoreProvider.Store.ErrKey))
  1065  		require.Empty(t, allVcs)
  1066  
  1067  		// iterator next error
  1068  		sp.MockStoreProvider.Store.ErrNext = errors.New(sampleContenttErr + uuid.New().String())
  1069  
  1070  		contentStore = newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
  1071  		require.NotEmpty(t, contentStore)
  1072  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
  1073  
  1074  		allVcs, err = contentStore.GetAllByCollection(token, collectionID, Credential)
  1075  		require.True(t, errors.Is(err, sp.MockStoreProvider.Store.ErrNext))
  1076  		require.Empty(t, allVcs)
  1077  
  1078  		// iterator next error
  1079  		sp.MockStoreProvider.Store.ErrQuery = errors.New(sampleContenttErr + uuid.New().String())
  1080  
  1081  		contentStore = newContentStore(sp, createTestDocumentLoader(t), &profile{ID: uuid.New().String()})
  1082  		require.NotEmpty(t, contentStore)
  1083  		require.NoError(t, contentStore.Open(keyMgr, &unlockOpts{}))
  1084  
  1085  		allVcs, err = contentStore.GetAllByCollection(token, collectionID, Credential)
  1086  		require.True(t, errors.Is(err, sp.MockStoreProvider.Store.ErrQuery))
  1087  		require.Empty(t, allVcs)
  1088  
  1089  		// wallet locked error
  1090  		require.True(t, contentStore.Close())
  1091  		allVcs, err = contentStore.GetAllByCollection(token, collectionID, Credential)
  1092  		require.True(t, errors.Is(err, ErrWalletLocked))
  1093  		require.Empty(t, allVcs)
  1094  	})
  1095  }
  1096  
  1097  type mockStorageProvider struct {
  1098  	*mockstorage.MockStoreProvider
  1099  	config  storage.StoreConfiguration
  1100  	failure error
  1101  }
  1102  
  1103  func (s *mockStorageProvider) SetStoreConfig(name string, config storage.StoreConfiguration) error {
  1104  	s.config = config
  1105  
  1106  	return s.failure
  1107  }
  1108  
  1109  func (s *mockStorageProvider) GetStoreConfig(name string) (storage.StoreConfiguration, error) {
  1110  	return s.config, nil
  1111  }
  1112  
  1113  func getMockStorageProvider() *mockStorageProvider {
  1114  	return &mockStorageProvider{MockStoreProvider: mockstorage.NewMockStoreProvider()}
  1115  }
  1116  
  1117  func createTestDocumentLoader(t *testing.T) *ld.DocumentLoader {
  1118  	t.Helper()
  1119  
  1120  	loader, err := ldtestutil.DocumentLoader()
  1121  	require.NoError(t, err)
  1122  
  1123  	return loader
  1124  }