Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support msg to create policy by cross chain #639

Merged
merged 7 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
129 changes: 122 additions & 7 deletions x/storage/keeper/cross_app_permission.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"

types2 "github.com/bnb-chain/greenfield/types"
gnfderrors "github.com/bnb-chain/greenfield/types/errors"
gnfdresource "github.com/bnb-chain/greenfield/types/resource"
permtypes "github.com/bnb-chain/greenfield/x/permission/types"
Expand Down Expand Up @@ -146,16 +147,88 @@ func (app *PermissionApp) handleCreatePolicySynPackage(ctx sdk.Context, createPo
}

var policy permtypes.Policy
var grn types2.GRN
err = policy.Unmarshal(createPolicyPackage.Data)
if err != nil {
return sdk.ExecuteResult{
Payload: types.CreatePolicyAckPackage{
Status: types.StatusFail,
Creator: createPolicyPackage.Operator,
ExtraData: createPolicyPackage.ExtraData,
}.MustSerialize(),
Err: err,
var msgPutPolicy types.MsgPutPolicy
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
err = msgPutPolicy.Unmarshal(createPolicyPackage.Data)
if err != nil {
return sdk.ExecuteResult{
Payload: types.CreatePolicyAckPackage{
Status: types.StatusFail,
Creator: createPolicyPackage.Operator,
ExtraData: createPolicyPackage.ExtraData,
}.MustSerialize(),
Err: err,
}
}
if msgPutPolicy.GetOperator() != createPolicyPackage.Operator.String() {
return sdk.ExecuteResult{
Payload: types.CreatePolicyAckPackage{
Status: types.StatusFail,
Creator: createPolicyPackage.Operator,
ExtraData: createPolicyPackage.ExtraData,
}.MustSerialize(),
Err: types.ErrAccessDenied.Wrapf(
"Only resource owner can put policy, operator (%s)",
msgPutPolicy.GetOperator()),
}
}

err = grn.ParseFromString(msgPutPolicy.Resource, true)
if err != nil {
return sdk.ExecuteResult{
Payload: types.CreatePolicyAckPackage{
Status: types.StatusFail,
Creator: createPolicyPackage.Operator,
ExtraData: createPolicyPackage.ExtraData,
}.MustSerialize(),
Err: err,
}
}

if msgPutPolicy.ExpirationTime != nil && msgPutPolicy.ExpirationTime.Before(ctx.BlockTime()) {
return sdk.ExecuteResult{
Payload: types.CreatePolicyAckPackage{
Status: types.StatusFail,
Creator: createPolicyPackage.Operator,
ExtraData: createPolicyPackage.ExtraData,
}.MustSerialize(),
Err: permtypes.ErrPermissionExpired.Wrapf("The specified policy expiration time is less than the current block time, block time: %s", ctx.BlockTime().String()),
}
}

for _, s := range msgPutPolicy.Statements {
if s.ExpirationTime != nil && s.ExpirationTime.Before(ctx.BlockTime()) {
return sdk.ExecuteResult{
Payload: types.CreatePolicyAckPackage{
Status: types.StatusFail,
Creator: createPolicyPackage.Operator,
ExtraData: createPolicyPackage.ExtraData,
}.MustSerialize(),
Err: permtypes.ErrPermissionExpired.Wrapf("The specified statement expiration time is less than the current block time, block time: %s", ctx.BlockTime().String()),
}
}
}

policy = permtypes.Policy{
ResourceType: grn.ResourceType(),
Principal: msgPutPolicy.Principal,
Statements: msgPutPolicy.Statements,
ExpirationTime: msgPutPolicy.ExpirationTime,
}
_, resID, err := app.getResourceOwnerAndIdFromGRN(ctx, grn)
if err != nil {
return sdk.ExecuteResult{
Payload: types.CreatePolicyAckPackage{
Status: types.StatusFail,
Creator: createPolicyPackage.Operator,
ExtraData: createPolicyPackage.ExtraData,
}.MustSerialize(),
Err: err,
}
}
policy.ResourceId = resID
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
}

resOwner, err := app.getResourceOwner(ctx, &policy)
Expand Down Expand Up @@ -243,3 +316,45 @@ func (app *PermissionApp) getResourceOwner(ctx sdk.Context, policy *permtypes.Po
}
return resOwner, nil
}

