github.com/hyperledger/aries-framework-go@v0.3.2/pkg/client/issuecredential/rfc0593/middleware.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package rfc0593 8 9 import ( 10 "errors" 11 "fmt" 12 13 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator" 14 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/issuecredential" 15 "github.com/hyperledger/aries-framework-go/spi/storage" 16 ) 17 18 // Middleware is the RFC0593 issuecredential.Middleware that can be injected into the protocol service. 19 type Middleware issuecredential.Middleware 20 21 // RegisterMiddleware registers the Middleware in the IssueCredentialService looked up from the ServiceProvider. 22 // 23 // See also: NewMiddleware. 24 func RegisterMiddleware(mw Middleware, p ServiceProvider) error { 25 typelessSvc, err := p.Service(issuecredential.Name) 26 if err != nil { 27 return fmt.Errorf("failed to lookup issuecredential service: %w", err) 28 } 29 30 svc, ok := typelessSvc.(IssueCredentialService) 31 if !ok { 32 return errors.New("unable to cast the issuecredential service to the required interface type") 33 } 34 35 svc.AddMiddleware(issuecredential.Middleware(mw)) 36 37 return nil 38 } 39 40 // NewMiddleware returns a new Middleware that can be used with the issuecredential protocol service 41 // in conjunction with AutoExecute when the protocol needs to be started with a request-credential 42 // message. 43 // 44 // Usage: 45 // framework, err := aries.New() 46 // if err != nil { 47 // panic(err) 48 // } 49 // ctx, err := framework.Context() 50 // if err != nil { 51 // panic(err) 52 // } 53 // mw, err := NewMiddleware(ctx) 54 // if err != nil { 55 // panic(err) 56 // } 57 // err = RegisterMiddleware(mw, ctx) 58 // if err != nil { 59 // panic(err) 60 // } 61 // client := issuecredential.Client = ... 62 // events = make(chan service.DIDCommAction) 63 // err := client.RegisterActionEvent(events) 64 // if err != nil { 65 // panic(err) 66 // } 67 // next := make(chan service.DIDCommAction) 68 // go AutoExecute(ctx, next)(events) 69 // for event := range next { 70 // // handle events from issue-credential that do not conform to RFC0593 71 // } 72 // 73 // See also: AutoExecute. 74 func NewMiddleware(p TransientStorage) (Middleware, error) { 75 s, err := p.ProtocolStateStorageProvider().OpenStore(StoreName) 76 if err != nil { 77 return nil, fmt.Errorf("rfc0593: failed to open store: %w", err) 78 } 79 80 return func(next issuecredential.Handler) issuecredential.Handler { 81 return &handler{ 82 next: next, 83 store: s, 84 } 85 }, nil 86 } 87 88 type handler struct { 89 next issuecredential.Handler 90 store storage.Store 91 } 92 93 // Handle the issuecredential.Metadata. 94 func (h *handler) Handle(md issuecredential.Metadata) error { 95 var ( 96 formats []issuecredential.Format 97 attachments []decorator.Attachment 98 err error 99 ) 100 101 switch md.Message().Type() { 102 case issuecredential.RequestCredentialMsgTypeV2: 103 p := &issuecredential.RequestCredentialV2{} 104 err = md.Message().Decode(p) 105 formats = p.Formats 106 attachments = p.RequestsAttach 107 default: 108 return h.next.Handle(md) 109 } 110 111 if err != nil { 112 return fmt.Errorf("rfc0593: failed to decode msg type %s: %w", md.Message().Type(), err) 113 } 114 115 attachment, err := FindAttachment(ProofVCDetailFormat, formats, attachments) 116 if errors.Is(err, ErrRFC0593NotApplicable) { 117 return h.next.Handle(md) 118 } 119 120 if err != nil { 121 return fmt.Errorf("rfc0593: failed to fetch attachment: %w", err) 122 } 123 124 spec := &CredentialSpec{} 125 126 err = unmarshalAttachmentContents(attachment, spec) 127 if err != nil { 128 return fmt.Errorf("rfc0593: failed to unmarshal attachment contents: %w", err) 129 } 130 131 err = saveOptionsIfNoError(nil, h.store, md.Message(), spec.Options) 132 if err != nil { 133 return fmt.Errorf("rfc0593: failed to save credential spec options: %w", err) 134 } 135 136 return h.next.Handle(md) 137 }