Skip to content

Commit d39e6c7

Browse files
authored
Merge pull request #19 from jianxiaoguo/dev
feat(workflow-cli): use OIDC login
2 parents 30ea7df + 8e7aac2 commit d39e6c7

9 files changed

Lines changed: 81 additions & 615 deletions

File tree

cli/cli.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ var Shortcuts = map[string]string{
99
"logout": "auth:logout",
1010
"logs": "apps:logs",
1111
"open": "apps:open",
12-
"passwd": "auth:passwd",
1312
"pull": "builds:create",
14-
"register": "auth:register",
1513
"rollback": "releases:rollback",
1614
"run": "apps:run",
1715
"scale": "ps:scale",

cmd/auth.go

Lines changed: 58 additions & 236 deletions
Original file line numberDiff line numberDiff line change
@@ -3,108 +3,88 @@ package cmd
33
import (
44
"errors"
55
"fmt"
6-
"strings"
7-
"syscall"
6+
"net/url"
7+
"os/exec"
8+
"runtime"
9+
"time"
810

911
drycc "github.com/drycc/controller-sdk-go"
12+
"github.com/drycc/controller-sdk-go/api"
1013
"github.com/drycc/controller-sdk-go/auth"
1114
"github.com/drycc/workflow-cli/settings"
12-
"golang.org/x/crypto/ssh/terminal"
1315
)
1416

15-
// Register creates a account on a Drycc controller.
16-
func (d *DryccCmd) Register(controller string, username string, password string, email string,
17-
sslVerify, login bool) error {
18-
19-
c, err := drycc.New(sslVerify, controller, "")
20-
21-
if err != nil {
17+
func (d *DryccCmd) doLogin(s settings.Settings) error {
18+
URL, err := auth.Login(s.Client)
19+
if d.checkAPICompatibility(s.Client, err) != nil {
2220
return err
2321
}
24-
25-
tempSettings, err := settings.Load(d.ConfigFile)
26-
27-
if err == nil && tempSettings.Client.ControllerURL.Host == c.ControllerURL.Host {
28-
c.Token = tempSettings.Client.Token
29-
}
30-
31-
// Set user agent for temporary client.
32-
c.UserAgent = settings.UserAgent
33-
34-
if err = c.CheckConnection(); d.checkAPICompatibility(c, err) != nil {
35-
return err
22+
if err != nil {
23+
return nil
3624
}
37-
38-
if username == "" {
39-
d.Print("username: ")
40-
fmt.Scanln(&username)
25+
fmt.Printf("Opening browser to %s\n", URL)
26+
d.Print("Waiting for login... ")
27+
err = d.openBrower(URL)
28+
if err != nil {
29+
d.Print("Cannot open browser, please visit the website in yourself")
4130
}
42-
43-
if password == "" {
44-
d.Print("password: ")
45-
password, err = readPassword()
46-
if err != nil {
47-
return err
48-
}
49-
50-
d.Printf("\npassword (confirm): ")
51-
passwordConfirm, err := readPassword()
52-
d.Println()
53-
54-
if err != nil {
55-
return err
56-
}
57-
58-
if password != passwordConfirm {
59-
return errors.New("password mismatch, aborting registration")
60-
}
31+
u, err := url.Parse(URL)
32+
if err != nil {
33+
return err
6134
}
35+
key := u.Query()["key"][0]
36+
quit := progress(d.WOut)
37+
d.doToken(s, key)
38+
quit <- true
39+
<-quit
40+
return nil
41+
}
6242

63-
if email == "" {
64-
d.Print("email: ")
65-
fmt.Scanln(&email)
43+
func (d *DryccCmd) openBrower(URL string) error {
44+
var commands = map[string]string{
45+
"windows": "start",
46+
"darwin": "open",
47+
"linux": "xdg-open",
6648
}
67-
68-
err = auth.Register(c, username, password, email)
69-
70-
c.Token = ""
71-
72-
if d.checkAPICompatibility(c, err) != nil {
73-
d.PrintErr("Registration failed: ")
74-
return err
49+
run, ok := commands[runtime.GOOS]
50+
if !ok {
51+
return errors.New("warning: Cannot open browser")
7552
}
76-
77-
d.Printf("Registered %s\n", username)
78-
79-
if login {
80-
return d.Login(controller, username, password, sslVerify)
53+
cmd := exec.Command(run, URL)
54+
err := cmd.Start()
55+
if err != nil {
56+
return errors.New("warning: Cannot open browser")
8157
}
8258

8359
return nil
8460
}
8561

86-
func (d *DryccCmd) doLogin(s settings.Settings, username, password string) error {
87-
token, err := auth.Login(s.Client, username, password)
88-
if d.checkAPICompatibility(s.Client, err) != nil {
89-
return err
62+
func (d *DryccCmd) doToken(s settings.Settings, key string) error {
63+
var token api.AuthLoginResponse
64+
for i := 0; i <= 120; i++ {
65+
token, _ = auth.Token(s.Client, key)
66+
if token != (api.AuthLoginResponse{}) {
67+
break
68+
}
69+
time.Sleep(time.Duration(5) * time.Second)
9070
}
91-
92-
s.Client.Token = token
93-
s.Username = username
94-
95-
filename, err := s.Save(d.ConfigFile)
96-
97-
if err != nil {
98-
return nil
71+
if token.Token == "" || token.Token == "fail" {
72+
d.Printf("Logged fail")
73+
} else {
74+
s.Client.Token = token.Token
75+
s.Username = token.Username
76+
filename, err := s.Save(d.ConfigFile)
77+
if err != nil {
78+
return nil
79+
}
80+
d.Printf("Logged in as %s\n", token.Username)
81+
d.Printf("Configuration file written to %s\n", filename)
9982
}
100-
101-
d.Printf("Logged in as %s\n", username)
102-
d.Printf("Configuration file written to %s\n", filename)
10383
return nil
10484
}
10585

10686
// Login to a Drycc controller.
107-
func (d *DryccCmd) Login(controller string, username string, password string, sslVerify bool) error {
87+
func (d *DryccCmd) Login(controller string, sslVerify bool) error {
10888
c, err := drycc.New(sslVerify, controller, "")
10989

11090
if err != nil {
@@ -118,23 +98,8 @@ func (d *DryccCmd) Login(controller string, username string, password string, ss
11898
return err
11999
}
120100

121-
if username == "" {
122-
d.Print("username: ")
123-
fmt.Scanln(&username)
124-
}
125-
126-
if password == "" {
127-
d.Print("password: ")
128-
password, err = readPassword()
129-
d.Println()
130-
131-
if err != nil {
132-
return err
133-
}
134-
}
135-
136101
s := settings.Settings{Client: c}
137-
return d.doLogin(s, username, password)
102+
return d.doLogin(s)
138103
}
139104

140105
// Logout from a Drycc controller.
@@ -147,117 +112,6 @@ func (d *DryccCmd) Logout() error {
147112
return nil
148113
}
149114

150-
// Passwd changes a user's password.
151-
func (d *DryccCmd) Passwd(username, password, newPassword string) error {
152-
s, err := settings.Load(d.ConfigFile)
153-
154-
if err != nil {
155-
return err
156-
}
157-
158-
if password == "" && username == "" {
159-
d.Print("current password: ")
160-
password, err = readPassword()
161-
d.Println()
162-
163-
if err != nil {
164-
return err
165-
}
166-
}
167-
168-
if newPassword == "" {
169-
d.Print("new password: ")
170-
newPassword, err = readPassword()
171-
if err != nil {
172-
return err
173-
}
174-
175-
d.Printf("\nnew password (confirm): ")
176-
passwordConfirm, err := readPassword()
177-
178-
d.Println()
179-
180-
if err != nil {
181-
return err
182-
}
183-
184-
if newPassword != passwordConfirm {
185-
return errors.New("password mismatch, not changing")
186-
}
187-
}
188-
189-
err = auth.Passwd(s.Client, username, password, newPassword)
190-
if d.checkAPICompatibility(s.Client, err) != nil {
191-
d.PrintErr("Password change failed: ")
192-
return err
193-
}
194-
195-
d.Println("Password change succeeded.")
196-
return nil
197-
}
198-
199-
// Cancel deletes a user's account.
200-
func (d *DryccCmd) Cancel(username, password string, yes bool) error {
201-
s, err := settings.Load(d.ConfigFile)
202-
203-
if err != nil {
204-
return err
205-
}
206-
207-
if username == "" || password != "" {
208-
d.Println("Please log in again in order to cancel this account")
209-
210-
if err = d.Login(s.Client.ControllerURL.String(), username, password, s.Client.VerifySSL); err != nil {
211-
return err
212-
}
213-
}
214-
215-
if !yes {
216-
confirm := ""
217-
218-
s, err = settings.Load(d.ConfigFile)
219-
220-
if err != nil {
221-
return err
222-
}
223-
224-
deletedUser := username
225-
226-
if deletedUser == "" {
227-
deletedUser = s.Username
228-
}
229-
230-
d.Printf("cancel account %s at %s? (y/N): ", deletedUser, s.Client.ControllerURL.String())
231-
fmt.Scanln(&confirm)
232-
233-
if strings.ToLower(confirm) == "y" {
234-
yes = true
235-
}
236-
}
237-
238-
if !yes {
239-
d.PrintErrln("Account not changed")
240-
return nil
241-
}
242-
243-
err = auth.Delete(s.Client, username)
244-
if err == drycc.ErrConflict {
245-
return fmt.Errorf("%s still has applications associated with it. Transfer ownership or delete them first", username)
246-
} else if d.checkAPICompatibility(s.Client, err) != nil {
247-
return err
248-
}
249-
250-
// If user targets themselves, logout.
251-
if username == "" || s.Username == username {
252-
if err := settings.Delete(d.ConfigFile); err != nil {
253-
return err
254-
}
255-
}
256-
257-
d.Println("Account cancelled")
258-
return nil
259-
}
260-
261115
// Whoami prints the logged in user. If all is true, it fetches info from the controller to know
262116
// more about the user.
263117
func (d *DryccCmd) Whoami(all bool) error {
@@ -278,35 +132,3 @@ func (d *DryccCmd) Whoami(all bool) error {
278132
}
279133
return nil
280134
}
281-
282-
// Regenerate regenenerates a user's token.
283-
func (d *DryccCmd) Regenerate(username string, all bool) error {
284-
s, err := settings.Load(d.ConfigFile)
285-
286-
if err != nil {
287-
return err
288-
}
289-
290-
token, err := auth.Regenerate(s.Client, username, all)
291-
if d.checkAPICompatibility(s.Client, err) != nil {
292-
return err
293-
}
294-
295-
if username == "" && !all {
296-
s.Client.Token = token
297-
_, err = s.Save(d.ConfigFile)
298-
299-
if err != nil {
300-
return err
301-
}
302-
}
303-
304-
d.Println("Token Regenerated")
305-
return nil
306-
}
307-
308-
func readPassword() (string, error) {
309-
password, err := terminal.ReadPassword(int(syscall.Stdin))
310-
311-
return string(password), err
312-
}

0 commit comments

Comments
 (0)