move git auth prompts to interact module #276

Merged
6543 merged 3 commits from noerw/tea:issue-231-refactor-prompt-2 into master 2020-12-08 01:21:05 +00:00
4 changed files with 38 additions and 22 deletions

View File

@ -15,13 +15,14 @@ import (
gogit_http "github.com/go-git/go-git/v5/plumbing/transport/http"
gogit_ssh "github.com/go-git/go-git/v5/plumbing/transport/ssh"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/terminal"
)
type pwCallback = func(ctx string) (string, error)
// GetAuthForURL returns the appropriate AuthMethod to be used in Push() / Pull()
// operations depending on the protocol, and prompts the user for credentials if
// necessary.
func GetAuthForURL(remoteURL *url.URL, authToken, keyFile string) (auth git_transport.AuthMethod, err error) {
func GetAuthForURL(remoteURL *url.URL, authToken, keyFile string, passwordCallback pwCallback) (auth git_transport.AuthMethod, err error) {
switch remoteURL.Scheme {
case "http", "https":
// gitea supports push/pull via app token as username.
@ -32,7 +33,7 @@ func GetAuthForURL(remoteURL *url.URL, authToken, keyFile string) (auth git_tran
user := remoteURL.User.Username()
auth, err = gogit_ssh.DefaultAuthBuilder(user)
if err != nil {
signer, err := readSSHPrivKey(keyFile)
signer, err := readSSHPrivKey(keyFile, passwordCallback)
if err != nil {
return nil, err
}
@ -46,7 +47,7 @@ func GetAuthForURL(remoteURL *url.URL, authToken, keyFile string) (auth git_tran
return auth, nil
}
func readSSHPrivKey(keyFile string) (sig ssh.Signer, err error) {
func readSSHPrivKey(keyFile string, passwordCallback pwCallback) (sig ssh.Signer, err error) {
if keyFile != "" {
keyFile, err = utils.AbsPathWithExpansion(keyFile)
} else {
@ -60,21 +61,19 @@ func readSSHPrivKey(keyFile string) (sig ssh.Signer, err error) {
return nil, err
}
sig, err = ssh.ParsePrivateKey(sshKey)
if err != nil {
pass, err := promptPass(keyFile)
if err != nil {
return nil, err
}
sig, err = ssh.ParsePrivateKeyWithPassphrase(sshKey, []byte(pass))
if err != nil {
return nil, err
if _, ok := err.(*ssh.PassphraseMissingError); ok {
// allow for up to 3 password attempts
for i := 0; i < 3; i++ {
var pass string
pass, err = passwordCallback(keyFile)
if err != nil {
return nil, err
}
sig, err = ssh.ParsePrivateKeyWithPassphrase(sshKey, []byte(pass))
if err == nil {
break
}
}
}
return sig, err
}
func promptPass(domain string) (string, error) {
fmt.Printf("%s password: ", domain)
pass, err := terminal.ReadPassword(0)
return string(pass), err
}

View File

@ -0,0 +1,16 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package interact
import (
"github.com/AlecAivazis/survey/v2"
)
// PromptPassword asks for a password and blocks until input was made.
func PromptPassword(name string) (pass string, err error) {
noerw marked this conversation as resolved Outdated
Outdated
Review

one nit, dont call it ctx, name it something like "sender" or so ... since ctx is normaly used for context.Contect

one nit, dont call it ctx, name it something like "sender" or so ... since ctx is normaly used for context.Contect
promptPW := &survey.Password{Message: name + " password:"}
err = survey.AskOne(promptPW, &pass, survey.WithValidator(survey.Required))
return
}

View File

@ -10,7 +10,7 @@ import (
"code.gitea.io/sdk/gitea"
"code.gitea.io/tea/modules/config"
local_git "code.gitea.io/tea/modules/git"
"code.gitea.io/tea/modules/interact"
"github.com/go-git/go-git/v5"
)
@ -60,7 +60,7 @@ func PullCheckout(login *config.Login, repoOwner, repoName string, index int64)
if err != nil {
return err
}
auth, err := local_git.GetAuthForURL(url, login.Token, login.SSHKey)
auth, err := local_git.GetAuthForURL(url, login.Token, login.SSHKey, interact.PromptPassword)
if err != nil {
return err
}

View File

@ -7,10 +7,11 @@ package task
import (
"fmt"
"code.gitea.io/sdk/gitea"
"code.gitea.io/tea/modules/config"
local_git "code.gitea.io/tea/modules/git"
"code.gitea.io/tea/modules/interact"
"code.gitea.io/sdk/gitea"
git_config "github.com/go-git/go-git/v5/config"
)
@ -78,7 +79,7 @@ call me again with the --ignore-sha flag`, pr.Head.Ref)
if err != nil {
return err
}
auth, err := local_git.GetAuthForURL(url, login.Token, login.SSHKey)
auth, err := local_git.GetAuthForURL(url, login.Token, login.SSHKey, interact.PromptPassword)
if err != nil {
return err
}