fix(clients): re-enable only quota-disabled clients on a traffic reset

Every traffic reset re-enabled its clients unconditionally, in the
client record and in the traffic row a master treats as the client's
state. A master forwards an inbound's scheduled reset and "reset all"
to its nodes through the per-client reset calls, so a client disabled
by hand on a node inbound came back on at the next scheduled reset.

Each reset now decides, before it zeroes the counters, which of its
clients the quota switched off, counting cross-panel usage, and
re-enables only those; a client disabled below its quota keeps its
record and traffic row off. The reset API docs say so.
This commit is contained in:
MHSanaei
2026-11-01 08:31:27 +01:00
parent 67820dc20d
commit 7f64a67ba5
10 changed files with 249 additions and 60 deletions
@@ -137,12 +137,12 @@ func depleteClientTraffic(t *testing.T, inboundId int, email string) {
t.Helper()
db := database.GetDB()
res := db.Model(&xray.ClientTraffic{}).Where("email = ?", email).
Updates(map[string]any{"enable": false, "up": 1, "down": 1})
Updates(map[string]any{"enable": false, "up": 1, "down": 1, "total": 2})
if res.Error != nil {
t.Fatalf("deplete traffic: %v", res.Error)
}
if res.RowsAffected == 0 {
if err := db.Create(&xray.ClientTraffic{InboundId: inboundId, Email: email, Enable: false, Up: 1, Down: 1}).Error; err != nil {
if err := db.Create(&xray.ClientTraffic{InboundId: inboundId, Email: email, Enable: false, Up: 1, Down: 1, Total: 2}).Error; err != nil {
t.Fatalf("create depleted traffic: %v", err)
}
}