From a4972b7fe5fa97665eff9b6d15879b5447f37ead Mon Sep 17 00:00:00 2001 From: Alex Shorsher Date: Mon, 11 Jul 2022 08:50:42 -0400 Subject: [PATCH 1/2] disable contract routes when missing blockchain Signed-off-by: Alex Shorsher --- internal/apiserver/route_get_contract_api_by_name.go | 4 ++++ internal/apiserver/route_get_contract_api_interface.go | 4 ++++ internal/apiserver/route_get_contract_api_listeners.go | 4 ++++ internal/apiserver/route_get_contract_apis.go | 4 ++++ internal/apiserver/route_get_contract_interface.go | 4 ++++ .../route_get_contract_interface_name_version.go | 4 ++++ .../apiserver/route_get_contract_interface_test.go | 1 + internal/apiserver/route_get_contract_interfaces.go | 4 ++++ .../route_get_contract_listener_by_name_or_id.go | 4 ++++ internal/apiserver/route_get_contract_listeners.go | 4 ++++ internal/apiserver/route_post_contract_api_invoke.go | 4 ++++ .../apiserver/route_post_contract_api_listeners.go | 4 ++++ internal/apiserver/route_post_contract_api_query.go | 4 ++++ .../route_post_contract_interface_generate.go | 4 ++++ internal/apiserver/route_post_contract_invoke.go | 4 ++++ internal/apiserver/route_post_contract_query.go | 4 ++++ internal/apiserver/route_post_new_contract_api.go | 4 ++++ internal/apiserver/route_post_new_contract_api_test.go | 3 +++ .../apiserver/route_post_new_contract_interface.go | 4 ++++ .../route_post_new_contract_interface_test.go | 3 +++ internal/apiserver/route_post_new_contract_listener.go | 4 ++++ internal/apiserver/route_put_contract_api.go | 4 ++++ internal/apiserver/route_put_contract_api_test.go | 3 +++ internal/coremsgs/en_error_messages.go | 1 + internal/orchestrator/orchestrator.go | 10 ++++++---- 25 files changed, 93 insertions(+), 4 deletions(-) diff --git a/internal/apiserver/route_get_contract_api_by_name.go b/internal/apiserver/route_get_contract_api_by_name.go index dc87e580d8..4df16be897 100644 --- a/internal/apiserver/route_get_contract_api_by_name.go +++ b/internal/apiserver/route_get_contract_api_by_name.go @@ -21,6 +21,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -37,6 +38,9 @@ var getContractAPIByName = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.ContractAPI{} }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { return cr.or.Contracts().GetContractAPI(cr.ctx, cr.apiBaseURL, r.PP["apiName"]) }, diff --git a/internal/apiserver/route_get_contract_api_interface.go b/internal/apiserver/route_get_contract_api_interface.go index e7cbae6a86..9b17a1d4d6 100644 --- a/internal/apiserver/route_get_contract_api_interface.go +++ b/internal/apiserver/route_get_contract_api_interface.go @@ -22,6 +22,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" ) var getContractAPIInterface = &ffapi.Route{ @@ -37,6 +38,9 @@ var getContractAPIInterface = &ffapi.Route{ JSONOutputValue: func() interface{} { return &fftypes.FFI{} }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { return cr.or.Contracts().GetContractAPIInterface(cr.ctx, r.PP["apiName"]) }, diff --git a/internal/apiserver/route_get_contract_api_listeners.go b/internal/apiserver/route_get_contract_api_listeners.go index 818716ddac..fd5fed0a38 100644 --- a/internal/apiserver/route_get_contract_api_listeners.go +++ b/internal/apiserver/route_get_contract_api_listeners.go @@ -21,6 +21,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" "github.com/hyperledger/firefly/pkg/database" ) @@ -39,6 +40,9 @@ var getContractAPIListeners = &ffapi.Route{ JSONOutputValue: func() interface{} { return []*core.ContractListener{} }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, FilterFactory: database.ContractListenerQueryFactory, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { return filterResult(cr.or.Contracts().GetContractAPIListeners(cr.ctx, r.PP["apiName"], r.PP["eventPath"], cr.filter)) diff --git a/internal/apiserver/route_get_contract_apis.go b/internal/apiserver/route_get_contract_apis.go index 6a739f4fcf..a061f73b13 100644 --- a/internal/apiserver/route_get_contract_apis.go +++ b/internal/apiserver/route_get_contract_apis.go @@ -21,6 +21,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" "github.com/hyperledger/firefly/pkg/database" ) @@ -36,6 +37,9 @@ var getContractAPIs = &ffapi.Route{ JSONOutputValue: func() interface{} { return []*core.ContractAPI{} }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, FilterFactory: database.ContractAPIQueryFactory, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { return filterResult(cr.or.Contracts().GetContractAPIs(cr.ctx, cr.apiBaseURL, cr.filter)) diff --git a/internal/apiserver/route_get_contract_interface.go b/internal/apiserver/route_get_contract_interface.go index 05365baa88..e35ec0a1ef 100644 --- a/internal/apiserver/route_get_contract_interface.go +++ b/internal/apiserver/route_get_contract_interface.go @@ -23,6 +23,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" ) var getContractInterface = &ffapi.Route{ @@ -40,6 +41,9 @@ var getContractInterface = &ffapi.Route{ JSONOutputValue: func() interface{} { return &fftypes.FFI{} }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { interfaceID, err := fftypes.ParseUUID(cr.ctx, r.PP["interfaceId"]) if err != nil { diff --git a/internal/apiserver/route_get_contract_interface_name_version.go b/internal/apiserver/route_get_contract_interface_name_version.go index ac19838f54..4c2d5d90f7 100644 --- a/internal/apiserver/route_get_contract_interface_name_version.go +++ b/internal/apiserver/route_get_contract_interface_name_version.go @@ -23,6 +23,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" ) var getContractInterfaceNameVersion = &ffapi.Route{ @@ -41,6 +42,9 @@ var getContractInterfaceNameVersion = &ffapi.Route{ JSONOutputValue: func() interface{} { return &fftypes.FFI{} }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { if strings.EqualFold(r.QP["fetchchildren"], "true") { return cr.or.Contracts().GetFFIWithChildren(cr.ctx, r.PP["name"], r.PP["version"]) diff --git a/internal/apiserver/route_get_contract_interface_test.go b/internal/apiserver/route_get_contract_interface_test.go index 7d4b60e6e2..a69f0a0329 100644 --- a/internal/apiserver/route_get_contract_interface_test.go +++ b/internal/apiserver/route_get_contract_interface_test.go @@ -32,6 +32,7 @@ import ( func TestGetContractInterfaceBadID(t *testing.T) { o, r := newTestAPIServer() o.On("Authorize", mock.Anything, mock.Anything).Return(nil) + o.On("Contracts").Return(&contractmocks.Manager{}) input := core.Datatype{} var buf bytes.Buffer json.NewEncoder(&buf).Encode(&input) diff --git a/internal/apiserver/route_get_contract_interfaces.go b/internal/apiserver/route_get_contract_interfaces.go index 96617bc2bd..16d60ac055 100644 --- a/internal/apiserver/route_get_contract_interfaces.go +++ b/internal/apiserver/route_get_contract_interfaces.go @@ -22,6 +22,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/database" ) @@ -36,6 +37,9 @@ var getContractInterfaces = &ffapi.Route{ JSONOutputValue: func() interface{} { return []*fftypes.FFI{} }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, FilterFactory: database.FFIQueryFactory, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { return filterResult(cr.or.Contracts().GetFFIs(cr.ctx, cr.filter)) diff --git a/internal/apiserver/route_get_contract_listener_by_name_or_id.go b/internal/apiserver/route_get_contract_listener_by_name_or_id.go index 1704e4cbb0..7424515f02 100644 --- a/internal/apiserver/route_get_contract_listener_by_name_or_id.go +++ b/internal/apiserver/route_get_contract_listener_by_name_or_id.go @@ -21,6 +21,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -37,6 +38,9 @@ var getContractListenerByNameOrID = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.ContractListener{} }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { return cr.or.Contracts().GetContractListenerByNameOrID(cr.ctx, r.PP["nameOrId"]) }, diff --git a/internal/apiserver/route_get_contract_listeners.go b/internal/apiserver/route_get_contract_listeners.go index baab052406..e0eb7bdfce 100644 --- a/internal/apiserver/route_get_contract_listeners.go +++ b/internal/apiserver/route_get_contract_listeners.go @@ -21,6 +21,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" "github.com/hyperledger/firefly/pkg/database" ) @@ -36,6 +37,9 @@ var getContractListeners = &ffapi.Route{ JSONOutputValue: func() interface{} { return []*core.ContractListener{} }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, FilterFactory: database.ContractListenerQueryFactory, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { return filterResult(cr.or.Contracts().GetContractListeners(cr.ctx, cr.filter)) diff --git a/internal/apiserver/route_post_contract_api_invoke.go b/internal/apiserver/route_post_contract_api_invoke.go index dbc4e0807b..2b0bf89441 100644 --- a/internal/apiserver/route_post_contract_api_invoke.go +++ b/internal/apiserver/route_post_contract_api_invoke.go @@ -22,6 +22,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -41,6 +42,9 @@ var postContractAPIInvoke = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.Operation{} }, JSONOutputCodes: []int{http.StatusOK, http.StatusAccepted}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) diff --git a/internal/apiserver/route_post_contract_api_listeners.go b/internal/apiserver/route_post_contract_api_listeners.go index c2130fe873..2ec2aecbe7 100644 --- a/internal/apiserver/route_post_contract_api_listeners.go +++ b/internal/apiserver/route_post_contract_api_listeners.go @@ -21,6 +21,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -38,6 +39,9 @@ var postContractAPIListeners = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.ContractListener{} }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { return cr.or.Contracts().AddContractAPIListener(cr.ctx, r.PP["apiName"], r.PP["eventPath"], r.Input.(*core.ContractListener)) }, diff --git a/internal/apiserver/route_post_contract_api_query.go b/internal/apiserver/route_post_contract_api_query.go index 004b0e9d9b..4b685d9bb4 100644 --- a/internal/apiserver/route_post_contract_api_query.go +++ b/internal/apiserver/route_post_contract_api_query.go @@ -21,6 +21,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -38,6 +39,9 @@ var postContractAPIQuery = &ffapi.Route{ JSONOutputValue: func() interface{} { return make(map[string]interface{}) }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { req := r.Input.(*core.ContractCallRequest) req.Type = core.CallTypeQuery diff --git a/internal/apiserver/route_post_contract_interface_generate.go b/internal/apiserver/route_post_contract_interface_generate.go index ec0b527133..0f3136a406 100644 --- a/internal/apiserver/route_post_contract_interface_generate.go +++ b/internal/apiserver/route_post_contract_interface_generate.go @@ -22,6 +22,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" ) var postContractInterfaceGenerate = &ffapi.Route{ @@ -35,6 +36,9 @@ var postContractInterfaceGenerate = &ffapi.Route{ JSONOutputValue: func() interface{} { return &fftypes.FFI{} }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { generationRequest := r.Input.(*fftypes.FFIGenerationRequest) return cr.or.Contracts().GenerateFFI(cr.ctx, generationRequest) diff --git a/internal/apiserver/route_post_contract_invoke.go b/internal/apiserver/route_post_contract_invoke.go index 02779e311b..69bd84db93 100644 --- a/internal/apiserver/route_post_contract_invoke.go +++ b/internal/apiserver/route_post_contract_invoke.go @@ -22,6 +22,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -38,6 +39,9 @@ var postContractInvoke = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.Operation{} }, JSONOutputCodes: []int{http.StatusOK, http.StatusAccepted}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) diff --git a/internal/apiserver/route_post_contract_query.go b/internal/apiserver/route_post_contract_query.go index e7fd49df1a..9d39973878 100644 --- a/internal/apiserver/route_post_contract_query.go +++ b/internal/apiserver/route_post_contract_query.go @@ -21,6 +21,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -35,6 +36,9 @@ var postContractQuery = &ffapi.Route{ JSONOutputValue: func() interface{} { return make(map[string]interface{}) }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { req := r.Input.(*core.ContractCallRequest) req.Type = core.CallTypeQuery diff --git a/internal/apiserver/route_post_new_contract_api.go b/internal/apiserver/route_post_new_contract_api.go index 5ae7496e2b..f5bf7a9f2e 100644 --- a/internal/apiserver/route_post_new_contract_api.go +++ b/internal/apiserver/route_post_new_contract_api.go @@ -22,6 +22,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -38,6 +39,9 @@ var postNewContractAPI = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.ContractAPI{} }, JSONOutputCodes: []int{http.StatusOK, http.StatusAccepted}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) diff --git a/internal/apiserver/route_post_new_contract_api_test.go b/internal/apiserver/route_post_new_contract_api_test.go index ec8ba24f16..97c668e6cd 100644 --- a/internal/apiserver/route_post_new_contract_api_test.go +++ b/internal/apiserver/route_post_new_contract_api_test.go @@ -22,6 +22,7 @@ import ( "net/http/httptest" "testing" + "github.com/hyperledger/firefly/mocks/contractmocks" "github.com/hyperledger/firefly/mocks/definitionsmocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" @@ -32,6 +33,7 @@ func TestPostNewContractAPI(t *testing.T) { o, r := newTestAPIServer() o.On("Authorize", mock.Anything, mock.Anything).Return(nil) mds := &definitionsmocks.Sender{} + o.On("Contracts").Return(&contractmocks.Manager{}) o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer @@ -50,6 +52,7 @@ func TestPostNewContractAPISync(t *testing.T) { o, r := newTestAPIServer() o.On("Authorize", mock.Anything, mock.Anything).Return(nil) mds := &definitionsmocks.Sender{} + o.On("Contracts").Return(&contractmocks.Manager{}) o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer diff --git a/internal/apiserver/route_post_new_contract_interface.go b/internal/apiserver/route_post_new_contract_interface.go index 4aecbbcc2d..1b408739ab 100644 --- a/internal/apiserver/route_post_new_contract_interface.go +++ b/internal/apiserver/route_post_new_contract_interface.go @@ -23,6 +23,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" ) var postNewContractInterface = &ffapi.Route{ @@ -38,6 +39,9 @@ var postNewContractInterface = &ffapi.Route{ JSONOutputValue: func() interface{} { return &fftypes.FFI{} }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) diff --git a/internal/apiserver/route_post_new_contract_interface_test.go b/internal/apiserver/route_post_new_contract_interface_test.go index b46ceb57ea..34b4794600 100644 --- a/internal/apiserver/route_post_new_contract_interface_test.go +++ b/internal/apiserver/route_post_new_contract_interface_test.go @@ -22,6 +22,7 @@ import ( "net/http/httptest" "testing" + "github.com/hyperledger/firefly/mocks/contractmocks" "github.com/hyperledger/firefly/mocks/definitionsmocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" @@ -32,6 +33,7 @@ func TestPostNewContractInterface(t *testing.T) { o, r := newTestAPIServer() o.On("Authorize", mock.Anything, mock.Anything).Return(nil) mds := &definitionsmocks.Sender{} + o.On("Contracts").Return(&contractmocks.Manager{}) o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer @@ -50,6 +52,7 @@ func TestPostNewContractInterfaceSync(t *testing.T) { o, r := newTestAPIServer() o.On("Authorize", mock.Anything, mock.Anything).Return(nil) mds := &definitionsmocks.Sender{} + o.On("Contracts").Return(&contractmocks.Manager{}) o.On("DefinitionSender").Return(mds) input := core.Datatype{} var buf bytes.Buffer diff --git a/internal/apiserver/route_post_new_contract_listener.go b/internal/apiserver/route_post_new_contract_listener.go index 2afcfba9c6..5c6f9f33f7 100644 --- a/internal/apiserver/route_post_new_contract_listener.go +++ b/internal/apiserver/route_post_new_contract_listener.go @@ -21,6 +21,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -35,6 +36,9 @@ var postNewContractListener = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.ContractListener{} }, JSONOutputCodes: []int{http.StatusOK}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { return cr.or.Contracts().AddContractListener(cr.ctx, r.Input.(*core.ContractListenerInput)) }, diff --git a/internal/apiserver/route_put_contract_api.go b/internal/apiserver/route_put_contract_api.go index 537571194d..28521ea315 100644 --- a/internal/apiserver/route_put_contract_api.go +++ b/internal/apiserver/route_put_contract_api.go @@ -23,6 +23,7 @@ import ( "github.com/hyperledger/firefly-common/pkg/ffapi" "github.com/hyperledger/firefly-common/pkg/fftypes" "github.com/hyperledger/firefly/internal/coremsgs" + "github.com/hyperledger/firefly/internal/orchestrator" "github.com/hyperledger/firefly/pkg/core" ) @@ -41,6 +42,9 @@ var putContractAPI = &ffapi.Route{ JSONOutputValue: func() interface{} { return &core.ContractAPI{} }, JSONOutputCodes: []int{http.StatusOK, http.StatusAccepted}, Extensions: &coreExtensions{ + EnabledIf: func(or orchestrator.Orchestrator) bool { + return or.Contracts() != nil + }, CoreJSONHandler: func(r *ffapi.APIRequest, cr *coreRequest) (output interface{}, err error) { waitConfirm := strings.EqualFold(r.QP["confirm"], "true") r.SuccessStatus = syncRetcode(waitConfirm) diff --git a/internal/apiserver/route_put_contract_api_test.go b/internal/apiserver/route_put_contract_api_test.go index 021a1738d6..eb6369c03c 100644 --- a/internal/apiserver/route_put_contract_api_test.go +++ b/internal/apiserver/route_put_contract_api_test.go @@ -22,6 +22,7 @@ import ( "net/http/httptest" "testing" + "github.com/hyperledger/firefly/mocks/contractmocks" "github.com/hyperledger/firefly/mocks/definitionsmocks" "github.com/hyperledger/firefly/pkg/core" "github.com/stretchr/testify/assert" @@ -33,6 +34,7 @@ func TestPutContractAPI(t *testing.T) { o.On("Authorize", mock.Anything, mock.Anything).Return(nil) mds := &definitionsmocks.Sender{} o.On("DefinitionSender").Return(mds) + o.On("Contracts").Return(&contractmocks.Manager{}) input := core.Datatype{} var buf bytes.Buffer json.NewEncoder(&buf).Encode(&input) @@ -51,6 +53,7 @@ func TestPutContractAPISync(t *testing.T) { o.On("Authorize", mock.Anything, mock.Anything).Return(nil) mds := &definitionsmocks.Sender{} o.On("DefinitionSender").Return(mds) + o.On("Contracts").Return(&contractmocks.Manager{}) input := core.Datatype{} var buf bytes.Buffer json.NewEncoder(&buf).Encode(&input) diff --git a/internal/coremsgs/en_error_messages.go b/internal/coremsgs/en_error_messages.go index 8da0bcfe23..0e81a44455 100644 --- a/internal/coremsgs/en_error_messages.go +++ b/internal/coremsgs/en_error_messages.go @@ -256,4 +256,5 @@ var ( MsgActionNotSupported = ffe("FF10414", "This action is not supported in this namespace", 400) MsgMessagesNotSupported = ffe("FF10415", "Messages are not supported in this namespace", 400) MsgInvalidSubscriptionForNetwork = ffe("FF10416", "Subscription name '%s' is invalid according to multiparty network rules in effect (network version=%d)") + MsgBlockchainNotConfigured = ffe("FF10417", "No blockchain plugin configured", 400) ) diff --git a/internal/orchestrator/orchestrator.go b/internal/orchestrator/orchestrator.go index 57de36fffc..a557d24412 100644 --- a/internal/orchestrator/orchestrator.go +++ b/internal/orchestrator/orchestrator.go @@ -458,10 +458,12 @@ func (or *orchestrator) initManagers(ctx context.Context) (err error) { } } - if or.contracts == nil { - or.contracts, err = contracts.NewContractManager(ctx, or.namespace, or.database(), or.blockchain(), or.identity, or.operations, or.txHelper, or.syncasync) - if err != nil { - return err + if or.blockchain() != nil { + if or.contracts == nil { + or.contracts, err = contracts.NewContractManager(ctx, or.namespace, or.database(), or.blockchain(), or.identity, or.operations, or.txHelper, or.syncasync) + if err != nil { + return err + } } } From 6689ae98e133d772c73190bd3259b032826a3e5d Mon Sep 17 00:00:00 2001 From: Alex Shorsher Date: Mon, 11 Jul 2022 09:48:12 -0400 Subject: [PATCH 2/2] make blockchain plugin optional in managers Signed-off-by: Alex Shorsher --- internal/coremsgs/en_error_messages.go | 2 +- internal/definitions/handler.go | 6 +- internal/definitions/sender.go | 6 +- internal/events/event_manager.go | 18 +++--- internal/identity/identitymanager.go | 21 ++++++- internal/identity/identitymanager_test.go | 67 +++++++++++++++++++++-- 6 files changed, 98 insertions(+), 22 deletions(-) diff --git a/internal/coremsgs/en_error_messages.go b/internal/coremsgs/en_error_messages.go index 0e81a44455..f159784603 100644 --- a/internal/coremsgs/en_error_messages.go +++ b/internal/coremsgs/en_error_messages.go @@ -256,5 +256,5 @@ var ( MsgActionNotSupported = ffe("FF10414", "This action is not supported in this namespace", 400) MsgMessagesNotSupported = ffe("FF10415", "Messages are not supported in this namespace", 400) MsgInvalidSubscriptionForNetwork = ffe("FF10416", "Subscription name '%s' is invalid according to multiparty network rules in effect (network version=%d)") - MsgBlockchainNotConfigured = ffe("FF10417", "No blockchain plugin configured", 400) + MsgBlockchainNotConfigured = ffe("FF10417", "No blockchain plugin configured") ) diff --git a/internal/definitions/handler.go b/internal/definitions/handler.go index 6c2f150bb1..56b0c1b43a 100644 --- a/internal/definitions/handler.go +++ b/internal/definitions/handler.go @@ -80,16 +80,16 @@ type definitionHandler struct { namespace string multiparty bool database database.Plugin - blockchain blockchain.Plugin + blockchain blockchain.Plugin // optional exchange dataexchange.Plugin // optional data data.Manager identity identity.Manager assets assets.Manager - contracts contracts.Manager + contracts contracts.Manager // optional } func newDefinitionHandler(ctx context.Context, ns string, multiparty bool, di database.Plugin, bi blockchain.Plugin, dx dataexchange.Plugin, dm data.Manager, im identity.Manager, am assets.Manager, cm contracts.Manager) (*definitionHandler, error) { - if di == nil || bi == nil || dm == nil || im == nil || am == nil || cm == nil { + if di == nil || dm == nil || im == nil || am == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "DefinitionHandler") } return &definitionHandler{ diff --git a/internal/definitions/sender.go b/internal/definitions/sender.go index d034293b20..542f26f84e 100644 --- a/internal/definitions/sender.go +++ b/internal/definitions/sender.go @@ -53,7 +53,7 @@ type definitionSender struct { broadcast broadcast.Manager // optional identity identity.Manager data data.Manager - contracts contracts.Manager + contracts contracts.Manager // optional handler *definitionHandler } @@ -71,8 +71,8 @@ func fakeBatch(ctx context.Context, handler func(context.Context, *core.BatchSta } func NewDefinitionSender(ctx context.Context, ns string, multiparty bool, di database.Plugin, bi blockchain.Plugin, dx dataexchange.Plugin, bm broadcast.Manager, im identity.Manager, dm data.Manager, am assets.Manager, cm contracts.Manager) (Sender, Handler, error) { - if di == nil || im == nil || dm == nil || cm == nil { - return nil, nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError) + if di == nil || im == nil || dm == nil { + return nil, nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "DefinitionSender") } ds := &definitionSender{ ctx: ctx, diff --git a/internal/events/event_manager.go b/internal/events/event_manager.go index cae7efb1ad..3f28d06025 100644 --- a/internal/events/event_manager.go +++ b/internal/events/event_manager.go @@ -99,12 +99,12 @@ type eventManager struct { data data.Manager subManager *subscriptionManager retry retry.Retry - aggregator *aggregator + aggregator *aggregator // optional broadcast broadcast.Manager // optional messaging privatemessaging.Manager // optional assets assets.Manager sharedDownload shareddownload.Manager // optional - blobReceiver *blobReceiver + blobReceiver *blobReceiver // optional newEventNotifier *eventNotifier newPinNotifier *eventNotifier defaultTransport string @@ -116,7 +116,7 @@ type eventManager struct { } func NewEventManager(ctx context.Context, ns string, ni sysmessaging.LocalNodeInfo, di database.Plugin, bi blockchain.Plugin, im identity.Manager, dh definitions.Handler, dm data.Manager, ds definitions.Sender, bm broadcast.Manager, pm privatemessaging.Manager, am assets.Manager, sd shareddownload.Manager, mm metrics.Manager, txHelper txcommon.Helper, transports map[string]events.Plugin, mp multiparty.Manager) (EventManager, error) { - if ni == nil || di == nil || bi == nil || im == nil || dh == nil || dm == nil || ds == nil || am == nil { + if ni == nil || di == nil || im == nil || dh == nil || dm == nil || ds == nil || am == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "EventManager") } newPinNotifier := newEventNotifier(ctx, "pins") @@ -144,14 +144,16 @@ func NewEventManager(ctx context.Context, ns string, ni sysmessaging.LocalNodeIn defaultTransport: config.GetString(coreconfig.EventTransportsDefault), newEventNotifier: newEventNotifier, newPinNotifier: newPinNotifier, - aggregator: newAggregator(ctx, ns, di, bi, pm, dh, im, dm, newPinNotifier, mm), metrics: mm, chainListenerCache: ccache.New(ccache.Configure().MaxSize(config.GetByteSize(coreconfig.EventListenerTopicCacheSize))), chainListenerCacheTTL: config.GetDuration(coreconfig.EventListenerTopicCacheTTL), } ie, _ := eifactory.GetPlugin(ctx, system.SystemEventsTransport) em.internalEvents = ie.(*system.Events) - em.blobReceiver = newBlobReceiver(ctx, em.aggregator) + if bi != nil { + em.aggregator = newAggregator(ctx, ns, di, bi, pm, dh, im, dm, newPinNotifier, mm) + em.blobReceiver = newBlobReceiver(ctx, em.aggregator) + } var err error if em.subManager, err = newSubscriptionManager(ctx, ns, di, dm, newEventNotifier, bm, pm, txHelper, transports); err != nil { @@ -164,8 +166,10 @@ func NewEventManager(ctx context.Context, ns string, ni sysmessaging.LocalNodeIn func (em *eventManager) Start() (err error) { err = em.subManager.start() if err == nil { - em.aggregator.start() - em.blobReceiver.start() + if em.aggregator != nil { + em.aggregator.start() + em.blobReceiver.start() + } } return err } diff --git a/internal/identity/identitymanager.go b/internal/identity/identitymanager.go index 7646593e7b..89ef88cf6d 100644 --- a/internal/identity/identitymanager.go +++ b/internal/identity/identitymanager.go @@ -56,7 +56,7 @@ type Manager interface { type identityManager struct { database database.Plugin - blockchain blockchain.Plugin + blockchain blockchain.Plugin // optional multiparty multiparty.Manager // optional namespace string defaultKey string @@ -69,7 +69,7 @@ type identityManager struct { } func NewIdentityManager(ctx context.Context, ns, defaultKey string, di database.Plugin, bi blockchain.Plugin, mp multiparty.Manager) (Manager, error) { - if di == nil || bi == nil { + if di == nil { return nil, i18n.NewError(ctx, coremsgs.MsgInitializationNilDepError, "IdentityManager") } im := &identityManager{ @@ -106,6 +106,14 @@ func ParseKeyNormalizationConfig(strConfigVal string) int { // or when the author is known by the caller and should not / cannot be confirmed prior to sending (identity claims) func (im *identityManager) NormalizeSigningKey(ctx context.Context, inputKey string, keyNormalizationMode int) (signingKey string, err error) { if inputKey == "" { + if im.blockchain == nil { + if im.defaultKey == "" { + return "", i18n.NewError(ctx, coremsgs.MsgNodeMissingBlockchainKey) + } + + return im.defaultKey, nil + } + verifierRef, err := im.getDefaultVerifier(ctx) if err != nil { return "", err @@ -130,6 +138,10 @@ func (im *identityManager) NormalizeSigningKey(ctx context.Context, inputKey str func (im *identityManager) ResolveInputSigningIdentity(ctx context.Context, signerRef *core.SignerRef) (err error) { log.L(ctx).Debugf("Resolving identity input: key='%s' author='%s'", signerRef.Key, signerRef.Author) + if im.blockchain == nil { + return i18n.NewError(ctx, coremsgs.MsgBlockchainNotConfigured) + } + var verifier *core.VerifierRef switch { case signerRef.Author == "" && signerRef.Key == "": @@ -259,6 +271,11 @@ func (im *identityManager) normalizeKeyViaBlockchainPlugin(ctx context.Context, if inputKey == "" { return nil, i18n.NewError(ctx, coremsgs.MsgBlockchainKeyNotSet) } + + if im.blockchain == nil { + return nil, i18n.NewError(ctx, coremsgs.MsgBlockchainNotConfigured) + } + if cached := im.signingKeyCache.Get(inputKey); cached != nil { cached.Extend(im.identityCacheTTL) return cached.Value().(*core.VerifierRef), nil diff --git a/internal/identity/identitymanager_test.go b/internal/identity/identitymanager_test.go index 91023fd7cc..dfa08f612c 100644 --- a/internal/identity/identitymanager_test.go +++ b/internal/identity/identitymanager_test.go @@ -112,6 +112,17 @@ func TestResolveInputSigningIdentityOrgFallbackOk(t *testing.T) { } +func TestResolveInputSigningIdentityMissingBlockchain(t *testing.T) { + ctx, im := newTestIdentityManager(t) + im.blockchain = nil + + msgIdentity := &core.SignerRef{ + Key: "mykey123", + } + err := im.ResolveInputSigningIdentity(ctx, msgIdentity) + assert.Regexp(t, "FF10417", err) +} + func TestResolveInputSigningIdentityByKeyOk(t *testing.T) { ctx, im := newTestIdentityManager(t) @@ -440,20 +451,54 @@ func TestResolveInputSigningIdentityByOrgVerifierFail(t *testing.T) { } func TestNormalizeSigningKeyDefault(t *testing.T) { - ctx, im := newTestIdentityManager(t) + im.blockchain = nil im.defaultKey = "key123" - mbi := im.blockchain.(*blockchainmocks.Plugin) - mbi.On("NormalizeSigningKey", ctx, "key123").Return("fullkey123", nil) - resolvedKey, err := im.NormalizeSigningKey(ctx, "", KeyNormalizationBlockchainPlugin) assert.NoError(t, err) - assert.Equal(t, "fullkey123", resolvedKey) + assert.Equal(t, "key123", resolvedKey) +} - mbi.AssertExpectations(t) +func TestGetDefaultVerifierNoBlockchain(t *testing.T) { + ctx, im := newTestIdentityManager(t) + im.blockchain = nil + im.defaultKey = "test" + verifier, err := im.getDefaultVerifier(ctx) + assert.Regexp(t, "FF10417", err) + assert.Nil(t, verifier) +} + +func TestNormalizeSigningKeyNoDefaultNoBlockchain(t *testing.T) { + ctx, im := newTestIdentityManager(t) + im.blockchain = nil + + resolvedKey, err := im.NormalizeSigningKey(ctx, "", KeyNormalizationBlockchainPlugin) + assert.Regexp(t, "FF10354", err) + assert.Equal(t, "", resolvedKey) + +} + +func TestNormalizeSigningKeyDefaultNoBlockchainInputFallback(t *testing.T) { + ctx, im := newTestIdentityManager(t) + im.blockchain = nil + im.defaultKey = "key123" + + resolvedKey, err := im.NormalizeSigningKey(ctx, "testKey", KeyNormalizationBlockchainPlugin) + assert.Regexp(t, "FF10417", err) + assert.Equal(t, "", resolvedKey) +} + +func TestNormalizeSigningKeyDefaultNoBlockchainDefaultKeyFallback(t *testing.T) { + ctx, im := newTestIdentityManager(t) + im.blockchain = nil + im.defaultKey = "key123" + + resolvedKey, err := im.NormalizeSigningKey(ctx, "", KeyNormalizationBlockchainPlugin) + assert.NoError(t, err) + assert.Equal(t, "key123", resolvedKey) } func TestNormalizeSigningKeyOrgFallbackOk(t *testing.T) { @@ -663,6 +708,16 @@ func TestNormalizeKeyViaBlockchainPluginEmptyRequest(t *testing.T) { } +func TestNormalizeKeyViaBlockchainPluginMissingBlockchain(t *testing.T) { + + ctx, im := newTestIdentityManager(t) + im.blockchain = nil + + _, err := im.normalizeKeyViaBlockchainPlugin(ctx, "testKey") + assert.Regexp(t, "FF10417", err) + +} + func TestNormalizeKeyViaBlockchainPluginCached(t *testing.T) { ctx, im := newTestIdentityManager(t)