package auth import ( "fmt" "os" "path/filepath" "strings" "gopkg.in/yaml.v3" ) type teaLogin struct { Name string `yaml:"name"` URL string `yaml:"url"` Token string `yaml:"token"` Default bool `yaml:"default"` } type teaConfig struct { Logins []teaLogin `yaml:"logins"` } func parseTea(path string) (*teaConfig, error) { data, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("read tea config %s: %w", path, err) } var cfg teaConfig if err := yaml.Unmarshal(data, &cfg); err != nil { return nil, fmt.Errorf("parse tea config %s: %w", path, err) } return &cfg, nil } func defaultTeaConfigPath() (string, error) { home, err := os.UserHomeDir() if err != nil { return "", fmt.Errorf("resolve home dir: %w", err) } return filepath.Join(home, ".config", "tea", "config.yml"), nil } // ResolveGiteaToken returns a Gitea token for the given host. // Resolution order: // 1. GITEA_TOKEN env var (if non-empty) // 2. ~/.config/tea/config.yml: entry matching host, else default login func ResolveGiteaToken(host string) (string, error) { return resolveGiteaToken(host, "") } func resolveGiteaToken(host, teaConfigPath string) (string, error) { if tok := os.Getenv("GITEA_TOKEN"); tok != "" { return tok, nil } if teaConfigPath == "" { var err error teaConfigPath, err = defaultTeaConfigPath() if err != nil { return "", err } } cfg, err := parseTea(teaConfigPath) if err != nil { return "", err } if len(cfg.Logins) == 0 { return "", fmt.Errorf("no logins in tea config %s", teaConfigPath) } want := strings.TrimRight(strings.ToLower(host), "/") // First try exact host match. for _, l := range cfg.Logins { loginHost := strings.TrimRight(strings.ToLower(l.URL), "/") if loginHost == want { if l.Token == "" { return "", fmt.Errorf("tea config login for host %s has empty token", host) } return l.Token, nil } } // Fall back to default login. var chosen *teaLogin for i := range cfg.Logins { if cfg.Logins[i].Default { chosen = &cfg.Logins[i] break } } if chosen == nil { chosen = &cfg.Logins[0] } if chosen.Token == "" { return "", fmt.Errorf("tea config default login has empty token") } return chosen.Token, nil }