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: Enhancement storage module #102

Merged
merged 3 commits into from
Mar 14, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
12 changes: 12 additions & 0 deletions e2e/tests/permission_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/bnb-chain/greenfield/e2e/core"
storageutil "github.com/bnb-chain/greenfield/testutil/storage"
types2 "github.com/bnb-chain/greenfield/types"
"github.com/bnb-chain/greenfield/types/resource"
"github.com/bnb-chain/greenfield/x/permission/types"
storagetypes "github.com/bnb-chain/greenfield/x/storage/types"
)
Expand Down Expand Up @@ -81,7 +82,18 @@ func (s *StorageTestSuite) TestDeleteBucketPermission() {
s.T().Logf("resp: %s, rep %s", verifyPermReq.String(), verifyPermResp.String())
s.Require().NoError(err)
s.Require().Equal(verifyPermResp.Effect, types.EFFECT_ALLOW)

// Query bucket policy
grn := types2.NewBucketGRN(bucketName)
queryPolicyForAccountReq := storagetypes.QueryPolicyForAccountRequest{Resource: grn.String(),
PrincipalAddress: user[1].GetAddr().String()}
queryPolicyForAccountResp, err := s.Client.QueryPolicyForAccount(ctx, &queryPolicyForAccountReq)
s.Require().NoError(err)
s.Require().Equal(queryPolicyForAccountResp.Policy.ResourceType, resource.RESOURCE_TYPE_BUCKET)
s.Require().Equal(queryPolicyForAccountResp.Policy.ResourceId, queryHeadBucketResponse.BucketInfo.Id)

// DeleteBucket
msgDeleteBucket := storagetypes.NewMsgDeleteBucket(user[1].GetAddr(), bucketName)
s.SendTxBlock(msgDeleteBucket, user[1])

}
58 changes: 58 additions & 0 deletions e2e/tests/storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"fmt"
"math"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -187,6 +188,63 @@ func (s *StorageTestSuite) TestCreateObject() {
s.SendTxBlock(msgDeleteBucket, user)
}

func (s *StorageTestSuite) TestCreateGroup() {
ctx := context.Background()

owner := s.GenAndChargeAccounts(1, 1000000)[0]
member := s.GenAndChargeAccounts(1, 1000000)[0]
groupName := storageutils.GenRandomGroupName()

// 1. CreateGroup
msgCreateGroup := storagetypes.NewMsgCreateGroup(owner.GetAddr(), groupName, []sdk.AccAddress{member.GetAddr()})
s.SendTxBlock(msgCreateGroup, owner)
s.T().Logf("CerateGroup success, owner: %s, group name: %s", owner.GetAddr().String(), groupName)

// 2. HeadGroup
queryHeadGroupReq := storagetypes.QueryHeadGroupRequest{GroupOwner: owner.GetAddr().String(), GroupName: groupName}
queryHeadGroupResp, err := s.Client.HeadGroup(ctx, &queryHeadGroupReq)
s.Require().NoError(err)
s.Require().Equal(queryHeadGroupResp.GroupInfo.GroupName, groupName)
s.Require().Equal(queryHeadGroupResp.GroupInfo.Owner, owner.GetAddr().String())

// 3. HeadGroupMember
queryHeadGroupMemberReq := storagetypes.QueryHeadGroupMemberRequest{
Member: member.GetAddr().String(),
GroupName: groupName,
GroupOwner: owner.GetAddr().String(),
}
queryHeadGroupMemberResp, err := s.Client.HeadGroupMember(ctx, &queryHeadGroupMemberReq)
s.Require().NoError(err)
s.Require().Equal(queryHeadGroupMemberResp.GroupInfo.GroupName, groupName)
s.Require().Equal(queryHeadGroupMemberResp.GroupInfo.Owner, owner.GetAddr().String())

// 4. UpdateGroupMember
member2 := s.GenAndChargeAccounts(1, 1000000)[0]
membersToAdd := []sdk.AccAddress{member2.GetAddr()}
membersToDelete := []sdk.AccAddress{member.GetAddr()}
msgUpdateGroupMember := storagetypes.NewMsgUpdateGroupMember(owner.GetAddr(), groupName, membersToAdd, membersToDelete)
s.SendTxBlock(msgUpdateGroupMember, owner)

// 5. HeadGroupMember (delete)
queryHeadGroupMemberReqDelete := storagetypes.QueryHeadGroupMemberRequest{
Member: member.GetAddr().String(),
GroupName: groupName,
GroupOwner: owner.GetAddr().String(),
}
_, err = s.Client.HeadGroupMember(ctx, &queryHeadGroupMemberReqDelete)
s.Require().True(strings.Contains(err.Error(), storagetypes.ErrNoSuchGroupMember.Error()))
// 5. HeadGroupMember (add)
queryHeadGroupMemberReqAdd := storagetypes.QueryHeadGroupMemberRequest{
Member: member2.GetAddr().String(),
GroupName: groupName,
GroupOwner: owner.GetAddr().String(),
}
queryHeadGroupMemberRespAdd, err := s.Client.HeadGroupMember(ctx, &queryHeadGroupMemberReqAdd)
s.Require().NoError(err)
s.Require().Equal(queryHeadGroupMemberRespAdd.GroupInfo.GroupName, groupName)
s.Require().Equal(queryHeadGroupMemberRespAdd.GroupInfo.Owner, owner.GetAddr().String())
}

