Files
warpbox-dev/backend/libs/services/bans_test.go
Daniel Legt 4eacb4cde2
All checks were successful
Build and Publish Docker Image / deploy (push) Successful in 1m42s
fix(handlers): bypass box creation limits for batched uploads
Update `createOrAppendBox` to accept the upload policy and admin status, allowing policy enforcement to be handled during the box creation/append decision process. This ensures that appending files to an existing batch does not incorrectly trigger daily or active box creation limits, as no new box is being created.

Also, add unit tests to verify that batched uploads successfully bypass both daily and active box creation caps.
2026-06-01 00:20:18 +03:00

129 lines
4.6 KiB
Go

package services
import (
"log/slog"
"path/filepath"
"testing"
"time"
)
func TestBanServiceMatchesIPAndCIDR(t *testing.T) {
bans := newTestBanService(t)
now := time.Date(2026, 5, 31, 12, 0, 0, 0, time.UTC)
ipBan, err := bans.createBan("203.0.113.5", "single IP", BanSourceManual, "test", now.Add(time.Hour), now)
if err != nil {
t.Fatalf("createBan IP returned error: %v", err)
}
cidrBan, err := bans.createBan("198.51.100.0/24", "CIDR", BanSourceManual, "test", now.Add(time.Hour), now)
if err != nil {
t.Fatalf("createBan CIDR returned error: %v", err)
}
if matched, ok, err := bans.Match("203.0.113.5", now); err != nil || !ok || matched.Ban.ID != ipBan.ID {
t.Fatalf("Match IP = %+v, %v, %v", matched, ok, err)
}
if matched, ok, err := bans.Match("198.51.100.42", now); err != nil || !ok || matched.Ban.ID != cidrBan.ID {
t.Fatalf("Match CIDR = %+v, %v, %v", matched, ok, err)
}
if _, ok, err := bans.Match("192.0.2.1", now); err != nil || ok {
t.Fatalf("Match unrelated = %v, %v", ok, err)
}
}
func TestBanServiceIgnoresExpiredAndUnbanned(t *testing.T) {
bans := newTestBanService(t)
now := time.Date(2026, 5, 31, 12, 0, 0, 0, time.UTC)
expired, err := bans.createBan("203.0.113.6", "expired", BanSourceManual, "test", now.Add(time.Hour), now)
if err != nil {
t.Fatalf("createBan expired returned error: %v", err)
}
if _, ok, err := bans.Match("203.0.113.6", now.Add(2*time.Hour)); err != nil || ok {
t.Fatalf("expired Match = %v, %v", ok, err)
}
active, err := bans.createBan("203.0.113.7", "active", BanSourceManual, "test", now.Add(time.Hour), now)
if err != nil {
t.Fatalf("createBan active returned error: %v", err)
}
if err := bans.Unban(active.ID, now.Add(time.Minute)); err != nil {
t.Fatalf("Unban returned error: %v", err)
}
if _, ok, err := bans.Match("203.0.113.7", now.Add(2*time.Minute)); err != nil || ok {
t.Fatalf("unbanned Match = %v, %v", ok, err)
}
if expired.Status(now.Add(2*time.Hour)) != "expired" {
t.Fatalf("expired status = %q", expired.Status(now.Add(2*time.Hour)))
}
}
func TestBanServiceAutoBanThresholdsAndDisabled(t *testing.T) {
bans := newTestBanService(t)
now := time.Date(2026, 5, 31, 12, 0, 0, 0, time.UTC)
if result, err := bans.RecordAbuse("203.0.113.8", AbuseKindMaliciousPath, "/.env", 3, now); err != nil || result.Enabled {
t.Fatalf("disabled RecordAbuse = %+v, %v", result, err)
}
settings, err := bans.Settings()
if err != nil {
t.Fatalf("Settings returned error: %v", err)
}
settings.AutoBanEnabled = true
if err := bans.UpdateSettings(settings); err != nil {
t.Fatalf("UpdateSettings returned error: %v", err)
}
for i := 0; i < 2; i++ {
result, err := bans.RecordAbuse("203.0.113.8", AbuseKindMaliciousPath, "/.env", 3, now.Add(time.Duration(i)*time.Minute))
if err != nil || result.Triggered {
t.Fatalf("RecordAbuse before threshold = %+v, %v", result, err)
}
}
result, err := bans.RecordAbuse("203.0.113.8", AbuseKindMaliciousPath, "/.env", 3, now.Add(3*time.Minute))
if err != nil || !result.Triggered || result.Ban.ID == "" {
t.Fatalf("RecordAbuse threshold = %+v, %v", result, err)
}
again, err := bans.RecordAbuse("203.0.113.8", AbuseKindMaliciousPath, "/.env", 3, now.Add(4*time.Minute))
if err != nil || !again.Triggered || again.Ban.ID != result.Ban.ID {
t.Fatalf("RecordAbuse duplicate = %+v, %v", again, err)
}
records, err := bans.ListBans()
if err != nil {
t.Fatalf("ListBans returned error: %v", err)
}
if len(records) != 1 {
t.Fatalf("ban count = %d, want 1", len(records))
}
}
func TestBanServiceMaliciousPathRules(t *testing.T) {
bans := newTestBanService(t)
if pattern, err := bans.MaliciousPattern("/foo/.ENV"); err != nil || pattern == "" {
t.Fatalf("MaliciousPattern .env = %q, %v", pattern, err)
}
if pattern, err := bans.MaliciousPattern("/static/.env"); err != nil || pattern != "" {
t.Fatalf("MaliciousPattern static = %q, %v", pattern, err)
}
if err := bans.SaveRules([]string{"/custom-probe"}, time.Now().UTC()); err != nil {
t.Fatalf("SaveRules returned error: %v", err)
}
if pattern, err := bans.MaliciousPattern("/x/CUSTOM-probe"); err != nil || pattern != "/custom-probe" {
t.Fatalf("MaliciousPattern custom = %q, %v", pattern, err)
}
}
func newTestBanService(t *testing.T) *BanService {
t.Helper()
root := t.TempDir()
upload, err := NewUploadService(1024*1024, filepath.Join(root, "data"), "http://example.test", slog.Default())
if err != nil {
t.Fatalf("NewUploadService returned error: %v", err)
}
t.Cleanup(func() {
if err := upload.Close(); err != nil {
t.Fatalf("Close returned error: %v", err)
}
})
bans, err := NewBanService(upload.DB())
if err != nil {
t.Fatalf("NewBanService returned error: %v", err)
}
return bans
}