Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions cmd/auth/login/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/charmbracelet/huh"
"github.com/fosrl/cli/internal/api"
"github.com/fosrl/cli/internal/companion"
"github.com/fosrl/cli/internal/config"
"github.com/fosrl/cli/internal/logger"
"github.com/fosrl/cli/internal/utils"
Expand Down Expand Up @@ -174,6 +175,11 @@ func LoginCmd() *cobra.Command {
}

func loginMain(cmd *cobra.Command, opts *LoginCmdOpts) error {
if err := companion.GuardMutatingAuth(cmd.Context()); err != nil {
logger.Error("%v", err)
return err
}

apiClient := api.FromContext(cmd.Context())
accountStore := config.AccountStoreFromContext(cmd.Context())

Expand Down Expand Up @@ -328,11 +334,11 @@ func loginMain(cmd *cobra.Command, opts *LoginCmdOpts) error {
} else if apiServerInfo != nil {
// Convert api.ServerInfo to config.ServerInfo
serverInfo := &config.ServerInfo{
Version: apiServerInfo.Version,
SupporterStatusValid: apiServerInfo.SupporterStatusValid,
Build: apiServerInfo.Build,
EnterpriseLicenseValid: apiServerInfo.EnterpriseLicenseValid,
EnterpriseLicenseType: apiServerInfo.EnterpriseLicenseType,
Version: apiServerInfo.Version,
SupporterStatusValid: apiServerInfo.SupporterStatusValid,
Build: apiServerInfo.Build,
EnterpriseLicenseValid: apiServerInfo.EnterpriseLicenseValid,
EnterpriseLicenseType: apiServerInfo.EnterpriseLicenseType,
}
// Update account with server info
account := accountStore.Accounts[user.UserID]
Expand Down
14 changes: 8 additions & 6 deletions cmd/auth/logout/logout.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/charmbracelet/huh"
"github.com/fosrl/cli/internal/api"
"github.com/fosrl/cli/internal/companion"
"github.com/fosrl/cli/internal/config"
"github.com/fosrl/cli/internal/logger"
"github.com/fosrl/cli/internal/olm"
Expand All @@ -29,6 +30,11 @@ func LogoutCmd() *cobra.Command {
}

func logoutMain(cmd *cobra.Command) error {
if err := companion.GuardMutatingAuth(cmd.Context()); err != nil {
logger.Error("%v", err)
return err
}

apiClient := api.FromContext(cmd.Context())

// Check if client is running before logout
Expand Down Expand Up @@ -84,12 +90,8 @@ func logoutMain(cmd *cobra.Command) error {
// If version doesn't match, skip client shutdown and continue with logout
}

// Check if there's an active session in the key store
accountStore, err := config.LoadAccountStore()
if err != nil {
logger.Error("Failed to load account store: %s", err)
return err
}
// Check if there's an active session in the account store.
accountStore := config.AccountStoreFromContext(cmd.Context())

if accountStore.ActiveUserID == "" {
logger.Success("Already logged out!")
Expand Down
21 changes: 20 additions & 1 deletion cmd/auth/status/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

"github.com/fosrl/cli/internal/api"
"github.com/fosrl/cli/internal/companion"
"github.com/fosrl/cli/internal/config"
"github.com/fosrl/cli/internal/logger"
"github.com/fosrl/cli/internal/utils"
Expand All @@ -30,14 +31,32 @@ func StatusCmd() *cobra.Command {
func statusMain(cmd *cobra.Command) error {
apiClient := api.FromContext(cmd.Context())
accountStore := config.AccountStoreFromContext(cmd.Context())
companionState := companion.StateFromContext(cmd.Context())

if companionState.Enabled && !companionState.Active {
logger.Info("Status: not logged in")
logger.Info("Open %s to log in", companionState.ProviderName)
logger.Info("Or run 'pangolin companion disable' to use standalone CLI auth")
return fmt.Errorf("not logged in")
}

account, err := accountStore.ActiveAccount()
if err != nil {
logger.Info("Status: %s", err)
logger.Info("Run 'pangolin login' to authenticate")
if companionState.Enabled {
logger.Info("Open %s to log in", companionState.ProviderName)
logger.Info("Or run 'pangolin companion disable' to use standalone CLI auth")
} else {
logger.Info("Run 'pangolin login' to authenticate")
}
return err
}

if companionState.Active {
logger.Info("Companion mode: using %s session", companionState.ProviderName)
fmt.Println()
}

// Check health before fetching user data
healthOk, healthErr := apiClient.CheckHealth()
isServerDown := healthErr != nil || !healthOk
Expand Down
9 changes: 9 additions & 0 deletions cmd/companion/companion_other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//go:build !windows

package companioncmd

import "github.com/spf13/cobra"

func CompanionCmd() *cobra.Command {
return nil
}
130 changes: 130 additions & 0 deletions cmd/companion/companion_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
//go:build windows

package companioncmd

import (
"fmt"

"github.com/fosrl/cli/internal/companion"
"github.com/fosrl/cli/internal/config"
"github.com/fosrl/cli/internal/logger"
"github.com/spf13/cobra"
)

func CompanionCmd() *cobra.Command {
clientName := companion.PlatformProviderName()
short := "Manage companion mode with the Pangolin desktop app"
long := "Enable or disable companion mode, which uses the Pangolin desktop app for authentication."
if clientName != "" {
short = "Manage companion mode with " + clientName
long = "Enable or disable companion mode, which uses " + clientName + " for authentication."
}

cmd := &cobra.Command{
Use: "companion",
Short: short,
Long: long,
}

cmd.AddCommand(companionEnableCmd())
cmd.AddCommand(companionDisableCmd())
cmd.AddCommand(companionStatusCmd())

return cmd
}

func companionEnableCmd() *cobra.Command {
return &cobra.Command{
Use: "enable",
Short: "Enable companion mode",
RunE: companionEnableMain,
}
}

func companionDisableCmd() *cobra.Command {
return &cobra.Command{
Use: "disable",
Short: "Disable companion mode",
RunE: companionDisableMain,
}
}

func companionStatusCmd() *cobra.Command {
return &cobra.Command{
Use: "status",
Short: "Show companion mode status",
RunE: companionStatusMain,
}
}

func companionEnableMain(cmd *cobra.Command, args []string) error {
cfg, err := config.LoadConfig()
if err != nil {
return err
}

cfg.SetCompanionModeEnabled(true)
if err := cfg.Save(); err != nil {
return err
}

logger.Success("Companion mode enabled")
logger.Info("This takes effect on the next pangolin command.")
if companion.RequiredDesktopAppVersion() != "" {
clientName := companion.PlatformProviderName()
logger.Info("Companion mode requires %s version %s or later.", clientName, companion.RequiredDesktopAppVersion())
}
return nil
}

func companionDisableMain(cmd *cobra.Command, args []string) error {
cfg, err := config.LoadConfig()
if err != nil {
return err
}

cfg.SetCompanionModeEnabled(false)
if err := cfg.Save(); err != nil {
return err
}

logger.Success("Companion mode disabled")
logger.Info("This takes effect on the next pangolin command.")
return nil
}

func companionStatusMain(cmd *cobra.Command, args []string) error {
cfg, err := config.LoadConfig()
if err != nil {
return err
}

report := companion.EvaluateStatus(cfg)
printStatusReport(report)
return nil
}

func printStatusReport(report companion.StatusReport) {
fmt.Printf("Companion mode: %s\n", report.ConfigState)

switch report.ConfigState {
case "disabled":
fmt.Println("Auth source: standalone CLI")
return
case "unavailable":
fmt.Printf("Client: %s\n", report.ClientName)
fmt.Println("Auth source: standalone CLI")
return
}

fmt.Printf("Client: %s\n", report.ClientName)
if report.Ready {
fmt.Println("Ready: yes")
return
}

fmt.Println("Ready: no")
if report.Suggestion != "" {
fmt.Println(report.Suggestion)
}
}
Loading
Loading