87 lines
2.6 KiB
Go
87 lines
2.6 KiB
Go
package whatsapp
|
|
|
|
import (
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/gochat/gochat/internal/model"
|
|
channelmodel "github.com/gochat/gochat/internal/model/channel"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func newWhatsAppWebhookTestDB(t *testing.T) *gorm.DB {
|
|
t.Helper()
|
|
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("open sqlite: %v", err)
|
|
}
|
|
if err := db.AutoMigrate(&model.Inbox{}, &channelmodel.ChannelWhatsApp{}); err != nil {
|
|
t.Fatalf("migrate whatsapp models: %v", err)
|
|
}
|
|
return db
|
|
}
|
|
|
|
func TestWhatsAppWebhookLookupByVerifyToken(t *testing.T) {
|
|
db := newWhatsAppWebhookTestDB(t)
|
|
inbox := model.Inbox{AccountID: 1, Name: "wa", ChannelType: "whatsapp", ChannelID: 1, Enabled: true}
|
|
if err := db.Create(&inbox).Error; err != nil {
|
|
t.Fatalf("create inbox: %v", err)
|
|
}
|
|
channel := channelmodel.ChannelWhatsApp{
|
|
AccountID: 1,
|
|
InboxID: inbox.ID,
|
|
PhoneNumber: "+15551234567",
|
|
PhoneNumberID: "phone-number-id",
|
|
AccessToken: "access-token",
|
|
Provider: "whatsapp_cloud",
|
|
WebhookVerifyToken: "verify-token",
|
|
ProviderConfig: `{"app_secret":"app-secret"}`,
|
|
BusinessAccountID: "waba-id",
|
|
WhatsAppAccountName: "WA",
|
|
}
|
|
if err := db.Create(&channel).Error; err != nil {
|
|
t.Fatalf("create whatsapp channel: %v", err)
|
|
}
|
|
|
|
repo := NewRepository(db)
|
|
provider := NewWhatsAppProvider(nil, repo, nil)
|
|
h := NewWebhookHandler(provider)
|
|
found, err := h.lookupByVerifyToken("verify-token")
|
|
if err != nil {
|
|
t.Fatalf("lookup verify token: %v", err)
|
|
}
|
|
if found.ID != channel.ID {
|
|
t.Fatalf("unexpected channel id: %d", found.ID)
|
|
}
|
|
if secret := resolveCloudAppSecret(found); secret != "app-secret" {
|
|
t.Fatalf("unexpected app secret: %q", secret)
|
|
}
|
|
}
|
|
|
|
func TestWhatsAppCloudSignatureUsesAppSecret(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
body := []byte(`{"object":"whatsapp_business_account"}`)
|
|
mac := hmac.New(sha256.New, []byte("app-secret"))
|
|
mac.Write(body)
|
|
signature := "sha256=" + hex.EncodeToString(mac.Sum(nil))
|
|
|
|
w := httptest.NewRecorder()
|
|
c, _ := gin.CreateTestContext(w)
|
|
c.Request = httptest.NewRequest(http.MethodPost, "/webhooks/whatsapp/phone", nil)
|
|
c.Request.Header.Set("X-Hub-Signature-256", signature)
|
|
|
|
h := NewWebhookHandler(nil)
|
|
if err := h.verifyCloudSignature(c, body, "app-secret"); err != nil {
|
|
t.Fatalf("verify signature: %v", err)
|
|
}
|
|
if err := h.verifyCloudSignature(c, body, "wrong-secret"); err == nil {
|
|
t.Fatal("expected wrong app secret to fail")
|
|
}
|
|
}
|