From fe23f2fce39ca30410fac5576305ad800fcc25c3 Mon Sep 17 00:00:00 2001 From: Romain Bertrand Date: Sun, 18 Jan 2026 11:45:46 +0100 Subject: [PATCH] feat: add auth logout and token helpers --- cmd/auth.go | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 4 deletions(-) diff --git a/cmd/auth.go b/cmd/auth.go index d52732f..0b2ef06 100644 --- a/cmd/auth.go +++ b/cmd/auth.go @@ -7,9 +7,10 @@ import ( "strings" "syscall" - "github.com/spf13/cobra" "codeberg.org/romaintb/fgj/internal/api" "codeberg.org/romaintb/fgj/internal/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" "golang.org/x/term" ) @@ -33,13 +34,31 @@ var authStatusCmd = &cobra.Command{ RunE: runAuthStatus, } +var authLogoutCmd = &cobra.Command{ + Use: "logout", + Short: "Remove authentication for a Forgejo instance", + Long: "Remove authentication for a configured Forgejo instance.", + RunE: runAuthLogout, +} + +var authTokenCmd = &cobra.Command{ + Use: "token", + Short: "Print the stored authentication token", + Long: "Print the stored authentication token for a configured Forgejo instance.", + RunE: runAuthToken, +} + func init() { rootCmd.AddCommand(authCmd) authCmd.AddCommand(authLoginCmd) authCmd.AddCommand(authStatusCmd) + authCmd.AddCommand(authLogoutCmd) + authCmd.AddCommand(authTokenCmd) authLoginCmd.Flags().String("hostname", "", "Forgejo instance hostname (e.g., codeberg.org)") authLoginCmd.Flags().StringP("token", "t", "", "Personal access token") + authLogoutCmd.Flags().String("hostname", "", "Forgejo instance hostname (e.g., codeberg.org)") + authTokenCmd.Flags().String("hostname", "", "Forgejo instance hostname (e.g., codeberg.org)") } func runAuthLogin(cmd *cobra.Command, args []string) error { @@ -87,9 +106,9 @@ func runAuthLogin(cmd *cobra.Command, args []string) error { } cfg.SetHost(hostname, config.HostConfig{ - Hostname: hostname, - Token: token, - User: user.UserName, + Hostname: hostname, + Token: token, + User: user.UserName, GitProtocol: "https", }) @@ -121,3 +140,66 @@ func runAuthStatus(cmd *cobra.Command, args []string) error { return nil } + +func runAuthLogout(cmd *cobra.Command, args []string) error { + cfg, err := config.Load() + if err != nil { + return fmt.Errorf("failed to load config: %w", err) + } + + hostname, _ := cmd.Flags().GetString("hostname") + resolved, err := resolveAuthHostname(cfg, hostname) + if err != nil { + return err + } + + delete(cfg.Hosts, resolved) + if err := cfg.Save(); err != nil { + return fmt.Errorf("failed to save config: %w", err) + } + + fmt.Printf("✓ Logged out from %s\n", resolved) + return nil +} + +func runAuthToken(cmd *cobra.Command, args []string) error { + cfg, err := config.Load() + if err != nil { + return fmt.Errorf("failed to load config: %w", err) + } + + hostname, _ := cmd.Flags().GetString("hostname") + resolved, err := resolveAuthHostname(cfg, hostname) + if err != nil { + return err + } + + fmt.Println(cfg.Hosts[resolved].Token) + return nil +} + +func resolveAuthHostname(cfg *config.Config, hostname string) (string, error) { + if hostname == "" { + hostname = viper.GetString("hostname") + } + if hostname == "" { + hostname = os.Getenv("FGJ_HOST") + } + if hostname == "" { + hostname = getDetectedHost() + } + if hostname == "" && len(cfg.Hosts) == 1 { + for host := range cfg.Hosts { + hostname = host + } + } + if hostname == "" { + hostname = "codeberg.org" + } + + if _, ok := cfg.Hosts[hostname]; !ok { + return "", fmt.Errorf("no configuration found for host %s", hostname) + } + + return hostname, nil +}