Skip to content
This repository has been archived by the owner on Mar 27, 2024. It is now read-only.

feat: Framework Init - base template with Outbound transport config #88

Merged
merged 1 commit into from
Aug 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions pkg/didcomm/protocol/exchange/exchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ type Connection struct {
DIDDoc *did.Doc `json:"did_doc,omitempty"`
}

// provider contains dependencies for the Exchange protocol and is typically created by using aries.Context()
type provider interface {
OutboundTransport() transport.OutboundTransport
}

// GenerateInviteWithPublicDID generates the DID exchange invitation string with public DID
func GenerateInviteWithPublicDID(invite *Invitation) (string, error) {
if invite.ID == "" || invite.DID == "" {
Expand All @@ -86,29 +91,41 @@ func GenerateInviteWithKeyAndEndpoint(invite *Invitation) (string, error) {
return encodedExchangeInvitation(invite)
}

// Protocol for exchange protocol
type Protocol struct {
outboundTransport transport.OutboundTransport
}

// New instanstiated new exchange client
// The argument takes a implementation of transport.OutboundTransport (dependencies required for Exchange protocol) and
// this is typically called by using aries.Context()
func New(prov provider) *Protocol {
troyronda marked this conversation as resolved.
Show resolved Hide resolved
return &Protocol{prov.OutboundTransport()}
}

// SendExchangeRequest sends exchange request
func SendExchangeRequest(exchangeRequest *Request, destination string, transport transport.OutboundTransport) error {
func (p *Protocol) SendExchangeRequest(exchangeRequest *Request, destination string) error {
if exchangeRequest == nil {
return errors.New("exchangeRequest cannot be nil")
}

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 := p.marshalAndSend(exchangeRequest, "Error Marshalling Exchange Request", destination)
return err
}

// SendExchangeResponse sends exchange response
func SendExchangeResponse(exchangeResponse *Response, destination string, transport transport.OutboundTransport) error {
func (p *Protocol) SendExchangeResponse(exchangeResponse *Response, destination string) error {
if exchangeResponse == nil {
return errors.New("exchangeResponse cannot be nil")
}

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 := p.marshalAndSend(exchangeResponse, "Error Marshalling Exchange Response", destination)
return err
}

Expand All @@ -123,10 +140,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 (p *Protocol) 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 p.outboundTransport.Send(string(jsonString), destination)
}
21 changes: 15 additions & 6 deletions pkg/didcomm/protocol/exchange/exchange_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ package exchange
import (
"testing"

"github.com/hyperledger/aries-framework-go/pkg/didcomm/transport"

mocktransport "github.com/hyperledger/aries-framework-go/pkg/internal/didcomm/transport/mock"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -83,19 +85,19 @@ func TestGenerateInviteWithKeyAndEndpoint(t *testing.T) {
}

func TestSendRequest(t *testing.T) {
oTr := mocktransport.NewOutboundTransport(successResponse)
prov := New(&mockProvider{})

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(&mockProvider{})

resp := &Response{
ID: "12345678900987654321",
Expand All @@ -104,6 +106,13 @@ 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))
}

type mockProvider struct {
}

func (p *mockProvider) OutboundTransport() transport.OutboundTransport {
return mocktransport.NewOutboundTransport(successResponse)
}
16 changes: 16 additions & 0 deletions pkg/framework/aries/api/factory.go
Original file line number Diff line number Diff line change
@@ -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/transport"
)

// TransportProviderFactory allows overriding of aries protocol providers
type TransportProviderFactory interface {
CreateOutboundTransport() transport.OutboundTransport
}
33 changes: 33 additions & 0 deletions pkg/framework/aries/default.go
Original file line number Diff line number Diff line change
@@ -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/transport"
)

// defFramework provides default framework configs
type defFramework struct{}

// transportProviderFactory provides default Outbound Transport provider factory
func (d defFramework) transportProviderFactory() api.TransportProviderFactory {
return transport.NewProviderFactory()
}

// defFrameworkOpts provides default framework options
func defFrameworkOpts() []Option {
// get the default framework configs
def := defFramework{}

var opts []Option
// protocol provider factory
opt := WithTransportProviderFactory(def.transportProviderFactory())
opts = append(opts, opt)

return opts
}
27 changes: 27 additions & 0 deletions pkg/framework/aries/factory/transport/transport_factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package transport

import (
"github.com/hyperledger/aries-framework-go/pkg/didcomm/transport"
)

// ProviderFactory represents the default transport provider factory.
type ProviderFactory struct {
}

// NewProviderFactory returns the default transport provider factory.
func NewProviderFactory() *ProviderFactory {
f := ProviderFactory{}
return &f
}

// CreateOutboundTransport returns a new default implementation of outbound transport provider
func (f *ProviderFactory) CreateOutboundTransport() transport.OutboundTransport {
// TODO - https://github.com/hyperledger/aries-framework-go/issues/83
return nil
}
18 changes: 18 additions & 0 deletions pkg/framework/aries/factory/transport/transport_factory_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package transport

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestNewProviderFactory(t *testing.T) {
f := NewProviderFactory()
require.Empty(t, f.CreateOutboundTransport())
}
52 changes: 52 additions & 0 deletions pkg/framework/aries/framework.go
Original file line number Diff line number Diff line change
@@ -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"
troyronda marked this conversation as resolved.
Show resolved Hide resolved
"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 {
transport api.TransportProviderFactory
}

