(cmd *cobra.Command, args []string)
| 17 | } |
| 18 | |
| 19 | func runInit(cmd *cobra.Command, args []string) error { |
| 20 | client, err := api.New() |
| 21 | if err != nil { |
| 22 | return err |
| 23 | } |
| 24 | |
| 25 | if client.IsInitialized() { |
| 26 | fmt.Println("Already authenticated. Use `cloudcent config` to view your credentials.") |
| 27 | return nil |
| 28 | } |
| 29 | |
| 30 | fmt.Println("Opening browser for authentication…") |
| 31 | |
| 32 | tokenResp, err := client.GenerateToken() |
| 33 | if err != nil { |
| 34 | return fmt.Errorf("failed to generate token: %w", err) |
| 35 | } |
| 36 | |
| 37 | authURL := fmt.Sprintf("%s?token=%s&exchange=%s", api.CLIBaseURL, tokenResp.AccessToken, tokenResp.ExchangeCode) |
| 38 | if err := browser.OpenURL(authURL); err != nil { |
| 39 | fmt.Printf("Could not open browser automatically. Please visit:\n%s\n", authURL) |
| 40 | } |
| 41 | |
| 42 | fmt.Println("Waiting for authentication (up to 5 minutes)…") |
| 43 | |
| 44 | const maxAttempts = 150 |
| 45 | for i := 0; i < maxAttempts; i++ { |
| 46 | time.Sleep(2 * time.Second) |
| 47 | |
| 48 | resp, err := client.ExchangeToken(tokenResp.ExchangeCode) |
| 49 | if err != nil { |
| 50 | continue |
| 51 | } |
| 52 | |
| 53 | if resp.CliID != nil && resp.APIKey != nil { |
| 54 | cfg := &config.Config{ |
| 55 | CliID: *resp.CliID, |
| 56 | APIKey: resp.APIKey, |
| 57 | } |
| 58 | if err := client.SaveConfig(cfg); err != nil { |
| 59 | return fmt.Errorf("failed to save config: %w", err) |
| 60 | } |
| 61 | fmt.Printf("Authentication successful! CLI ID: %s\n", *resp.CliID) |
| 62 | return nil |
| 63 | } |
| 64 | |
| 65 | if resp.Status != nil { |
| 66 | switch *resp.Status { |
| 67 | case "expired": |
| 68 | return fmt.Errorf("authentication token expired") |
| 69 | case "pending": |
| 70 | continue |
| 71 | } |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | return fmt.Errorf("authentication timed out after 5 minutes") |
| 76 | } |
nothing calls this directly
no test coverage detected