From 419821d236f0f0d8310f6a92a76763e6351bdaad Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Fri, 18 Mar 2022 17:26:21 -0400 Subject: [PATCH 1/7] Add route to lookup identity by DID See #583 Signed-off-by: Andrew Richardson --- docs/swagger/swagger.yaml | 54 ++++++++++++++++++++ internal/apiserver/route_get_net_did.go | 44 ++++++++++++++++ internal/apiserver/route_get_net_did_test.go | 42 +++++++++++++++ internal/apiserver/routes.go | 1 + internal/networkmap/data_query.go | 10 ++++ internal/networkmap/manager.go | 1 + mocks/networkmapmocks/manager.go | 23 +++++++++ 7 files changed, 175 insertions(+) create mode 100644 internal/apiserver/route_get_net_did.go create mode 100644 internal/apiserver/route_get_net_did_test.go diff --git a/docs/swagger/swagger.yaml b/docs/swagger/swagger.yaml index cdb705564c..685b0ad47d 100644 --- a/docs/swagger/swagger.yaml +++ b/docs/swagger/swagger.yaml @@ -9043,6 +9043,60 @@ paths: description: Success default: description: "" + /network/did: + get: + description: 'TODO: Description' + operationId: getIdentityByDID + parameters: + - description: 'TODO: Description' + in: query + name: did + schema: + type: string + - description: Server-side request timeout (millseconds, or set a custom suffix + like 10s) + in: header + name: Request-Timeout + schema: + default: 120s + type: string + responses: + "200": + content: + application/json: + schema: + properties: + created: {} + description: + type: string + did: + type: string + id: {} + messages: + properties: + claim: {} + update: {} + verification: {} + type: object + name: + type: string + namespace: + type: string + parent: {} + profile: + additionalProperties: {} + type: object + type: + enum: + - org + - node + - custom + type: string + updated: {} + type: object + description: Success + default: + description: "" /network/nodes: get: description: 'TODO: Description' diff --git a/internal/apiserver/route_get_net_did.go b/internal/apiserver/route_get_net_did.go new file mode 100644 index 0000000000..25764efe0c --- /dev/null +++ b/internal/apiserver/route_get_net_did.go @@ -0,0 +1,44 @@ +// Copyright © 2022 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package apiserver + +import ( + "net/http" + + "github.com/hyperledger/firefly/internal/i18n" + "github.com/hyperledger/firefly/internal/oapispec" + "github.com/hyperledger/firefly/pkg/fftypes" +) + +var getIdentityByDID = &oapispec.Route{ + Name: "getIdentityByDID", + Path: "network/did", + Method: http.MethodGet, + PathParams: nil, + QueryParams: []*oapispec.QueryParam{ + {Name: "did", Description: i18n.MsgTBD}, + }, + FilterFactory: nil, + Description: i18n.MsgTBD, + JSONInputValue: nil, + JSONOutputValue: func() interface{} { return &fftypes.Identity{} }, + JSONOutputCodes: []int{http.StatusOK}, + JSONHandler: func(r *oapispec.APIRequest) (output interface{}, err error) { + output, err = getOr(r.Ctx).NetworkMap().GetIdentityByDID(r.Ctx, r.QP["did"]) + return output, err + }, +} diff --git a/internal/apiserver/route_get_net_did_test.go b/internal/apiserver/route_get_net_did_test.go new file mode 100644 index 0000000000..1eb3bdfa56 --- /dev/null +++ b/internal/apiserver/route_get_net_did_test.go @@ -0,0 +1,42 @@ +// Copyright © 2021 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package apiserver + +import ( + "net/http/httptest" + "testing" + + "github.com/hyperledger/firefly/mocks/networkmapmocks" + "github.com/hyperledger/firefly/pkg/fftypes" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func TestGetIdentityByDID(t *testing.T) { + o, r := newTestAPIServer() + nmn := &networkmapmocks.Manager{} + o.On("NetworkMap").Return(nmn) + req := httptest.NewRequest("GET", "/api/v1/network/did?did=did:firefly:org/org_1", nil) + req.Header.Set("Content-Type", "application/json; charset=utf-8") + res := httptest.NewRecorder() + + nmn.On("GetIdentityByDID", mock.Anything, "did:firefly:org/org_1"). + Return(&fftypes.Identity{}, nil) + r.ServeHTTP(res, req) + + assert.Equal(t, 200, res.Result().StatusCode) +} diff --git a/internal/apiserver/routes.go b/internal/apiserver/routes.go index 560c4b13a9..ff6a6e4989 100644 --- a/internal/apiserver/routes.go +++ b/internal/apiserver/routes.go @@ -47,6 +47,7 @@ var routes = []*oapispec.Route{ getGroups, getIdentities, getIdentityByID, + getIdentityByDID, getIdentityDID, getIdentityVerifiers, getMsgByID, diff --git a/internal/networkmap/data_query.go b/internal/networkmap/data_query.go index 4acf915895..c39810e93e 100644 --- a/internal/networkmap/data_query.go +++ b/internal/networkmap/data_query.go @@ -90,6 +90,16 @@ func (nm *networkMap) GetIdentityByID(ctx context.Context, ns, id string) (*ffty return identity, nil } +func (nm *networkMap) GetIdentityByDID(ctx context.Context, did string) (*fftypes.Identity, error) { + fb := database.IdentityQueryFactory.NewFilter(ctx) + filter := fb.And().Condition(fb.Eq("did", did)) + results, _, err := nm.database.GetIdentities(ctx, filter) + if err != nil || len(results) == 0 { + return nil, err + } + return results[0], nil +} + func (nm *networkMap) GetIdentities(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.Identity, *database.FilterResult, error) { filter.Condition(filter.Builder().Eq("namespace", ns)) return nm.database.GetIdentities(ctx, filter) diff --git a/internal/networkmap/manager.go b/internal/networkmap/manager.go index 6570fd7736..f8b1437d87 100644 --- a/internal/networkmap/manager.go +++ b/internal/networkmap/manager.go @@ -40,6 +40,7 @@ type Manager interface { GetNodeByID(ctx context.Context, id string) (*fftypes.Identity, error) GetNodes(ctx context.Context, filter database.AndFilter) ([]*fftypes.Identity, *database.FilterResult, error) GetIdentityByID(ctx context.Context, ns string, id string) (*fftypes.Identity, error) + GetIdentityByDID(ctx context.Context, did string) (*fftypes.Identity, error) GetIdentities(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.Identity, *database.FilterResult, error) GetIdentityVerifiers(ctx context.Context, ns, id string, filter database.AndFilter) ([]*fftypes.Verifier, *database.FilterResult, error) GetVerifiers(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.Verifier, *database.FilterResult, error) diff --git a/mocks/networkmapmocks/manager.go b/mocks/networkmapmocks/manager.go index 7ec1c297d3..4e6908e566 100644 --- a/mocks/networkmapmocks/manager.go +++ b/mocks/networkmapmocks/manager.go @@ -73,6 +73,29 @@ func (_m *Manager) GetIdentities(ctx context.Context, ns string, filter database return r0, r1, r2 } +// GetIdentityByDID provides a mock function with given fields: ctx, did +func (_m *Manager) GetIdentityByDID(ctx context.Context, did string) (*fftypes.Identity, error) { + ret := _m.Called(ctx, did) + + var r0 *fftypes.Identity + if rf, ok := ret.Get(0).(func(context.Context, string) *fftypes.Identity); ok { + r0 = rf(ctx, did) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fftypes.Identity) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, did) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetIdentityByID provides a mock function with given fields: ctx, ns, id func (_m *Manager) GetIdentityByID(ctx context.Context, ns string, id string) (*fftypes.Identity, error) { ret := _m.Called(ctx, ns, id) From 01b7833b748ab25a5b2c6fa1e56aa8e2567fb53f Mon Sep 17 00:00:00 2001 From: Peter Broadhurst Date: Sun, 20 Mar 2022 12:29:34 -0400 Subject: [PATCH 2/7] Use path param Signed-off-by: Peter Broadhurst --- docs/swagger/swagger.yaml | 5 +++-- internal/apiserver/route_get_net_did.go | 11 +++++------ internal/apiserver/route_get_net_did_test.go | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/swagger/swagger.yaml b/docs/swagger/swagger.yaml index 685b0ad47d..fffc38761d 100644 --- a/docs/swagger/swagger.yaml +++ b/docs/swagger/swagger.yaml @@ -9043,14 +9043,15 @@ paths: description: Success default: description: "" - /network/did: + /network/identities/{did:.+}: get: description: 'TODO: Description' operationId: getIdentityByDID parameters: - description: 'TODO: Description' - in: query + in: path name: did + required: true schema: type: string - description: Server-side request timeout (millseconds, or set a custom suffix diff --git a/internal/apiserver/route_get_net_did.go b/internal/apiserver/route_get_net_did.go index 25764efe0c..d7cfa1bdd1 100644 --- a/internal/apiserver/route_get_net_did.go +++ b/internal/apiserver/route_get_net_did.go @@ -25,11 +25,10 @@ import ( ) var getIdentityByDID = &oapispec.Route{ - Name: "getIdentityByDID", - Path: "network/did", - Method: http.MethodGet, - PathParams: nil, - QueryParams: []*oapispec.QueryParam{ + Name: "getIdentityByDID", + Path: "network/identities/{did:.+}", + Method: http.MethodGet, + PathParams: []*oapispec.PathParam{ {Name: "did", Description: i18n.MsgTBD}, }, FilterFactory: nil, @@ -38,7 +37,7 @@ var getIdentityByDID = &oapispec.Route{ JSONOutputValue: func() interface{} { return &fftypes.Identity{} }, JSONOutputCodes: []int{http.StatusOK}, JSONHandler: func(r *oapispec.APIRequest) (output interface{}, err error) { - output, err = getOr(r.Ctx).NetworkMap().GetIdentityByDID(r.Ctx, r.QP["did"]) + output, err = getOr(r.Ctx).NetworkMap().GetIdentityByDID(r.Ctx, r.PP["did"]) return output, err }, } diff --git a/internal/apiserver/route_get_net_did_test.go b/internal/apiserver/route_get_net_did_test.go index 1eb3bdfa56..a0eb5c4968 100644 --- a/internal/apiserver/route_get_net_did_test.go +++ b/internal/apiserver/route_get_net_did_test.go @@ -30,7 +30,7 @@ func TestGetIdentityByDID(t *testing.T) { o, r := newTestAPIServer() nmn := &networkmapmocks.Manager{} o.On("NetworkMap").Return(nmn) - req := httptest.NewRequest("GET", "/api/v1/network/did?did=did:firefly:org/org_1", nil) + req := httptest.NewRequest("GET", "/api/v1/network/identities/did:firefly:org/org_1", nil) req.Header.Set("Content-Type", "application/json; charset=utf-8") res := httptest.NewRecorder() From 69aab3540b8760601b939151a35a157cdbd36895 Mon Sep 17 00:00:00 2001 From: Peter Broadhurst Date: Sun, 20 Mar 2022 12:40:11 -0400 Subject: [PATCH 3/7] Remove gorilla mux custom regex syntax from swagger Signed-off-by: Peter Broadhurst --- docs/swagger/swagger.yaml | 2 +- internal/oapispec/openapi3.go | 4 ++++ internal/oapispec/openapi3_test.go | 21 +++++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/docs/swagger/swagger.yaml b/docs/swagger/swagger.yaml index 66ac8ee68b..cba44ea94d 100644 --- a/docs/swagger/swagger.yaml +++ b/docs/swagger/swagger.yaml @@ -9069,7 +9069,7 @@ paths: description: Success default: description: "" - /network/identities/{did:.+}: + /network/identities/{did}: get: description: 'TODO: Description' operationId: getIdentityByDID diff --git a/internal/oapispec/openapi3.go b/internal/oapispec/openapi3.go index fbd53e5837..1c95cdd095 100644 --- a/internal/oapispec/openapi3.go +++ b/internal/oapispec/openapi3.go @@ -23,6 +23,7 @@ import ( "log" "net/http" "reflect" + "regexp" "sort" "strconv" "strings" @@ -41,6 +42,8 @@ type SwaggerGenConfig struct { Description string } +var customRegexRemoval = regexp.MustCompile(`{(\w+)\:[^}]+}`) + func SwaggerGen(ctx context.Context, routes []*Route, conf *SwaggerGenConfig) *openapi3.T { doc := &openapi3.T{ @@ -72,6 +75,7 @@ func getPathItem(doc *openapi3.T, path string) *openapi3.PathItem { if !strings.HasPrefix(path, "/") { path = "/" + path } + path = customRegexRemoval.ReplaceAllString(path, `{$1}`) if doc.Paths == nil { doc.Paths = openapi3.Paths{} } diff --git a/internal/oapispec/openapi3_test.go b/internal/oapispec/openapi3_test.go index 6fd85ce061..f9b3afe587 100644 --- a/internal/oapispec/openapi3_test.go +++ b/internal/oapispec/openapi3_test.go @@ -178,3 +178,24 @@ func TestBadCustomSchema(t *testing.T) { }) }) } + +func TestWildcards(t *testing.T) { + + config.Reset() + routes := []*Route{ + { + Name: "op1", + Path: "namespaces/{ns}/example1/{id:.*wildcard.*}", + Method: http.MethodPost, + JSONInputValue: func() interface{} { return &fftypes.Message{} }, + JSONInputMask: []string{"id"}, + JSONOutputCodes: []int{http.StatusOK}, + }, + } + swagger := SwaggerGen(context.Background(), routes, &SwaggerGenConfig{ + Title: "UnitTest", + Version: "1.0", + BaseURL: "http://localhost:12345/api/v1", + }) + assert.NotNil(t, swagger.Paths["/namespaces/{ns}/example1/{id}"]) +} From a20e09f6bc3a4b36f8214e5077fd1d6cfd4a2137 Mon Sep 17 00:00:00 2001 From: Peter Broadhurst Date: Sun, 20 Mar 2022 23:25:03 -0400 Subject: [PATCH 4/7] Fix coverage miss Signed-off-by: Peter Broadhurst --- internal/networkmap/data_query.go | 5 +++- internal/networkmap/data_query_test.go | 36 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/internal/networkmap/data_query.go b/internal/networkmap/data_query.go index 7dd75661dd..589b6a341b 100644 --- a/internal/networkmap/data_query.go +++ b/internal/networkmap/data_query.go @@ -100,9 +100,12 @@ func (nm *networkMap) GetIdentityByDID(ctx context.Context, did string) (*fftype fb := database.IdentityQueryFactory.NewFilter(ctx) filter := fb.And().Condition(fb.Eq("did", did)) results, _, err := nm.database.GetIdentities(ctx, filter) - if err != nil || len(results) == 0 { + if err != nil { return nil, err } + if len(results) == 0 { + return nil, i18n.NewError(ctx, i18n.Msg404NotFound) + } return results[0], nil } diff --git a/internal/networkmap/data_query_test.go b/internal/networkmap/data_query_test.go index 6644766a69..16cb01612a 100644 --- a/internal/networkmap/data_query_test.go +++ b/internal/networkmap/data_query_test.go @@ -286,3 +286,39 @@ func TestGetVerifierByHashBadUUID(t *testing.T) { _, err := nm.GetVerifierByHash(nm.ctx, "ns1", "bad") assert.Regexp(t, "FF10232", err) } + +func TestGetVerifierByDIDOk(t *testing.T) { + nm, cancel := newTestNetworkmap(t) + defer cancel() + nm.database.(*databasemocks.Plugin).On("GetIdentities", nm.ctx, mock.MatchedBy(func(f database.Filter) bool { + fi, err := f.Finalize() + assert.NoError(t, err) + v, err := fi.Children[0].Value.Value() + assert.NoError(t, err) + return v == "did:firefly:org/abc" + })). + Return([]*fftypes.Identity{testOrg("abc")}, nil, nil) + id, err := nm.GetIdentityByDID(nm.ctx, "did:firefly:org/abc") + assert.NoError(t, err) + assert.Equal(t, "did:firefly:org/abc", id.DID) +} + +func TestGetVerifierByDIDNotFound(t *testing.T) { + nm, cancel := newTestNetworkmap(t) + defer cancel() + nm.database.(*databasemocks.Plugin).On("GetIdentities", nm.ctx, mock.Anything). + Return([]*fftypes.Identity{}, nil, nil) + id, err := nm.GetIdentityByDID(nm.ctx, "did:firefly:org/abc") + assert.Regexp(t, "FF10109", err) + assert.Nil(t, id) +} + +func TestGetVerifierByDIDNotErr(t *testing.T) { + nm, cancel := newTestNetworkmap(t) + defer cancel() + nm.database.(*databasemocks.Plugin).On("GetIdentities", nm.ctx, mock.Anything). + Return(nil, nil, fmt.Errorf("pop")) + id, err := nm.GetIdentityByDID(nm.ctx, "did:firefly:org/abc") + assert.Regexp(t, "pop", err) + assert.Nil(t, id) +} From fd139928fc543c5335b067d80b90a74eb873852b Mon Sep 17 00:00:00 2001 From: Peter Broadhurst Date: Mon, 21 Mar 2022 08:55:34 -0400 Subject: [PATCH 5/7] Use standard cached lookup mechanism for DID route and resolve parents by DID/org-name in identity registration Signed-off-by: Peter Broadhurst --- internal/networkmap/data_query.go | 8 ++-- internal/networkmap/data_query_test.go | 19 ++++----- internal/networkmap/register_identity.go | 16 ++++++- internal/networkmap/register_identity_test.go | 42 +++++++++++++++---- internal/networkmap/register_node.go | 2 +- pkg/fftypes/identity.go | 2 +- 6 files changed, 61 insertions(+), 28 deletions(-) diff --git a/internal/networkmap/data_query.go b/internal/networkmap/data_query.go index 589b6a341b..d150c6a5f3 100644 --- a/internal/networkmap/data_query.go +++ b/internal/networkmap/data_query.go @@ -97,16 +97,14 @@ func (nm *networkMap) GetIdentityByID(ctx context.Context, ns, id string) (*ffty } func (nm *networkMap) GetIdentityByDID(ctx context.Context, did string) (*fftypes.Identity, error) { - fb := database.IdentityQueryFactory.NewFilter(ctx) - filter := fb.And().Condition(fb.Eq("did", did)) - results, _, err := nm.database.GetIdentities(ctx, filter) + identity, _, err := nm.identity.CachedIdentityLookup(ctx, did) if err != nil { return nil, err } - if len(results) == 0 { + if identity == nil { return nil, i18n.NewError(ctx, i18n.Msg404NotFound) } - return results[0], nil + return identity, nil } func (nm *networkMap) GetIdentities(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.Identity, *database.FilterResult, error) { diff --git a/internal/networkmap/data_query_test.go b/internal/networkmap/data_query_test.go index 16cb01612a..364a270062 100644 --- a/internal/networkmap/data_query_test.go +++ b/internal/networkmap/data_query_test.go @@ -21,6 +21,7 @@ import ( "testing" "github.com/hyperledger/firefly/mocks/databasemocks" + "github.com/hyperledger/firefly/mocks/identitymanagermocks" "github.com/hyperledger/firefly/pkg/database" "github.com/hyperledger/firefly/pkg/fftypes" "github.com/stretchr/testify/assert" @@ -290,14 +291,8 @@ func TestGetVerifierByHashBadUUID(t *testing.T) { func TestGetVerifierByDIDOk(t *testing.T) { nm, cancel := newTestNetworkmap(t) defer cancel() - nm.database.(*databasemocks.Plugin).On("GetIdentities", nm.ctx, mock.MatchedBy(func(f database.Filter) bool { - fi, err := f.Finalize() - assert.NoError(t, err) - v, err := fi.Children[0].Value.Value() - assert.NoError(t, err) - return v == "did:firefly:org/abc" - })). - Return([]*fftypes.Identity{testOrg("abc")}, nil, nil) + nm.identity.(*identitymanagermocks.Manager).On("CachedIdentityLookup", nm.ctx, "did:firefly:org/abc"). + Return(testOrg("abc"), true, nil) id, err := nm.GetIdentityByDID(nm.ctx, "did:firefly:org/abc") assert.NoError(t, err) assert.Equal(t, "did:firefly:org/abc", id.DID) @@ -306,8 +301,8 @@ func TestGetVerifierByDIDOk(t *testing.T) { func TestGetVerifierByDIDNotFound(t *testing.T) { nm, cancel := newTestNetworkmap(t) defer cancel() - nm.database.(*databasemocks.Plugin).On("GetIdentities", nm.ctx, mock.Anything). - Return([]*fftypes.Identity{}, nil, nil) + nm.identity.(*identitymanagermocks.Manager).On("CachedIdentityLookup", nm.ctx, "did:firefly:org/abc"). + Return(nil, true, nil) id, err := nm.GetIdentityByDID(nm.ctx, "did:firefly:org/abc") assert.Regexp(t, "FF10109", err) assert.Nil(t, id) @@ -316,8 +311,8 @@ func TestGetVerifierByDIDNotFound(t *testing.T) { func TestGetVerifierByDIDNotErr(t *testing.T) { nm, cancel := newTestNetworkmap(t) defer cancel() - nm.database.(*databasemocks.Plugin).On("GetIdentities", nm.ctx, mock.Anything). - Return(nil, nil, fmt.Errorf("pop")) + nm.identity.(*identitymanagermocks.Manager).On("CachedIdentityLookup", nm.ctx, "did:firefly:org/abc"). + Return(nil, true, fmt.Errorf("pop")) id, err := nm.GetIdentityByDID(nm.ctx, "did:firefly:org/abc") assert.Regexp(t, "pop", err) assert.Nil(t, id) diff --git a/internal/networkmap/register_identity.go b/internal/networkmap/register_identity.go index a2956abfe4..8cd0fb5aea 100644 --- a/internal/networkmap/register_identity.go +++ b/internal/networkmap/register_identity.go @@ -25,6 +25,20 @@ import ( func (nm *networkMap) RegisterIdentity(ctx context.Context, ns string, dto *fftypes.IdentityCreateDTO, waitConfirm bool) (identity *fftypes.Identity, err error) { + // The parent can be a UUID directly + var parent *fftypes.UUID + if dto.Parent != "" { + parent, err = fftypes.ParseUUID(ctx, dto.Parent) + if err != nil { + // Or a DID + parentIdentity, _, err := nm.identity.CachedIdentityLookup(ctx, dto.Parent) + if err != nil { + return nil, err + } + parent = parentIdentity.ID + } + } + // Parse the input DTO identity = &fftypes.Identity{ IdentityBase: fftypes.IdentityBase{ @@ -32,7 +46,7 @@ func (nm *networkMap) RegisterIdentity(ctx context.Context, ns string, dto *ffty Namespace: ns, Name: dto.Name, Type: dto.Type, - Parent: dto.Parent, + Parent: parent, }, IdentityProfile: fftypes.IdentityProfile{ Description: dto.Description, diff --git a/internal/networkmap/register_identity_test.go b/internal/networkmap/register_identity_test.go index 1ae41c53a7..f578e43af7 100644 --- a/internal/networkmap/register_identity_test.go +++ b/internal/networkmap/register_identity_test.go @@ -66,7 +66,7 @@ func TestRegisterIdentityOrgWithParentOk(t *testing.T) { org, err := nm.RegisterIdentity(nm.ctx, fftypes.SystemNamespace, &fftypes.IdentityCreateDTO{ Name: "child1", Key: "0x12345", - Parent: fftypes.NewUUID(), + Parent: fftypes.NewUUID().String(), }, false) assert.NoError(t, err) assert.Equal(t, *mockMsg1.Header.ID, *org.Messages.Claim) @@ -124,7 +124,7 @@ func TestRegisterIdentityOrgWithParentWaitConfirmOk(t *testing.T) { _, err := nm.RegisterIdentity(nm.ctx, fftypes.SystemNamespace, &fftypes.IdentityCreateDTO{ Name: "child1", Key: "0x12345", - Parent: fftypes.NewUUID(), + Parent: fftypes.NewUUID().String(), }, true) assert.NoError(t, err) @@ -142,6 +142,12 @@ func TestRegisterIdentityCustomWithParentFail(t *testing.T) { mim := nm.identity.(*identitymanagermocks.Manager) mim.On("VerifyIdentityChain", nm.ctx, mock.AnythingOfType("*fftypes.Identity")).Return(parentIdentity, false, nil) + mim.On("CachedIdentityLookup", nm.ctx, "did:firefly:org/parent1").Return(&fftypes.Identity{ + IdentityBase: fftypes.IdentityBase{ + ID: fftypes.NewUUID(), + DID: "did:firefly:org/parent1", + }, + }, false, nil) mim.On("ResolveIdentitySigner", nm.ctx, parentIdentity).Return(&fftypes.SignerRef{ Key: "0x23456", }, nil) @@ -168,7 +174,7 @@ func TestRegisterIdentityCustomWithParentFail(t *testing.T) { _, err := nm.RegisterIdentity(nm.ctx, "ns1", &fftypes.IdentityCreateDTO{ Name: "custom1", Key: "0x12345", - Parent: fftypes.NewUUID(), + Parent: "did:firefly:org/parent1", }, false) assert.Regexp(t, "pop", err) @@ -190,7 +196,7 @@ func TestRegisterIdentityGetParentMsgFail(t *testing.T) { _, err := nm.RegisterIdentity(nm.ctx, "ns1", &fftypes.IdentityCreateDTO{ Name: "custom1", Key: "0x12345", - Parent: fftypes.NewUUID(), + Parent: fftypes.NewUUID().String(), }, false) assert.Regexp(t, "pop", err) @@ -215,8 +221,9 @@ func TestRegisterIdentityRootBroadcastFail(t *testing.T) { fftypes.SystemTagIdentityClaim, false).Return(nil, fmt.Errorf("pop")) _, err := nm.RegisterIdentity(nm.ctx, "ns1", &fftypes.IdentityCreateDTO{ - Name: "custom1", - Key: "0x12345", + Name: "custom1", + Key: "0x12345", + Parent: fftypes.NewUUID().String(), }, false) assert.Regexp(t, "pop", err) @@ -233,7 +240,8 @@ func TestRegisterIdentityMissingKey(t *testing.T) { mim.On("VerifyIdentityChain", nm.ctx, mock.AnythingOfType("*fftypes.Identity")).Return(nil, false, nil) _, err := nm.RegisterIdentity(nm.ctx, "ns1", &fftypes.IdentityCreateDTO{ - Name: "custom1", + Name: "custom1", + Parent: fftypes.NewUUID().String(), }, false) assert.Regexp(t, "FF10352", err) @@ -249,7 +257,25 @@ func TestRegisterIdentityVerifyFail(t *testing.T) { mim.On("VerifyIdentityChain", nm.ctx, mock.AnythingOfType("*fftypes.Identity")).Return(nil, false, fmt.Errorf("pop")) _, err := nm.RegisterIdentity(nm.ctx, "ns1", &fftypes.IdentityCreateDTO{ - Name: "custom1", + Name: "custom1", + Parent: fftypes.NewUUID().String(), + }, false) + assert.Regexp(t, "pop", err) + + mim.AssertExpectations(t) +} + +func TestRegisterIdentityBadParent(t *testing.T) { + + nm, cancel := newTestNetworkmap(t) + defer cancel() + + mim := nm.identity.(*identitymanagermocks.Manager) + mim.On("CachedIdentityLookup", nm.ctx, "did:firefly:org/1").Return(nil, false, fmt.Errorf("pop")) + + _, err := nm.RegisterIdentity(nm.ctx, "ns1", &fftypes.IdentityCreateDTO{ + Name: "custom1", + Parent: "did:firefly:org/1", }, false) assert.Regexp(t, "pop", err) diff --git a/internal/networkmap/register_node.go b/internal/networkmap/register_node.go index f860f86b01..12c106ca93 100644 --- a/internal/networkmap/register_node.go +++ b/internal/networkmap/register_node.go @@ -32,7 +32,7 @@ func (nm *networkMap) RegisterNode(ctx context.Context, waitConfirm bool) (ident } nodeRequest := &fftypes.IdentityCreateDTO{ - Parent: nodeOwningOrg.ID, + Parent: nodeOwningOrg.ID.String(), Name: config.GetString(config.NodeName), Type: fftypes.IdentityTypeNode, IdentityProfile: fftypes.IdentityProfile{ diff --git a/pkg/fftypes/identity.go b/pkg/fftypes/identity.go index e0f17d164d..5d3cab7055 100644 --- a/pkg/fftypes/identity.go +++ b/pkg/fftypes/identity.go @@ -82,7 +82,7 @@ type Identity struct { type IdentityCreateDTO struct { Name string `json:"name"` Type IdentityType `json:"type,omitempty"` - Parent *UUID `json:"parent,omitempty"` + Parent string `json:"parent,omitempty"` // can be a DID for resolution, or the UUID directly Key string `json:"key,omitempty"` IdentityProfile } From f1e5bd8270119962ca44397e88542fbca094ead6 Mon Sep 17 00:00:00 2001 From: Peter Broadhurst Date: Mon, 21 Mar 2022 09:07:40 -0400 Subject: [PATCH 6/7] Swagger build mismatch Signed-off-by: Peter Broadhurst --- docs/swagger/swagger.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/swagger/swagger.yaml b/docs/swagger/swagger.yaml index cba44ea94d..ba0bc5d61c 100644 --- a/docs/swagger/swagger.yaml +++ b/docs/swagger/swagger.yaml @@ -9597,7 +9597,8 @@ paths: type: string name: type: string - parent: {} + parent: + type: string profile: additionalProperties: {} type: object From a2aaa4cd7cabf3ac5b7747bc59c0cb9ae5a489bc Mon Sep 17 00:00:00 2001 From: Nicko Guyer Date: Mon, 21 Mar 2022 11:11:26 -0400 Subject: [PATCH 7/7] Fix identity E2E test Signed-off-by: Nicko Guyer --- test/e2e/restclient_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/restclient_test.go b/test/e2e/restclient_test.go index c5210f5a31..19976e424e 100644 --- a/test/e2e/restclient_test.go +++ b/test/e2e/restclient_test.go @@ -263,7 +263,7 @@ func ClaimCustomIdentity(t *testing.T, client *resty.Client, key, name, desc str SetBody(fftypes.IdentityCreateDTO{ Name: name, Type: fftypes.IdentityTypeCustom, - Parent: parent, + Parent: parent.String(), Key: key, IdentityProfile: fftypes.IdentityProfile{ Description: desc,