up
This commit is contained in:
@@ -5,16 +5,24 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// CloudflareConfig almacena el API Token de Cloudflare.
|
||||
// CloudflareConfig almacena las credenciales de Cloudflare.
|
||||
// Solo un registro puede estar activo a la vez.
|
||||
//
|
||||
// AuthType puede ser:
|
||||
// - "token" → API Token (recomendado, 40 chars, Bearer auth)
|
||||
// - "global_key" → Global API Key (legacy, X-Auth-Email + X-Auth-Key)
|
||||
type CloudflareConfig struct {
|
||||
gorm.Model
|
||||
// API Token (recomendado) – se usa como Bearer token
|
||||
APIToken string `json:"api_token" gorm:"column:api_token;type:text;not null"`
|
||||
// Tipo de autenticación: "token" (defecto) o "global_key"
|
||||
AuthType string `json:"auth_type" gorm:"column:auth_type;type:varchar(20);default:'token'"`
|
||||
// API Token (AuthType=token) o Global API Key (AuthType=global_key)
|
||||
APIToken string `json:"api_token" gorm:"column:api_token;type:text;not null"`
|
||||
// Email de la cuenta (requerido solo para AuthType=global_key)
|
||||
Email string `json:"email" gorm:"column:email;type:text"`
|
||||
// Account ID principal (opcional, para endpoints de cuenta)
|
||||
AccountID string `json:"account_id" gorm:"column:account_id;type:text"`
|
||||
Activo bool `json:"activo" gorm:"column:activo;default:true"`
|
||||
Nota string `json:"nota" gorm:"column:nota;type:text"`
|
||||
Activo bool `json:"activo" gorm:"column:activo;default:true"`
|
||||
Nota string `json:"nota" gorm:"column:nota;type:text"`
|
||||
}
|
||||
|
||||
func (CloudflareConfig) TableName() string { return "cloudflare_config" }
|
||||
@@ -35,7 +43,9 @@ func SaveCloudflareConfig(s CloudflareConfig) error {
|
||||
s.Activo = true
|
||||
if s.ID > 0 {
|
||||
return app.Http.Database.DB.Model(&s).Updates(map[string]interface{}{
|
||||
"auth_type": s.AuthType,
|
||||
"api_token": s.APIToken,
|
||||
"email": s.Email,
|
||||
"account_id": s.AccountID,
|
||||
"nota": s.Nota,
|
||||
"activo": true,
|
||||
|
||||
@@ -12,13 +12,18 @@ import (
|
||||
const cloudflareBaseURL = "https://api.cloudflare.com/client/v4"
|
||||
|
||||
// CloudflareClient es el cliente HTTP para la API de Cloudflare.
|
||||
// Soporta dos modos de autenticación:
|
||||
// - API Token (recomendado): Authorization: Bearer <token>
|
||||
// - Global API Key (legacy): X-Auth-Email + X-Auth-Key
|
||||
type CloudflareClient struct {
|
||||
token string
|
||||
token string // API Token o Global API Key
|
||||
email string // Solo para Global API Key
|
||||
globalKey bool // true = usar X-Auth-Email + X-Auth-Key
|
||||
accountID string
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
// NewCloudflareClient crea un cliente con el API Token.
|
||||
// NewCloudflareClient crea un cliente con API Token (Bearer).
|
||||
func NewCloudflareClient(token, accountID string) *CloudflareClient {
|
||||
return &CloudflareClient{
|
||||
token: token,
|
||||
@@ -29,14 +34,40 @@ func NewCloudflareClient(token, accountID string) *CloudflareClient {
|
||||
}
|
||||
}
|
||||
|
||||
// get realiza una petición GET autenticada y devuelve el body.
|
||||
// NewCloudflareClientGlobalKey crea un cliente con Global API Key (X-Auth-Email + X-Auth-Key).
|
||||
func NewCloudflareClientGlobalKey(email, apiKey, accountID string) *CloudflareClient {
|
||||
return &CloudflareClient{
|
||||
token: apiKey,
|
||||
email: email,
|
||||
globalKey: true,
|
||||
accountID: accountID,
|
||||
httpClient: &http.Client{
|
||||
Timeout: 20 * time.Second,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// IsGlobalKey indica si el cliente usa Global API Key en lugar de API Token.
|
||||
func (c *CloudflareClient) IsGlobalKey() bool { return c.globalKey }
|
||||
|
||||
// addAuth aplica los headers de autenticación correctos según el tipo de credencial.
|
||||
func (c *CloudflareClient) addAuth(req *http.Request) {
|
||||
if c.globalKey {
|
||||
req.Header.Set("X-Auth-Email", c.email)
|
||||
req.Header.Set("X-Auth-Key", c.token)
|
||||
} else {
|
||||
req.Header.Set("Authorization", "Bearer "+c.token)
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
// get realiza una petición GET autenticada y decodifica el result.
|
||||
func (c *CloudflareClient) get(path string, dest interface{}) error {
|
||||
req, err := http.NewRequest(http.MethodGet, cloudflareBaseURL+path, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cloudflare: crear request: %w", err)
|
||||
}
|
||||
req.Header.Set("Authorization", "Bearer "+c.token)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
c.addAuth(req)
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
@@ -258,8 +289,7 @@ func (c *CloudflareClient) getWithInfo(path string, dest interface{}) (cfResultI
|
||||
if err != nil {
|
||||
return cfResultInfo{}, fmt.Errorf("cloudflare: crear request: %w", err)
|
||||
}
|
||||
req.Header.Set("Authorization", "Bearer "+c.token)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
c.addAuth(req)
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
@@ -381,8 +411,7 @@ func (c *CloudflareClient) doRequest(method, path string, payload interface{}, d
|
||||
if err != nil {
|
||||
return fmt.Errorf("cloudflare: crear request: %w", err)
|
||||
}
|
||||
req.Header.Set("Authorization", "Bearer "+c.token)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
c.addAuth(req)
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user