Skip to content

Commit 9ec938e

Browse files
committed
Add login prompt for non-first-time-user case
1 parent 3bb3164 commit 9ec938e

File tree

3 files changed

+98
-8
lines changed

3 files changed

+98
-8
lines changed

cli/login.go

Lines changed: 96 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,30 @@ package cli
22

33
import (
44
"fmt"
5+
"io/ioutil"
56
"net/url"
7+
"os/exec"
68
"os/user"
9+
"runtime"
710
"strings"
811

912
"github.com/fatih/color"
1013
"github.com/go-playground/validator/v10"
1114
"github.com/manifoldco/promptui"
15+
"github.com/pkg/browser"
1216
"github.com/spf13/cobra"
1317
"golang.org/x/xerrors"
1418

1519
"github.com/coder/coder/coderd"
1620
"github.com/coder/coder/codersdk"
1721
)
1822

23+
const (
24+
goosWindows = "windows"
25+
goosLinux = "linux"
26+
goosDarwin = "darwin"
27+
)
28+
1929
func login() *cobra.Command {
2030
return &cobra.Command{
2131
Use: "login <url>",
@@ -116,21 +126,99 @@ func login() *cobra.Command {
116126
if err != nil {
117127
return xerrors.Errorf("login with password: %w", err)
118128
}
119-
config := createConfig(cmd)
120-
err = config.Session().Write(resp.SessionToken)
121-
if err != nil {
122-
return xerrors.Errorf("write session token: %w", err)
123-
}
124-
err = config.URL().Write(serverURL.String())
129+
130+
err = saveSessionToken(cmd, client, resp.SessionToken, serverURL)
125131
if err != nil {
126-
return xerrors.Errorf("write server url: %w", err)
132+
return xerrors.Errorf("save session token: %w", err)
127133
}
128134

129-
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s Welcome to Coder, %s! You're authenticated.\n", color.HiBlackString(">"), color.HiCyanString(username))
130135
return nil
131136
}
132137

138+
authURL := *serverURL
139+
authURL.Path = serverURL.Path + "/cli-auth"
140+
if err := openURL(authURL.String()); err != nil {
141+
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "Open the following in your browser:\n\n\t%s\n\n", authURL.String())
142+
} else {
143+
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "Your browser has been opened to visit:\n\n\t%s\n\n", authURL.String())
144+
}
145+
146+
apiKey, err := prompt(cmd, &promptui.Prompt{
147+
Label: "Paste your token here:",
148+
Validate: func(token string) error {
149+
client.SessionToken = token
150+
_, err := client.User(cmd.Context(), "me")
151+
if err != nil {
152+
return xerrors.New("That's not a valid token!")
153+
}
154+
return err
155+
},
156+
})
157+
if err != nil {
158+
return xerrors.Errorf("specify email prompt: %w", err)
159+
}
160+
161+
err = saveSessionToken(cmd, client, apiKey, serverURL)
162+
if err != nil {
163+
return xerrors.Errorf("save session token after login: %w", err)
164+
}
165+
133166
return nil
134167
},
135168
}
136169
}
170+
171+
func saveSessionToken(cmd *cobra.Command, client *codersdk.Client, sessionToken string, serverURL *url.URL) error {
172+
// Login to get user data - verify it is OK before persisting
173+
client.SessionToken = sessionToken
174+
resp, err := client.User(cmd.Context(), "me")
175+
if err != nil {
176+
return xerrors.Errorf("get user: ", err)
177+
}
178+
179+
config := createConfig(cmd)
180+
err = config.Session().Write(sessionToken)
181+
if err != nil {
182+
return xerrors.Errorf("write session token: %w", err)
183+
}
184+
err = config.URL().Write(serverURL.String())
185+
if err != nil {
186+
return xerrors.Errorf("write server url: %w", err)
187+
}
188+
189+
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s Welcome to Coder, %s! You're authenticated.\n", color.HiBlackString(">"), color.HiCyanString(resp.Username))
190+
return nil
191+
}
192+
193+
// isWSL determines if coder-cli is running within Windows Subsystem for Linux
194+
func isWSL() (bool, error) {
195+
if runtime.GOOS == goosDarwin || runtime.GOOS == goosWindows {
196+
return false, nil
197+
}
198+
data, err := ioutil.ReadFile("/proc/version")
199+
if err != nil {
200+
return false, xerrors.Errorf("read /proc/version: %w", err)
201+
}
202+
return strings.Contains(strings.ToLower(string(data)), "microsoft"), nil
203+
}
204+
205+
// openURL opens the provided URL via user's default browser
206+
func openURL(url string) error {
207+
var cmd string
208+
var args []string
209+
210+
wsl, err := isWSL()
211+
if err != nil {
212+
return xerrors.Errorf("test running Windows Subsystem for Linux: %w", err)
213+
}
214+
215+
if wsl {
216+
cmd = "cmd.exe"
217+
args = []string{"/c", "start"}
218+
url = strings.ReplaceAll(url, "&", "^&")
219+
args = append(args, url)
220+
return exec.Command(cmd, args...).Start()
221+
}
222+
223+
return browser.OpenURL(url)
224+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ require (
113113
github.com/pion/stun v0.3.5 // indirect
114114
github.com/pion/turn/v2 v2.0.6 // indirect
115115
github.com/pion/udp v0.1.1 // indirect
116+
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
116117
github.com/pkg/errors v0.9.1 // indirect
117118
github.com/pmezard/go-difflib v1.0.0 // indirect
118119
github.com/sirupsen/logrus v1.8.1 // indirect

go.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,7 @@ github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M
10601060
github.com/pion/webrtc/v3 v3.1.23 h1:suyNiF9o2/6SBsyWA1UweraUWYkaHCNJdt/16b61I5w=
10611061
github.com/pion/webrtc/v3 v3.1.23/go.mod h1:L5S/oAhL0Fzt/rnftVQRrP80/j5jygY7XRZzWwFx6P4=
10621062
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
1063+
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
10631064
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
10641065
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
10651066
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=

0 commit comments

Comments
 (0)