veza/veza-backend-api/internal/api/routes_webhooks_test.go
2026-03-05 23:03:43 +01:00

92 lines
2.9 KiB
Go

package api
import (
"bytes"
"net/http"
"net/http/httptest"
"os"
"testing"
"time"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"veza-backend-api/internal/config"
"veza-backend-api/internal/database"
"veza-backend-api/internal/metrics"
)
func setupWebhookTestRouter(t *testing.T, webhookSecret string) *gin.Engine {
t.Helper()
os.Setenv("ENABLE_CLAMAV", "false")
os.Setenv("CLAMAV_REQUIRED", "false")
gin.SetMode(gin.TestMode)
router := gin.New()
gormDB, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
require.NoError(t, err)
sqlDB, err := gormDB.DB()
require.NoError(t, err)
vezaDB := &database.Database{
DB: sqlDB,
GormDB: gormDB,
Logger: zap.NewNop(),
}
cfg := &config.Config{
HyperswitchWebhookSecret: webhookSecret,
JWTSecret: "test-jwt-secret-key-minimum-32-characters-long",
JWTIssuer: "veza-api",
JWTAudience: "veza-app",
Logger: zap.NewNop(),
RedisClient: nil,
ErrorMetrics: metrics.NewErrorMetrics(),
UploadDir: "uploads/test",
Env: "development",
Database: vezaDB,
CORSOrigins: []string{"*"},
HandlerTimeout: 30 * time.Second,
RateLimitLimit: 100,
RateLimitWindow: 60,
AuthRateLimitLoginAttempts: 10,
AuthRateLimitLoginWindow: 15,
}
require.NoError(t, cfg.InitServicesForTest())
require.NoError(t, cfg.InitMiddlewaresForTest())
apiRouter := NewAPIRouter(vezaDB, cfg)
require.NoError(t, apiRouter.Setup(router))
return router
}
// TestHyperswitchWebhook_EmptySecret_Returns500 verifies that when HyperswitchWebhookSecret
// is empty, the webhook handler returns 500 (VEZA-SEC-005).
func TestHyperswitchWebhook_EmptySecret_Returns500(t *testing.T) {
router := setupWebhookTestRouter(t, "")
req := httptest.NewRequest(http.MethodPost, "/api/v1/webhooks/hyperswitch", bytes.NewReader([]byte(`{"test": true}`)))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
assert.Equal(t, http.StatusInternalServerError, w.Code, "empty webhook secret must return 500")
}
// TestHyperswitchWebhook_ValidSecret_InvalidSignature_Returns401 verifies that with a configured secret,
// invalid signature returns 401 (smoke test that verification path is exercised).
func TestHyperswitchWebhook_ValidSecret_InvalidSignature_Returns401(t *testing.T) {
router := setupWebhookTestRouter(t, "test-secret-at-least-32-chars-long")
req := httptest.NewRequest(http.MethodPost, "/api/v1/webhooks/hyperswitch", bytes.NewReader([]byte(`{"test": true}`)))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
assert.Equal(t, http.StatusUnauthorized, w.Code, "invalid signature must return 401")
}