feat(authz): autocli query support (backport #16986) (#16988)

Co-authored-by: Julien Robert <julien@rbrt.fr>
This commit is contained in:
mergify[bot] 2023-07-13 15:33:55 +00:00 committed by GitHub
parent 4076c6a918
commit bc7221f5c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 98 additions and 850 deletions

View File

@ -199,7 +199,7 @@ func (s *E2ETestSuite) TestQueryGranterGrantsGRPC() {
fmt.Sprintf("%s/cosmos/authz/v1beta1/grants/granter/%s", val.APIAddress, val.Address.String()),
false,
"",
7,
6,
},
}
for _, tc := range testCases {

View File

@ -1,269 +0,0 @@
package authz
import (
"fmt"
"strings"
"time"
"cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/codec/address"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/authz"
"github.com/cosmos/cosmos-sdk/x/authz/client/cli"
authzclitestutil "github.com/cosmos/cosmos-sdk/x/authz/client/testutil"
)
func (s *E2ETestSuite) TestQueryAuthorizations() {
val := s.network.Validators[0]
grantee := s.grantee[0]
twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix()
_, err := authzclitestutil.CreateGrant(
val.ClientCtx,
[]string{
grantee.String(),
"send",
fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()),
},
)
s.Require().NoError(err)
s.Require().NoError(s.network.WaitForNextBlock())
testCases := []struct {
name string
args []string
expectErr bool
expErrMsg string
}{
{
"Error: Invalid grantee",
[]string{
val.Address.String(),
"invalid grantee",
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
true,
"decoding bech32 failed: invalid character in string: ' '",
},
{
"Error: Invalid granter",
[]string{
"invalid granter",
grantee.String(),
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
true,
"decoding bech32 failed: invalid character in string: ' '",
},
{
"Valid txn (json)",
[]string{
val.Address.String(),
grantee.String(),
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
false,
``,
},
}
for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
cmd := cli.GetCmdQueryGrants(address.NewBech32Codec("cosmos"))
clientCtx := val.ClientCtx
resp, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expectErr {
s.Require().Error(err)
s.Require().Contains(string(resp.Bytes()), tc.expErrMsg)
} else {
s.Require().NoError(err)
var grants authz.QueryGrantsResponse
err = val.ClientCtx.Codec.UnmarshalJSON(resp.Bytes(), &grants)
s.Require().NoError(err)
}
})
}
}
func (s *E2ETestSuite) TestQueryAuthorization() {
val := s.network.Validators[0]
grantee := s.grantee[0]
twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix()
_, err := authzclitestutil.CreateGrant(
val.ClientCtx,
[]string{
grantee.String(),
"send",
fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()),
},
)
s.Require().NoError(err)
s.Require().NoError(s.network.WaitForNextBlock())
testCases := []struct {
name string
args []string
expectErr bool
expectedOutput string
}{
{
"Error: Invalid grantee",
[]string{
val.Address.String(),
"invalid grantee",
typeMsgSend,
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
true,
"",
},
{
"Error: Invalid granter",
[]string{
"invalid granter",
grantee.String(),
typeMsgSend,
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
true,
"",
},
{
"no authorization found",
[]string{
val.Address.String(),
grantee.String(),
"typeMsgSend",
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
true,
"",
},
{
"Valid txn (json)",
[]string{
val.Address.String(),
grantee.String(),
typeMsgSend,
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
false,
`{"@type":"/cosmos.bank.v1beta1.SendAuthorization","spend_limit":[{"denom":"stake","amount":"100"}],"allow_list":[]}`,
},
{
"Valid txn with allowed list (json)",
[]string{
val.Address.String(),
s.grantee[3].String(),
typeMsgSend,
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
false,
fmt.Sprintf(`{"@type":"/cosmos.bank.v1beta1.SendAuthorization","spend_limit":[{"denom":"stake","amount":"88"}],"allow_list":["%s"]}`, s.grantee[4]),
},
}
for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
cmd := cli.GetCmdQueryGrants(address.NewBech32Codec("cosmos"))
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expectErr {
s.Require().Error(err)
} else {
s.Require().NoError(err)
s.Require().Contains(strings.TrimSpace(out.String()), tc.expectedOutput)
}
})
}
}
func (s *E2ETestSuite) TestQueryGranterGrants() {
val := s.network.Validators[0]
grantee := s.grantee[0]
require := s.Require()
testCases := []struct {
name string
args []string
expectErr bool
expectedErr string
expItems int
}{
{
"invalid address",
[]string{
"invalid-address",
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
true,
"decoding bech32 failed",
0,
},
{
"no authorization found",
[]string{
grantee.String(),
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
false,
"",
0,
},
{
"valid case",
[]string{
val.Address.String(),
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
false,
"",
7,
},
{
"valid case with pagination",
[]string{
val.Address.String(),
"--limit=2",
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
false,
"",
2,
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
cmd := cli.GetQueryGranterGrants(address.NewBech32Codec("cosmos"))
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expectErr {
require.Error(err)
require.Contains(out.String(), tc.expectedErr)
} else {
require.NoError(err)
var grants authz.QueryGranterGrantsResponse
require.NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &grants))
require.Len(grants.Grants, tc.expItems)
}
})
}
}

View File

@ -1,195 +0,0 @@
package cli
import (
"fmt"
"strings"
"github.com/spf13/cobra"
"cosmossdk.io/core/address"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/version"
"github.com/cosmos/cosmos-sdk/x/authz"
bank "github.com/cosmos/cosmos-sdk/x/bank/types"
)
// GetQueryCmd returns the cli query commands for this module
func GetQueryCmd(ac address.Codec) *cobra.Command {
authorizationQueryCmd := &cobra.Command{
Use: authz.ModuleName,
Short: "Querying commands for the authz module",
Long: "",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
authorizationQueryCmd.AddCommand(
GetCmdQueryGrants(ac),
GetQueryGranterGrants(ac),
GetQueryGranteeGrants(ac),
)
return authorizationQueryCmd
}
// GetCmdQueryGrants implements the query authorization command.
func GetCmdQueryGrants(ac address.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "grants [granter-addr] [grantee-addr] [msg-type-url]?",
Args: cobra.RangeArgs(2, 3),
Short: "query grants for a granter-grantee pair and optionally a msg-type-url",
Long: strings.TrimSpace(
fmt.Sprintf(`Query authorization grants for a granter-grantee pair. If msg-type-url
is set, it will select grants only for that msg type.
Examples:
$ %s query %s grants cosmos1skj.. cosmos1skjwj..
$ %s query %s grants cosmos1skjw.. cosmos1skjwj.. %s
`,
version.AppName, authz.ModuleName,
version.AppName, authz.ModuleName, bank.SendAuthorization{}.MsgTypeURL()),
),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := authz.NewQueryClient(clientCtx)
_, err = ac.StringToBytes(args[0])
if err != nil {
return err
}
_, err = ac.StringToBytes(args[1])
if err != nil {
return err
}
msgAuthorized := ""
if len(args) == 3 {
msgAuthorized = args[2]
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
res, err := queryClient.Grants(
cmd.Context(),
&authz.QueryGrantsRequest{
Granter: args[0],
Grantee: args[1],
MsgTypeUrl: msgAuthorized,
Pagination: pageReq,
},
)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "grants")
return cmd
}
// GetQueryGranterGrants returns cmd to query for all grants for a granter.
func GetQueryGranterGrants(ac address.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "grants-by-granter [granter-addr]",
Args: cobra.ExactArgs(1),
Short: "query authorization grants granted by granter",
Long: strings.TrimSpace(
fmt.Sprintf(`Query authorization grants granted by granter.
Examples:
$ %s q %s grants-by-granter cosmos1skj..
`,
version.AppName, authz.ModuleName),
),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
_, err = ac.StringToBytes(args[0])
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
queryClient := authz.NewQueryClient(clientCtx)
res, err := queryClient.GranterGrants(
cmd.Context(),
&authz.QueryGranterGrantsRequest{
Granter: args[0],
Pagination: pageReq,
},
)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "granter-grants")
return cmd
}
// GetQueryGranteeGrants returns cmd to query for all grants for a grantee.
func GetQueryGranteeGrants(ac address.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "grants-by-grantee [grantee-addr]",
Args: cobra.ExactArgs(1),
Short: "query authorization grants granted to a grantee",
Long: strings.TrimSpace(
fmt.Sprintf(`Query authorization grants granted to a grantee.
Examples:
$ %s q %s grants-by-grantee cosmos1skj..
`,
version.AppName, authz.ModuleName),
),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
_, err = ac.StringToBytes(args[0])
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
queryClient := authz.NewQueryClient(clientCtx)
res, err := queryClient.GranteeGrants(
cmd.Context(),
&authz.QueryGranteeGrantsRequest{
Grantee: args[0],
Pagination: pageReq,
},
)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "grantee-grants")
return cmd
}

View File

@ -1,315 +0,0 @@
package cli_test
import (
"fmt"
"time"
sdkmath "cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/client/flags"
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
"github.com/cosmos/cosmos-sdk/testutil"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/authz"
"github.com/cosmos/cosmos-sdk/x/authz/client/cli"
authzclitestutil "github.com/cosmos/cosmos-sdk/x/authz/client/testutil"
)
func (s *CLITestSuite) TestQueryAuthorizations() {
val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
grantee := s.grantee[0]
twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix()
_, err := authzclitestutil.CreateGrant(
s.clientCtx,
[]string{
grantee.String(),
"send",
fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
},
)
s.Require().NoError(err)
testCases := []struct {
name string
args []string
expectErr bool
expErrMsg string
}{
{
"Error: Invalid grantee",
[]string{
val[0].Address.String(),
"invalid grantee",
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
true,
"decoding bech32 failed: invalid character in string: ' '",
},
{
"Error: Invalid granter",
[]string{
"invalid granter",
grantee.String(),
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
true,
"decoding bech32 failed: invalid character in string: ' '",
},
{
"Valid txn (json)",
[]string{
val[0].Address.String(),
grantee.String(),
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
false,
``,
},
}
for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
cmd := cli.GetCmdQueryGrants(addresscodec.NewBech32Codec("cosmos"))
resp, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args)
if tc.expectErr {
s.Require().Error(err)
s.Require().Contains(string(resp.Bytes()), tc.expErrMsg)
} else {
s.Require().NoError(err)
var grants authz.QueryGrantsResponse
err = s.clientCtx.Codec.UnmarshalJSON(resp.Bytes(), &grants)
s.Require().NoError(err)
}
})
}
}
func (s *CLITestSuite) TestQueryAuthorization() {
val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
grantee := s.grantee[0]
twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix()
_, err := authzclitestutil.CreateGrant(
s.clientCtx,
[]string{
grantee.String(),
"send",
fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
},
)
s.Require().NoError(err)
testCases := []struct {
name string
args []string
expectErr bool
}{
{
"Error: Invalid grantee",
[]string{
val[0].Address.String(),
"invalid grantee",
typeMsgSend,
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
true,
},
{
"Error: Invalid granter",
[]string{
"invalid granter",
grantee.String(),
typeMsgSend,
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
true,
},
{
"Valid txn (json)",
[]string{
val[0].Address.String(),
grantee.String(),
typeMsgSend,
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
false,
},
{
"Valid txn with allowed list (json)",
[]string{
val[0].Address.String(),
s.grantee[3].String(),
typeMsgSend,
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
false,
},
}
for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
cmd := cli.GetCmdQueryGrants(addresscodec.NewBech32Codec("cosmos"))
_, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args)
if tc.expectErr {
s.Require().Error(err)
} else {
s.Require().NoError(err)
}
})
}
}
func (s *CLITestSuite) TestQueryGranteeGrants() {
val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
grantee := s.grantee[0]
twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix()
require := s.Require()
_, err := authzclitestutil.CreateGrant(
s.clientCtx,
[]string{
grantee.String(),
"send",
fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
},
)
s.Require().NoError(err)
testCases := []struct {
name string
args []string
expectErr bool
expectedErr string
}{
{
"invalid address",
[]string{
"invalid-address",
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
true,
"decoding bech32 failed",
},
{
"valid case",
[]string{
grantee.String(),
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
false,
"",
},
{
"valid case with pagination",
[]string{
grantee.String(),
"--limit=2",
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
false,
"",
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
cmd := cli.GetQueryGranteeGrants(addresscodec.NewBech32Codec("cosmos"))
out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args)
if tc.expectErr {
require.Error(err)
require.Contains(out.String(), tc.expectedErr)
} else {
require.NoError(err)
var grants authz.QueryGranteeGrantsResponse
require.NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &grants))
}
})
}
}
func (s *CLITestSuite) TestQueryGranterGrants() {
val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
grantee := s.grantee[0]
require := s.Require()
testCases := []struct {
name string
args []string
expectErr bool
expectedErr string
}{
{
"invalid address",
[]string{
"invalid-address",
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
true,
"decoding bech32 failed",
},
{
"no authorization found",
[]string{
grantee.String(),
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
false,
"",
},
{
"valid case",
[]string{
val[0].Address.String(),
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
false,
"",
},
{
"valid case with pagination",
[]string{
val[0].Address.String(),
"--limit=2",
fmt.Sprintf("--%s=json", flags.FlagOutput),
},
false,
"",
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
cmd := cli.GetQueryGranterGrants(addresscodec.NewBech32Codec("cosmos"))
out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args)
if tc.expectErr {
require.Error(err)
require.Contains(out.String(), tc.expectedErr)
} else {
require.NoError(err)
var grants authz.QueryGranterGrantsResponse
require.NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &grants))
}
})
}
}

