Переглянути джерело

fix panics when login called w/ user-issued token, and when browser listener function cannot find code query param

Alexander Belanger 4 роки тому
батько
коміт
69a12c5e3b
3 змінених файлів з 67 додано та 77 видалено
  1. 10 5
      cli/cmd/api/api.go
  2. 49 70
      cli/cmd/auth.go
  3. 8 2
      cli/cmd/login/server.go

+ 10 - 5
cli/cmd/api/api.go

@@ -144,11 +144,11 @@ type TokenProjectID struct {
 	ProjectID uint `json:"project_id"`
 }
 
-func GetProjectIDFromToken(token string) (uint, error) {
+func GetProjectIDFromToken(token string) (uint, bool, error) {
 	var encoded string
 
 	if tokenSplit := strings.Split(token, "."); len(tokenSplit) != 3 {
-		return 0, fmt.Errorf("invalid jwt token format")
+		return 0, false, fmt.Errorf("invalid jwt token format")
 	} else {
 		encoded = tokenSplit[1]
 	}
@@ -156,7 +156,7 @@ func GetProjectIDFromToken(token string) (uint, error) {
 	decodedBytes, err := base64.RawStdEncoding.DecodeString(encoded)
 
 	if err != nil {
-		return 0, fmt.Errorf("could not decode jwt token from base64: %v", err)
+		return 0, false, fmt.Errorf("could not decode jwt token from base64: %v", err)
 	}
 
 	res := &TokenProjectID{}
@@ -164,8 +164,13 @@ func GetProjectIDFromToken(token string) (uint, error) {
 	err = json.Unmarshal(decodedBytes, res)
 
 	if err != nil {
-		return 0, fmt.Errorf("could not get token project id: %v", err)
+		return 0, false, fmt.Errorf("could not get token project id: %v", err)
 	}
 
-	return res.ProjectID, nil
+	// if the project ID is 0, this is a token signed for a user, not a specific project
+	if res.ProjectID == 0 {
+		return 0, false, nil
+	}
+
+	return res.ProjectID, true, nil
 }

+ 49 - 70
cli/cmd/auth.go

@@ -56,7 +56,6 @@ var logoutCmd = &cobra.Command{
 	},
 }
 
-var token string = ""
 var manual bool = false
 
 func init() {
@@ -80,27 +79,39 @@ func login() error {
 	user, _ := client.AuthCheck(context.Background())
 
 	if user != nil {
+		// set the token if the user calls login with the --token flag or the PORTER_TOKEN env
 		if config.Token != "" {
-			// set the token if the user calls login with the --token flag
 			config.SetToken(config.Token)
 			color.New(color.FgGreen).Println("Successfully logged in!")
 
-			projID, err := api.GetProjectIDFromToken(config.Token)
+			projID, exists, err := api.GetProjectIDFromToken(config.Token)
 
 			if err != nil {
 				return err
 			}
 
-			err = config.SetProject(projID)
+			// if project ID does not exist for the token, this is a user-issued CLI token, so the project
+			// ID should be queried
+			if !exists {
+				err = setProjectForUser(client, user.ID)
 
-			if err != nil {
-				return err
-			}
+				if err != nil {
+					return err
+				}
+			} else {
+				// if the project ID does exist for the token, this is a project-issued token, and
+				// the project should be set automatically
+				err = config.SetProject(projID)
 
-			err = setProjectCluster(client, projID)
+				if err != nil {
+					return err
+				}
 
-			if err != nil {
-				return err
+				err = setProjectCluster(client, projID)
+
+				if err != nil {
+					return err
+				}
 			}
 		} else {
 			color.Yellow("You are already logged in. If you'd like to log out, run \"porter auth logout\".")
@@ -114,78 +125,46 @@ func login() error {
 		return loginManual()
 	}
 
-	// check for a token
-	var err error
-
-	if token == "" {
-		token, err = loginBrowser.Login(config.Host)
-
-		if err != nil {
-			return err
-		}
-
-		// set the token in config
-		err = config.SetToken(token)
-
-		if err != nil {
-			return err
-		}
-
-		client := api.NewClientWithToken(config.Host+"/api", token)
-
-		user, err := client.AuthCheck(context.Background())
-
-		if user == nil {
-			color.Red("Invalid token.")
-			return err
-		}
-
-		color.New(color.FgGreen).Println("Successfully logged in!")
-
-		// get a list of projects, and set the current project
-		projects, err := client.ListUserProjects(context.Background(), user.ID)
+	// log the user in
+	token, err := loginBrowser.Login(config.Host)
 
-		if err != nil {
-			return err
-		}
-
-		if len(projects) > 0 {
-			config.SetProject(projects[0].ID)
+	if err != nil {
+		return err
+	}
 
-			err = setProjectCluster(client, projects[0].ID)
+	// set the token in config
+	err = config.SetToken(token)
 
-			if err != nil {
-				return err
-			}
-		}
-	} else {
-		// set the token in config
-		err = config.SetToken(token)
+	if err != nil {
+		return err
+	}
 
-		if err != nil {
-			return err
-		}
+	client = api.NewClientWithToken(config.Host+"/api", token)
 
-		client := api.NewClientWithToken(config.Host+"/api", token)
+	user, err = client.AuthCheck(context.Background())
 
-		user, err := client.AuthCheck(context.Background())
+	if user == nil {
+		color.Red("Invalid token.")
+		return err
+	}
 
-		if user == nil {
-			color.Red("Invalid token.")
-			return err
-		}
+	color.New(color.FgGreen).Println("Successfully logged in!")
 
-		color.New(color.FgGreen).Println("Successfully logged in!")
+	return setProjectForUser(client, user.ID)
+}
 
-		projID, err := api.GetProjectIDFromToken(token)
+func setProjectForUser(client *api.Client, userID uint) error {
+	// get a list of projects, and set the current project
+	projects, err := client.ListUserProjects(context.Background(), userID)
 
-		if err != nil {
-			return err
-		}
+	if err != nil {
+		return err
+	}
 
-		config.SetProject(projID)
+	if len(projects) > 0 {
+		config.SetProject(projects[0].ID)
 
-		err = setProjectCluster(client, projID)
+		err = setProjectCluster(client, projects[0].ID)
 
 		if err != nil {
 			return err

+ 8 - 2
cli/cmd/login/server.go

@@ -19,9 +19,15 @@ func redirect(
 		w.Header().Set("Content-Type", "text/html; charset=utf-8")
 		fmt.Fprint(w, successScreen)
 
-		queryParams, _ := url.ParseQuery(r.URL.RawQuery)
+		queryParams, err := url.ParseQuery(r.URL.RawQuery)
 
-		codechan <- queryParams["code"][0]
+		if err != nil {
+			return
+		}
+
+		if codeParam, exists := queryParams["code"]; exists && len(codeParam) > 0 {
+			codechan <- queryParams["code"][0]
+		}
 	}
 }