func (app *PermissionApp) getResourceOwnerAndIdFromGRN(ctx sdk.Context, grn types2.GRN) (resOwner sdk.AccAddress, resID math.Uint, err error) {
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
switch grn.ResourceType() {
case gnfdresource.RESOURCE_TYPE_BUCKET:
bucketName, grnErr := grn.GetBucketName()
if grnErr != nil {
return resOwner, resID, grnErr
}
bucketInfo, found := app.storageKeeper.GetBucketInfo(ctx, bucketName)
if !found {
return resOwner, resID, types.ErrNoSuchBucket.Wrapf("bucketName: %s", bucketName)
}
resOwner = sdk.MustAccAddressFromHex(bucketInfo.Owner)
resID = bucketInfo.Id
case gnfdresource.RESOURCE_TYPE_OBJECT:
bucketName, objectName, grnErr := grn.GetBucketAndObjectName()
if grnErr != nil {
return resOwner, resID, grnErr
}
objectInfo, found := app.storageKeeper.GetObjectInfo(ctx, bucketName, objectName)
if !found {
return resOwner, resID, types.ErrNoSuchObject.Wrapf("BucketName: %s, objectName: %s", bucketName, objectName)
}
resOwner = sdk.MustAccAddressFromHex(objectInfo.Owner)
resID = objectInfo.Id
case gnfdresource.RESOURCE_TYPE_GROUP:
groupOwner, groupName, grnErr := grn.GetGroupOwnerAndAccount()
if grnErr != nil {
return resOwner, resID, grnErr
}
groupInfo, found := app.storageKeeper.GetGroupInfo(ctx, groupOwner, groupName)
if !found {
return resOwner, resID, types.ErrNoSuchBucket.Wrapf("groupOwner: %s, groupName: %s", groupOwner.String(), groupName)
}
resOwner = sdk.MustAccAddressFromHex(groupInfo.Owner)
resID = groupInfo.Id
default:
return resOwner, resID, gnfderrors.ErrInvalidGRN.Wrap("Unknown resource type in greenfield resource name")
}

return resOwner, resID, nil
}
87 changes: 87 additions & 0 deletions x/storage/keeper/cross_app_permission_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/golang/mock/gomock"

"github.com/bnb-chain/greenfield/testutil/sample"
types2 "github.com/bnb-chain/greenfield/types"
"github.com/bnb-chain/greenfield/x/permission/types"
"github.com/bnb-chain/greenfield/x/storage/keeper"
storageTypes "github.com/bnb-chain/greenfield/x/storage/types"
Expand Down Expand Up @@ -71,3 +72,89 @@ func (s *TestSuite) TestSynDeletePolicy() {
s.Require().ErrorIs(res.Err, storageTypes.ErrNoSuchPolicy)
s.Require().NotEmpty(res.Payload)
}

func (s *TestSuite) TestSynCreatePolicyByMsgErr() {
ctrl := gomock.NewController(s.T())
storageKeeper := storageTypes.NewMockStorageKeeper(ctrl)
permissionKeeper := storageTypes.NewMockPermissionKeeper(ctrl)

//resourceIds := []math.Uint{math.NewUint(rand.Uint64()), math.NewUint(rand.Uint64()), math.NewUint(rand.Uint64())}
// policy without expiry
op := sample.RandAccAddress()
resource := types2.NewBucketGRN("test-bucket").String()
policy := storageTypes.MsgPutPolicy{
Principal: &types.Principal{
Type: types.PRINCIPAL_TYPE_GNFD_GROUP,
Value: sample.RandAccAddressHex(),
},
Operator: op.String(),
Resource: resource,
Statements: nil,
ExpirationTime: nil,
}

app := keeper.NewPermissionApp(storageKeeper, permissionKeeper)
data, err := policy.Marshal()
s.NoError(err)

synPackage := storageTypes.CreatePolicySynPackage{
Operator: op,
Data: data,
ExtraData: []byte("extra data"),
}
serializedSynPackage := synPackage.MustSerialize()
serializedSynPackage = append([]byte{storageTypes.OperationCreatePolicy}, serializedSynPackage...)

// case 1: bucket not found
storageKeeper.EXPECT().GetBucketInfo(gomock.Any(), gomock.Any()).Return(nil, false)
res := app.ExecuteSynPackage(s.ctx, &sdk.CrossChainAppContext{}, serializedSynPackage)
s.Require().ErrorIs(res.Err, storageTypes.ErrNoSuchBucket)
}