View File

@ -57,7 +57,19 @@ func (suite *TestSuite) TestGRPCQueryAuthorization() {
func(require *require.Assertions, res *authz.QueryGrantsResponse) {},
},
{
"Success",
"authorization not found",
func(require *require.Assertions) {
req = &authz.QueryGrantsRequest{
Granter: addrs[1].String(),
Grantee: addrs[0].String(),
MsgTypeUrl: banktypes.SendAuthorization{}.MsgTypeURL(),
}
},
"authorization not found for /cosmos.bank.v1beta1.MsgSend",
func(require *require.Assertions, res *authz.QueryGrantsResponse) {},
},
{
"success",
func(require *require.Assertions) {
expAuthorization = suite.createSendAuthorization(addrs[0], addrs[1])
req = &authz.QueryGrantsRequest{
@ -76,6 +88,28 @@ func (suite *TestSuite) TestGRPCQueryAuthorization() {
require.Equal(auth.String(), expAuthorization.String())
},
},
{
"success with allow list",
func(require *require.Assertions) {
expAuthorization = suite.createSendAuthorizationWithAllowList(addrs[0], addrs[1])
require.Len(expAuthorization.(*banktypes.SendAuthorization).GetAllowList(), 1)
req = &authz.QueryGrantsRequest{
Granter: addrs[1].String(),
Grantee: addrs[0].String(),
MsgTypeUrl: expAuthorization.MsgTypeURL(),
}
},
"",
func(require *require.Assertions, res *authz.QueryGrantsResponse) {
var auth authz.Authorization
require.Equal(1, len(res.Grants))
err := suite.encCfg.InterfaceRegistry.UnpackAny(res.Grants[0].Authorization, &auth)
require.NoError(err)
require.NotNil(auth)
require.Equal(auth.String(), expAuthorization.String())
require.Equal(auth.(*banktypes.SendAuthorization).GetAllowList(), expAuthorization.(*banktypes.SendAuthorization).GetAllowList())
},
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
@ -93,70 +127,6 @@ func (suite *TestSuite) TestGRPCQueryAuthorization() {
}
}
func (suite *TestSuite) TestGRPCQueryAuthorizations() {
queryClient, addrs := suite.queryClient, suite.addrs
var (
req *authz.QueryGrantsRequest
expAuthorization authz.Authorization
)
testCases := []struct {
msg string
malleate func()
expPass bool
postTest func(res *authz.QueryGrantsResponse)
}{
{
"fail invalid granter addr",
func() {
req = &authz.QueryGrantsRequest{}
},
false,
func(res *authz.QueryGrantsResponse) {},
},
{
"fail invalid grantee addr",
func() {
req = &authz.QueryGrantsRequest{
Granter: addrs[0].String(),
}
},
false,
func(res *authz.QueryGrantsResponse) {},
},
{
"Success",
func() {
expAuthorization = suite.createSendAuthorization(addrs[0], addrs[1])
req = &authz.QueryGrantsRequest{
Granter: addrs[1].String(),
Grantee: addrs[0].String(),
}
},
true,
func(res *authz.QueryGrantsResponse) {
var auth authz.Authorization
suite.Require().Equal(1, len(res.Grants))
err := suite.encCfg.InterfaceRegistry.UnpackAny(res.Grants[0].Authorization, &auth)
suite.Require().NoError(err)
suite.Require().NotNil(auth)
suite.Require().Equal(auth.String(), expAuthorization.String())
},
},
}
for _, testCase := range testCases {
suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() {
testCase.malleate()
result, err := queryClient.Grants(gocontext.Background(), req)
if testCase.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
testCase.postTest(result)
})
}
}
func (suite *TestSuite) TestGRPCQueryGranterGrants() {
require := suite.Require()
queryClient, addrs := suite.queryClient, suite.addrs
@ -312,3 +282,12 @@ func (suite *TestSuite) createSendAuthorization(grantee, granter sdk.AccAddress)
suite.Require().NoError(err)
return authorization
}
func (suite *TestSuite) createSendAuthorizationWithAllowList(grantee, granter sdk.AccAddress) authz.Authorization {
exp := suite.ctx.BlockHeader().Time.Add(time.Hour)
newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100))
authorization := &banktypes.SendAuthorization{SpendLimit: newCoins, AllowList: []string{suite.addrs[5].String()}}
err := suite.authzKeeper.SaveGrant(suite.ctx, grantee, granter, authorization, &exp)
suite.Require().NoError(err)
return authorization
}

