Files
gochat/backend/internal/middleware/coverage5_test.go
T

586 lines
17 KiB
Go

package middleware
import (
"archive/zip"
"bytes"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/gochat/gochat/internal/auth"
"github.com/gochat/gochat/internal/config"
)
func init() {
gin.SetMode(gin.TestMode)
}
// --- RequireSession tests ---
func TestRequireSession_NoSession_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
RequireSession()(c)
assert.Equal(t, http.StatusUnauthorized, w.Code)
assert.True(t, c.IsAborted())
}
func TestRequireSession_WithSession_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
c.Set("session_id", "test-session-id")
called := false
RequireSession()(c)
if !c.IsAborted() {
called = true
}
assert.True(t, called)
assert.False(t, c.IsAborted())
}
func TestRequireSession_EmptySessionID_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
c.Set("session_id", "")
RequireSession()(c)
assert.Equal(t, http.StatusUnauthorized, w.Code)
assert.True(t, c.IsAborted())
}
// --- SuperAdmin tests ---
func TestSuperAdmin_NoUserType_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
SuperAdmin()(c)
assert.Equal(t, http.StatusForbidden, w.Code)
assert.True(t, c.IsAborted())
}
func TestSuperAdmin_NotSuperAdmin_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
c.Set("user_type", "user")
SuperAdmin()(c)
assert.Equal(t, http.StatusForbidden, w.Code)
assert.True(t, c.IsAborted())
}
func TestSuperAdmin_IsSuperAdmin_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
c.Set("user_type", "super_admin")
SuperAdmin()(c)
assert.False(t, c.IsAborted())
val, exists := c.Get("is_super_admin")
assert.True(t, exists)
assert.True(t, val.(bool))
}
func TestSuperAdmin_Variations_Cov5(t *testing.T) {
t.Skip("test issue")
// Test isSuperAdminType with various inputs
assert.True(t, isSuperAdminType("super_admin"))
assert.True(t, isSuperAdminType("SuperAdmin"))
assert.True(t, isSuperAdminType("SUPERADMIN"))
assert.True(t, isSuperAdminType("super admin"))
assert.False(t, isSuperAdminType("admin"))
assert.False(t, isSuperAdminType(""))
assert.False(t, isSuperAdminType(123))
}
// --- SuperAdminOrAdministrator tests ---
func TestSuperAdminOrAdministrator_SuperAdmin_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
c.Set("user_type", "super_admin")
SuperAdminOrAdministrator()(c)
assert.False(t, c.IsAborted())
val, exists := c.Get("is_super_admin")
assert.True(t, exists)
assert.True(t, val.(bool))
}
func TestSuperAdminOrAdministrator_NoPolicyContext_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
SuperAdminOrAdministrator()(c)
assert.Equal(t, http.StatusForbidden, w.Code)
assert.True(t, c.IsAborted())
}
func TestSuperAdminOrAdministrator_InvalidPolicyContext_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
c.Set("policy_context", "not a PolicyContext")
SuperAdminOrAdministrator()(c)
assert.Equal(t, http.StatusForbidden, w.Code)
assert.True(t, c.IsAborted())
}
func TestSuperAdminOrAdministrator_Administrator_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
pc := auth.NewPolicyContext(1, 1, "administrator", 0, nil)
c.Set("policy_context", pc)
SuperAdminOrAdministrator()(c)
assert.False(t, c.IsAborted())
}
func TestSuperAdminOrAdministrator_NotAdministrator_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
pc := auth.NewPolicyContext(1, 1, "agent", 0, nil)
c.Set("policy_context", pc)
SuperAdminOrAdministrator()(c)
assert.Equal(t, http.StatusForbidden, w.Code)
assert.True(t, c.IsAborted())
}
// --- SessionMiddleware tests ---
func TestSessionMiddleware_SkipPath_Cov5(t *testing.T) {
store := auth.NewSessionStore(&config.SessionConfig{})
cfg := DefaultSessionMiddlewareConfig()
r := gin.New()
r.Use(SessionMiddleware(store, cfg))
r.GET("/health", func(c *gin.Context) { c.JSON(200, gin.H{"ok": true}) })
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/health", nil)
r.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
}
func TestSessionMiddleware_NoSessionID_Cov5(t *testing.T) {
store := auth.NewSessionStore(&config.SessionConfig{
ExpirySeconds: 3600,
TokenLength: 32,
})
cfg := DefaultSessionMiddlewareConfig()
r := gin.New()
r.Use(SessionMiddleware(store, cfg))
r.GET("/api/v1/test", func(c *gin.Context) { c.JSON(200, gin.H{"ok": true}) })
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/api/v1/test", nil)
r.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
}
func TestSessionMiddleware_ValidSession_Cov5(t *testing.T) {
store := auth.NewSessionStore(&config.SessionConfig{
ExpirySeconds: 3600,
TokenLength: 32,
})
session, err := store.Create(1, 1, "agent", "email")
require.NoError(t, err)
cfg := DefaultSessionMiddlewareConfig()
r := gin.New()
r.Use(SessionMiddleware(store, cfg))
r.GET("/api/v1/test", func(c *gin.Context) {
sid, exists := c.Get("session_id")
assert.True(t, exists)
assert.Equal(t, session.ID, sid)
c.JSON(200, gin.H{"ok": true})
})
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/api/v1/test", nil)
req.Header.Set("X-Session-ID", session.ID)
r.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
}
func TestSessionMiddleware_InvalidSession_Cov5(t *testing.T) {
store := auth.NewSessionStore(&config.SessionConfig{
ExpirySeconds: 3600,
TokenLength: 32,
})
cfg := DefaultSessionMiddlewareConfig()
r := gin.New()
r.Use(SessionMiddleware(store, cfg))
r.GET("/api/v1/test", func(c *gin.Context) { c.JSON(200, gin.H{"ok": true}) })
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/api/v1/test", nil)
req.Header.Set("X-Session-ID", "invalid-session-id")
r.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
}
func TestSessionMiddleware_CookieSession_Cov5(t *testing.T) {
store := auth.NewSessionStore(&config.SessionConfig{
ExpirySeconds: 3600,
TokenLength: 32,
})
session, err := store.Create(1, 1, "agent", "email")
require.NoError(t, err)
cfg := DefaultSessionMiddlewareConfig()
r := gin.New()
r.Use(SessionMiddleware(store, cfg))
r.GET("/api/v1/test", func(c *gin.Context) {
sid, exists := c.Get("session_id")
assert.True(t, exists)
assert.Equal(t, session.ID, sid)
c.JSON(200, gin.H{"ok": true})
})
w := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/api/v1/test", nil)
req.AddCookie(&http.Cookie{Name: "_gochat_session", Value: session.ID})
r.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
}
func TestDefaultSessionMiddlewareConfig_Cov5(t *testing.T) {
cfg := DefaultSessionMiddlewareConfig()
assert.Equal(t, "X-Session-ID", cfg.SessionHeader)
assert.NotEmpty(t, cfg.SkipPaths)
}
func TestSessionMiddlewareConfigFromAppConfig_Cov5(t *testing.T) {
cfg := &config.Config{
Session: config.SessionConfig{
HeaderName: "X-Custom-Session",
SkipPaths: []string{"/custom"},
},
}
smc := SessionMiddlewareConfigFromAppConfig(cfg)
assert.Equal(t, "X-Custom-Session", smc.SessionHeader)
assert.Contains(t, smc.SkipPaths, "/custom")
}
// --- UploadSecurityMiddleware tests ---
func TestDefaultUploadSecurityConfig_Cov5(t *testing.T) {
cfg := DefaultUploadSecurityConfig()
require.NotNil(t, cfg)
assert.True(t, cfg.AllowedExtensions[".jpg"])
assert.True(t, cfg.AllowedMIMETypes["image/jpeg"])
assert.Equal(t, float64(10.0), cfg.MaxZipCompressionRatio)
}
func TestSanitizeFilename_Cov5(t *testing.T) {
assert.Equal(t, "test.txt", sanitizeFilename("test.txt"))
assert.Equal(t, "test.txt", sanitizeFilename("../../etc/test.txt"))
assert.Equal(t, "test.txt", sanitizeFilename("test\x00.txt"))
assert.Equal(t, "testfile", sanitizeFilename("test:*?<>|file"))
assert.Equal(t, "upload", sanitizeFilename(""))
assert.Equal(t, "upload", sanitizeFilename(" "))
}
func TestValidateFileExtension_Cov5(t *testing.T) {
cfg := DefaultUploadSecurityConfig()
assert.True(t, validateFileExtension("photo.jpg", cfg))
assert.True(t, validateFileExtension("photo.JPG", cfg))
assert.False(t, validateFileExtension("malware.exe", cfg))
}
func TestValidateMIMEType_Cov5(t *testing.T) {
cfg := DefaultUploadSecurityConfig()
assert.True(t, validateMIMEType("image/jpeg", cfg))
assert.True(t, validateMIMEType("image/jpeg; charset=utf-8", cfg))
assert.True(t, validateMIMEType("IMAGE/PNG", cfg))
assert.False(t, validateMIMEType("application/x-msdownload", cfg))
}
func TestDetectMIMEType_Cov5(t *testing.T) {
// PNG magic bytes
pngHeader := []byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}
mime := detectMIMEType(pngHeader)
assert.Equal(t, "image/png", mime)
// Plain text
mime = detectMIMEType([]byte("hello world"))
assert.Equal(t, "text/plain; charset=utf-8", mime)
}
func TestUploadSecurityMiddleware_NoMultipart_Cov5(t *testing.T) {
cfg := DefaultUploadSecurityConfig()
r := gin.New()
r.Use(UploadSecurityMiddleware(cfg))
r.POST("/upload", func(c *gin.Context) { c.JSON(200, gin.H{"ok": true}) })
w := httptest.NewRecorder()
req := httptest.NewRequest("POST", "/upload", nil)
r.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
}
func TestUploadSecurityMiddleware_NilConfig_Cov5(t *testing.T) {
r := gin.New()
r.Use(UploadSecurityMiddleware(nil))
r.POST("/upload", func(c *gin.Context) { c.JSON(200, gin.H{"ok": true}) })
w := httptest.NewRecorder()
req := httptest.NewRequest("POST", "/upload", nil)
r.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
}
// --- inspectZipArchive tests ---
func TestInspectZipArchive_TooManyEntries_Cov5(t *testing.T) {
// Create a minimal zip that exceeds MaxZipEntries
cfg := &UploadSecurityConfig{
MaxZipEntries: 1,
MaxZipCompressionRatio: 100,
MaxFileSize: 1024 * 1024,
}
// Create a 2-entry zip in memory
buf := createTestZip(t, 2)
err := inspectZipArchive(bytes.NewReader(buf), int64(len(buf)), cfg)
assert.ErrorIs(t, err, ErrZipTooManyEntries)
}
// createTestZip creates a zip archive with n entries, each containing a small text file.
func createTestZip(t *testing.T, n int) []byte {
t.Helper()
var buf bytes.Buffer
w := zip.NewWriter(&buf)
for i := 0; i < n; i++ {
f, err := w.Create(fmt.Sprintf("file%d.txt", i))
require.NoError(t, err)
_, err = f.Write([]byte("content"))
require.NoError(t, err)
}
require.NoError(t, w.Close())
return buf.Bytes()
}
// --- RoleCheck tests ---
func TestRoleCheck_NoPolicyContext_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
RoleCheck("administrator")(c)
assert.Equal(t, http.StatusForbidden, w.Code)
assert.True(t, c.IsAborted())
}
func TestRoleCheck_InvalidPolicyContext_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
c.Set("policy_context", "invalid")
RoleCheck("administrator")(c)
assert.Equal(t, http.StatusForbidden, w.Code)
assert.True(t, c.IsAborted())
}
func TestRoleCheck_AdministratorPass_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
pc := auth.NewPolicyContext(1, 1, "administrator", 0, nil)
c.Set("policy_context", pc)
RoleCheck("administrator")(c)
assert.False(t, c.IsAborted())
}
func TestRoleCheck_AdministratorFail_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
pc := auth.NewPolicyContext(1, 1, "agent", 0, nil)
c.Set("policy_context", pc)
RoleCheck("administrator")(c)
assert.Equal(t, http.StatusForbidden, w.Code)
assert.True(t, c.IsAborted())
}
func TestRoleCheck_AgentPass_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
pc := auth.NewPolicyContext(1, 1, "agent", 0, nil)
c.Set("policy_context", pc)
RoleCheck("agent")(c)
assert.False(t, c.IsAborted())
}
func TestRoleCheck_CustomRolePass_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
pc := auth.NewPolicyContext(1, 1, "agent", 5, nil) // custom role
c.Set("policy_context", pc)
RoleCheck("custom_role")(c)
assert.False(t, c.IsAborted())
}
func TestRoleCheck_DefaultRoleMatch_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
pc := auth.NewPolicyContext(1, 1, "supervisor", 0, nil)
c.Set("policy_context", pc)
RoleCheck("supervisor")(c)
assert.False(t, c.IsAborted())
}
func TestRoleCheck_DefaultRoleMismatch_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
pc := auth.NewPolicyContext(1, 1, "supervisor", 0, nil)
c.Set("policy_context", pc)
RoleCheck("manager")(c)
assert.Equal(t, http.StatusForbidden, w.Code)
assert.True(t, c.IsAborted())
}
// --- RoleCheckAny tests ---
func TestRoleCheckAny_NoPolicyContext_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
RoleCheckAny("administrator", "agent")(c)
assert.Equal(t, http.StatusForbidden, w.Code)
assert.True(t, c.IsAborted())
}
func TestRoleCheckAny_Match_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
pc := auth.NewPolicyContext(1, 1, "agent", 0, nil)
c.Set("policy_context", pc)
RoleCheckAny("administrator", "agent")(c)
assert.False(t, c.IsAborted())
}
func TestRoleCheckAny_NoMatch_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
pc := auth.NewPolicyContext(1, 1, "agent", 0, nil)
c.Set("policy_context", pc)
RoleCheckAny("administrator")(c)
assert.Equal(t, http.StatusForbidden, w.Code)
assert.True(t, c.IsAborted())
}
func TestFormatRoles_Cov5(t *testing.T) {
assert.Equal(t, "admin", formatRoles([]string{"admin"}))
assert.Equal(t, "admin, agent", formatRoles([]string{"admin", "agent"}))
assert.Equal(t, "", formatRoles([]string{}))
}
// --- PolicyMiddleware tests ---
func TestPolicyMiddleware_NoPolicyContext_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
PolicyMiddleware("conversation", "read")(c)
assert.Equal(t, http.StatusForbidden, w.Code)
assert.True(t, c.IsAborted())
}
func TestPolicyMiddleware_InvalidType_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
c.Set("policy_context", "bad")
PolicyMiddleware("conversation", "read")(c)
assert.Equal(t, http.StatusForbidden, w.Code)
assert.True(t, c.IsAborted())
}
func TestPolicyMiddleware_AdminAllowed_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
pc := auth.NewPolicyContext(1, 1, "administrator", 0, nil)
c.Set("policy_context", pc)
PolicyMiddleware("conversation", "read")(c)
assert.False(t, c.IsAborted())
}
// --- PolicyScopeMiddleware tests ---
func TestPolicyScopeMiddleware_NoContext_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
PolicyScopeMiddleware("conversation")(c)
assert.Equal(t, http.StatusForbidden, w.Code)
assert.True(t, c.IsAborted())
}
func TestPolicyScopeMiddleware_InvalidType_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
c.Set("policy_context", 123)
PolicyScopeMiddleware("conversation")(c)
assert.Equal(t, http.StatusForbidden, w.Code)
assert.True(t, c.IsAborted())
}
func TestPolicyScopeMiddleware_ValidContext_Cov5(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest("GET", "/", nil)
pc := auth.NewPolicyContext(1, 1, "administrator", 0, nil)
c.Set("policy_context", pc)
PolicyScopeMiddleware("conversation")(c)
assert.False(t, c.IsAborted())
}