func (s *TestSuite) TestSynCreatePolicyByMsg() {
ctrl := gomock.NewController(s.T())
storageKeeper := storageTypes.NewMockStorageKeeper(ctrl)
permissionKeeper := storageTypes.NewMockPermissionKeeper(ctrl)

//resourceIds := []math.Uint{math.NewUint(rand.Uint64()), math.NewUint(rand.Uint64()), math.NewUint(rand.Uint64())}
// policy without expiry
op := sample.RandAccAddress()
resource := types2.NewBucketGRN("test-bucket").String()
policy := storageTypes.MsgPutPolicy{
Principal: &types.Principal{
Type: types.PRINCIPAL_TYPE_GNFD_GROUP,
Value: sample.RandAccAddressHex(),
},
Operator: op.String(),
Resource: resource,
Statements: nil,
ExpirationTime: nil,
}

app := keeper.NewPermissionApp(storageKeeper, permissionKeeper)
data, err := policy.Marshal()
s.NoError(err)

synPackage := storageTypes.CreatePolicySynPackage{
Operator: op,
Data: data,
ExtraData: []byte("extra data"),
}
serializedSynPackage := synPackage.MustSerialize()
serializedSynPackage = append([]byte{storageTypes.OperationCreatePolicy}, serializedSynPackage...)

// case 1: bucket not found
storageKeeper.EXPECT().GetBucketInfo(gomock.Any(), gomock.Any()).Return(&storageTypes.BucketInfo{
Owner: op.String(),
BucketName: "test-bucket",
}, true)
storageKeeper.EXPECT().GetBucketInfoById(gomock.Any(), gomock.Any()).Return(&storageTypes.BucketInfo{
Owner: op.String(),
BucketName: "test-bucket",
}, true)
storageKeeper.EXPECT().NormalizePrincipal(gomock.Any(), gomock.Any()).Return().AnyTimes()
storageKeeper.EXPECT().ValidatePrincipal(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
permissionKeeper.EXPECT().PutPolicy(gomock.Any(), gomock.Any()).Return(math.NewUint(1), nil).AnyTimes()
res := app.ExecuteSynPackage(s.ctx, &sdk.CrossChainAppContext{}, serializedSynPackage)
s.Require().ErrorIs(res.Err, nil)
}
24 changes: 6 additions & 18 deletions x/storage/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ func (k Keeper) DeleteBucket(ctx sdk.Context, operator sdk.AccAddress, bucketNam
if !found {
return types.ErrNoSuchBucket
}
if bucketInfo.SourceType != opts.SourceType {
if bucketInfo.SourceType != types.SOURCE_TYPE_ORIGIN && bucketInfo.SourceType != opts.SourceType {
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
return types.ErrSourceTypeMismatch
}

Expand Down Expand Up @@ -417,10 +417,6 @@ func (k Keeper) UpdateBucketInfo(ctx sdk.Context, operator sdk.AccAddress, bucke
if !found {
return types.ErrNoSuchBucket
}
// check bucket source
if bucketInfo.SourceType != opts.SourceType {
return types.ErrSourceTypeMismatch
}

if ctx.IsUpgraded(upgradetypes.Hulunbeier) {
sp := k.MustGetPrimarySPForBucket(ctx, bucketInfo)
Expand Down Expand Up @@ -987,10 +983,6 @@ func (k Keeper) CancelCreateObject(
return types.ErrObjectNotCreated.Wrapf("Object status: %s", objectInfo.ObjectStatus.String())
}

if objectInfo.SourceType != opts.SourceType {
return types.ErrSourceTypeMismatch
}

var creator sdk.AccAddress
owner := sdk.MustAccAddressFromHex(objectInfo.Owner)
if objectInfo.Creator != "" {
Expand Down Expand Up @@ -1056,7 +1048,7 @@ func (k Keeper) DeleteObject(
objectInfo.ObjectName)
}

if objectInfo.SourceType != opts.SourceType {
if objectInfo.SourceType != types.SOURCE_TYPE_ORIGIN && objectInfo.SourceType != opts.SourceType {
return types.ErrSourceTypeMismatch
}

Expand Down Expand Up @@ -1211,10 +1203,6 @@ func (k Keeper) CopyObject(
return sdkmath.ZeroUint(), errors.Wrapf(types.ErrNoSuchObject, "src object name (%s)", srcObjectName)
}

if srcObjectInfo.SourceType != opts.SourceType {
return sdkmath.ZeroUint(), types.ErrSourceTypeMismatch
}

if srcObjectInfo.IsUpdating {
return sdkmath.ZeroUint(), types.ErrAccessDenied.Wrapf("the object is being updated, can not be copied")
}
Expand Down Expand Up @@ -1552,7 +1540,7 @@ func (k Keeper) DeleteGroup(ctx sdk.Context, operator sdk.AccAddress, groupName
if !found {
return types.ErrNoSuchGroup
}
if groupInfo.SourceType != opts.SourceType {
if groupInfo.SourceType != types.SOURCE_TYPE_ORIGIN && groupInfo.SourceType != opts.SourceType {
return types.ErrSourceTypeMismatch
}
// check permission
Expand Down Expand Up @@ -1588,7 +1576,7 @@ func (k Keeper) LeaveGroup(
if !found {
return types.ErrNoSuchGroup
}
if groupInfo.SourceType != opts.SourceType {
if groupInfo.SourceType != types.SOURCE_TYPE_ORIGIN && groupInfo.SourceType != opts.SourceType {
return types.ErrSourceTypeMismatch
}

Expand All @@ -1610,7 +1598,7 @@ func (k Keeper) LeaveGroup(
}

func (k Keeper) UpdateGroupMember(ctx sdk.Context, operator sdk.AccAddress, groupInfo *types.GroupInfo, opts types.UpdateGroupMemberOptions) error {
if groupInfo.SourceType != opts.SourceType {
if groupInfo.SourceType != types.SOURCE_TYPE_ORIGIN && groupInfo.SourceType != opts.SourceType {
return types.ErrSourceTypeMismatch
}

Expand Down Expand Up @@ -1665,7 +1653,7 @@ func (k Keeper) UpdateGroupMember(ctx sdk.Context, operator sdk.AccAddress, grou
}

func (k Keeper) RenewGroupMember(ctx sdk.Context, operator sdk.AccAddress, groupInfo *types.GroupInfo, opts types.RenewGroupMemberOptions) error {
if groupInfo.SourceType != opts.SourceType {
if groupInfo.SourceType != types.SOURCE_TYPE_ORIGIN && groupInfo.SourceType != opts.SourceType {
return types.ErrSourceTypeMismatch
}

Expand Down
2 changes: 2 additions & 0 deletions x/storage/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ type VirtualGroupKeeper interface {
type StorageKeeper interface {
Logger(ctx sdk.Context) log.Logger
GetBucketInfoById(ctx sdk.Context, bucketId sdkmath.Uint) (*BucketInfo, bool)
GetBucketInfo(ctx sdk.Context, bucketName string) (*BucketInfo, bool)
GetObjectInfo(ctx sdk.Context, bucketName, objectName string) (*ObjectInfo, bool)
SetBucketInfo(ctx sdk.Context, bucketInfo *BucketInfo)
CreateBucket(
ctx sdk.Context, ownerAcc sdk.AccAddress, bucketName string,
Expand Down
30 changes: 30 additions & 0 deletions x/storage/types/expected_keepers_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading