El widget hacía `data.respuesta || data.message` sin mirar el status, así que un 403/404/500 se pintaba en una burbuja como si lo hubiera dicho el agente. Imposible distinguir "el bot contestó raro" de "el widget está siendo rechazado", que es justo el lazo en el que se puede quedar alguien diagnosticando esto. Además los rechazos del middleware ocurren ANTES del motor, así que no dejaban rastro en ningún lado: ni en la auditoría del agente ni en el navegador. De ahí el síntoma "el chat de prueba anda pero el widget no". - El widget mira r.ok, manda el motivo real a la consola y al visitante le muestra un mensaje neutro. - AuthUmindWidget distingue las tres causas que el chat de prueba NO tiene (agente inactivo, tenant inactivo, dominio no autorizado) y las registra en la auditoría del agente con el detalle accionable — incluyendo qué dominio llamó y cuáles están permitidos. - GetUmindAgentePorSiteKey busca sin filtrar por activo, para poder decir "está apagado" en vez de "no existe". - Test del allowlist de dominios: es fail-closed y www.ejemplo.com NO matchea ejemplo.com, la causa más probable de este síntoma. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
57 lines
2.0 KiB
Go
57 lines
2.0 KiB
Go
package middlewares
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
|
|
)
|
|
|
|
// El widget valida el dominio; el chat de prueba no. Cuando alguien reporta
|
|
// "el chat de prueba anda pero el widget no", esta comparación es casi siempre
|
|
// la causa, así que la regla queda fijada acá.
|
|
func TestDominioPermitidoEsFailClosed(t *testing.T) {
|
|
casos := []struct {
|
|
nombre string
|
|
lista string
|
|
host string
|
|
permitido bool
|
|
}{
|
|
{"lista vacía no permite nada", "", "ejemplo.com", false},
|
|
{"sin host no permite", "ejemplo.com", "", false},
|
|
{"dominio exacto", "ejemplo.com", "ejemplo.com", true},
|
|
{"dominio distinto", "ejemplo.com", "otro.com", false},
|
|
{"www no entra por el dominio pelado", "ejemplo.com", "www.ejemplo.com", false},
|
|
{"www listado explícitamente", "ejemplo.com,www.ejemplo.com", "www.ejemplo.com", true},
|
|
{"comodín cubre subdominio", "*.ejemplo.com", "app.ejemplo.com", true},
|
|
{"comodín no cubre otro dominio", "*.ejemplo.com", "app.otro.com", false},
|
|
{"espacios alrededor no molestan", " ejemplo.com , otro.com ", "otro.com", true},
|
|
{"mayúsculas no molestan", "Ejemplo.COM", "ejemplo.com", true},
|
|
}
|
|
|
|
for _, cas := range casos {
|
|
t.Run(cas.nombre, func(t *testing.T) {
|
|
tenant := &models.UmindTenant{DominiosPermitidos: cas.lista}
|
|
if got := tenant.DominioPermitido(cas.host); got != cas.permitido {
|
|
t.Errorf("DominioPermitido(%q) con lista %q = %v, esperaba %v",
|
|
cas.host, cas.lista, got, cas.permitido)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// hostDeOrigen recibe el header Origin o Referer, no un host pelado.
|
|
func TestHostDeOrigen(t *testing.T) {
|
|
casos := map[string]string{
|
|
"https://ejemplo.com": "ejemplo.com",
|
|
"https://ejemplo.com/una/pagina": "ejemplo.com",
|
|
"https://ejemplo.com:8443": "ejemplo.com", // el puerto no cuenta
|
|
"http://WWW.Ejemplo.com": "www.ejemplo.com",
|
|
"": "",
|
|
}
|
|
for entrada, esperado := range casos {
|
|
if got := hostDeOrigen(entrada); got != esperado {
|
|
t.Errorf("hostDeOrigen(%q) = %q, esperaba %q", entrada, got, esperado)
|
|
}
|
|
}
|
|
}
|