From f4a9ffc938e46fb640514954eef882c1518e1871 Mon Sep 17 00:00:00 2001 From: Rolson Quadras Date: Mon, 12 Aug 2019 10:51:12 -0400 Subject: [PATCH] feat: Framework Init - base template with Outbound transport config - Add New(opts) function which takes in the options to configuration - Support outbound transport configuration Signed-off-by: Rolson Quadras --- pkg/didcomm/protocol/exchange/exchange.go | 27 +++++++--- .../protocol/exchange/exchange_test.go | 12 ++--- pkg/framework/aries/api/factory.go | 16 ++++++ pkg/framework/aries/default.go | 33 ++++++++++++ .../factory/protocol/protocol_factory.go | 27 ++++++++++ .../factory/protocol/protocol_factory_test.go | 18 +++++++ pkg/framework/aries/framework.go | 52 +++++++++++++++++++ pkg/framework/aries/framework_test.go | 50 ++++++++++++++++++ pkg/framework/context/context.go | 45 ++++++++++++++++ pkg/framework/context/context_test.go | 30 +++++++++++ 10 files changed, 298 insertions(+), 12 deletions(-) create mode 100644 pkg/framework/aries/api/factory.go create mode 100644 pkg/framework/aries/default.go create mode 100644 pkg/framework/aries/factory/protocol/protocol_factory.go create mode 100644 pkg/framework/aries/factory/protocol/protocol_factory_test.go create mode 100644 pkg/framework/aries/framework.go create mode 100644 pkg/framework/aries/framework_test.go create mode 100644 pkg/framework/context/context.go create mode 100644 pkg/framework/context/context_test.go diff --git a/pkg/didcomm/protocol/exchange/exchange.go b/pkg/didcomm/protocol/exchange/exchange.go index bb87dc47f4..1d4354c9b1 100644 --- a/pkg/didcomm/protocol/exchange/exchange.go +++ b/pkg/didcomm/protocol/exchange/exchange.go @@ -68,6 +68,11 @@ type Connection struct { DIDDoc *did.Doc `json:"did_doc,omitempty"` } +// Provider for exchange protocol +type Provider interface { + transport.OutboundTransport +} + // GenerateInviteWithPublicDID generates the DID exchange invitation string with public DID func GenerateInviteWithPublicDID(invite *Invitation) (string, error) { if invite.ID == "" || invite.DID == "" { @@ -86,8 +91,18 @@ func GenerateInviteWithKeyAndEndpoint(invite *Invitation) (string, error) { return encodedExchangeInvitation(invite) } +// Client for exchange protocol +type Client struct { + prov transport.OutboundTransport +} + +// New instanstiated new exchange client +func New(prov Provider) *Client { + return &Client{prov: prov} +} + // SendExchangeRequest sends exchange request -func SendExchangeRequest(exchangeRequest *Request, destination string, transport transport.OutboundTransport) error { +func (c *Client) SendExchangeRequest(exchangeRequest *Request, destination string) error { if exchangeRequest == nil { return errors.New("exchangeRequest cannot be nil") } @@ -95,12 +110,12 @@ func SendExchangeRequest(exchangeRequest *Request, destination string, transport exchangeRequest.Type = connectionRequest // ignore response data as it is not used in this communication mode as defined in the spec - _, err := marshalAndSend(exchangeRequest, "Error Marshalling Exchange Request", destination, transport) + _, err := c.marshalAndSend(exchangeRequest, "Error Marshalling Exchange Request", destination) return err } // SendExchangeResponse sends exchange response -func SendExchangeResponse(exchangeResponse *Response, destination string, transport transport.OutboundTransport) error { +func (c *Client) SendExchangeResponse(exchangeResponse *Response, destination string) error { if exchangeResponse == nil { return errors.New("exchangeResponse cannot be nil") } @@ -108,7 +123,7 @@ func SendExchangeResponse(exchangeResponse *Response, destination string, transp exchangeResponse.Type = connectionResponse // ignore response data as it is not used in this communication mode as defined in the spec - _, err := marshalAndSend(exchangeResponse, "Error Marshalling Exchange Response", destination, transport) + _, err := c.marshalAndSend(exchangeResponse, "Error Marshalling Exchange Response", destination) return err } @@ -123,10 +138,10 @@ func encodedExchangeInvitation(inviteMessage *Invitation) (string, error) { return base64.URLEncoding.EncodeToString(invitationJSON), nil } -func marshalAndSend(data interface{}, errorMsg, destination string, transport transport.OutboundTransport) (string, error) { +func (c *Client) marshalAndSend(data interface{}, errorMsg, destination string) (string, error) { jsonString, err := json.Marshal(data) if err != nil { return "", errors.Errorf("%s : %w", errorMsg, err) } - return transport.Send(string(jsonString), destination) + return c.prov.Send(string(jsonString), destination) } diff --git a/pkg/didcomm/protocol/exchange/exchange_test.go b/pkg/didcomm/protocol/exchange/exchange_test.go index 6fb1b563c0..a4c85619c1 100644 --- a/pkg/didcomm/protocol/exchange/exchange_test.go +++ b/pkg/didcomm/protocol/exchange/exchange_test.go @@ -83,19 +83,19 @@ func TestGenerateInviteWithKeyAndEndpoint(t *testing.T) { } func TestSendRequest(t *testing.T) { - oTr := mocktransport.NewOutboundTransport(successResponse) + prov := New(mocktransport.NewOutboundTransport(successResponse)) req := &Request{ ID: "5678876542345", Label: "Bob", } - require.NoError(t, SendExchangeRequest(req, destinationURL, oTr)) - require.Error(t, SendExchangeRequest(nil, destinationURL, oTr)) + require.NoError(t, prov.SendExchangeRequest(req, destinationURL)) + require.Error(t, prov.SendExchangeRequest(nil, destinationURL)) } func TestSendResponse(t *testing.T) { - oTr := mocktransport.NewOutboundTransport(successResponse) + prov := New(mocktransport.NewOutboundTransport(successResponse)) resp := &Response{ ID: "12345678900987654321", @@ -104,6 +104,6 @@ func TestSendResponse(t *testing.T) { }, } - require.NoError(t, SendExchangeResponse(resp, destinationURL, oTr)) - require.Error(t, SendExchangeResponse(nil, destinationURL, oTr)) + require.NoError(t, prov.SendExchangeResponse(resp, destinationURL)) + require.Error(t, prov.SendExchangeResponse(nil, destinationURL)) } diff --git a/pkg/framework/aries/api/factory.go b/pkg/framework/aries/api/factory.go new file mode 100644 index 0000000000..e16929efb3 --- /dev/null +++ b/pkg/framework/aries/api/factory.go @@ -0,0 +1,16 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package api + +import ( + "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/exchange" +) + +// ProtocolProviderFactory allows overriding of aries protocol providers +type ProtocolProviderFactory interface { + CreateExchangeProvider() exchange.Provider +} diff --git a/pkg/framework/aries/default.go b/pkg/framework/aries/default.go new file mode 100644 index 0000000000..05784ad868 --- /dev/null +++ b/pkg/framework/aries/default.go @@ -0,0 +1,33 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package aries + +import ( + "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api" + "github.com/hyperledger/aries-framework-go/pkg/framework/aries/factory/protocol" +) + +// defFramework provides default framework configs +type defFramework struct{} + +// outboundTransport provides default OutboundTransport +func (d defFramework) protocolProviderFactory() api.ProtocolProviderFactory { + return protocol.NewProviderFactory() +} + +// defFrameworkOpts provides default framework options +func defFrameworkOpts() []Option { + // get the default framework configs + def := defFramework{} + + var opts []Option + // protocol provider factory + opt := WithProtocolProviderFactory(def.protocolProviderFactory()) + opts = append(opts, opt) + + return opts +} diff --git a/pkg/framework/aries/factory/protocol/protocol_factory.go b/pkg/framework/aries/factory/protocol/protocol_factory.go new file mode 100644 index 0000000000..9605d08175 --- /dev/null +++ b/pkg/framework/aries/factory/protocol/protocol_factory.go @@ -0,0 +1,27 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package protocol + +import ( + "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/exchange" +) + +// ProviderFactory represents the default protocol provider factory. +type ProviderFactory struct { +} + +// NewProviderFactory returns the default protocol provider factory. +func NewProviderFactory() *ProviderFactory { + f := ProviderFactory{} + return &f +} + +// CreateExchangeProvider returns a new default implementation of Exchange provider +func (f *ProviderFactory) CreateExchangeProvider() exchange.Provider { + // TODO - https://github.com/hyperledger/aries-framework-go/issues/83 + return nil +} diff --git a/pkg/framework/aries/factory/protocol/protocol_factory_test.go b/pkg/framework/aries/factory/protocol/protocol_factory_test.go new file mode 100644 index 0000000000..f6834bc8b2 --- /dev/null +++ b/pkg/framework/aries/factory/protocol/protocol_factory_test.go @@ -0,0 +1,18 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package protocol + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestNewProviderFactory(t *testing.T) { + f := NewProviderFactory() + require.Empty(t, f.CreateExchangeProvider()) +} diff --git a/pkg/framework/aries/framework.go b/pkg/framework/aries/framework.go new file mode 100644 index 0000000000..c8029d010a --- /dev/null +++ b/pkg/framework/aries/framework.go @@ -0,0 +1,52 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package aries + +import ( + "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api" + "github.com/hyperledger/aries-framework-go/pkg/framework/context" + errors "golang.org/x/xerrors" +) + +// Aries provides access to clients being managed by the framework. +type Aries struct { + protocol api.ProtocolProviderFactory +} + +// Option configures the framework. +type Option func(opts *Aries) error + +// New initializes the Aries framework based on the set of options provided. +func New(opts ...Option) (*Aries, error) { + // get the default framework options + defOpts := defFrameworkOpts() + + frameworkOpts := &Aries{} + + // generate framework configs from options + for _, option := range append(defOpts, opts...) { + err := option(frameworkOpts) + if err != nil { + return nil, errors.Errorf("Error in option passed to New: %w", err) + } + } + + return frameworkOpts, nil +} + +// WithProtocolProviderFactory injects a protocol provider factory interface to Aries +func WithProtocolProviderFactory(ot api.ProtocolProviderFactory) Option { + return func(opts *Aries) error { + opts.protocol = ot + return nil + } +} + +// Context provides handle to framework context +func (a *Aries) Context() (*context.Provider, error) { + return context.New(context.WithExchangeProvider(a.protocol.CreateExchangeProvider())) +} diff --git a/pkg/framework/aries/framework_test.go b/pkg/framework/aries/framework_test.go new file mode 100644 index 0000000000..acefed856a --- /dev/null +++ b/pkg/framework/aries/framework_test.go @@ -0,0 +1,50 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package aries + +import ( + "testing" + + "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/exchange" + mocktransport "github.com/hyperledger/aries-framework-go/pkg/internal/didcomm/transport/mock" + "github.com/stretchr/testify/require" + errors "golang.org/x/xerrors" +) + +func TestFramework(t *testing.T) { + // framework new - error + _, err := New(func(opts *Aries) error { + return errors.New("error creating the framework option") + }) + require.Error(t, err) + + // framework new - success + aries, err := New(WithProtocolProviderFactory(&mockProtocolProviderFactory{})) + require.NoError(t, err) + + // context + ctx, err := aries.Context() + require.NoError(t, err) + + // exchange client + exClient := exchange.New(ctx.ExchangeProvider()) + require.NoError(t, err) + + req := &exchange.Request{ + ID: "5678876542345", + Label: "Bob", + } + require.NoError(t, exClient.SendExchangeRequest(req, "http://example/didexchange")) + require.Error(t, exClient.SendExchangeRequest(req, "")) +} + +type mockProtocolProviderFactory struct { +} + +func (f *mockProtocolProviderFactory) CreateExchangeProvider() exchange.Provider { + return mocktransport.NewOutboundTransport("success") +} diff --git a/pkg/framework/context/context.go b/pkg/framework/context/context.go new file mode 100644 index 0000000000..08346887e0 --- /dev/null +++ b/pkg/framework/context/context.go @@ -0,0 +1,45 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package context + +import ( + "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/exchange" + errors "golang.org/x/xerrors" +) + +// Provider supplies the framework configuration to client objects. +type Provider struct { + exProv exchange.Provider +} + +// New instantiated new context provider +func New(opts ...ProviderOption) (*Provider, error) { + ctxProvider := Provider{} + for _, opt := range opts { + err := opt(&ctxProvider) + if err != nil { + return nil, errors.Errorf("Error in option passed to New: %w", err) + } + } + return &ctxProvider, nil +} + +// ExchangeProvider returns exchange protocol provider +func (p *Provider) ExchangeProvider() exchange.Provider { + return p.exProv +} + +// ProviderOption configures the framework. +type ProviderOption func(opts *Provider) error + +// WithExchangeProvider injects exchange provider into the framework +func WithExchangeProvider(ot exchange.Provider) ProviderOption { + return func(opts *Provider) error { + opts.exProv = ot + return nil + } +} diff --git a/pkg/framework/context/context_test.go b/pkg/framework/context/context_test.go new file mode 100644 index 0000000000..3279f867b8 --- /dev/null +++ b/pkg/framework/context/context_test.go @@ -0,0 +1,30 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package context + +import ( + "testing" + + mocktransport "github.com/hyperledger/aries-framework-go/pkg/internal/didcomm/transport/mock" + "github.com/stretchr/testify/require" + errors "golang.org/x/xerrors" +) + +func TestNewProvider(t *testing.T) { + prov, err := New() + require.NoError(t, err) + require.Empty(t, prov.ExchangeProvider()) + + prov, err = New(WithExchangeProvider(mocktransport.NewOutboundTransport("success"))) + require.NoError(t, err) + require.NotEmpty(t, prov.ExchangeProvider()) + + _, err = New(func(opts *Provider) error { + return errors.New("error creating the framework option") + }) + require.Error(t, err) +}