diff --git a/e2e/tests/permission_test.go b/e2e/tests/permission_test.go index 13671b99e..f64318904 100644 --- a/e2e/tests/permission_test.go +++ b/e2e/tests/permission_test.go @@ -1911,7 +1911,60 @@ func (s *StorageTestSuite) TestGrantsPermissionToObjectWithWildcardInName() { s.Require().True(strings.Contains(err.Error(), "No such object")) } -func (s *StorageTestSuite) TestExpiredPolicyGCAndRePut() { +func (s *StorageTestSuite) TestExpiredAccountPolicyGCAndRePut() { + var err error + ctx := context.Background() + user1 := s.GenAndChargeAccounts(1, 1000000)[0] + + _, owner, bucketName, _, _, objectId := s.createObjectWithVisibility(storagetypes.VISIBILITY_TYPE_PUBLIC_READ) + + principal := types.NewPrincipalWithAccount(user1.GetAddr()) + + // Put bucket policy + bucketStatement := &types.Statement{ + Actions: []types.ActionType{types.ACTION_DELETE_BUCKET}, + Effect: types.EFFECT_ALLOW, + } + expirationTime := time.Now().Add(5 * time.Second) + + msgPutBucketPolicy := storagetypes.NewMsgPutPolicy(owner.GetAddr(), types2.NewBucketGRN(bucketName).String(), + principal, []*types.Statement{bucketStatement}, &expirationTime) + s.SendTxBlock(owner, msgPutBucketPolicy) + + // Query the policy which is enforced on bucket + grn1 := types2.NewBucketGRN(bucketName) + queryPolicyForAccountResp, err := s.Client.QueryPolicyForAccount(ctx, &storagetypes.QueryPolicyForAccountRequest{ + Resource: grn1.String(), + PrincipalAddress: user1.GetAddr().String(), + }) + s.Require().NoError(err) + s.Require().Equal(objectId, queryPolicyForAccountResp.Policy.ResourceId) + + // wait for policy expired + time.Sleep(5 * time.Second) + + // query the policy, which is already GC, should get err. + _, err = s.Client.QueryPolicyForAccount(ctx, &storagetypes.QueryPolicyForAccountRequest{ + Resource: grn1.String(), + PrincipalAddress: user1.GetAddr().String(), + }) + s.Require().Error(err) + + // the user should be able to re-put policy for the bucket. + msgPutBucketPolicy = storagetypes.NewMsgPutPolicy(owner.GetAddr(), types2.NewBucketGRN(bucketName).String(), + principal, []*types.Statement{bucketStatement}, nil) + s.SendTxBlock(owner, msgPutBucketPolicy) + + // Query the policy which is enforced on bucket. + queryPolicyForAccountResp, err = s.Client.QueryPolicyForAccount(ctx, &storagetypes.QueryPolicyForAccountRequest{ + Resource: grn1.String(), + PrincipalAddress: user1.GetAddr().String(), + }) + s.Require().NoError(err) + s.Require().Equal(objectId, queryPolicyForAccountResp.Policy.ResourceId) +} + +func (s *StorageTestSuite) TestExpiredGroupPolicyGCAndRePut() { var err error ctx := context.Background() user1 := s.GenAndChargeAccounts(1, 1000000)[0] diff --git a/x/permission/keeper/keeper.go b/x/permission/keeper/keeper.go index 80a7bb640..d196464a8 100644 --- a/x/permission/keeper/keeper.go +++ b/x/permission/keeper/keeper.go @@ -535,17 +535,33 @@ func (k Keeper) RemoveExpiredPolicies(ctx sdk.Context) { policyId := types.ParsePolicyIdFromQueueKey(iterator.Key()) var policy types.Policy k.cdc.MustUnmarshal(store.Get(types.GetPolicyByIDKey(policyId)), &policy) + store.Delete(types.GetPolicyByIDKey(policyId)) - // delete policyKey -> policyId + //1. the policy is an account policy, delete policyKey -> policyId. + //2. the policy is group policy within a policy group, delete the index in the policy group if ctx.IsUpgraded(upgradetypes.Pampas) { - policyKey := types.GetPolicyForAccountKey(policy.ResourceId, policy.ResourceType, - policy.Principal.MustGetAccountAddress()) - store.Delete(policyKey) + if policy.Principal.Type == types.PRINCIPAL_TYPE_GNFD_ACCOUNT { + policyKey := types.GetPolicyForAccountKey(policy.ResourceId, policy.ResourceType, + policy.Principal.MustGetAccountAddress()) + store.Delete(policyKey) + } else if policy.Principal.Type == types.PRINCIPAL_TYPE_GNFD_GROUP { + policyGroupKey := types.GetPolicyForGroupKey(policy.ResourceId, policy.ResourceType) + bz := store.Get(policyGroupKey) + if bz != nil { + policyGroup := types.PolicyGroup{} + k.cdc.MustUnmarshal(bz, &policyGroup) + for i := 0; i < len(policyGroup.Items); i++ { + if policyGroup.Items[i].PolicyId.Equal(policyId) { + policyGroup.Items = append(policyGroup.Items[:i], policyGroup.Items[i+1:]...) + break + } + } + store.Set(policyGroupKey, k.cdc.MustMarshal(&policyGroup)) + } + } + ctx.EventManager().EmitTypedEvents(&types.EventDeletePolicy{PolicyId: policyId}) //nolint: errcheck + count++ } - - ctx.EventManager().EmitTypedEvents(&types.EventDeletePolicy{PolicyId: policyId}) //nolint: errcheck - - count++ } }