123 lines
2.9 KiB
Go
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
|
|
}
|