diff --git a/rest/controllers/cloudflare_controller.go b/rest/controllers/cloudflare_controller.go index 6d3f8bd..2918f9c 100644 --- a/rest/controllers/cloudflare_controller.go +++ b/rest/controllers/cloudflare_controller.go @@ -115,23 +115,71 @@ func VerifyCloudflareToken(c *fiber.Ctx) error { if token == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"ok": false, "error": "Token vacío"}) } - // Si la longitud cambia después de sanear, había caracteres basura dirty := len([]rune(raw)) != len([]rune(token)) client := services.NewCloudflareClient(token, sanitizeCFToken(cfg.AccountID)) - result, err := client.VerifyToken() + + // Primer carácter y último para diagnóstico sin exponer el token completo + runes := []rune(token) + preview := "" + if len(runes) >= 8 { + preview = string(runes[:4]) + "…" + string(runes[len(runes)-4:]) + } + + // 1. Verificar que el token sea válido + verify, err := client.VerifyToken() if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "ok": false, + "step": "verify_token", "error": err.Error(), + "hint": "El token no es válido. Crea uno nuevo en dash.cloudflare.com → Mi Perfil → API Tokens", "token_len": len(token), + "token_prev": preview, "was_dirty": dirty, }) } + + // 2. Probar Zone:Zone:Read (listar zonas) + _, zonesErr := client.GetZones() + zonesOK := zonesErr == nil + zonesErrMsg := "" + if zonesErr != nil { + zonesErrMsg = zonesErr.Error() + } + + // 3. Probar Zone:DNS:Read (leer DNS de la primera zona disponible) + dnsOK := false + dnsErrMsg := "" + if zonesOK { + zones, _ := client.GetZones() + if len(zones) > 0 { + _, dnsErr := client.GetDNSRecords(zones[0].ID) + dnsOK = dnsErr == nil + if dnsErr != nil { + dnsErrMsg = dnsErr.Error() + } + } + } + return c.JSON(fiber.Map{ - "ok": true, - "data": result, - "token_len": len(token), - "was_dirty": dirty, + "ok": true, + "token_len": len(token), + "token_prev": preview, + "was_dirty": dirty, + "token_status": verify.Status, + "permissions": fiber.Map{ + "zone_read": fiber.Map{"ok": zonesOK, "error": zonesErrMsg}, + "dns_read": fiber.Map{"ok": dnsOK, "error": dnsErrMsg}, + }, + "hint": func() string { + if !zonesOK { + return "Falta permiso Zone:Zone:Read en el token" + } + if !dnsOK { + return "Falta permiso Zone:DNS:Read en el token. Edita el token en Cloudflare y agrega ese permiso." + } + return "Token válido con todos los permisos necesarios" + }(), }) }