github.com/hyperledger/aries-framework-go@v0.3.2/pkg/didcomm/protocol/middleware/issuecredential/middlewares_test.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package issuecredential 8 9 import ( 10 "encoding/json" 11 "errors" 12 "fmt" 13 "testing" 14 "time" 15 16 "github.com/golang/mock/gomock" 17 "github.com/stretchr/testify/require" 18 19 "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service" 20 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator" 21 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/issuecredential" 22 "github.com/hyperledger/aries-framework-go/pkg/doc/did" 23 "github.com/hyperledger/aries-framework-go/pkg/doc/util" 24 "github.com/hyperledger/aries-framework-go/pkg/doc/verifiable" 25 mocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/didcomm/protocol/middleware/issuecredential" 26 mockvdr "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/framework/aries/api/vdr" 27 mockstore "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/store/verifiable" 28 "github.com/hyperledger/aries-framework-go/pkg/internal/ldtestutil" 29 ) 30 31 func getCredential() *verifiable.Credential { 32 return &verifiable.Credential{ 33 Context: []string{ 34 "https://www.w3.org/2018/credentials/v1", 35 "https://www.w3.org/2018/credentials/examples/v1", 36 }, 37 ID: "http://example.edu/credentials/1872", 38 Types: []string{ 39 "VerifiableCredential", 40 "UniversityDegreeCredential", 41 }, 42 Subject: struct { 43 ID string 44 }{ID: "SubjectID"}, 45 Issuer: verifiable.Issuer{ 46 ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", 47 CustomFields: verifiable.CustomFields{"name": "Example University"}, 48 }, 49 Issued: util.NewTime(time.Date(2010, time.January, 1, 19, 23, 24, 0, time.UTC)), 50 Schemas: []verifiable.TypedID{}, 51 CustomFields: map[string]interface{}{ 52 "referenceNumber": 83294847, 53 }, 54 } 55 } 56 57 func TestSaveCredentials(t *testing.T) { 58 ctrl := gomock.NewController(t) 59 defer ctrl.Finish() 60 61 provider := mocks.NewMockProvider(ctrl) 62 provider.EXPECT().VDRegistry().Return(nil).AnyTimes() 63 provider.EXPECT().VerifiableStore().Return(nil).AnyTimes() 64 provider.EXPECT().JSONLDDocumentLoader().Return(nil).AnyTimes() 65 66 next := issuecredential.HandlerFunc(func(metadata issuecredential.Metadata) error { 67 return nil 68 }) 69 70 t.Run("Ignores processing", func(t *testing.T) { 71 metadata := mocks.NewMockMetadata(ctrl) 72 metadata.EXPECT().StateName().Return("state-name") 73 require.NoError(t, SaveCredentials(provider)(next).Handle(metadata)) 74 }) 75 76 t.Run("Credentials not provided", func(t *testing.T) { 77 metadata := mocks.NewMockMetadata(ctrl) 78 metadata.EXPECT().StateName().Return(stateNameCredentialReceived) 79 metadata.EXPECT().Message().Return(service.NewDIDCommMsgMap(issuecredential.IssueCredentialV2{ 80 Type: issuecredential.IssueCredentialMsgTypeV2, 81 })) 82 metadata.EXPECT().Properties().Return(map[string]interface{}{ 83 myDIDKey: myDIDKey, 84 theirDIDKey: theirDIDKey, 85 }) 86 87 err := SaveCredentials(provider)(next).Handle(metadata) 88 require.EqualError(t, err, "credentials were not provided") 89 }) 90 91 t.Run("Marshal credentials error", func(t *testing.T) { 92 metadata := mocks.NewMockMetadata(ctrl) 93 metadata.EXPECT().StateName().Return(stateNameCredentialReceived) 94 metadata.EXPECT().Message().Return(service.NewDIDCommMsgMap(issuecredential.IssueCredentialV2{ 95 Type: issuecredential.IssueCredentialMsgTypeV2, 96 CredentialsAttach: []decorator.Attachment{ 97 {Data: decorator.AttachmentData{JSON: struct{ C chan int }{}}}, 98 }, 99 })) 100 metadata.EXPECT().Properties().Return(map[string]interface{}{ 101 myDIDKey: myDIDKey, 102 theirDIDKey: theirDIDKey, 103 }) 104 105 err := SaveCredentials(provider)(next).Handle(metadata) 106 require.Contains(t, fmt.Sprintf("%v", err), "json: unsupported type") 107 }) 108 109 t.Run("Decode error", func(t *testing.T) { 110 metadata := mocks.NewMockMetadata(ctrl) 111 metadata.EXPECT().StateName().Return(stateNameCredentialReceived) 112 metadata.EXPECT().Message().Return(service.DIDCommMsgMap{"@type": map[int]int{}}) 113 metadata.EXPECT().Properties().Return(map[string]interface{}{ 114 myDIDKey: myDIDKey, 115 theirDIDKey: theirDIDKey, 116 }) 117 118 err := SaveCredentials(provider)(next).Handle(metadata) 119 require.Contains(t, fmt.Sprintf("%v", err), "got unconvertible type") 120 }) 121 122 t.Run("Invalid credentials", func(t *testing.T) { 123 metadata := mocks.NewMockMetadata(ctrl) 124 metadata.EXPECT().StateName().Return(stateNameCredentialReceived) 125 metadata.EXPECT().Message().Return(service.NewDIDCommMsgMap(issuecredential.IssueCredentialV2{ 126 Type: issuecredential.IssueCredentialMsgTypeV2, 127 CredentialsAttach: []decorator.Attachment{ 128 {Data: decorator.AttachmentData{JSON: &verifiable.Credential{ 129 Context: []string{"https://www.w3.org/2018/credentials/v1"}, 130 }}}, 131 }, 132 })) 133 metadata.EXPECT().Properties().Return(map[string]interface{}{ 134 myDIDKey: myDIDKey, 135 theirDIDKey: theirDIDKey, 136 }) 137 138 err := SaveCredentials(provider)(next).Handle(metadata) 139 require.Contains(t, fmt.Sprintf("%v", err), "to verifiable credentials") 140 }) 141 142 t.Run("DB error", func(t *testing.T) { 143 const ( 144 vcName = "vc-name" 145 errMsg = "error message" 146 ) 147 148 metadata := mocks.NewMockMetadata(ctrl) 149 metadata.EXPECT().StateName().Return(stateNameCredentialReceived) 150 metadata.EXPECT().CredentialNames().Return([]string{vcName}).Times(2) 151 metadata.EXPECT().Properties().Return(map[string]interface{}{ 152 myDIDKey: myDIDKey, 153 theirDIDKey: theirDIDKey, 154 }) 155 metadata.EXPECT().Message().Return(service.NewDIDCommMsgMap(issuecredential.IssueCredentialV2{ 156 Type: issuecredential.IssueCredentialMsgTypeV2, 157 CredentialsAttach: []decorator.Attachment{ 158 {Data: decorator.AttachmentData{JSON: getCredential()}}, 159 }, 160 })) 161 162 verifiableStore := mockstore.NewMockStore(ctrl) 163 verifiableStore.EXPECT().SaveCredential(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 164 Return(errors.New(errMsg)) 165 166 loader, err := ldtestutil.DocumentLoader() 167 require.NoError(t, err) 168 169 p := mocks.NewMockProvider(ctrl) 170 p.EXPECT().VDRegistry().Return(nil).AnyTimes() 171 p.EXPECT().VerifiableStore().Return(verifiableStore) 172 p.EXPECT().JSONLDDocumentLoader().Return(loader) 173 174 require.EqualError(t, SaveCredentials(p)(next).Handle(metadata), "save credential: "+errMsg) 175 }) 176 177 t.Run("No DIDs", func(t *testing.T) { 178 metadata := mocks.NewMockMetadata(ctrl) 179 metadata.EXPECT().StateName().Return(stateNameCredentialReceived) 180 metadata.EXPECT().Properties().Return(map[string]interface{}{}) 181 metadata.EXPECT().Message().Return(service.NewDIDCommMsgMap(issuecredential.IssueCredentialV2{ 182 Type: issuecredential.IssueCredentialMsgTypeV2, 183 CredentialsAttach: []decorator.Attachment{ 184 {Data: decorator.AttachmentData{JSON: getCredential()}}, 185 }, 186 })) 187 188 loader, err := ldtestutil.DocumentLoader() 189 require.NoError(t, err) 190 191 p := mocks.NewMockProvider(ctrl) 192 p.EXPECT().VDRegistry().Return(nil).AnyTimes() 193 p.EXPECT().VerifiableStore().Return(mockstore.NewMockStore(ctrl)) 194 p.EXPECT().JSONLDDocumentLoader().Return(loader) 195 196 require.EqualError(t, SaveCredentials(p)(next).Handle(metadata), "myDID or theirDID is absent") 197 }) 198 199 t.Run("Success", func(t *testing.T) { 200 const vcName = "vc-name" 201 202 props := map[string]interface{}{ 203 myDIDKey: myDIDKey, 204 theirDIDKey: theirDIDKey, 205 } 206 207 metadata := mocks.NewMockMetadata(ctrl) 208 metadata.EXPECT().StateName().Return(stateNameCredentialReceived) 209 metadata.EXPECT().CredentialNames().Return([]string{vcName}).Times(2) 210 metadata.EXPECT().Properties().Return(props) 211 metadata.EXPECT().Message().Return(service.NewDIDCommMsgMap(issuecredential.IssueCredentialV2{ 212 Type: issuecredential.IssueCredentialMsgTypeV2, 213 CredentialsAttach: []decorator.Attachment{ 214 {Data: decorator.AttachmentData{JSON: getCredential()}}, 215 }, 216 })) 217 218 verifiableStore := mockstore.NewMockStore(ctrl) 219 verifiableStore.EXPECT().SaveCredential(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 220 Return(nil) 221 222 loader, err := ldtestutil.DocumentLoader() 223 require.NoError(t, err) 224 225 p := mocks.NewMockProvider(ctrl) 226 p.EXPECT().VDRegistry().Return(nil).AnyTimes() 227 p.EXPECT().VerifiableStore().Return(verifiableStore) 228 p.EXPECT().JSONLDDocumentLoader().Return(loader) 229 230 require.NoError(t, SaveCredentials(p)(next).Handle(metadata)) 231 require.Equal(t, props["names"], []string{vcName}) 232 }) 233 234 t.Run("Success - no save", func(t *testing.T) { 235 props := map[string]interface{}{ 236 myDIDKey: myDIDKey, 237 theirDIDKey: theirDIDKey, 238 SkipCredentialSaveKey: true, 239 } 240 241 metadata := mocks.NewMockMetadata(ctrl) 242 metadata.EXPECT().StateName().Return(stateNameCredentialReceived) 243 metadata.EXPECT().Properties().Return(props) 244 245 require.NoError(t, SaveCredentials(provider)(next).Handle(metadata)) 246 }) 247 248 t.Run("Success V3", func(t *testing.T) { 249 const vcName = "vc-name" 250 251 props := map[string]interface{}{ 252 myDIDKey: myDIDKey, 253 theirDIDKey: theirDIDKey, 254 } 255 256 metadata := mocks.NewMockMetadata(ctrl) 257 metadata.EXPECT().StateName().Return(stateNameCredentialReceived) 258 metadata.EXPECT().CredentialNames().Return([]string{vcName}).Times(2) 259 metadata.EXPECT().Properties().Return(props) 260 metadata.EXPECT().Message().Return(service.NewDIDCommMsgMap(issuecredential.IssueCredentialV3{ 261 Type: issuecredential.IssueCredentialMsgTypeV3, 262 Attachments: []decorator.AttachmentV2{ 263 {Data: decorator.AttachmentData{JSON: getCredential()}}, 264 }, 265 })) 266 267 verifiableStore := mockstore.NewMockStore(ctrl) 268 verifiableStore.EXPECT().SaveCredential(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 269 Return(nil) 270 271 loader, err := ldtestutil.DocumentLoader() 272 require.NoError(t, err) 273 274 provider := mocks.NewMockProvider(ctrl) 275 provider.EXPECT().VDRegistry().Return(nil).AnyTimes() 276 provider.EXPECT().VerifiableStore().Return(verifiableStore) 277 provider.EXPECT().JSONLDDocumentLoader().Return(loader) 278 279 require.NoError(t, SaveCredentials(provider)(next).Handle(metadata)) 280 require.Equal(t, props["names"], []string{vcName}) 281 }) 282 283 t.Run("Success (no ID)", func(t *testing.T) { 284 props := map[string]interface{}{ 285 myDIDKey: myDIDKey, 286 theirDIDKey: theirDIDKey, 287 } 288 289 cred := getCredential() 290 cred.ID = "" 291 292 metadata := mocks.NewMockMetadata(ctrl) 293 metadata.EXPECT().StateName().Return(stateNameCredentialReceived) 294 metadata.EXPECT().CredentialNames().Return([]string{}) 295 metadata.EXPECT().Properties().Return(props) 296 metadata.EXPECT().Message().Return(service.NewDIDCommMsgMap(issuecredential.IssueCredentialV2{ 297 Type: issuecredential.IssueCredentialMsgTypeV2, 298 CredentialsAttach: []decorator.Attachment{ 299 {Data: decorator.AttachmentData{JSON: cred}}, 300 }, 301 })) 302 303 verifiableStore := mockstore.NewMockStore(ctrl) 304 verifiableStore.EXPECT().SaveCredential(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 305 Return(nil) 306 307 loader, err := ldtestutil.DocumentLoader() 308 require.NoError(t, err) 309 310 provider := mocks.NewMockProvider(ctrl) 311 provider.EXPECT().VDRegistry().Return(nil).AnyTimes() 312 provider.EXPECT().VerifiableStore().Return(verifiableStore) 313 provider.EXPECT().JSONLDDocumentLoader().Return(loader) 314 315 require.NoError(t, SaveCredentials(provider)(next).Handle(metadata)) 316 require.Equal(t, len(props["names"].([]string)), 1) 317 require.NotEmpty(t, props["names"].([]string)[0]) 318 }) 319 320 t.Run("Success (credential with a proof)", func(t *testing.T) { 321 const vcName = "vc-name" 322 323 var credential map[string]interface{} 324 // nolint: lll 325 require.NoError(t, json.Unmarshal([]byte(`{ 326 "@context": [ 327 "https://www.w3.org/2018/credentials/v1", 328 "https://www.w3.org/2018/credentials/examples/v1" 329 ], 330 "credentialSubject": { 331 "degree": { 332 "type": "BachelorDegree", 333 "university": "MIT" 334 }, 335 "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 336 "name": "Jayden Doe", 337 "spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1" 338 }, 339 "expirationDate": "2020-01-01T19:23:24Z", 340 "id": "http://example.edu/credentials/1872", 341 "issuanceDate": "2009-01-01T19:23:24Z", 342 "issuer": { 343 "id": "did:example:76e12ec712ebc6f1c221ebfeb1f", 344 "name": "Example University" 345 }, 346 "proof": { 347 "created": "2010-01-01T19:23:24Z", 348 "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..lrkhpRH4tWl6KzQKHlcyAwSm8qUTXIMSKmD3QASF_uI5QW8NWLxLebXmnQpIM8H7umhLA6dINSYVowcaPdpwBw", 349 "proofPurpose": "assertionMethod", 350 "type": "Ed25519Signature2018", 351 "verificationMethod": "did:example:123456#key1" 352 }, 353 "referenceNumber": 83294849, 354 "type": [ 355 "VerifiableCredential", 356 "UniversityDegreeCredential" 357 ] 358 }`), &credential)) 359 360 props := map[string]interface{}{ 361 myDIDKey: myDIDKey, 362 theirDIDKey: theirDIDKey, 363 } 364 365 metadata := mocks.NewMockMetadata(ctrl) 366 metadata.EXPECT().StateName().Return(stateNameCredentialReceived) 367 metadata.EXPECT().CredentialNames().Return([]string{vcName}).Times(2) 368 metadata.EXPECT().Properties().Return(props) 369 metadata.EXPECT().Message().Return(service.NewDIDCommMsgMap(issuecredential.IssueCredentialV2{ 370 Type: issuecredential.IssueCredentialMsgTypeV2, 371 CredentialsAttach: []decorator.Attachment{ 372 {Data: decorator.AttachmentData{JSON: credential}}, 373 }, 374 })) 375 376 verifiableStore := mockstore.NewMockStore(ctrl) 377 verifiableStore.EXPECT().SaveCredential(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 378 Return(nil) 379 380 loader, err := ldtestutil.DocumentLoader() 381 require.NoError(t, err) 382 383 registry := mockvdr.NewMockRegistry(ctrl) 384 registry.EXPECT().Resolve("did:example:123456").Return(&did.DocResolution{DIDDocument: &did.Doc{ 385 VerificationMethod: []did.VerificationMethod{{ 386 ID: "#key1", 387 Value: []byte{ 388 234, 100, 192, 93, 251, 181, 198, 73, 122, 220, 27, 48, 93, 73, 166, 389 33, 152, 140, 168, 36, 9, 205, 59, 161, 137, 7, 164, 9, 176, 252, 1, 171, 390 }, 391 }}, 392 }}, nil) 393 394 provider := mocks.NewMockProvider(ctrl) 395 provider.EXPECT().VDRegistry().Return(registry).AnyTimes() 396 provider.EXPECT().VerifiableStore().Return(verifiableStore) 397 provider.EXPECT().JSONLDDocumentLoader().Return(loader) 398 399 require.NoError(t, SaveCredentials(provider)(next).Handle(metadata)) 400 require.Equal(t, props["names"], []string{vcName}) 401 }) 402 }