After completing the interactive `gh auth login` flow, the `hosts.yml` config file will have been populated with both `oauth_token` and `user` properties for the GitHub host. However, after `auth login --with-token` only the `oauth_token` is persisted but no username. This fixes `auth git-credential` behavior so it allows authentication even if the `user` property is missing. It's entirely optional to send a proper username for git authentication, since GitHub seems to ignore the actual value sent and just focuses on the token itself.
235 lines
5.2 KiB
Go
235 lines
5.2 KiB
Go
package login
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/MakeNowJust/heredoc"
|
|
"github.com/cli/cli/v2/pkg/iostreams"
|
|
)
|
|
|
|
// why not just use the config stub argh
|
|
type tinyConfig map[string]string
|
|
|
|
func (c tinyConfig) GetWithSource(host, key string) (string, string, error) {
|
|
return c[fmt.Sprintf("%s:%s", host, key)], c["_source"], nil
|
|
}
|
|
|
|
func Test_helperRun(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
opts CredentialOptions
|
|
input string
|
|
wantStdout string
|
|
wantStderr string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "host only, credentials found",
|
|
opts: CredentialOptions{
|
|
Operation: "get",
|
|
Config: func() (config, error) {
|
|
return tinyConfig{
|
|
"_source": "/Users/monalisa/.config/gh/hosts.yml",
|
|
"example.com:user": "monalisa",
|
|
"example.com:oauth_token": "OTOKEN",
|
|
}, nil
|
|
},
|
|
},
|
|
input: heredoc.Doc(`
|
|
protocol=https
|
|
host=example.com
|
|
`),
|
|
wantErr: false,
|
|
wantStdout: heredoc.Doc(`
|
|
protocol=https
|
|
host=example.com
|
|
username=monalisa
|
|
password=OTOKEN
|
|
`),
|
|
wantStderr: "",
|
|
},
|
|
{
|
|
name: "host plus user",
|
|
opts: CredentialOptions{
|
|
Operation: "get",
|
|
Config: func() (config, error) {
|
|
return tinyConfig{
|
|
"_source": "/Users/monalisa/.config/gh/hosts.yml",
|
|
"example.com:user": "monalisa",
|
|
"example.com:oauth_token": "OTOKEN",
|
|
}, nil
|
|
},
|
|
},
|
|
input: heredoc.Doc(`
|
|
protocol=https
|
|
host=example.com
|
|
username=monalisa
|
|
`),
|
|
wantErr: false,
|
|
wantStdout: heredoc.Doc(`
|
|
protocol=https
|
|
host=example.com
|
|
username=monalisa
|
|
password=OTOKEN
|
|
`),
|
|
wantStderr: "",
|
|
},
|
|
{
|
|
name: "gist host",
|
|
opts: CredentialOptions{
|
|
Operation: "get",
|
|
Config: func() (config, error) {
|
|
return tinyConfig{
|
|
"_source": "/Users/monalisa/.config/gh/hosts.yml",
|
|
"github.com:user": "monalisa",
|
|
"github.com:oauth_token": "OTOKEN",
|
|
}, nil
|
|
},
|
|
},
|
|
input: heredoc.Doc(`
|
|
protocol=https
|
|
host=gist.github.com
|
|
username=monalisa
|
|
`),
|
|
wantErr: false,
|
|
wantStdout: heredoc.Doc(`
|
|
protocol=https
|
|
host=gist.github.com
|
|
username=monalisa
|
|
password=OTOKEN
|
|
`),
|
|
wantStderr: "",
|
|
},
|
|
{
|
|
name: "url input",
|
|
opts: CredentialOptions{
|
|
Operation: "get",
|
|
Config: func() (config, error) {
|
|
return tinyConfig{
|
|
"_source": "/Users/monalisa/.config/gh/hosts.yml",
|
|
"example.com:user": "monalisa",
|
|
"example.com:oauth_token": "OTOKEN",
|
|
}, nil
|
|
},
|
|
},
|
|
input: heredoc.Doc(`
|
|
url=https://monalisa@example.com
|
|
`),
|
|
wantErr: false,
|
|
wantStdout: heredoc.Doc(`
|
|
protocol=https
|
|
host=example.com
|
|
username=monalisa
|
|
password=OTOKEN
|
|
`),
|
|
wantStderr: "",
|
|
},
|
|
{
|
|
name: "host only, no credentials found",
|
|
opts: CredentialOptions{
|
|
Operation: "get",
|
|
Config: func() (config, error) {
|
|
return tinyConfig{
|
|
"_source": "/Users/monalisa/.config/gh/hosts.yml",
|
|
"example.com:user": "monalisa",
|
|
}, nil
|
|
},
|
|
},
|
|
input: heredoc.Doc(`
|
|
protocol=https
|
|
host=example.com
|
|
`),
|
|
wantErr: true,
|
|
wantStdout: "",
|
|
wantStderr: "",
|
|
},
|
|
{
|
|
name: "user mismatch",
|
|
opts: CredentialOptions{
|
|
Operation: "get",
|
|
Config: func() (config, error) {
|
|
return tinyConfig{
|
|
"_source": "/Users/monalisa/.config/gh/hosts.yml",
|
|
"example.com:user": "monalisa",
|
|
"example.com:oauth_token": "OTOKEN",
|
|
}, nil
|
|
},
|
|
},
|
|
input: heredoc.Doc(`
|
|
protocol=https
|
|
host=example.com
|
|
username=hubot
|
|
`),
|
|
wantErr: true,
|
|
wantStdout: "",
|
|
wantStderr: "",
|
|
},
|
|
{
|
|
name: "no username configured",
|
|
opts: CredentialOptions{
|
|
Operation: "get",
|
|
Config: func() (config, error) {
|
|
return tinyConfig{
|
|
"_source": "/Users/monalisa/.config/gh/hosts.yml",
|
|
"example.com:oauth_token": "OTOKEN",
|
|
}, nil
|
|
},
|
|
},
|
|
input: heredoc.Doc(`
|
|
protocol=https
|
|
host=example.com
|
|
`),
|
|
wantErr: false,
|
|
wantStdout: heredoc.Doc(`
|
|
protocol=https
|
|
host=example.com
|
|
username=x-access-token
|
|
password=OTOKEN
|
|
`),
|
|
wantStderr: "",
|
|
},
|
|
{
|
|
name: "token from env",
|
|
opts: CredentialOptions{
|
|
Operation: "get",
|
|
Config: func() (config, error) {
|
|
return tinyConfig{
|
|
"_source": "GITHUB_ENTERPRISE_TOKEN",
|
|
"example.com:oauth_token": "OTOKEN",
|
|
}, nil
|
|
},
|
|
},
|
|
input: heredoc.Doc(`
|
|
protocol=https
|
|
host=example.com
|
|
username=hubot
|
|
`),
|
|
wantErr: false,
|
|
wantStdout: heredoc.Doc(`
|
|
protocol=https
|
|
host=example.com
|
|
username=x-access-token
|
|
password=OTOKEN
|
|
`),
|
|
wantStderr: "",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
io, stdin, stdout, stderr := iostreams.Test()
|
|
fmt.Fprint(stdin, tt.input)
|
|
opts := &tt.opts
|
|
opts.IO = io
|
|
if err := helperRun(opts); (err != nil) != tt.wantErr {
|
|
t.Fatalf("helperRun() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
if tt.wantStdout != stdout.String() {
|
|
t.Errorf("stdout: got %q, wants %q", stdout.String(), tt.wantStdout)
|
|
}
|
|
if tt.wantStderr != stderr.String() {
|
|
t.Errorf("stderr: got %q, wants %q", stderr.String(), tt.wantStderr)
|
|
}
|
|
})
|
|
}
|
|
}
|