func (s *StorageTestSuite) TestDeleteBucket() {
var err error
user := s.GenAndChargeAccounts(1, 1000000)[0]
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ require (
github.com/cosmos/cosmos-proto v1.0.0-beta.1
github.com/cosmos/cosmos-sdk v0.46.4
github.com/cosmos/go-bip39 v1.0.0
github.com/cosmos/gogoproto v1.4.6
github.com/cosmos/ibc-go/v5 v5.0.0
github.com/ethereum/go-ethereum v1.10.19
github.com/evmos/ethermint v0.6.1-0.20220919141022-34226aa7b1fa //TODO: update to ethermint v0.20.0 after it's released.
Expand All @@ -34,6 +33,8 @@ require (
sigs.k8s.io/yaml v1.3.0
)

require github.com/cosmos/gogoproto v1.4.6

require (
filippo.io/edwards25519 v1.0.0-rc.1 // indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
Expand Down
78 changes: 69 additions & 9 deletions proto/greenfield/storage/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ service Query {
option (google.api.http).get = "/greenfield/storage/head_object/{bucket_name}/{object_name}";
}

// Queries a object by id
// Queries an object by id
rpc HeadObjectById(QueryHeadObjectByIdRequest) returns (QueryHeadObjectResponse) {
option (google.api.http).get = "/greenfield/storage/head_object_by_id/{object_id}";
}
Expand Down Expand Up @@ -73,15 +73,36 @@ service Query {
rpc HeadGroupNFT(QueryNFTRequest) returns (QueryGroupNFTResponse) {
option (google.api.http).get = "/greenfield/storage/head_group_nft/{token_id}";
}
// Queries policy by policyID
rpc GetPolicy(QueryGetPolicyRequest) returns (QueryGetPolicyResponse) {
option (google.api.http).get = "/greenfield/storage/get_policy/{policy_id}";

// Queries a policy which grants permission to account
rpc QueryPolicyForAccount(QueryPolicyForAccountRequest) returns (QueryPolicyForAccountResponse) {
option (google.api.http).get = "/greenfield/storage/policy_for_account/{resource}/{principal_address}";
}

// Queries a list of VerifyPermission items.
rpc VerifyPermission(QueryVerifyPermissionRequest) returns (QueryVerifyPermissionResponse) {
option (google.api.http).get = "/greenfield/storage/verify_permission/{operator}/{bucket_name}/{object_name}/{action_type}";
}

// Queries a group with specify owner and name .
rpc HeadGroup(QueryHeadGroupRequest) returns (QueryHeadGroupResponse) {
option (google.api.http).get = "/greenfield/storage/head_group/{group_owner}/{group_name}";
}

// Queries a list of ListGroup items.
rpc ListGroup(QueryListGroupRequest) returns (QueryListGroupResponse) {
option (google.api.http).get = "/bnb-chain/greenfield/storage/list_group";
}

// Queries a list of HeadGroupMember items.
rpc HeadGroupMember(QueryHeadGroupMemberRequest) returns (QueryHeadGroupMemberResponse) {
option (google.api.http).get = "/bnb-chain/greenfield/storage/head_group_member";
}

// Queries a policy that grants permission to a group
rpc QueryPolicyForGroup(QueryPolicyForGroupRequest) returns (QueryPolicyForGroupResponse) {
option (google.api.http).get = "/bnb-chain/greenfield/storage/policy_for_group/{resource}/{principal_group_id}";
}
}

// QueryParamsRequest is request type for the Query/Params RPC method.
Expand Down Expand Up @@ -124,7 +145,7 @@ message QueryListBucketsRequest {
}

message QueryListBucketsResponse {
repeated BucketInfo bucket_infos = 1 [(gogoproto.nullable) = false];
repeated BucketInfo bucket_infos = 1;
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

Expand All @@ -139,7 +160,7 @@ message QueryListObjectsByBucketIdRequest {
}

message QueryListObjectsResponse {
repeated ObjectInfo object_infos = 1 [(gogoproto.nullable) = false];
repeated ObjectInfo object_infos = 1;
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

Expand All @@ -159,11 +180,12 @@ message QueryGroupNFTResponse {
GroupMetaData meta_data = 1;
}

message QueryGetPolicyRequest {
string policy_id = 1;
message QueryPolicyForAccountRequest {
string resource = 1;
string principal_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

message QueryGetPolicyResponse {
message QueryPolicyForAccountResponse {
permission.Policy policy = 1;
}

Expand All @@ -177,3 +199,41 @@ message QueryVerifyPermissionRequest {
message QueryVerifyPermissionResponse {
permission.Effect effect = 1;
}

message QueryHeadGroupRequest {
string group_owner = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string group_name = 2;
}

message QueryHeadGroupResponse {
GroupInfo group_info = 1;
}

message QueryListGroupRequest {
cosmos.base.query.v1beta1.PageRequest pagination = 1;
string group_owner = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

message QueryListGroupResponse {
cosmos.base.query.v1beta1.PageResponse pagination = 1;
repeated GroupInfo group_infos = 2;
}

message QueryHeadGroupMemberRequest {
string member = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string group_owner = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string group_name = 3;
}

message QueryHeadGroupMemberResponse {
GroupInfo group_info = 1;
}

message QueryPolicyForGroupRequest {
string resource = 1;
string principal_group_id = 2;
}

message QueryPolicyForGroupResponse {
permission.Policy policy = 1;
}
47 changes: 34 additions & 13 deletions x/permission/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger {

func (k Keeper) AddGroupMember(ctx sdk.Context, groupID math.Uint, member sdk.AccAddress) error {
store := ctx.KVStore(k.storeKey)
policy, found := k.getPolicyToAccount(ctx, groupID, resource.RESOURCE_TYPE_GROUP, member)
policy, found := k.GetPolicyForAccount(ctx, groupID, resource.RESOURCE_TYPE_GROUP, member)
if !found {
policy = types.NewDefaultPolicyForGroupMember(groupID, member)
policy.Id = k.policySeq.NextVal(store)
Expand All @@ -77,11 +77,11 @@ func (k Keeper) AddGroupMember(ctx sdk.Context, groupID math.Uint, member sdk.Ac
func (k Keeper) RemoveGroupMember(ctx sdk.Context, groupID math.Uint, member sdk.AccAddress) {
store := ctx.KVStore(k.storeKey)

policy, found := k.getPolicyToAccount(ctx, groupID, resource.RESOURCE_TYPE_GROUP, member)
policy, found := k.GetPolicyForAccount(ctx, groupID, resource.RESOURCE_TYPE_GROUP, member)
if found {
if policy.Statements == nil {
store.Delete(types.GetPolicyByIDKey(policy.Id))
store.Delete(types.GetPolicyToAccountKey(groupID, resource.RESOURCE_TYPE_GROUP, member))
store.Delete(types.GetPolicyForAccountKey(groupID, resource.RESOURCE_TYPE_GROUP, member))
} else {
policy.MemberStatement = nil
store.Set(types.GetPolicyByIDKey(policy.Id), k.cdc.MustMarshal(policy))
Expand All @@ -99,7 +99,7 @@ func (k Keeper) PutPolicy(ctx sdk.Context, policy *types.Policy) (math.Uint, err
store := ctx.KVStore(k.storeKey)

if policy.Principal.Type == types.TYPE_GNFD_ACCOUNT {
policyKey := types.GetPolicyToAccountKey(policy.ResourceId, policy.ResourceType,
policyKey := types.GetPolicyForAccountKey(policy.ResourceId, policy.ResourceType,
policy.Principal.MustGetAccountAddress())
bz := store.Get(policyKey)
if bz != nil {
Expand All @@ -112,7 +112,7 @@ func (k Keeper) PutPolicy(ctx sdk.Context, policy *types.Policy) (math.Uint, err
store.Set(types.GetPolicyByIDKey(policy.Id), bz)
}
} else if policy.Principal.Type == types.TYPE_GNFD_GROUP {
policyGroupKey := types.GetPolicyToGroupKey(policy.ResourceId, policy.ResourceType)
policyGroupKey := types.GetPolicyForGroupKey(policy.ResourceId, policy.ResourceType)
bz := store.Get(policyGroupKey)
if bz != nil {
policyGroup := types.PolicyGroup{}
Expand Down Expand Up @@ -173,11 +173,11 @@ func (k Keeper) MustGetPolicyByID(ctx sdk.Context, policyID math.Uint) *types.Po
return policy
}

func (k Keeper) getPolicyToAccount(ctx sdk.Context, resourceID math.Uint,
func (k Keeper) GetPolicyForAccount(ctx sdk.Context, resourceID math.Uint,
resourceType resource.ResourceType, addr sdk.AccAddress) (policy *types.Policy,
isFound bool) {
store := ctx.KVStore(k.storeKey)
policyKey := types.GetPolicyToAccountKey(resourceID, resourceType, addr)
policyKey := types.GetPolicyForAccountKey(resourceID, resourceType, addr)

bz := store.Get(policyKey)
if bz == nil {
Expand All @@ -187,10 +187,31 @@ func (k Keeper) getPolicyToAccount(ctx sdk.Context, resourceID math.Uint,
return k.GetPolicyByID(ctx, sequence.DecodeSequence(bz))
}

func (k Keeper) GetPolicyForGroup(ctx sdk.Context, resourceID math.Uint,
resourceType resource.ResourceType, groupID math.Uint) (policy *types.Policy,
isFound bool) {
store := ctx.KVStore(k.storeKey)
policyGroupKey := types.GetPolicyForGroupKey(resourceID, resourceType)

bz := store.Get(policyGroupKey)
if bz == nil {
return policy, false
}

var policyGroup types.PolicyGroup
k.cdc.MustUnmarshal(bz, &policyGroup)
for _, item := range policyGroup.Items {
if item.GroupId == groupID {
return k.GetPolicyByID(ctx, item.PolicyId)
}
}
return nil, false
}

func (k Keeper) setPolicyToAccount(ctx sdk.Context, resourceID math.Uint,
resourceType resource.ResourceType, addr sdk.AccAddress, policy *types.Policy) {
store := ctx.KVStore(k.storeKey)
policyKey := types.GetPolicyToAccountKey(resourceID, resourceType, addr)
policyKey := types.GetPolicyForAccountKey(resourceID, resourceType, addr)

store.Set(policyKey, sequence.EncodeSequence(policy.Id))
store.Set(types.GetPolicyByIDKey(policy.Id), k.cdc.MustMarshal(policy))
Expand All @@ -199,7 +220,7 @@ func (k Keeper) setPolicyToAccount(ctx sdk.Context, resourceID math.Uint,
func (k Keeper) VerifyPolicy(ctx sdk.Context, resourceID math.Uint, resourceType resource.ResourceType,
operator sdk.AccAddress, action types.ActionType, resource *string) types.Effect {
// verify policy which grant permission to account
policy, found := k.getPolicyToAccount(ctx, resourceID, resourceType, operator)
policy, found := k.GetPolicyForAccount(ctx, resourceID, resourceType, operator)
if found {
effect := policy.Eval(action, resource)
if effect != types.EFFECT_PASS {
Expand All @@ -209,7 +230,7 @@ func (k Keeper) VerifyPolicy(ctx sdk.Context, resourceID math.Uint, resourceType

// verify policy which grant permission to group
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.GetPolicyToGroupKey(resourceID, resourceType))
bz := store.Get(types.GetPolicyForGroupKey(resourceID, resourceType))
policyGroup := types.PolicyGroup{}
k.cdc.MustUnmarshal(bz, &policyGroup)

Expand All @@ -220,7 +241,7 @@ func (k Keeper) VerifyPolicy(ctx sdk.Context, resourceID math.Uint, resourceType
effect := p.Eval(action, resource)
if effect != types.EFFECT_PASS {
// check the operator is the member of this group
groupPolicy, found := k.getPolicyToAccount(ctx, item.GroupId, resourceType, operator)
groupPolicy, found := k.GetPolicyForAccount(ctx, item.GroupId, resourceType, operator)
if found {
memberEffect := groupPolicy.Eval(types.ACTION_GROUP_MEMBER, nil)
if memberEffect != types.EFFECT_PASS {
Expand All @@ -247,7 +268,7 @@ func (k Keeper) DeletePolicy(ctx sdk.Context, principal *types.Principal, resour
var policyID math.Uint
if principal.Type == types.TYPE_GNFD_ACCOUNT {
accAddr := sdk.MustAccAddressFromHex(principal.Value)
policyKey := types.GetPolicyToAccountKey(resourceID, resourceType, accAddr)
policyKey := types.GetPolicyForAccountKey(resourceID, resourceType, accAddr)
bz := store.Get(policyKey)
policyID = sequence.DecodeSequence(bz)
if bz != nil {
Expand All @@ -259,7 +280,7 @@ func (k Keeper) DeletePolicy(ctx sdk.Context, principal *types.Principal, resour
if err != nil {
return math.ZeroUint(), err
}
bz := store.Get(types.GetPolicyToGroupKey(resourceID, resourceType))
bz := store.Get(types.GetPolicyForGroupKey(resourceID, resourceType))
if bz != nil {
policyGroup := types.PolicyGroup{}
k.cdc.MustUnmarshal(bz, &policyGroup)
Expand Down
7 changes: 7 additions & 0 deletions x/permission/types/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ func NewPrincipalWithAccount(addr sdk.AccAddress) *Principal {
}
}

func NewPrincipalWithGroup(groupID sdkmath.Uint) *Principal {
return &Principal{
Type: TYPE_GNFD_GROUP,
Value: groupID.String(),
}
}

func (p *Principal) ValidateBasic() error {
switch p.Type {
case TYPE_GNFD_ACCOUNT:
Expand Down
Loading