package middlewares import ( "net/url" "strings" "github.com/gofiber/fiber/v2" "github.com/sujit-baniya/fiber-boilerplate/pkg/models" ) // AuthUmindWidget resuelve el tenant a partir de la site_key en la URL y // valida que la petición venga de uno de sus dominios permitidos (Origin, o // Referer si el navegador no manda Origin). La site_key no es un secreto — // cualquiera puede verla en el HTML público del sitio — la protección real es // el chequeo de dominio, igual que una site key de reCAPTCHA/Analytics. func AuthUmindWidget(c *fiber.Ctx) error { siteKey := c.Params("site_key") if siteKey == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": true, "message": "site_key requerida"}) } tenant, err := models.GetUmindTenantBySiteKey(siteKey) if err != nil { return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": true, "message": "sitio no encontrado"}) } origen := c.Get("Origin") if origen == "" { origen = c.Get("Referer") } host := hostDeOrigen(origen) if !tenant.DominioPermitido(host) { return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": true, "message": "dominio no autorizado para este sitio"}) } if origen != "" { c.Set("Access-Control-Allow-Origin", origen) c.Set("Vary", "Origin") } c.Locals("umind_tenant", tenant) return c.Next() } // UmindWidgetCORS responde el preflight OPTIONS que el navegador manda antes // del POST real (el widget corre en un dominio distinto al de la API). func UmindWidgetCORS(c *fiber.Ctx) error { origen := c.Get("Origin") if origen != "" { c.Set("Access-Control-Allow-Origin", origen) c.Set("Vary", "Origin") } c.Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS") c.Set("Access-Control-Allow-Headers", "Content-Type") c.Set("Access-Control-Max-Age", "600") return c.SendStatus(fiber.StatusNoContent) } func hostDeOrigen(origenURL string) string { if origenURL == "" { return "" } u, err := url.Parse(origenURL) if err != nil { return "" } return strings.ToLower(u.Hostname()) }