// 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()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a thought.
Not sure about having default factory settings as opts, if someone passes custom opts then we may have duplicate opts. It may work here in this case due to order of opts. Need proper test cases to see if overriding actually works (I can see in one of the test you passed mock transport factory), just to be at safe side we shouldn't pass default settings as opts.

Instead at line number 28, initialize Aries struct with default opts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was done based on comments.

Copy link
Contributor

@sudeshrshetty sudeshrshetty Aug 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine for me if order of opts are intact.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes order of opts needs to be kept intact.


frameworkOpts := &Aries{}

// generate framework configs from options
for _, option := range append(defOpts, opts...) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defOpts has default and append opts to it may duplicate options, this can lead to unexpected behaviour

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second opts(user opts) will overwrite the defOpts.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - second opt can override.

The other way around this type of problem seems to be to force framework users to pass the default option, rather than implicitly include as the first option. This has its own negative trade-off, of course.

Copy link
Contributor

@troyronda troyronda Aug 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we could also introduce a functional argument like WithoutDefaults(). Created #110.

err := option(frameworkOpts)
if err != nil {
return nil, errors.Errorf("Error in option passed to New: %w", err)
}
}

return frameworkOpts, nil
}

// WithTransportProviderFactory injects a protocol provider factory interface to Aries
func WithTransportProviderFactory(ot api.TransportProviderFactory) Option {
return func(opts *Aries) error {
opts.transport = ot
return nil
}
}

// Context provides handle to framework context
func (a *Aries) Context() (*context.Provider, error) {
return context.New(context.WithOutboundTransport(a.transport.CreateOutboundTransport()))
}
52 changes: 52 additions & 0 deletions pkg/framework/aries/framework_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
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/transport"

"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(WithTransportProviderFactory(&mockTransportProviderFactory{}))
require.NoError(t, err)

// context
ctx, err := aries.Context()
require.NoError(t, err)

// exchange client
exClient := exchange.New(ctx)
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 mockTransportProviderFactory struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we move all mocks to common pkg if possible?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@troyronda @Baha-sk @fqutishat thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is meant by “all mocks”? I generally think mocks should be near its real implementation.

}

func (f *mockTransportProviderFactory) CreateOutboundTransport() transport.OutboundTransport {
return mocktransport.NewOutboundTransport("success")
}
45 changes: 45 additions & 0 deletions pkg/framework/context/context.go
Original file line number Diff line number Diff line change
@@ -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/transport"
errors "golang.org/x/xerrors"
)

// Provider supplies the framework configuration to client objects.
type Provider struct {
outboundTransport transport.OutboundTransport
}

// 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
}

// OutboundTransport returns the outbound transport provider
func (p *Provider) OutboundTransport() transport.OutboundTransport {
return p.outboundTransport
}

// ProviderOption configures the framework.
type ProviderOption func(opts *Provider) error

// WithOutboundTransport injects transport provider into the framework
func WithOutboundTransport(ot transport.OutboundTransport) ProviderOption {
return func(opts *Provider) error {
opts.outboundTransport = ot
return nil
}
}
Loading