Przeglądaj źródła

fix(db): mark the IP-limit cleanup seeder done on a fresh install

ResetIpLimitNoFail2ban is a one-time migration that, on a host without fail2ban,
zeroes every existing client's limitIp because the limit can't be enforced. It
was missing from the fresh-install fast-path seeder list, so on a brand-new DB it
did not run on the first boot but fired on the second — wiping any IP limits the
admin had set in between. Add it to the fast-path so a truly fresh install marks
it done up front (there is nothing to clean), leaving later admin-set limits
intact.
MHSanaei 1 dzień temu
rodzic
commit
9b258becd0

+ 1 - 1
internal/database/db.go

@@ -1057,7 +1057,7 @@ func runSeeders(isUsersEmpty bool) error {
 	}
 
 	if empty && isUsersEmpty {
-		seeders := []string{"UserPasswordHash", "ClientsTable", "InboundClientsArrayFix", "InboundClientTgIdFix", "InboundClientSubIdFix", "FreedomFinalRulesReverseFix", "ApiTokensHash", "LegacyProxySettingsCleanup", "WireguardPeersToClients", "MtprotoSecretsToClients", "NodeInboundsAdopted"}
+		seeders := []string{"UserPasswordHash", "ClientsTable", "InboundClientsArrayFix", "InboundClientTgIdFix", "InboundClientSubIdFix", "FreedomFinalRulesReverseFix", "ApiTokensHash", "LegacyProxySettingsCleanup", "WireguardPeersToClients", "MtprotoSecretsToClients", "NodeInboundsAdopted", "ResetIpLimitNoFail2ban"}
 		for _, name := range seeders {
 			if err := db.Create(&model.HistoryOfSeeders{SeederName: name}).Error; err != nil {
 				return err

+ 41 - 0
internal/database/seeder_fastpath_test.go

@@ -0,0 +1,41 @@
+package database
+
+import (
+	"path/filepath"
+	"testing"
+
+	"github.com/mhsanaei/3x-ui/v3/internal/database/model"
+)
+
+// On a fresh install the fast path marks the one-time migration seeders as done
+// without running them. ResetIpLimitNoFail2ban must be in that set: otherwise it
+// is skipped on the first boot and runs on the second, where — on a host without
+// fail2ban — it destructively zeroes every client's limitIp, including limits the
+// admin configured between the two boots.
+func TestFreshInstallFastPathMarksResetIpLimitSeeder(t *testing.T) {
+	if err := InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
+		t.Fatalf("InitDB: %v", err)
+	}
+	t.Cleanup(func() { _ = CloseDB() })
+
+	if err := db.Where("1 = 1").Delete(&model.HistoryOfSeeders{}).Error; err != nil {
+		t.Fatalf("reset seeder history: %v", err)
+	}
+	if err := db.Where("1 = 1").Delete(&model.User{}).Error; err != nil {
+		t.Fatalf("reset users: %v", err)
+	}
+
+	if err := runSeeders(true); err != nil {
+		t.Fatalf("runSeeders: %v", err)
+	}
+
+	var cnt int64
+	if err := db.Model(&model.HistoryOfSeeders{}).
+		Where("seeder_name = ?", "ResetIpLimitNoFail2ban").
+		Count(&cnt).Error; err != nil {
+		t.Fatalf("count seeder history: %v", err)
+	}
+	if cnt != 1 {
+		t.Fatal("fresh-install fast path must mark ResetIpLimitNoFail2ban done so it cannot wipe admin-set IP limits on the next boot")
+	}
+}