Commit 6eb36d31 authored by Binh Nguyen's avatar Binh Nguyen Committed by Gerrit Code Review
Browse files

Merge "FAB-10314 Hide ACLs behind capability"

parents f2c8b1ee 0ee18c2b
......@@ -35,11 +35,10 @@ const (
// ApplicationProvider provides capabilities information for application level config.
type ApplicationProvider struct {
*registry
v11 bool
v12 bool
v11PvtDataExperimental bool
v11ResourcesTreeExperimental bool
v12LifecycleExperimental bool
v11 bool
v12 bool
v11PvtDataExperimental bool
v12LifecycleExperimental bool
}
// NewApplicationProvider creates a application capabilities provider.
......@@ -49,7 +48,6 @@ func NewApplicationProvider(capabilities map[string]*cb.Capability) *Application
_, ap.v11 = capabilities[ApplicationV1_1]
_, ap.v12 = capabilities[ApplicationV1_2]
_, ap.v11PvtDataExperimental = capabilities[ApplicationPvtDataExperimental]
_, ap.v11ResourcesTreeExperimental = capabilities[ApplicationResourcesTreeExperimental]
_, ap.v12LifecycleExperimental = capabilities[ApplicationChaincodeLifecycleExperimental]
return ap
}
......@@ -59,9 +57,9 @@ func (ap *ApplicationProvider) Type() string {
return applicationTypeName
}
// ResourcesTree returns whether the experimental resources tree transaction processing should be enabled.
func (ap *ApplicationProvider) ResourcesTree() bool {
return ap.v11ResourcesTreeExperimental
// ACLs returns whether ACLs may be specified in the channel application config
func (ap *ApplicationProvider) ACLs() bool {
return ap.v12
}
// ForbidDuplicateTXIdInBlock specifies whether two transactions with the same TXId are permitted
......
......@@ -52,6 +52,13 @@ func TestApplicationPvtDataExperimental(t *testing.T) {
}
func TestApplicationACLs(t *testing.T) {
ap := NewApplicationProvider(map[string]*cb.Capability{
ApplicationV1_2: {},
})
assert.True(t, ap.ACLs())
}
func TestApplicationCollectionUpgrade(t *testing.T) {
op := NewApplicationProvider(map[string]*cb.Capability{
ApplicationV1_2: {},
......
......@@ -123,8 +123,8 @@ type ApplicationCapabilities interface {
// in the same block or whether we mark the second one as TxValidationCode_DUPLICATE_TXID
ForbidDuplicateTXIdInBlock() bool
// ResourcesTree returns true if the peer should process the experimental resources transactions
ResourcesTree() bool
// ACLs returns true is ACLs may be specified in the Application portion of the config tree
ACLs() bool
// PrivateChannelData returns true if support for private channel data (a.k.a. collections) is enabled.
// In v1.1, the private channel data is experimental and has to be enabled explicitly.
......
......@@ -45,6 +45,12 @@ func NewApplicationConfig(appGroup *cb.ConfigGroup, mspConfig *MSPConfigHandler)
return nil, errors.Wrap(err, "failed to deserialize values")
}
if !ac.Capabilities().ACLs() {
if _, ok := appGroup.Values[ACLsKey]; ok {
return nil, errors.New("ACLs may not be specified without the required capability")
}
}
var err error
for orgName, orgGroup := range appGroup.Groups {
ac.applicationOrgs[orgName], err = NewApplicationOrgConfig(orgName, orgGroup, mspConfig)
......
......@@ -9,6 +9,12 @@ package channelconfig
import (
"testing"
"github.com/hyperledger/fabric/common/capabilities"
cb "github.com/hyperledger/fabric/protos/common"
"github.com/hyperledger/fabric/protos/utils"
"github.com/golang/protobuf/proto"
. "github.com/onsi/gomega"
logging "github.com/op/go-logging"
)
......@@ -19,3 +25,36 @@ func init() {
func TestApplicationInterface(t *testing.T) {
_ = Application((*ApplicationConfig)(nil))
}
func TestACL(t *testing.T) {
g := NewGomegaWithT(t)
cgt := &cb.ConfigGroup{
Values: map[string]*cb.ConfigValue{
ACLsKey: {
Value: utils.MarshalOrPanic(
ACLValues(map[string]string{}).Value(),
),
},
CapabilitiesKey: {
Value: utils.MarshalOrPanic(
CapabilitiesValue(map[string]bool{
capabilities.ApplicationV1_2: true,
}).Value(),
),
},
},
}
t.Run("Success", func(t *testing.T) {
cg := proto.Clone(cgt).(*cb.ConfigGroup)
_, err := NewApplicationConfig(proto.Clone(cg).(*cb.ConfigGroup), nil)
g.Expect(err).NotTo(HaveOccurred())
})
t.Run("MissingCapability", func(t *testing.T) {
cg := proto.Clone(cgt).(*cb.ConfigGroup)
delete(cg.Values, CapabilitiesKey)
_, err := NewApplicationConfig(cg, nil)
g.Expect(err).To(MatchError("ACLs may not be specified without the required capability"))
})
}
......@@ -38,7 +38,7 @@ func (m *MockApplication) APIPolicyMapper() channelconfig.PolicyMapper {
type MockApplicationCapabilities struct {
SupportedRv error
ForbidDuplicateTXIdInBlockRv bool
ResourcesTreeRv bool
ACLsRv bool
PrivateChannelDataRv bool
CollectionUpgradeRv bool
V1_1ValidationRv bool
......@@ -55,8 +55,8 @@ func (mac *MockApplicationCapabilities) ForbidDuplicateTXIdInBlock() bool {
return mac.ForbidDuplicateTXIdInBlockRv
}
func (mac *MockApplicationCapabilities) ResourcesTree() bool {
return mac.ResourcesTreeRv
func (mac *MockApplicationCapabilities) ACLs() bool {
return mac.ACLsRv
}
func (mac *MockApplicationCapabilities) PrivateChannelData() bool {
......
......@@ -8,8 +8,8 @@ type Capabilities struct {
mock.Mock
}
// CollectionUpgrade provides a mock function with given fields:
func (_m *Capabilities) CollectionUpgrade() bool {
// ACLs provides a mock function with given fields:
func (_m *Capabilities) ACLs() bool {
ret := _m.Called()
var r0 bool
......@@ -22,8 +22,8 @@ func (_m *Capabilities) CollectionUpgrade() bool {
return r0
}
// ForbidDuplicateTXIdInBlock provides a mock function with given fields:
func (_m *Capabilities) ForbidDuplicateTXIdInBlock() bool {
// CollectionUpgrade provides a mock function with given fields:
func (_m *Capabilities) CollectionUpgrade() bool {
ret := _m.Called()
var r0 bool
......@@ -36,8 +36,8 @@ func (_m *Capabilities) ForbidDuplicateTXIdInBlock() bool {
return r0
}
// KeyLevelEndorsement provides a mock function with given fields:
func (_m *Capabilities) KeyLevelEndorsement() bool {
// ForbidDuplicateTXIdInBlock provides a mock function with given fields:
func (_m *Capabilities) ForbidDuplicateTXIdInBlock() bool {
ret := _m.Called()
var r0 bool
......@@ -50,8 +50,8 @@ func (_m *Capabilities) KeyLevelEndorsement() bool {
return r0
}
// MetadataLifecycle provides a mock function with given fields:
func (_m *Capabilities) MetadataLifecycle() bool {
// KeyLevelEndorsement provides a mock function with given fields:
func (_m *Capabilities) KeyLevelEndorsement() bool {
ret := _m.Called()
var r0 bool
......@@ -64,8 +64,8 @@ func (_m *Capabilities) MetadataLifecycle() bool {
return r0
}
// PrivateChannelData provides a mock function with given fields:
func (_m *Capabilities) PrivateChannelData() bool {
// MetadataLifecycle provides a mock function with given fields:
func (_m *Capabilities) MetadataLifecycle() bool {
ret := _m.Called()
var r0 bool
......@@ -78,8 +78,8 @@ func (_m *Capabilities) PrivateChannelData() bool {
return r0
}
// ResourcesTree provides a mock function with given fields:
func (_m *Capabilities) ResourcesTree() bool {
// PrivateChannelData provides a mock function with given fields:
func (_m *Capabilities) PrivateChannelData() bool {
ret := _m.Called()
var r0 bool
......
......@@ -19,8 +19,8 @@ type Capabilities interface {
// in the same block or whether we mark the second one as TxValidationCode_DUPLICATE_TXID
ForbidDuplicateTXIdInBlock() bool
// ResourcesTree returns true if the peer should process the experimental resources transactions
ResourcesTree() bool
// ACLs returns true if the peer supports ACLs in the channel config
ACLs() bool
// PrivateChannelData returns true if support for private channel data (a.k.a. collections) is enabled.
PrivateChannelData() bool
......
......@@ -8,8 +8,8 @@ type Capabilities struct {
mock.Mock
}
// CollectionUpgrade provides a mock function with given fields:
func (_m *Capabilities) CollectionUpgrade() bool {
// ACLs provides a mock function with given fields:
func (_m *Capabilities) ACLs() bool {
ret := _m.Called()
var r0 bool
......@@ -22,8 +22,8 @@ func (_m *Capabilities) CollectionUpgrade() bool {
return r0
}
// ForbidDuplicateTXIdInBlock provides a mock function with given fields:
func (_m *Capabilities) ForbidDuplicateTXIdInBlock() bool {
// CollectionUpgrade provides a mock function with given fields:
func (_m *Capabilities) CollectionUpgrade() bool {
ret := _m.Called()
var r0 bool
......@@ -36,8 +36,8 @@ func (_m *Capabilities) ForbidDuplicateTXIdInBlock() bool {
return r0
}
// KeyLevelEndorsement provides a mock function with given fields:
func (_m *Capabilities) KeyLevelEndorsement() bool {
// ForbidDuplicateTXIdInBlock provides a mock function with given fields:
func (_m *Capabilities) ForbidDuplicateTXIdInBlock() bool {
ret := _m.Called()
var r0 bool
......@@ -50,8 +50,8 @@ func (_m *Capabilities) KeyLevelEndorsement() bool {
return r0
}
// MetadataLifecycle provides a mock function with given fields:
func (_m *Capabilities) MetadataLifecycle() bool {
// KeyLevelEndorsement provides a mock function with given fields:
func (_m *Capabilities) KeyLevelEndorsement() bool {
ret := _m.Called()
var r0 bool
......@@ -64,8 +64,8 @@ func (_m *Capabilities) MetadataLifecycle() bool {
return r0
}
// PrivateChannelData provides a mock function with given fields:
func (_m *Capabilities) PrivateChannelData() bool {
// MetadataLifecycle provides a mock function with given fields:
func (_m *Capabilities) MetadataLifecycle() bool {
ret := _m.Called()
var r0 bool
......@@ -78,8 +78,8 @@ func (_m *Capabilities) PrivateChannelData() bool {
return r0
}
// ResourcesTree provides a mock function with given fields:
func (_m *Capabilities) ResourcesTree() bool {
// PrivateChannelData provides a mock function with given fields:
func (_m *Capabilities) PrivateChannelData() bool {
ret := _m.Called()
var r0 bool
......
......@@ -62,7 +62,7 @@ func TestConfigTxCreateLedger(t *testing.T) {
assert.Equal(t, proto.CompactTextString(chanConf), proto.CompactTextString(retrievedchanConf))
}
func TestConfigTxUpdateResConfig(t *testing.T) {
func TestConfigTxUpdateChanConfig(t *testing.T) {
helper := &testHelper{t: t}
cleanup := setupPeerFS(t)
defer cleanup()
......@@ -125,8 +125,7 @@ func (h *testHelper) sampleChannelConfig(sequence uint64, enableV11Capability bo
profile.Orderer.Capabilities = make(map[string]bool)
profile.Orderer.Capabilities[capabilities.ApplicationV1_1] = true
profile.Application.Capabilities = make(map[string]bool)
profile.Application.Capabilities[capabilities.ApplicationV1_1] = true
profile.Application.Capabilities[capabilities.ApplicationResourcesTreeExperimental] = true
profile.Application.Capabilities[capabilities.ApplicationV1_2] = true
}
channelGroup, _ := encoder.NewChannelGroup(profile)
return &common.Config{
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment