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
+14 -6
View File
@@ -680,12 +680,14 @@ func (s *InboundService) ResetClientTrafficByEmail(clientEmail string) error {
if err := adjustGroupBaselinesForRemovedTraffic(tx, []string{clientEmail}); err != nil {
return err
}
if err := clearGlobalTraffic(tx, clientEmail); err != nil {
keepOff, err := handDisabledEmails(tx, []string{clientEmail})
if err != nil {
return err
}
if err := tx.Model(xray.ClientTraffic{}).
Where("email = ?", clientEmail).
Updates(map[string]any{"enable": true, "up": 0, "down": 0}).Error; err != nil {
if _, err := zeroClientTraffics(tx, []string{clientEmail}, keepOff); err != nil {
return err
}
if err := clearGlobalTraffic(tx, clientEmail); err != nil {
return err
}
return tx.Where("email = ?", clientEmail).Delete(&model.NodeClientTraffic{}).Error
@@ -723,8 +725,14 @@ func (s *InboundService) resetClientTrafficLocked(id int, clientEmail string) (b
if err != nil {
return false, nil, err
}
// A reset lifts the quota gate only: a client switched off by hand stays off.
keepOff, err := handDisabledEmails(database.GetDB(), []string{clientEmail})
if err != nil {
return false, nil, err
}
handDisabled := len(keepOff) > 0
if !traffic.Enable {
if !traffic.Enable && !handDisabled {
inbound, err := s.GetInbound(id)
if err != nil {
return false, nil, err
@@ -766,7 +774,7 @@ func (s *InboundService) resetClientTrafficLocked(id int, clientEmail string) (b
traffic.Up = 0
traffic.Down = 0
traffic.Enable = true
traffic.Enable = !handDisabled
db := database.GetDB()
now := time.Now().UnixMilli()