Refactor Caddy configuration management to include security settings
- Updated `GenerateConfig` function calls in tests to include additional security parameters. - Enhanced `Manager` struct to hold a `SecurityConfig` instance for managing security-related settings. - Implemented `computeEffectiveFlags` method to determine the effective state of security features based on both static configuration and runtime database settings. - Added comprehensive tests for the new security configuration handling, ensuring correct behavior for various scenarios including ACL and CrowdSec settings. - Adjusted existing tests to accommodate the new structure and ensure compatibility with the updated configuration management.
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"testing"
|
||||
"strings"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
"github.com/Wikid82/charon/backend/internal/logger"
|
||||
"github.com/Wikid82/charon/backend/internal/services"
|
||||
@@ -26,8 +27,11 @@ func TestBackupHandlerSanitizesFilename(t *testing.T) {
|
||||
svc := &services.BackupService{DataDir: tmpDir, BackupDir: tmpDir, DatabaseName: "db.sqlite", Cron: nil}
|
||||
h := NewBackupHandler(svc)
|
||||
|
||||
router := gin.New()
|
||||
router.GET("/backups/:filename/restore", h.Restore)
|
||||
// Create a gin test context and use it to call handler directly
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
// Ensure request-scoped logger is present and writes to our buffer
|
||||
c.Set("logger", logger.WithFields(map[string]interface{}{"test": "1"}))
|
||||
|
||||
// initialize logger to buffer
|
||||
buf := &bytes.Buffer{}
|
||||
@@ -35,16 +39,27 @@ func TestBackupHandlerSanitizesFilename(t *testing.T) {
|
||||
|
||||
// Create a malicious filename with newline and path components
|
||||
malicious := "../evil\nname"
|
||||
// Use path escape to send as URL
|
||||
req := httptest.NewRequest(http.MethodPost, "/backups/"+strings.ReplaceAll(malicious, "\n", "%0A")+"/restore", nil)
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
c.Request = httptest.NewRequest(http.MethodGet, "/backups/"+strings.ReplaceAll(malicious, "\n", "%0A")+"/restore", nil)
|
||||
// Call handler directly with the test context
|
||||
h.Restore(c)
|
||||
|
||||
out := buf.String()
|
||||
if strings.Contains(out, "\n") {
|
||||
t.Fatalf("log contained raw newline in filename: %s", out)
|
||||
// Optionally we could assert on the response status code here if needed
|
||||
textRegex := regexp.MustCompile(`filename=?"?([^"\s]*)"?`)
|
||||
jsonRegex := regexp.MustCompile(`"filename":"([^"]*)"`)
|
||||
var loggedFilename string
|
||||
if m := textRegex.FindStringSubmatch(out); len(m) == 2 {
|
||||
loggedFilename = m[1]
|
||||
} else if m := jsonRegex.FindStringSubmatch(out); len(m) == 2 {
|
||||
loggedFilename = m[1]
|
||||
} else {
|
||||
t.Fatalf("could not extract filename from logs: %s", out)
|
||||
}
|
||||
if strings.Contains(out, "..") {
|
||||
t.Fatalf("log contained path traversals in filename: %s", out)
|
||||
|
||||
if strings.Contains(loggedFilename, "\n") || strings.Contains(loggedFilename, "\r") {
|
||||
t.Fatalf("log filename contained raw newline: %q", loggedFilename)
|
||||
}
|
||||
if strings.Contains(loggedFilename, "..") {
|
||||
t.Fatalf("log filename contained path traversals in filename: %q", loggedFilename)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@@ -58,12 +57,10 @@ func TestCertificateHandler_List(t *testing.T) {
|
||||
// Setup temp dir
|
||||
tmpDir := t.TempDir()
|
||||
caddyDir := filepath.Join(tmpDir, "caddy", "certificates", "acme-v02.api.letsencrypt.org-directory")
|
||||
err := os.MkdirAll(caddyDir, 0755)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, os.MkdirAll(caddyDir, 0755))
|
||||
|
||||
// Setup in-memory DB
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
db := OpenTestDB(t)
|
||||
require.NoError(t, db.AutoMigrate(&models.SSLCertificate{}))
|
||||
|
||||
service := services.NewCertificateService(tmpDir, db)
|
||||
@@ -80,7 +77,7 @@ func TestCertificateHandler_List(t *testing.T) {
|
||||
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
var certs []services.CertificateInfo
|
||||
err = json.Unmarshal(w.Body.Bytes(), &certs)
|
||||
err := json.Unmarshal(w.Body.Bytes(), &certs)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, certs)
|
||||
}
|
||||
@@ -88,8 +85,7 @@ func TestCertificateHandler_List(t *testing.T) {
|
||||
func TestCertificateHandler_Upload(t *testing.T) {
|
||||
// Setup
|
||||
tmpDir := t.TempDir()
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
db := OpenTestDB(t)
|
||||
require.NoError(t, db.AutoMigrate(&models.SSLCertificate{}))
|
||||
|
||||
service := services.NewCertificateService(tmpDir, db)
|
||||
@@ -125,7 +121,7 @@ func TestCertificateHandler_Upload(t *testing.T) {
|
||||
assert.Equal(t, http.StatusCreated, w.Code)
|
||||
|
||||
var cert models.SSLCertificate
|
||||
err = json.Unmarshal(w.Body.Bytes(), &cert)
|
||||
err := json.Unmarshal(w.Body.Bytes(), &cert)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "Test Cert", cert.Name)
|
||||
}
|
||||
@@ -134,8 +130,7 @@ func TestCertificateHandler_Delete(t *testing.T) {
|
||||
// Setup
|
||||
tmpDir := t.TempDir()
|
||||
// Use WAL mode and busy timeout for better concurrency with race detector
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared&_journal_mode=WAL&_busy_timeout=5000"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
db := OpenTestDB(t)
|
||||
require.NoError(t, db.AutoMigrate(&models.SSLCertificate{}))
|
||||
|
||||
// Seed a cert
|
||||
@@ -143,8 +138,7 @@ func TestCertificateHandler_Delete(t *testing.T) {
|
||||
UUID: "test-uuid",
|
||||
Name: "To Delete",
|
||||
}
|
||||
err = db.Create(&cert).Error
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.Create(&cert).Error)
|
||||
require.NotZero(t, cert.ID)
|
||||
|
||||
service := services.NewCertificateService(tmpDir, db)
|
||||
@@ -165,15 +159,14 @@ func TestCertificateHandler_Delete(t *testing.T) {
|
||||
|
||||
// Verify deletion
|
||||
var deletedCert models.SSLCertificate
|
||||
err = db.First(&deletedCert, cert.ID).Error
|
||||
err := db.First(&deletedCert, cert.ID).Error
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, gorm.ErrRecordNotFound, err)
|
||||
}
|
||||
|
||||
func TestCertificateHandler_Upload_Errors(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
db := OpenTestDB(t)
|
||||
require.NoError(t, db.AutoMigrate(&models.SSLCertificate{}))
|
||||
|
||||
service := services.NewCertificateService(tmpDir, db)
|
||||
@@ -208,8 +201,7 @@ func TestCertificateHandler_Upload_Errors(t *testing.T) {
|
||||
|
||||
func TestCertificateHandler_Delete_NotFound(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
db := OpenTestDB(t)
|
||||
require.NoError(t, db.AutoMigrate(&models.SSLCertificate{}, &models.NotificationProvider{}))
|
||||
|
||||
service := services.NewCertificateService(tmpDir, db)
|
||||
@@ -229,8 +221,7 @@ func TestCertificateHandler_Delete_NotFound(t *testing.T) {
|
||||
|
||||
func TestCertificateHandler_Delete_InvalidID(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
db := OpenTestDB(t)
|
||||
require.NoError(t, db.AutoMigrate(&models.SSLCertificate{}))
|
||||
|
||||
service := services.NewCertificateService(tmpDir, db)
|
||||
@@ -249,8 +240,7 @@ func TestCertificateHandler_Delete_InvalidID(t *testing.T) {
|
||||
|
||||
func TestCertificateHandler_Upload_InvalidCertificate(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
db := OpenTestDB(t)
|
||||
require.NoError(t, db.AutoMigrate(&models.SSLCertificate{}))
|
||||
|
||||
service := services.NewCertificateService(tmpDir, db)
|
||||
@@ -284,8 +274,7 @@ func TestCertificateHandler_Upload_InvalidCertificate(t *testing.T) {
|
||||
|
||||
func TestCertificateHandler_Upload_MissingKeyFile(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
db := OpenTestDB(t)
|
||||
require.NoError(t, db.AutoMigrate(&models.SSLCertificate{}))
|
||||
|
||||
service := services.NewCertificateService(tmpDir, db)
|
||||
@@ -317,8 +306,7 @@ func TestCertificateHandler_Upload_MissingKeyFile(t *testing.T) {
|
||||
|
||||
func TestCertificateHandler_Upload_MissingName(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
db := OpenTestDB(t)
|
||||
require.NoError(t, db.AutoMigrate(&models.SSLCertificate{}))
|
||||
|
||||
service := services.NewCertificateService(tmpDir, db)
|
||||
@@ -354,11 +342,9 @@ func TestCertificateHandler_Upload_MissingName(t *testing.T) {
|
||||
func TestCertificateHandler_List_WithCertificates(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
caddyDir := filepath.Join(tmpDir, "caddy", "certificates", "acme-v02.api.letsencrypt.org-directory")
|
||||
err := os.MkdirAll(caddyDir, 0755)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, os.MkdirAll(caddyDir, 0755))
|
||||
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
db := OpenTestDB(t)
|
||||
require.NoError(t, db.AutoMigrate(&models.SSLCertificate{}))
|
||||
|
||||
// Seed a certificate in DB
|
||||
@@ -366,8 +352,7 @@ func TestCertificateHandler_List_WithCertificates(t *testing.T) {
|
||||
UUID: "test-uuid",
|
||||
Name: "Test Cert",
|
||||
}
|
||||
err = db.Create(&cert).Error
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.Create(&cert).Error)
|
||||
|
||||
service := services.NewCertificateService(tmpDir, db)
|
||||
ns := services.NewNotificationService(db)
|
||||
@@ -383,7 +368,7 @@ func TestCertificateHandler_List_WithCertificates(t *testing.T) {
|
||||
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
var certs []services.CertificateInfo
|
||||
err = json.Unmarshal(w.Body.Bytes(), &certs)
|
||||
err := json.Unmarshal(w.Body.Bytes(), &certs)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, certs)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@@ -36,10 +35,7 @@ func (f *fakeExec) Status(ctx context.Context, configDir string) (bool, int, err
|
||||
}
|
||||
|
||||
func setupCrowdDB(t *testing.T) *gorm.DB {
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
||||
if err != nil {
|
||||
t.Fatalf("db open: %v", err)
|
||||
}
|
||||
db := OpenTestDB(t)
|
||||
return db
|
||||
}
|
||||
|
||||
|
||||
@@ -8,17 +8,13 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/Wikid82/charon/backend/internal/models"
|
||||
)
|
||||
|
||||
func setupFlagsDB(t *testing.T) *gorm.DB {
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to open in-memory sqlite: %v", err)
|
||||
}
|
||||
db := OpenTestDB(t)
|
||||
if err := db.AutoMigrate(&models.Setting{}); err != nil {
|
||||
t.Fatalf("auto migrate failed: %v", err)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/Wikid82/charon/backend/internal/api/handlers"
|
||||
@@ -19,11 +18,8 @@ import (
|
||||
"github.com/Wikid82/charon/backend/internal/services"
|
||||
)
|
||||
|
||||
func setupTestDB() *gorm.DB {
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:"), &gorm.Config{})
|
||||
if err != nil {
|
||||
panic("failed to connect to test database")
|
||||
}
|
||||
func setupTestDB(t *testing.T) *gorm.DB {
|
||||
db := handlers.OpenTestDB(t)
|
||||
|
||||
// Auto migrate
|
||||
db.AutoMigrate(
|
||||
@@ -38,7 +34,7 @@ func setupTestDB() *gorm.DB {
|
||||
|
||||
func TestRemoteServerHandler_List(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
db := setupTestDB()
|
||||
db := setupTestDB(t)
|
||||
|
||||
// Create test server
|
||||
server := &models.RemoteServer{
|
||||
@@ -72,7 +68,7 @@ func TestRemoteServerHandler_List(t *testing.T) {
|
||||
|
||||
func TestRemoteServerHandler_Create(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
db := setupTestDB()
|
||||
db := setupTestDB(t)
|
||||
|
||||
ns := services.NewNotificationService(db)
|
||||
handler := handlers.NewRemoteServerHandler(services.NewRemoteServerService(db), ns)
|
||||
@@ -105,7 +101,7 @@ func TestRemoteServerHandler_Create(t *testing.T) {
|
||||
|
||||
func TestRemoteServerHandler_TestConnection(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
db := setupTestDB()
|
||||
db := setupTestDB(t)
|
||||
|
||||
// Create test server
|
||||
server := &models.RemoteServer{
|
||||
@@ -139,7 +135,7 @@ func TestRemoteServerHandler_TestConnection(t *testing.T) {
|
||||
|
||||
func TestRemoteServerHandler_Get(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
db := setupTestDB()
|
||||
db := setupTestDB(t)
|
||||
|
||||
// Create test server
|
||||
server := &models.RemoteServer{
|
||||
@@ -172,7 +168,7 @@ func TestRemoteServerHandler_Get(t *testing.T) {
|
||||
|
||||
func TestRemoteServerHandler_Update(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
db := setupTestDB()
|
||||
db := setupTestDB(t)
|
||||
|
||||
// Create test server
|
||||
server := &models.RemoteServer{
|
||||
@@ -217,7 +213,7 @@ func TestRemoteServerHandler_Update(t *testing.T) {
|
||||
|
||||
func TestRemoteServerHandler_Delete(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
db := setupTestDB()
|
||||
db := setupTestDB(t)
|
||||
|
||||
// Create test server
|
||||
server := &models.RemoteServer{
|
||||
@@ -252,7 +248,7 @@ func TestRemoteServerHandler_Delete(t *testing.T) {
|
||||
|
||||
func TestProxyHostHandler_List(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
db := setupTestDB()
|
||||
db := setupTestDB(t)
|
||||
|
||||
// Create test proxy host
|
||||
host := &models.ProxyHost{
|
||||
@@ -287,7 +283,7 @@ func TestProxyHostHandler_List(t *testing.T) {
|
||||
|
||||
func TestProxyHostHandler_Create(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
db := setupTestDB()
|
||||
db := setupTestDB(t)
|
||||
|
||||
ns := services.NewNotificationService(db)
|
||||
handler := handlers.NewProxyHostHandler(db, nil, ns, nil)
|
||||
@@ -340,7 +336,7 @@ func TestHealthHandler(t *testing.T) {
|
||||
|
||||
func TestRemoteServerHandler_Errors(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
db := setupTestDB()
|
||||
db := setupTestDB(t)
|
||||
|
||||
ns := services.NewNotificationService(db)
|
||||
handler := handlers.NewRemoteServerHandler(services.NewRemoteServerService(db), ns)
|
||||
|
||||
@@ -6,25 +6,28 @@ import (
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"encoding/json"
|
||||
"regexp"
|
||||
|
||||
"github.com/Wikid82/charon/backend/internal/logger"
|
||||
"github.com/Wikid82/charon/backend/internal/api/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
func TestImportUploadSanitizesFilename(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
tmpDir := t.TempDir()
|
||||
// set up in-memory DB for handler
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to open in-memory db: %v", err)
|
||||
}
|
||||
svc := NewImportHandler(db, "/usr/bin/caddy", tmpDir, "")
|
||||
db := OpenTestDB(t)
|
||||
// Create a fake caddy executable to avoid dependency on system binary
|
||||
fakeCaddy := filepath.Join(tmpDir, "caddy")
|
||||
os.WriteFile(fakeCaddy, []byte("#!/bin/sh\nexit 0"), 0755)
|
||||
svc := NewImportHandler(db, fakeCaddy, tmpDir, "")
|
||||
|
||||
router := gin.New()
|
||||
router.Use(middleware.RequestID())
|
||||
router.POST("/import/upload", svc.Upload)
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
@@ -39,10 +42,24 @@ func TestImportUploadSanitizesFilename(t *testing.T) {
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
out := buf.String()
|
||||
if strings.Contains(out, "\n") {
|
||||
t.Fatalf("log contained raw newline in filename: %s", out)
|
||||
|
||||
// Extract the logged filename from either text or JSON log format
|
||||
textRegex := regexp.MustCompile(`filename=?"?([^"\s]*)"?`)
|
||||
jsonRegex := regexp.MustCompile(`"filename":"([^"]*)"`)
|
||||
var loggedFilename string
|
||||
if m := textRegex.FindStringSubmatch(out); len(m) == 2 {
|
||||
loggedFilename = m[1]
|
||||
} else if m := jsonRegex.FindStringSubmatch(out); len(m) == 2 {
|
||||
loggedFilename = m[1]
|
||||
} else {
|
||||
// if we can't extract a filename value, fail the test
|
||||
t.Fatalf("could not extract filename from logs: %s", out)
|
||||
}
|
||||
if strings.Contains(out, "..") {
|
||||
t.Fatalf("log contained path traversal in filename: %s", out)
|
||||
|
||||
if strings.Contains(loggedFilename, "\n") || strings.Contains(loggedFilename, "\r") {
|
||||
t.Fatalf("log filename contained raw newline: %q", loggedFilename)
|
||||
}
|
||||
if strings.Contains(loggedFilename, "..") {
|
||||
t.Fatalf("log filename contained path traversal: %q", loggedFilename)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,11 @@ import (
|
||||
)
|
||||
|
||||
func setupNotificationTestDB() *gorm.DB {
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:"), &gorm.Config{})
|
||||
// Use openTestDB helper via temporary t trick
|
||||
// Since this function lacks t param, keep calling openTestDB with a dummy testing.T
|
||||
// But to avoid changing many callers, we'll reuse openTestDB by creating a short-lived testing.T wrapper isn't possible.
|
||||
// Instead, set WAL and busy timeout using a simple gorm.Open with shared memory but minimal changes.
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared&_journal_mode=WAL&_busy_timeout=5000"), &gorm.Config{})
|
||||
if err != nil {
|
||||
panic("failed to connect to test database")
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/Wikid82/charon/backend/internal/api/handlers"
|
||||
@@ -20,8 +19,7 @@ import (
|
||||
|
||||
func setupNotificationProviderTest(t *testing.T) (*gin.Engine, *gorm.DB) {
|
||||
t.Helper()
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
db := handlers.OpenTestDB(t)
|
||||
require.NoError(t, db.AutoMigrate(&models.NotificationProvider{}))
|
||||
|
||||
service := services.NewNotificationService(db)
|
||||
|
||||
@@ -13,14 +13,12 @@ import (
|
||||
"github.com/Wikid82/charon/backend/internal/services"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func setupDB(t *testing.T) *gorm.DB {
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
db.AutoMigrate(&models.NotificationTemplate{})
|
||||
db := OpenTestDB(t)
|
||||
require.NoError(t, db.AutoMigrate(&models.NotificationTemplate{}))
|
||||
return db
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/Wikid82/charon/backend/internal/caddy"
|
||||
"github.com/Wikid82/charon/backend/internal/config"
|
||||
"github.com/Wikid82/charon/backend/internal/models"
|
||||
"github.com/Wikid82/charon/backend/internal/services"
|
||||
)
|
||||
@@ -154,7 +155,7 @@ func TestProxyHostErrors(t *testing.T) {
|
||||
// Setup Caddy Manager
|
||||
tmpDir := t.TempDir()
|
||||
client := caddy.NewClient(caddyServer.URL)
|
||||
manager := caddy.NewManager(client, db, tmpDir, "", false)
|
||||
manager := caddy.NewManager(client, db, tmpDir, "", false, config.SecurityConfig{})
|
||||
|
||||
// Setup Handler
|
||||
ns := services.NewNotificationService(db)
|
||||
@@ -341,7 +342,7 @@ func TestProxyHostWithCaddyIntegration(t *testing.T) {
|
||||
// Setup Caddy Manager
|
||||
tmpDir := t.TempDir()
|
||||
client := caddy.NewClient(caddyServer.URL)
|
||||
manager := caddy.NewManager(client, db, tmpDir, "", false)
|
||||
manager := caddy.NewManager(client, db, tmpDir, "", false, config.SecurityConfig{})
|
||||
|
||||
// Setup Handler
|
||||
ns := services.NewNotificationService(db)
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
|
||||
func setupRemoteServerTest_New(t *testing.T) (*gin.Engine, *handlers.RemoteServerHandler) {
|
||||
t.Helper()
|
||||
db := setupTestDB()
|
||||
db := setupTestDB(t)
|
||||
// Ensure RemoteServer table exists
|
||||
db.AutoMigrate(&models.RemoteServer{})
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// openTestDB creates a SQLite in-memory DB unique per test and applies
|
||||
// a busy timeout and WAL journal mode to reduce SQLITE locking during parallel tests.
|
||||
func OpenTestDB(t *testing.T) *gorm.DB {
|
||||
t.Helper()
|
||||
dsnName := strings.ReplaceAll(t.Name(), "/", "_")
|
||||
dsn := fmt.Sprintf("file:%s?mode=memory&cache=shared&_journal_mode=WAL&_busy_timeout=5000", dsnName)
|
||||
db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to open test db: %v", err)
|
||||
}
|
||||
return db
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/Wikid82/charon/backend/internal/api/handlers"
|
||||
@@ -21,8 +20,7 @@ import (
|
||||
|
||||
func setupUptimeHandlerTest(t *testing.T) (*gin.Engine, *gorm.DB) {
|
||||
t.Helper()
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
db := handlers.OpenTestDB(t)
|
||||
require.NoError(t, db.AutoMigrate(&models.UptimeMonitor{}, &models.UptimeHeartbeat{}, &models.UptimeHost{}, &models.RemoteServer{}, &models.NotificationProvider{}, &models.Notification{}, &models.ProxyHost{}))
|
||||
|
||||
ns := services.NewNotificationService(db)
|
||||
|
||||
@@ -218,7 +218,7 @@ func Register(router *gin.Engine, db *gorm.DB, cfg config.Config) error {
|
||||
|
||||
// Caddy Manager
|
||||
caddyClient := caddy.NewClient(cfg.CaddyAdminAPI)
|
||||
caddyManager := caddy.NewManager(caddyClient, db, cfg.CaddyConfigDir, cfg.FrontendDir, cfg.ACMEStaging)
|
||||
caddyManager := caddy.NewManager(caddyClient, db, cfg.CaddyConfigDir, cfg.FrontendDir, cfg.ACMEStaging, cfg.Security)
|
||||
|
||||
proxyHostHandler := handlers.NewProxyHostHandler(db, caddyManager, notificationService, uptimeService)
|
||||
proxyHostHandler.RegisterRoutes(api)
|
||||
|
||||
Reference in New Issue
Block a user