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: authz add query all grants by granter #10326

Merged
merged 5 commits into from
Oct 11, 2021
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (bank) [\#9618](https://github.com/cosmos/cosmos-sdk/pull/9618) Update bank.Metadata: add URI and URIHash attributes.
* [\#9837](https://github.com/cosmos/cosmos-sdk/issues/9837) `--generate-only` flag will accept the keyname now.
* [\#10045](https://github.com/cosmos/cosmos-sdk/pull/10045) Revert [#8549](https://github.com/cosmos/cosmos-sdk/pull/8549). Do not route grpc queries through Tendermint.
* [\#10326](https://github.com/cosmos/cosmos-sdk/pull/10326) `x/authz` add query all grants by granter query.

### API Breaking Changes

Expand Down
35 changes: 35 additions & 0 deletions docs/core/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
- [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization)

- [cosmos/authz/v1beta1/query.proto](#cosmos/authz/v1beta1/query.proto)
- [QueryGranterGrantsRequest](#cosmos.authz.v1beta1.QueryGranterGrantsRequest)
- [QueryGranterGrantsResponse](#cosmos.authz.v1beta1.QueryGranterGrantsResponse)
- [QueryGrantsRequest](#cosmos.authz.v1beta1.QueryGrantsRequest)
- [QueryGrantsResponse](#cosmos.authz.v1beta1.QueryGrantsResponse)

Expand Down Expand Up @@ -1274,6 +1276,38 @@ GrantAuthorization defines the GenesisState/GrantAuthorization type.



<a name="cosmos.authz.v1beta1.QueryGranterGrantsRequest"></a>

### QueryGranterGrantsRequest
QueryGranterGrantsRequest is the request type for the Query/Grants RPC method.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `granter` | [string](#string) | | |
| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. |






<a name="cosmos.authz.v1beta1.QueryGranterGrantsResponse"></a>

### QueryGranterGrantsResponse
QueryGranterGrantsResponse is the response type for the Query/GranterGrants RPC method.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `grants` | [Grant](#cosmos.authz.v1beta1.Grant) | repeated | authorizations is a list of grants granted for grantee by granter. |
| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. |






<a name="cosmos.authz.v1beta1.QueryGrantsRequest"></a>

### QueryGrantsRequest
Expand Down Expand Up @@ -1322,6 +1356,7 @@ Query defines the gRPC querier service.
| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
| `Grants` | [QueryGrantsRequest](#cosmos.authz.v1beta1.QueryGrantsRequest) | [QueryGrantsResponse](#cosmos.authz.v1beta1.QueryGrantsResponse) | Returns list of `Authorization`, granted to the grantee by the granter. | GET|/cosmos/authz/v1beta1/grants|
| `GranterGrants` | [QueryGranterGrantsRequest](#cosmos.authz.v1beta1.QueryGranterGrantsRequest) | [QueryGranterGrantsResponse](#cosmos.authz.v1beta1.QueryGranterGrantsResponse) | GranterGrants returns list of `Authorization`, granted by granter. | GET|/cosmos/authz/v1beta1/grants/{granter}|

<!-- end services -->

Expand Down
21 changes: 21 additions & 0 deletions proto/cosmos/authz/v1beta1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ service Query {
rpc Grants(QueryGrantsRequest) returns (QueryGrantsResponse) {
option (google.api.http).get = "/cosmos/authz/v1beta1/grants";
}

// GranterGrants returns list of `Authorization`, granted by granter.
rpc GranterGrants(QueryGranterGrantsRequest) returns (QueryGranterGrantsResponse) {
option (google.api.http).get = "/cosmos/authz/v1beta1/grants/{granter}";
}
}

// QueryGrantsRequest is the request type for the Query/Grants RPC method.
Expand All @@ -33,3 +38,19 @@ message QueryGrantsResponse {
// pagination defines an pagination for the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

// QueryGranterGrantsRequest is the request type for the Query/GranterGrants RPC method.
message QueryGranterGrantsRequest {
string granter = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];

// pagination defines an pagination for the request.
cosmos.base.query.v1beta1.PageRequest pagination = 2;
}

// QueryGranterGrantsResponse is the response type for the Query/GranterGrants RPC method.
message QueryGranterGrantsResponse {
// authorizations is a list of grants granted for grantee by granter.
repeated cosmos.authz.v1beta1.Grant grants = 1;
// pagination defines an pagination for the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
49 changes: 49 additions & 0 deletions x/authz/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func GetQueryCmd() *cobra.Command {

authorizationQueryCmd.AddCommand(
GetCmdQueryGrants(),
GetQueryGranterGrants(),
)

return authorizationQueryCmd
Expand Down Expand Up @@ -91,3 +92,51 @@ $ %s query %s grants cosmos1skjw.. cosmos1skjwj.. %s
flags.AddPaginationFlagsToCmd(cmd, "grants")
return cmd
}

func GetQueryGranterGrants() *cobra.Command {
aleem1314 marked this conversation as resolved.
Show resolved Hide resolved
cmd := &cobra.Command{
Use: "granter-grants [granter-addr]",
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved
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 granter-grants cosmos1skj..
`,
version.AppName, authz.ModuleName),
),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}

granter, err := sdk.AccAddressFromBech32(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: granter.String(),
Pagination: pageReq,
},
)
if err != nil {
return err
}

return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "granter-grants")
return cmd
}
57 changes: 57 additions & 0 deletions x/authz/client/testutil/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,60 @@ func (s *IntegrationTestSuite) TestQueryGrantsGRPC() {
})
}
}

func (s *IntegrationTestSuite) TestQueryGranterGrantsGRPC() {
val := s.network.Validators[0]
grantee := s.grantee[1]
require := s.Require()

testCases := []struct {
name string
url string
expectErr bool
errMsg string
numItems int
}{
{
"invalid account address",
fmt.Sprintf("%s/cosmos/authz/v1beta1/grants/%s", val.APIAddress, "invalid address"),
true,
"decoding bech32 failed",
0,
},
{
"no authorizations found",
fmt.Sprintf("%s/cosmos/authz/v1beta1/grants/%s", val.APIAddress, grantee.String()),
false,
"",
0,
},
{
"valid query",
fmt.Sprintf("%s/cosmos/authz/v1beta1/grants/%s", val.APIAddress, val.Address.String()),
false,
"",
6,
},
{
"valid query: expect two grants",
fmt.Sprintf("%s/cosmos/authz/v1beta1/grants/%s", val.APIAddress, val.Address.String()),
false,
"",
6,
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
resp, _ := rest.GetRequest(tc.url)
if tc.expectErr {
require.Contains(string(resp), tc.errMsg)
} else {
var authorizations authz.QueryGrantsResponse
err := val.ClientCtx.Codec.UnmarshalJSON(resp, &authorizations)
require.NoError(err)
require.Len(authorizations.Grants, tc.numItems)
}

})
}
}
72 changes: 72 additions & 0 deletions x/authz/client/testutil/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,75 @@ func (s *IntegrationTestSuite) TestQueryAuthorization() {
})
}
}

func (s *IntegrationTestSuite) 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", tmcli.OutputFlag),
},
true,
"decoding bech32 failed",
0,
},
{
"no authorization found",
[]string{
grantee.String(),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
},
false,
"",
0,
},
{
"valid case",
[]string{
val.Address.String(),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
},
false,
"",
6,
},
{
"valid case with pagination",
[]string{
val.Address.String(),
"--limit=2",
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
},
false,
"",
2,
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
cmd := cli.GetQueryGranterGrants()
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)
}
})
}
}
47 changes: 47 additions & 0 deletions x/authz/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,53 @@ func (k Keeper) Grants(c context.Context, req *authz.QueryGrantsRequest) (*authz
}, nil
}

// GranterGrants implements the Query/GranterGrants gRPC method.
func (k Keeper) GranterGrants(c context.Context, req *authz.QueryGranterGrantsRequest) (*authz.QueryGranterGrantsResponse, error) {
if req == nil {
return nil, status.Errorf(codes.InvalidArgument, "empty request")
}

granter, err := sdk.AccAddressFromBech32(req.Granter)
if err != nil {
return nil, err
}

ctx := sdk.UnwrapSDKContext(c)
store := ctx.KVStore(k.storeKey)
authzStore := prefix.NewStore(store, grantStoreKey(nil, granter, ""))

var authorizations []*authz.Grant
pageRes, err := query.FilteredPaginate(authzStore, req.Pagination, func(key []byte, value []byte,
accumulate bool) (bool, error) {
auth, err := unmarshalAuthorization(k.cdc, value)
if err != nil {
return false, err
}

auth1 := auth.GetAuthorization()
if accumulate {
any, err := codectypes.NewAnyWithValue(auth1)
if err != nil {
return false, status.Errorf(codes.Internal, err.Error())
}

authorizations = append(authorizations, &authz.Grant{
Authorization: any,
Expiration: auth.Expiration,
})
}
return true, nil
})
if err != nil {
return nil, err
}

return &authz.QueryGranterGrantsResponse{
Grants: authorizations,
Pagination: pageRes,
}, nil
}

// unmarshal an authorization from a store value
func unmarshalAuthorization(cdc codec.BinaryCodec, value []byte) (v authz.Grant, err error) {
err = cdc.Unmarshal(value, &v)
Expand Down
Loading