126 lines
3.2 KiB
Go
126 lines
3.2 KiB
Go
package gitea
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/rs/zerolog"
|
|
|
|
"github.com/vincentc-afk/gitea-notification-hub/internal/config"
|
|
)
|
|
|
|
// GiteaUser represents a user from Gitea API
|
|
type GiteaUser struct {
|
|
ID int64 `json:"id"`
|
|
Login string `json:"login"`
|
|
FullName string `json:"full_name"`
|
|
Email string `json:"email"`
|
|
AvatarURL string `json:"avatar_url"`
|
|
}
|
|
|
|
// Provider implements email lookup via Gitea API
|
|
type Provider struct {
|
|
baseURL string
|
|
token string
|
|
httpClient *http.Client
|
|
logger zerolog.Logger
|
|
}
|
|
|
|
// New creates a new Gitea API provider
|
|
func New(cfg *config.GiteaConfig, logger zerolog.Logger) *Provider {
|
|
return &Provider{
|
|
baseURL: cfg.URL,
|
|
token: cfg.Token,
|
|
httpClient: &http.Client{
|
|
Timeout: 10 * time.Second,
|
|
},
|
|
logger: logger.With().Str("component", "gitea-provider").Logger(),
|
|
}
|
|
}
|
|
|
|
// LookupEmail fetches the real email for a Gitea username via API
|
|
func (p *Provider) LookupEmail(ctx context.Context, username string) (string, error) {
|
|
url := fmt.Sprintf("%s/api/v1/users/%s", p.baseURL, username)
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
|
if err != nil {
|
|
return "", fmt.Errorf("creating request: %w", err)
|
|
}
|
|
|
|
// Add authorization header if token is provided
|
|
if p.token != "" {
|
|
req.Header.Set("Authorization", "token "+p.token)
|
|
}
|
|
req.Header.Set("Accept", "application/json")
|
|
|
|
resp, err := p.httpClient.Do(req)
|
|
if err != nil {
|
|
return "", fmt.Errorf("fetching user from Gitea: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == http.StatusNotFound {
|
|
return "", fmt.Errorf("user %s not found in Gitea", username)
|
|
}
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return "", fmt.Errorf("Gitea API returned status %d", resp.StatusCode)
|
|
}
|
|
|
|
var user GiteaUser
|
|
if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
|
|
return "", fmt.Errorf("decoding Gitea response: %w", err)
|
|
}
|
|
|
|
if user.Email == "" {
|
|
return "", fmt.Errorf("user %s has no email in Gitea", username)
|
|
}
|
|
|
|
p.logger.Debug().
|
|
Str("username", username).
|
|
Str("email", user.Email).
|
|
Str("full_name", user.FullName).
|
|
Msg("found user email via Gitea API")
|
|
|
|
return user.Email, nil
|
|
}
|
|
|
|
// GetUser fetches full user info from Gitea API
|
|
func (p *Provider) GetUser(ctx context.Context, username string) (*GiteaUser, error) {
|
|
url := fmt.Sprintf("%s/api/v1/users/%s", p.baseURL, username)
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("creating request: %w", err)
|
|
}
|
|
|
|
if p.token != "" {
|
|
req.Header.Set("Authorization", "token "+p.token)
|
|
}
|
|
req.Header.Set("Accept", "application/json")
|
|
|
|
resp, err := p.httpClient.Do(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("fetching user from Gitea: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == http.StatusNotFound {
|
|
return nil, fmt.Errorf("user %s not found in Gitea", username)
|
|
}
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("Gitea API returned status %d", resp.StatusCode)
|
|
}
|
|
|
|
var user GiteaUser
|
|
if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
|
|
return nil, fmt.Errorf("decoding Gitea response: %w", err)
|
|
}
|
|
|
|
return &user, nil
|
|
}
|