-
Notifications
You must be signed in to change notification settings - Fork 68
Expand file tree
/
Copy pathlogin.go
More file actions
149 lines (117 loc) · 3.87 KB
/
login.go
File metadata and controls
149 lines (117 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"context"
"flag"
"fmt"
"io"
"net/url"
"os"
"github.com/sourcegraph/src-cli/internal/api"
"github.com/sourcegraph/src-cli/internal/cmderrors"
"github.com/sourcegraph/src-cli/internal/oauth"
)
func init() {
usage := `'src login' helps you authenticate 'src' to access a Sourcegraph instance with your user credentials.
Usage:
src login [flags] SOURCEGRAPH_URL
Examples:
Authenticate to a Sourcegraph instance at https://sourcegraph.example.com:
$ src login https://sourcegraph.example.com
Authenticate to Sourcegraph.com:
$ src login https://sourcegraph.com
If no access token is configured, 'src login' uses OAuth device flow automatically:
$ src login https://sourcegraph.com
`
flagSet := flag.NewFlagSet("login", flag.ExitOnError)
usageFunc := func() {
fmt.Fprintln(flag.CommandLine.Output(), usage)
flagSet.PrintDefaults()
}
var (
apiFlags = api.NewFlags(flagSet)
)
handler := func(args []string) error {
if err := flagSet.Parse(args); err != nil {
return err
}
var loginEndpointURL *url.URL
if flagSet.NArg() >= 1 {
arg := flagSet.Arg(0)
u, err := parseEndpoint(arg)
if err != nil {
return cmderrors.Usage(fmt.Sprintf("invalid endpoint URL: %s", arg))
}
loginEndpointURL = u
}
client := cfg.apiClient(apiFlags, io.Discard)
return loginCmd(context.Background(), loginParams{
cfg: cfg,
client: client,
out: os.Stdout,
apiFlags: apiFlags,
oauthClient: oauth.NewClient(oauth.DefaultClientID),
loginEndpointURL: loginEndpointURL,
})
}
commands = append(commands, &command{
flagSet: flagSet,
handler: handler,
usageFunc: usageFunc,
})
}
type loginParams struct {
cfg *config
client api.Client
out io.Writer
apiFlags *api.Flags
oauthClient oauth.Client
loginEndpointURL *url.URL
}
type loginFlow func(context.Context, loginParams) error
type loginFlowKind int
const (
loginFlowOAuth loginFlowKind = iota
loginFlowMissingAuth
loginFlowEndpointConflict
loginFlowValidate
)
func loginCmd(ctx context.Context, p loginParams) error {
if err := p.cfg.requireCIAccessToken(); err != nil {
return err
}
if p.cfg.configFilePath != "" {
fmt.Fprintln(p.out)
fmt.Fprintf(p.out, "⚠️ Warning: Configuring src with a JSON file is deprecated. Please migrate to using the env vars SRC_ENDPOINT, SRC_ACCESS_TOKEN, and SRC_PROXY instead, and then remove %s. See https://github.com/sourcegraph/src-cli#readme for more information.\n", p.cfg.configFilePath)
}
_, flow := selectLoginFlow(p)
if err := flow(ctx, p); err != nil {
return err
}
fmt.Fprintf(p.out, "\n💡 Tip: To use this endpoint in your shell, run:\n\n export SRC_ENDPOINT=%s\n\n", p.cfg.endpointURL)
return nil
}
// selectLoginFlow decides what login flow to run based on configured AuthMode.
func selectLoginFlow(p loginParams) (loginFlowKind, loginFlow) {
if p.loginEndpointURL != nil && p.loginEndpointURL.String() != p.cfg.endpointURL.String() {
return loginFlowEndpointConflict, runEndpointConflictLogin
}
switch p.cfg.AuthMode() {
case AuthModeOAuth:
return loginFlowOAuth, runOAuthLogin
case AuthModeAccessToken:
return loginFlowValidate, runValidatedLogin
default:
return loginFlowMissingAuth, runMissingAuthLogin
}
}
func printLoginProblem(out io.Writer, problem string) {
fmt.Fprintf(out, "❌ Problem: %s\n", problem)
}
func loginAccessTokenMessage(endpointURL *url.URL) string {
return fmt.Sprintf("\n"+`🛠 To fix: Create an access token by going to %s/user/settings/tokens, then set the following environment variables in your terminal:
export SRC_ENDPOINT=%s
export SRC_ACCESS_TOKEN=(your access token)
To verify that it's working, run the login command again.
Alternatively, you can try logging in interactively by running: src login %s
`, endpointURL, endpointURL, endpointURL)
}