53
x/authz/module/autocli.go Normal file
View File

@ -0,0 +1,53 @@
package authz
import (
"fmt"
authzv1beta1 "cosmossdk.io/api/cosmos/authz/v1beta1"
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
"github.com/cosmos/cosmos-sdk/version"
bank "github.com/cosmos/cosmos-sdk/x/bank/types"
)
// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface.
func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
return &autocliv1.ModuleOptions{
Query: &autocliv1.ServiceCommandDescriptor{
Service: authzv1beta1.Query_ServiceDesc.ServiceName,
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
{
RpcMethod: "Grants",
Use: "grants [granter-addr] [grantee-addr] <msg-type-url>",
Short: "Query grants for a granter-grantee pair and optionally a msg-type-url",
Long: "Query authorization grants for a granter-grantee pair. If msg-type-url is set, it will select grants only for that msg type.",
Example: fmt.Sprintf("%s query authz grants cosmos1skj.. cosmos1skjwj.. %s", version.AppName, bank.SendAuthorization{}.MsgTypeURL()),
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "granter"},
{ProtoField: "grantee"},
{ProtoField: "msg_type_url", Optional: true},
},
},
{
RpcMethod: "GranterGrants",
Use: "grants-by-granter [granter-addr]",
Short: "Query authorization grants granted by granter",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "granter"},
},
},
{
RpcMethod: "GranteeGrants",
Use: "grants-by-grantee [grantee-addr]",
Short: "Query authorization grants granted to a grantee",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "grantee"},
},
},
},
},
Tx: &autocliv1.ServiceCommandDescriptor{
Service: authzv1beta1.Msg_ServiceDesc.ServiceName,
},
}
}

View File

@ -90,11 +90,6 @@ func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx sdkclient.Context, mux
}
}
// GetQueryCmd returns the cli query commands for the authz module
func (ab AppModuleBasic) GetQueryCmd() *cobra.Command {
return cli.GetQueryCmd(ab.ac)
}
// GetTxCmd returns the transaction commands for the authz module
func (ab AppModuleBasic) GetTxCmd() *cobra.Command {
return cli.GetTxCmd(ab.ac)