package contract import ( "encoding/base64" "git.frostfs.info/TrueCloudLab/frostfs-contract/commonclient" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/dkirillov/policy-reader/internal/resolver" "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/spf13/cobra" "github.com/spf13/viper" ) var listChainsByPrefixCmd = &cobra.Command{ Use: "list-chains-by-prefix", Short: "Invoke 'iteratorChainsByPrefix' method", Long: "Invoke 'iteratorChainsByPrefix' method in policy contract and print results to stdout", Example: `policy-reader contract -r http://localhost:40332 list-chains-by-prefix policy-reader contract -r http://localhost:40332 --policy-hash 81c1a41d09e08087a4b679418b12be5d3ab15742 list-chains-by-prefix --type container --name 7h7NcXcF6k6b1yidqEHc1jkyXUm1MfUDrrTuHAefhiDe`, PreRunE: func(cmd *cobra.Command, _ []string) error { if viper.IsSet(nameFlag) { return cmd.Flags().Set(nameFlag, viper.GetString(nameFlag)) } return nil }, RunE: runListChainsByPrefixCmd, } const ( prefixFlag = "prefix" prefixBase64Flag = "prefix-base64" decodeIDFlag = "decode-id" ) func initListChainsByPrefixCmd() { listChainsByPrefixCmd.Flags().String(typeFlag, "namespace", "Target type to list (namespace/container/group/user/iam)") listChainsByPrefixCmd.Flags().String(nameFlag, "", "Target name to list") listChainsByPrefixCmd.Flags().String(prefixFlag, "", "Prefix to list") listChainsByPrefixCmd.Flags().Bool(prefixBase64Flag, false, "Use this flag if you provide prefix in base64 format") listChainsByPrefixCmd.Flags().Bool(nameBase64Flag, false, "Use this flag if you provide name in base64 format") listChainsByPrefixCmd.Flags().Bool(decodeIDFlag, false, "Use this flag to additionally decode chain id") _ = listChainsByPrefixCmd.MarkFlagRequired(nameFlag) } func runListChainsByPrefixCmd(cmd *cobra.Command, _ []string) error { typ := viper.GetString(typeFlag) entity, err := parseTargetType(typ) if err != nil { return err } entityNameStr := viper.GetString(nameFlag) var entityName []byte if viper.GetBool(nameBase64Flag) { if entityName, err = base64.StdEncoding.DecodeString(entityNameStr); err != nil { return err } } else { entityName = []byte(entityNameStr) } prefixStr := viper.GetString(prefixFlag) var prefix []byte if viper.GetBool(prefixBase64Flag) { if prefix, err = base64.StdEncoding.DecodeString(prefixStr); err != nil { return err } } else { prefix = []byte(prefixStr) } endpoint := viper.GetString(rpcEndpointFlag) policyHash, err := resolver.ResolveContractHash(endpoint, viper.GetString(policyHashFlag)) if err != nil { return err } rpcCli, err := rpcclient.New(cmd.Context(), endpoint, rpcclient.Options{}) if err != nil { return err } res, err := commonclient.ReadIteratorItems(invoker.New(rpcCli, nil), 100, policyHash, "iteratorChainsByPrefix", entity, entityName, prefix) if err != nil { return err } cmd.Printf("%s target chains names: %d\n", typ, len(res)) decodeID := viper.GetBool(decodeIDFlag) for _, re := range res { bytes, err := re.TryBytes() if err != nil { return err } if typ == "iam" { cmd.Println(string(bytes)) continue } var chain apechain.Chain if err = chain.DecodeBytes(bytes); err != nil { cmd.Printf("invalid chain format: %s\n", base64.StdEncoding.EncodeToString(bytes)) continue } raw, err := chain.MarshalJSON() if err != nil { return err } if decodeID { cmd.Println(string(chain.ID), string(raw)) } else { cmd.Println(string(raw)) } } return nil }