Expose new and list via cli

This commit is contained in:
Ethan Frey
2017-02-28 18:52:52 +01:00
parent 78bb9f9cd8
commit 506ff7d85a
16 changed files with 173 additions and 80 deletions
+7 -14
View File
@@ -18,7 +18,6 @@ import (
"fmt"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
// listCmd represents the list command
@@ -28,22 +27,16 @@ var listCmd = &cobra.Command{
Long: `Return a list of all public keys stored by this key manager
along with their associated name and address.`,
Run: func(cmd *cobra.Command, args []string) {
// TODO: Work your own magic here
fmt.Println("list called")
fmt.Println(viper.Get("format"))
infos, err := manager.List()
if err != nil {
fmt.Println(err.Error())
return
}
printInfos(infos)
},
}
func init() {
RootCmd.AddCommand(listCmd)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// listCmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
listCmd.Flags().StringP("format", "f", "text", "Format to display (text|json)")
}
+30 -12
View File
@@ -22,28 +22,46 @@ import (
// newCmd represents the new command
var newCmd = &cobra.Command{
Use: "new",
Use: "new <name>",
Short: "Create a new public/private key pair",
Long: `Add a public/private key pair to the key store.
The password muts be entered in the terminal and not
passed as a command line argument for security.`,
Run: func(cmd *cobra.Command, args []string) {
// TODO: Work your own magic here
fmt.Println("new called")
},
Run: newPassword,
}
func init() {
RootCmd.AddCommand(newCmd)
}
// Here you will define your flags and configuration settings.
func newPassword(cmd *cobra.Command, args []string) {
if len(args) != 1 || len(args[0]) == 0 {
fmt.Print("You must provide a name for the key")
return
}
name := args[0]
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// newCmd.PersistentFlags().String("foo", "", "A help for foo")
// TODO: own function???
pass, err := getPassword("Enter a passphrase:")
if err != nil {
fmt.Println(err.Error())
return
}
pass2, err := getPassword("Repeat the passphrase:")
if err != nil {
fmt.Println(err.Error())
return
}
if pass != pass2 {
fmt.Println("Passphrases don't match")
return
}
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// newCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
info, err := manager.Create(name, pass)
if err != nil {
fmt.Println(err.Error())
return
}
printInfo(info)
}
+27 -6
View File
@@ -17,16 +17,22 @@ package cmd
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
keys "github.com/tendermint/go-keys"
"github.com/tendermint/go-keys/cryptostore"
"github.com/tendermint/go-keys/storage/filestorage"
)
var (
rootDir string
format string
output string
keyDir string
manager keys.Manager
)
// RootCmd represents the base command when called without any subcommands
@@ -53,7 +59,8 @@ func Execute() {
func init() {
cobra.OnInitialize(initEnv)
RootCmd.PersistentFlags().StringP("root", "r", os.ExpandEnv("$HOME/.tlc"), "root directory for config and data (default is TM_ROOT or $HOME/.tlc)")
RootCmd.PersistentFlags().StringP("format", "f", "text", "Output format (text|json)")
RootCmd.PersistentFlags().StringP("output", "o", "text", "Output format (text|json)")
RootCmd.PersistentFlags().StringP("keydir", "", "keys", "Directory to store private keys (subdir of root)")
}
// initEnv sets to use ENV variables if set.
@@ -85,11 +92,25 @@ func bindFlags(cmd *cobra.Command, args []string) error {
// validateFlags asserts all RootCmd flags are valid
func validateFlags(cmd *cobra.Command) error {
format = viper.GetString("format")
switch format {
// validate output format
output = viper.GetString("output")
switch output {
case "text", "json":
return nil
default:
return errors.Errorf("Unsupported format: %s", format)
return errors.Errorf("Unsupported output format: %s", output)
}
// store the keys directory
keyDir = viper.GetString("keydir")
if !filepath.IsAbs(keyDir) {
keyDir = filepath.Join(rootDir, keyDir)
}
// and construct the key manager
manager = cryptostore.New(
cryptostore.GenEd25519, // TODO - cli switch???
cryptostore.SecretBox,
filestorage.New(keyDir),
)
return nil
}
+56
View File
@@ -0,0 +1,56 @@
package cmd
import (
"fmt"
"github.com/bgentry/speakeasy"
"github.com/pkg/errors"
data "github.com/tendermint/go-data"
keys "github.com/tendermint/go-keys"
)
const PassLength = 10
func getPassword(prompt string) (string, error) {
pass, err := speakeasy.Ask(prompt)
if err != nil {
return "", err
}
if len(pass) < PassLength {
return "", errors.Errorf("Password must be at least %d characters", PassLength)
}
return pass, nil
}
func printInfo(info keys.Info) {
switch output {
case "text":
key, err := data.ToText(info.PubKey)
if err != nil {
panic(err) // really shouldn't happen...
}
fmt.Printf("%s\t%s\n", info.Name, key)
case "json":
json, err := data.ToJSON(info)
if err != nil {
panic(err) // really shouldn't happen...
}
fmt.Println(string(json))
}
}
func printInfos(infos keys.Infos) {
switch output {
case "text":
fmt.Println("All keys:")
for _, i := range infos {
printInfo(i)
}
case "json":
json, err := data.ToJSON(infos)
if err != nil {
panic(err) // really shouldn't happen...
}
fmt.Println(string(json))
}
}