fj/cmd/auth.go
2025-12-08 09:49:07 +01:00

123 lines
2.9 KiB
Go

package cmd
import (
"bufio"
"fmt"
"os"
"strings"
"syscall"
"github.com/spf13/cobra"
"codeberg.org/romaintb/fgj/internal/api"
"codeberg.org/romaintb/fgj/internal/config"
"golang.org/x/term"
)
var authCmd = &cobra.Command{
Use: "auth",
Short: "Authenticate fgj with a Forgejo instance",
Long: "Manage authentication state for Forgejo instances.",
}
var authLoginCmd = &cobra.Command{
Use: "login",
Short: "Authenticate with a Forgejo instance",
Long: "Authenticate with a Forgejo instance using a personal access token.",
RunE: runAuthLogin,
}
var authStatusCmd = &cobra.Command{
Use: "status",
Short: "View authentication status",
Long: "Display the authentication status for configured Forgejo instances.",
RunE: runAuthStatus,
}
func init() {
rootCmd.AddCommand(authCmd)
authCmd.AddCommand(authLoginCmd)
authCmd.AddCommand(authStatusCmd)
authLoginCmd.Flags().String("hostname", "", "Forgejo instance hostname (e.g., codeberg.org)")
authLoginCmd.Flags().StringP("token", "t", "", "Personal access token")
}
func runAuthLogin(cmd *cobra.Command, args []string) error {
hostname, _ := cmd.Flags().GetString("hostname")
token, _ := cmd.Flags().GetString("token")
reader := bufio.NewReader(os.Stdin)
if hostname == "" {
fmt.Print("Forgejo instance hostname (default: codeberg.org): ")
input, _ := reader.ReadString('\n')
hostname = strings.TrimSpace(input)
if hostname == "" {
hostname = "codeberg.org"
}
}
if token == "" {
fmt.Print("Personal access token: ")
tokenBytes, err := term.ReadPassword(int(syscall.Stdin))
if err != nil {
return fmt.Errorf("failed to read token: %w", err)
}
fmt.Println()
token = strings.TrimSpace(string(tokenBytes))
}
if token == "" {
return fmt.Errorf("token is required")
}
client, err := api.NewClient(hostname, token)
if err != nil {
return fmt.Errorf("failed to create client: %w", err)
}
user, _, err := client.GetMyUserInfo()
if err != nil {
return fmt.Errorf("authentication failed: %w", err)
}
cfg, err := config.Load()
if err != nil {
return fmt.Errorf("failed to load config: %w", err)
}
cfg.SetHost(hostname, config.HostConfig{
Hostname: hostname,
Token: token,
User: user.UserName,
GitProtocol: "https",
})
if err := cfg.Save(); err != nil {
return fmt.Errorf("failed to save config: %w", err)
}
fmt.Printf("✓ Authenticated as %s on %s\n", user.UserName, hostname)
return nil
}
func runAuthStatus(cmd *cobra.Command, args []string) error {
cfg, err := config.Load()
if err != nil {
return fmt.Errorf("failed to load config: %w", err)
}
if len(cfg.Hosts) == 0 {
fmt.Println("Not authenticated with any Forgejo instances")
fmt.Println("Run 'fgj auth login' to authenticate")
return nil
}
fmt.Println("Authenticated instances:")
for hostname, host := range cfg.Hosts {
fmt.Printf(" • %s (user: %s)\n", hostname, host.User)
}
return nil
}