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

Improve context usage #388

Merged
merged 1 commit into from
Oct 9, 2017
Merged
Show file tree
Hide file tree
Changes from all 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
48 changes: 38 additions & 10 deletions action/clihelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ func (s *Action) ConfirmRecipients(ctx context.Context, name string, recipients

fmt.Printf("gopass: Encrypting %s for these recipients:\n", name)
for _, r := range recipients {
// check for context cancelation
select {
case <-ctx.Done():
return nil, errors.New("user aborted")
default:
}

kl, err := s.gpg.FindPublicKeys(ctx, r)
if err != nil {
fmt.Println(color.RedString("Failed to read public key for '%s': %s", name, err))
Expand All @@ -41,7 +48,7 @@ func (s *Action) ConfirmRecipients(ctx context.Context, name string, recipients
}
fmt.Println("")

yes, err := s.askForBool("Do you want to continue?", true)
yes, err := s.askForBool(ctx, "Do you want to continue?", true)
if err != nil {
return recipients, errors.Wrapf(err, "failed to read user input")
}
Expand All @@ -61,7 +68,7 @@ func (s *Action) AskForConfirmation(ctx context.Context, text string) bool {
}

for i := 0; i < maxTries; i++ {
if choice, err := s.askForBool(text, false); err == nil {
if choice, err := s.askForBool(ctx, text, false); err == nil {
return choice
}
}
Expand All @@ -71,13 +78,13 @@ func (s *Action) AskForConfirmation(ctx context.Context, text string) bool {
// askForBool ask for a bool (yes or no) exactly once.
// The empty answer uses the specified default, any other answer
// is an error.
func (s *Action) askForBool(text string, def bool) (bool, error) {
func (s *Action) askForBool(ctx context.Context, text string, def bool) (bool, error) {
choices := "y/N"
if def {
choices = "Y/n"
}

str, err := s.askForString(text, choices)
str, err := s.askForString(ctx, text, choices)
if err != nil {
return false, errors.Wrapf(err, "failed to read user input")
}
Expand All @@ -101,7 +108,14 @@ func (s *Action) askForBool(text string, def bool) (bool, error) {

// askForString asks for a string once, using the default if the
// anser is empty. Errors are only returned on I/O errors
func (s *Action) askForString(text, def string) (string, error) {
func (s *Action) askForString(ctx context.Context, text, def string) (string, error) {
// check for context cancelation
select {
case <-ctx.Done():
return "", errors.New("user aborted")
default:
}

reader := bufio.NewReader(os.Stdin)

fmt.Printf("%s [%s]: ", text, def)
Expand All @@ -118,8 +132,8 @@ func (s *Action) askForString(text, def string) (string, error) {

// askForInt asks for an valid interger once. If the input
// can not be converted to an int it returns an error
func (s *Action) askForInt(text string, def int) (int, error) {
str, err := s.askForString(text, strconv.Itoa(def))
func (s *Action) askForInt(ctx context.Context, text string, def int) (int, error) {
str, err := s.askForString(ctx, text, strconv.Itoa(def))
if err != nil {
return 0, err
}
Expand All @@ -143,6 +157,13 @@ func (s *Action) askForPassword(ctx context.Context, name string, askFn func(con
askFn = s.promptPass
}
for i := 0; i < maxTries; i++ {
// check for context cancelation
select {
case <-ctx.Done():
return "", errors.New("user aborted")
default:
}

pass, err := askFn(ctx, fmt.Sprintf("Enter password for %s", name))
if err != nil {
return "", err
Expand Down Expand Up @@ -171,7 +192,7 @@ func (s *Action) AskForKeyImport(ctx context.Context, key string) bool {
return false
}

ok, err := s.askForBool(fmt.Sprintf("Do you want to import the public key '%s' into your keyring?", key), false)
ok, err := s.askForBool(ctx, fmt.Sprintf("Do you want to import the public key '%s' into your keyring?", key), false)
if err != nil {
return false
}
Expand All @@ -196,12 +217,18 @@ func (s *Action) askForPrivateKey(ctx context.Context, prompt string) (string, e
if ctxutil.IsAlwaysYes(ctx) {
return kl[0].Fingerprint, nil
}
// check for context cancelation
select {
case <-ctx.Done():
return "", errors.New("user aborted")
default:
}

fmt.Println(prompt)
for i, k := range kl {
fmt.Printf("[%d] %s\n", i, k.OneLine())
}
iv, err := s.askForInt(fmt.Sprintf("Please enter the number of a key (0-%d)", len(kl)-1), 0)
iv, err := s.askForInt(ctx, fmt.Sprintf("Please enter the number of a key (0-%d)", len(kl)-1), 0)
if err != nil {
continue
}
Expand Down Expand Up @@ -243,7 +270,8 @@ func (s *Action) askForGitConfigUser(ctx context.Context) (string, string, error
}

useCurrent, err = s.askForBool(
fmt.Sprintf("Use %s (%s) for password store git config?", identity.Name, identity.Email), false)
ctx,
fmt.Sprintf("Use %s (%s) for password store git config?", identity.Name, identity.Email), true)
if err != nil {
return "", "", err
}
Expand Down
58 changes: 29 additions & 29 deletions action/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,19 @@ func (s *Action) createWebsite(ctx context.Context, c *cli.Context) error {
err error
genPw bool
)
urlStr, err = s.askForString("Please enter the URL", "")
urlStr, err = s.askForString(ctx, "Please enter the URL", "")
if err != nil {
return err
}
u, err := url.Parse(urlStr)
if err != nil {
return errors.Wrapf(err, "Can not parse URL. Please use 'gopass edit' to manually create the secret")
}
username, err = s.askForString("Please enter the Username/Login", "")
username, err = s.askForString(ctx, "Please enter the Username/Login", "")
if err != nil {
return err
}
genPw, err = s.askForBool("Do you want to generate a new password?", true)
genPw, err = s.askForBool(ctx, "Do you want to generate a new password?", true)
if err != nil {
return err
}
Expand All @@ -85,7 +85,7 @@ func (s *Action) createWebsite(ctx context.Context, c *cli.Context) error {
return err
}
}
comment, _ = s.askForString("Comments (optional)", "")
comment, _ = s.askForString(ctx, "Comments (optional)", "")
// select store
stores := []string{"<root>"}
stores = append(stores, s.Store.MountPoints()...)
Expand All @@ -105,7 +105,7 @@ func (s *Action) createWebsite(ctx context.Context, c *cli.Context) error {
}
name := fmt.Sprintf("%swebsites/%s/%s", store, u.Hostname(), username)
if s.Store.Exists(ctx, name) {
name, err = s.askForString("Secret already exists, please choose another path", name)
name, err = s.askForString(ctx, "Secret already exists, please choose another path", name)
if err != nil {
return err
}
Expand Down Expand Up @@ -136,15 +136,15 @@ func (s *Action) createPIN(ctx context.Context, c *cli.Context) error {
err error
genPw bool
)
authority, err = s.askForString("Please enter the authoriy (e.g. MyBank) this PIN is for", "")
authority, err = s.askForString(ctx, "Please enter the authoriy (e.g. MyBank) this PIN is for", "")
if err != nil {
return err
}
application, err = s.askForString("Please enter the entity (e.g. Credit Card) this PIN is for", "")
application, err = s.askForString(ctx, "Please enter the entity (e.g. Credit Card) this PIN is for", "")
if err != nil {
return err
}
genPw, err = s.askForBool("Do you want to generate a new PIN?", true)
genPw, err = s.askForBool(ctx, "Do you want to generate a new PIN?", true)
if err != nil {
return err
}
Expand All @@ -159,7 +159,7 @@ func (s *Action) createPIN(ctx context.Context, c *cli.Context) error {
return err
}
}
comment, _ = s.askForString("Comments (optional)", "")
comment, _ = s.askForString(ctx, "Comments (optional)", "")
// select store
stores := []string{"<root>"}
stores = append(stores, s.Store.MountPoints()...)
Expand All @@ -179,7 +179,7 @@ func (s *Action) createPIN(ctx context.Context, c *cli.Context) error {
}
name := fmt.Sprintf("%spins/%s/%s", store, authority, application)
if s.Store.Exists(ctx, name) {
name, err = s.askForString("Secret already exists, please choose another path", name)
name, err = s.askForString(ctx, "Secret already exists, please choose another path", name)
if err != nil {
return err
}
Expand Down Expand Up @@ -209,23 +209,23 @@ func (s *Action) createAWS(ctx context.Context, c *cli.Context) error {
store string
err error
)
account, err = s.askForString("Please enter the AWS Account this key belongs to", "")
account, err = s.askForString(ctx, "Please enter the AWS Account this key belongs to", "")
if err != nil {
return err
}
username, err = s.askForString("Please enter the name of the AWS IAM User this key belongs to", "")
username, err = s.askForString(ctx, "Please enter the name of the AWS IAM User this key belongs to", "")
if err != nil {
return err
}
accesskey, err = s.askForString("Please enter the Access Key ID (AWS_ACCESS_KEY_ID)", "")
accesskey, err = s.askForString(ctx, "Please enter the Access Key ID (AWS_ACCESS_KEY_ID)", "")
if err != nil {
return err
}
secretkey, err = s.askForPassword(ctx, "Please enter the Secret Access Key (AWS_SECRET_ACCESS_KEY)", nil)
if err != nil {
return err
}
region, _ = s.askForString("Please enter the default Region (AWS_DEFAULT_REGION) (optional)", "")
region, _ = s.askForString(ctx, "Please enter the default Region (AWS_DEFAULT_REGION) (optional)", "")
// select store
stores := []string{"<root>"}
stores = append(stores, s.Store.MountPoints()...)
Expand All @@ -245,7 +245,7 @@ func (s *Action) createAWS(ctx context.Context, c *cli.Context) error {
}
name := fmt.Sprintf("%saws/iam/%s/%s", store, account, username)
if s.Store.Exists(ctx, name) {
name, err = s.askForString("Secret already exists, please choose another path", name)
name, err = s.askForString(ctx, "Secret already exists, please choose another path", name)
if err != nil {
return err
}
Expand All @@ -269,7 +269,7 @@ func (s *Action) createGCP(ctx context.Context, c *cli.Context) error {
store string
err error
)
svcaccfn, err = s.askForString("Please enter path to the Service Account JSON file", "")
svcaccfn, err = s.askForString(ctx, "Please enter path to the Service Account JSON file", "")
if err != nil {
return err
}
Expand All @@ -282,13 +282,13 @@ func (s *Action) createGCP(ctx context.Context, c *cli.Context) error {
return err
}
if username == "" {
username, err = s.askForString("Please enter the name of this service account", "")
username, err = s.askForString(ctx, "Please enter the name of this service account", "")
if err != nil {
return err
}
}
if project == "" {
project, err = s.askForString("Please enter the name of this GCP project", "")
project, err = s.askForString(ctx, "Please enter the name of this GCP project", "")
if err != nil {
return err
}
Expand All @@ -312,7 +312,7 @@ func (s *Action) createGCP(ctx context.Context, c *cli.Context) error {
}
name := fmt.Sprintf("%sgcp/iam/%s/%s", store, project, username)
if s.Store.Exists(ctx, name) {
name, err = s.askForString("Secret already exists, please choose another path", name)
name, err = s.askForString(ctx, "Secret already exists, please choose another path", name)
if err != nil {
return err
}
Expand Down Expand Up @@ -349,11 +349,11 @@ func (s *Action) createGeneric(ctx context.Context, c *cli.Context) error {
err error
genPw bool
)
shortname, err = s.askForString("Please enter a name for the secret", "")
shortname, err = s.askForString(ctx, "Please enter a name for the secret", "")
if err != nil {
return err
}
genPw, err = s.askForBool("Do you want to generate a new password?", true)
genPw, err = s.askForBool(ctx, "Do you want to generate a new password?", true)
if err != nil {
return err
}
Expand Down Expand Up @@ -387,22 +387,22 @@ func (s *Action) createGeneric(ctx context.Context, c *cli.Context) error {
}
name := fmt.Sprintf("%smisc/%s", store, shortname)
if s.Store.Exists(ctx, name) {
name, err = s.askForString("Secret already exists, please choose another path", name)
name, err = s.askForString(ctx, "Secret already exists, please choose another path", name)
if err != nil {
return err
}
}
sec := secret.New(password, "")
fmt.Println("Enter zero or more key value pairs for this secret:")
for {
key, err := s.askForString("Name for Key Value pair (enter to quit)", "")
key, err := s.askForString(ctx, "Name for Key Value pair (enter to quit)", "")
if err != nil {
return err
}
if key == "" {
break
}
val, err := s.askForString("Value for Key '"+key+"'", "")
val, err := s.askForString(ctx, "Value for Key '"+key+"'", "")
if err != nil {
return err
}
Expand All @@ -421,12 +421,12 @@ func (s *Action) createGeneric(ctx context.Context, c *cli.Context) error {
}

func (s *Action) createGeneratePassword(ctx context.Context) (string, error) {
xkcd, err := s.askForBool("Do you want an rememberable password?", true)
xkcd, err := s.askForBool(ctx, "Do you want an rememberable password?", true)
if err != nil {
return "", err
}
if xkcd {
length, err := s.askForInt("How many words should be cominbed into a passphrase?", 4)
length, err := s.askForInt(ctx, "How many words should be cominbed into a passphrase?", 4)
if err != nil {
return "", err
}
Expand All @@ -437,19 +437,19 @@ func (s *Action) createGeneratePassword(ctx context.Context) (string, error) {
return string(g.GeneratePassword()), nil
}

length, err := s.askForInt("How long should the password be?", defaultLength)
length, err := s.askForInt(ctx, "How long should the password be?", defaultLength)
if err != nil {
return "", err
}
symbols, err := s.askForBool("Do you want to include symbols?", false)
symbols, err := s.askForBool(ctx, "Do you want to include symbols?", false)
if err != nil {
return "", err
}
return string(pwgen.GeneratePassword(length, symbols)), nil
}

func (s *Action) createGeneratePIN(ctx context.Context) (string, error) {
length, err := s.askForInt("How long should the PIN be?", 4)
length, err := s.askForInt(ctx, "How long should the PIN be?", 4)
if err != nil {
return "", err
}
Expand Down
4 changes: 2 additions & 2 deletions action/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (s *Action) Generate(ctx context.Context, c *cli.Context) error {

if name == "" {
var err error
name, err = s.askForString("Which name do you want to use?", "")
name, err = s.askForString(ctx, "Which name do you want to use?", "")
if err != nil || name == "" {
return s.exitError(ctx, ExitNoName, err, "please provide a password name")
}
Expand All @@ -70,7 +70,7 @@ func (s *Action) Generate(ctx context.Context, c *cli.Context) error {
question = "How many words should be combined to a password?"
}
var err error
if length, err = s.askForString(question, string(candidateLength)); err != nil {
if length, err = s.askForString(ctx, question, string(candidateLength)); err != nil {
panic(err) // panic on i/o error only, string -> int conversion is done below
}
}
Expand Down
4 changes: 2 additions & 2 deletions action/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ func (s *Action) gitInit(ctx context.Context, store, sk string) error {

if userName == "" {
var err error
userName, err = s.askForString(color.CyanString("Please enter a user name for password store git config"), userName)
userName, err = s.askForString(ctx, color.CyanString("Please enter a user name for password store git config"), userName)
if err != nil {
return errors.Wrapf(err, "failed to ask for user input")
}
}
if userEmail == "" {
var err error
userEmail, err = s.askForString(color.CyanString("Please enter an email address for password store git config"), userEmail)
userEmail, err = s.askForString(ctx, color.CyanString("Please enter an email address for password store git config"), userEmail)
if err != nil {
return errors.Wrapf(err, "failed to ask for user input")
}
Expand Down
Loading