Skip to content

Commit

Permalink
fix: Refactor credential manifest output descriptors
Browse files Browse the repository at this point in the history
closes trustbloc#580

Signed-off-by: talwinder50 <talwinderkaur50@gmail.com>
  • Loading branch information
talwinder50 committed Feb 23, 2022
1 parent 869218a commit 40b5615
Show file tree
Hide file tree
Showing 7 changed files with 331 additions and 115 deletions.
47 changes: 16 additions & 31 deletions cmd/adapter-rest/startcmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ package startcmd
import (
"crypto/tls"
"crypto/x509"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
Expand All @@ -23,7 +22,6 @@ import (
"time"

"github.com/cenkalti/backoff"
"github.com/google/uuid"
"github.com/gorilla/mux"
"github.com/hyperledger/aries-framework-go-ext/component/storage/mongodb"
"github.com/hyperledger/aries-framework-go-ext/component/storage/mysql"
Expand All @@ -36,10 +34,8 @@ import (
ldrest "github.com/hyperledger/aries-framework-go/pkg/controller/rest/ld"
"github.com/hyperledger/aries-framework-go/pkg/didcomm/messaging/msghandler"
arieshttp "github.com/hyperledger/aries-framework-go/pkg/didcomm/transport/http"
"github.com/hyperledger/aries-framework-go/pkg/doc/cm"
ariesld "github.com/hyperledger/aries-framework-go/pkg/doc/ld"
"github.com/hyperledger/aries-framework-go/pkg/doc/ldcontext/remote"
"github.com/hyperledger/aries-framework-go/pkg/doc/presexch"
"github.com/hyperledger/aries-framework-go/pkg/framework/aries"
"github.com/hyperledger/aries-framework-go/pkg/framework/aries/api"
"github.com/hyperledger/aries-framework-go/pkg/framework/aries/defaults"
Expand All @@ -57,6 +53,7 @@ import (
"github.com/trustbloc/edge-adapter/pkg/did"
"github.com/trustbloc/edge-adapter/pkg/hydra"
"github.com/trustbloc/edge-adapter/pkg/ld"
"github.com/trustbloc/edge-adapter/pkg/memcmdescriptor"
"github.com/trustbloc/edge-adapter/pkg/presentationex"
"github.com/trustbloc/edge-adapter/pkg/restapi/healthcheck"
"github.com/trustbloc/edge-adapter/pkg/restapi/issuer"
Expand Down Expand Up @@ -826,7 +823,7 @@ func addIssuerHandlers(parameters *adapterRestParameters, framework *aries.Aries
return fmt.Errorf("aries-framework - failed to get aries context : %w", err)
}

cmDescriptors, err := readCMOutputDescriptorFile(parameters.cmOutputDescriptorsFilePath)
cmDescriptorsProvider, err := getCMOutputDescriptorProvider(parameters.cmOutputDescriptorsFilePath)
if err != nil {
return fmt.Errorf("failed to read and validate manifest output descriptors : %w", err)
}
Expand Down Expand Up @@ -863,7 +860,7 @@ func addIssuerHandlers(parameters *adapterRestParameters, framework *aries.Aries
ExternalURL: parameters.externalURL,
DidDomain: parameters.trustblocDomain,
JSONLDDocumentLoader: ariesCtx.JSONLDDocumentLoader(),
CMDescriptors: cmDescriptors,
CMDescriptors: cmDescriptorsProvider,
})
if err != nil {
return fmt.Errorf("failed to init issuer ops: %w", err)
Expand Down Expand Up @@ -1162,39 +1159,27 @@ func getPresentationExchangeProvider(configFile string) (*presentationex.Provide
return p, nil
}

func readCMOutputDescriptorFile(cmDescriptorsFile string) (cmDescriptor map[string]*issuerops.CMAttachmentDescriptors,
err error) {
func getCMOutputDescriptorProvider(cmDescriptorsFile string) (*memcmdescriptor.Provider, error) {
if cmDescriptorsFile == "" {
return make(map[string]*issuerops.CMAttachmentDescriptors), nil
return &memcmdescriptor.Provider{}, nil
}

credentialDescriptorsBytes, err := ioutil.ReadFile(filepath.Clean(cmDescriptorsFile))
reader, err := os.Open(filepath.Clean(cmDescriptorsFile))
if err != nil {
return nil, fmt.Errorf("read credential manifest descriptors file : %w", err)
return nil, fmt.Errorf("read credential manifest descriptors file %s: %w", cmDescriptorsFile, err)
}

err = json.Unmarshal(credentialDescriptorsBytes, &cmDescriptor)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal credential manifest descriptors file: %w", err)
}

for _, descriptors := range cmDescriptor {
err := cm.ValidateOutputDescriptors(descriptors.OutputDesc)
if err != nil {
return nil, fmt.Errorf("aries-framework - failed to validate output "+
"descriptors: %w", err)
defer func() {
closeErr := reader.Close()
if closeErr != nil {
logger.Warnf("failed to close %s: %w", cmDescriptorsFile, closeErr)
}
}()

if descriptors.InputDesc != nil {
presDef := presexch.PresentationDefinition{ID: uuid.NewString(), InputDescriptors: descriptors.InputDesc}

err := presDef.ValidateSchema()
if err != nil {
return nil, fmt.Errorf("aries-framework - failed to validate input "+
"descriptors: %w", err)
}
}
memCMProvider, err := memcmdescriptor.New(reader)
if err != nil {
return nil, fmt.Errorf("failed to init cm output descriptor provider: %w", err)
}

return cmDescriptor, nil
return memCMProvider, nil
}
22 changes: 8 additions & 14 deletions cmd/adapter-rest/startcmd/start_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -632,30 +632,24 @@ func TestAdapterModes(t *testing.T) { // nolint:paralleltest // shared environme
require.Contains(t, err.Error(), "failed to initialize wallet bridge")
})
}
func TestReadOutputDescriptorFile(t *testing.T) { // nolint:paralleltest
func TestGetCMOutputDescriptorProvider(t *testing.T) { // nolint:paralleltest
t.Run("read output descriptor file success", // nolint:paralleltest
func(t *testing.T) {
cmOutputdesc, err := readCMOutputDescriptorFile("./testdata/outputdescriptors.json")
cmOutputdesc, err := getCMOutputDescriptorProvider("./testdata/outputdescriptors.json")
require.NoError(t, err)
require.NotNil(t, cmOutputdesc)
for k, v := range cmOutputdesc {
require.Equal(t, "udc-scope-1", k)
require.Equal(t, 1, len(cmOutputdesc))
require.NotNil(t, v)
}
})
t.Run("cm output descriptor file is not provided", // nolint:paralleltest
func(t *testing.T) {
cmOutputdesc, err := readCMOutputDescriptorFile("")
cmOutputdesc, err := getCMOutputDescriptorProvider("")
require.NoError(t, err)
require.Empty(t, cmOutputdesc)
})
t.Run("no such output descriptor file", // nolint:paralleltest
func(t *testing.T) {
cmOutputdesc, err := readCMOutputDescriptorFile("./testingWrongFile")
cmOutputdesc, err := getCMOutputDescriptorProvider("./testingWrongFile")
require.Error(t, err)
require.Equal(t, "read credential manifest descriptors file : open testingWrongFile: no such file or directory",
err.Error())
require.Contains(t, err.Error(), "read credential manifest descriptors file")
require.Nil(t, cmOutputdesc)
})
t.Run("aries-framework - failed to unmarshal credential manifest descriptors file", // nolint:paralleltest
Expand All @@ -666,7 +660,7 @@ func TestReadOutputDescriptorFile(t *testing.T) { // nolint:paralleltest
_, err = file.WriteString(cmDescDataWrongFormat)
require.NoError(t, err)

cmOutputdesc, err := readCMOutputDescriptorFile(file.Name())
cmOutputdesc, err := getCMOutputDescriptorProvider(file.Name())
require.Error(t, err)
require.Contains(t, err.Error(), "failed to unmarshal credential manifest descriptors file")
require.Nil(t, cmOutputdesc)
Expand All @@ -679,7 +673,7 @@ func TestReadOutputDescriptorFile(t *testing.T) { // nolint:paralleltest
_, err = file.WriteString(cmOutDescData)
require.NoError(t, err)

cmOutputdesc, err := readCMOutputDescriptorFile(file.Name())
cmOutputdesc, err := getCMOutputDescriptorProvider(file.Name())
require.Error(t, err)
require.Contains(t, err.Error(), "aries-framework - failed to validate output descriptors: "+
"missing ID for output descriptor")
Expand All @@ -693,7 +687,7 @@ func TestReadOutputDescriptorFile(t *testing.T) { // nolint:paralleltest
_, err = file.WriteString(cmDescData)
require.NoError(t, err)

cmDesc, err := readCMOutputDescriptorFile(file.Name())
cmDesc, err := getCMOutputDescriptorProvider(file.Name())
require.Error(t, err)
require.Contains(t, err.Error(), "aries-framework - failed to validate input descriptors")
require.Nil(t, cmDesc)
Expand Down
69 changes: 69 additions & 0 deletions pkg/memcmdescriptor/provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package memcmdescriptor

import (
"encoding/json"
"fmt"
"io"

"github.com/google/uuid"
"github.com/hyperledger/aries-framework-go/pkg/doc/cm"
"github.com/hyperledger/aries-framework-go/pkg/doc/presexch"
)

// CMAttachmentDescriptors defines the part of properties of credential manifest
type CMAttachmentDescriptors struct {
OutputDesc []*cm.OutputDescriptor `json:"output_descriptor,omitempty"`
// TODO [#Issue-612] Support for submission requirement will put whole presentation_definition here
// instead of input_descriptor
InputDesc []*presexch.InputDescriptor `json:"input_descriptor,omitempty"`
Options map[string]string `json:"options,omitempty"`
}

// Provider provide credential attachment descriptors ops.
type Provider struct {
cmDescriptors map[string]*CMAttachmentDescriptors
}

// New return new provider for credential manifest descriptor provider.
func New(cmDescriptorsFile io.Reader) (*Provider, error) {
p := &Provider{
cmDescriptors: map[string]*CMAttachmentDescriptors{},
}

err := json.NewDecoder(cmDescriptorsFile).Decode(&p.cmDescriptors)
if err != nil {
return nil, fmt.Errorf("failed to decode credential manifest descriptors file: %w", err)
}

for _, descriptors := range p.cmDescriptors {
err := cm.ValidateOutputDescriptors(descriptors.OutputDesc)
if err != nil {
return nil, fmt.Errorf("aries-framework - failed to validate output "+
"descriptors: %w", err)
}

if descriptors.InputDesc != nil {
presDef := presexch.PresentationDefinition{ID: uuid.NewString(), InputDescriptors: descriptors.InputDesc}

err := presDef.ValidateSchema()
if err != nil {
return nil, fmt.Errorf("aries-framework - failed to validate input "+
"descriptors: %w", err)
}
}
}

return p, nil
}

// FetchCMDescriptorsByScope allows to fetch the descriptor by scope
func (p *Provider) FetchCMDescriptorsByScope(scope string) (*CMAttachmentDescriptors, bool) {
descriptor, ok := p.cmDescriptors[scope]

return descriptor, ok
}
138 changes: 138 additions & 0 deletions pkg/memcmdescriptor/provider_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package memcmdescriptor

import (
"bytes"
"encoding/json"
"io"
"testing"

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

// nolint:gochecknoglobals
var cmOutDescData = `{
"udc-scope": {
"output_descriptor": [{
"uri": "https://trustbloc.github.io/context/vc/examples-ext-v1.jsonld"
}]
}
}`

// nolint:gochecknoglobals
var cmDescData = `
{
"prc":{
"output_descriptor":[
{
"id":"udc_output",
"schema":"https://www.w3.org/2018/credentials/examples/v1"
}
],
"input_descriptor":[
{
"id":"prc_input",
"schema":[
{
"uri":"https://w3id.org/citizenship#PermanentResidentCard"
}
]
}
]
}
}
`

// nolint:gochecknoglobals
var invalidCMDescData = `
{
"prc":{
"output_descriptor":[
{
"id":"udc_output",
"schema":"https://www.w3.org/2018/credentials/examples/v1"
}
],
"input_descriptor":[
{
"id":"prc_input"
}
]
}
}
`

func TestProvider_New(t *testing.T) {
t.Parallel()

t.Run("test success", func(t *testing.T) {
t.Parallel()

p, err := New(reader(t, map[string]*Provider{}))
require.NoError(t, err)
require.NotNil(t, p)
})

t.Run("test failed to decode credential manifest descriptors file", func(t *testing.T) {
t.Parallel()

_, err := New(bytes.NewReader([]byte("{")))
require.Error(t, err)
require.Contains(t, err.Error(), "failed to decode credential manifest descriptors file")
})
t.Run("aries-framework - failed to validate output descriptors", // nolint:paralleltest
func(t *testing.T) {
cmOutputdesc, err := New(bytes.NewReader([]byte(cmOutDescData)))
require.Error(t, err)
require.Contains(t, err.Error(), "aries-framework - failed to validate output descriptors: "+
"missing ID for output descriptor")
require.Nil(t, cmOutputdesc)
})
t.Run("aries-framework - failed to validate input descriptors", // nolint:paralleltest
func(t *testing.T) {
cmDesc, err := New(bytes.NewReader([]byte(invalidCMDescData)))
require.Error(t, err)
require.Contains(t, err.Error(), "aries-framework - failed to validate input descriptors")
require.Nil(t, cmDesc)
})
}

func TestFetchCMDescriptorsByScope(t *testing.T) {
t.Parallel()

t.Run("fetch cm descriptor success", func(t *testing.T) {
t.Parallel()

p, err := New(bytes.NewReader([]byte(cmDescData)))
require.NoError(t, err)
require.NotNil(t, p)

val, found := p.FetchCMDescriptorsByScope("prc")
require.True(t, found)
require.NotNil(t, val)
})
t.Run("fetch cm descriptor not found", func(t *testing.T) {
t.Parallel()

p, err := New(reader(t, map[string]*Provider{}))
require.NoError(t, err)
require.NotNil(t, p)

val, found := p.FetchCMDescriptorsByScope("prc")
require.False(t, found)
require.Nil(t, val)
})
}

func reader(t *testing.T, jsn interface{}) io.Reader {
t.Helper()

bits, err := json.Marshal(jsn)
require.NoError(t, err)

return bytes.NewReader(bits)
}
Loading

0 comments on commit 40b5615

Please sign in to comment.