feat(quota): add tunnel traffic quota with daily/monthly limits (#291) (#308)

Implement per-tunnel traffic quota feature:
- Add TunnelQuota model with daily/monthly usage tracking
- Integrate quota enforcement into flow accumulation path
- Pause forwards and disable tunnel when quota exceeded
- Block new forward creation/resume when tunnel quota disabled
- Auto-reset daily/monthly windows at 00:05 via maintenance job
- Add manual reset API endpoint for admins
- Include quota config in tunnel backup/restore
- Add frontend UI for quota settings and usage display

Entire-Checkpoint: e629b27ca437
This commit is contained in:
sagit
2026-03-11 16:09:03 +08:00
committed by GitHub
parent 69faeaa9a6
commit 5e96a8de72
16 changed files with 1133 additions and 13 deletions
@@ -44,6 +44,11 @@ func (h *Handler) processFlowItem(nodeID int64, item flowItem) {
if ok {
inFlow, outFlow := h.scaleFlowByTunnel(forwardID, item.D, item.U)
_ = h.repo.AddFlow(forwardID, userID, userTunnelID, inFlow, outFlow)
if forward, err := h.getForwardRecord(forwardID); err == nil && forward != nil {
if quota, quotaErr := h.repo.AddTunnelQuotaUsage(forward.TunnelID, inFlow+outFlow, time.Now()); quotaErr == nil {
h.enforceTunnelQuotaIfNeeded(forward.TunnelID, quota)
}
}
h.processPeerShareFlowFromForward(forwardID, nodeID, serviceName, item)
if userTunnelID > 0 {
@@ -356,6 +361,9 @@ func (h *Handler) ensureUserTunnelForwardAllowed(userID int64, tunnelID int64, n
if flowLimit < current {
return errors.New("流量已超额,禁止开启转发")
}
if err := h.ensureTunnelForwardAllowedByQuota(tunnelID, now); err != nil {
return err
}
userTunnelID, _, _, err := h.resolveUserTunnelAndLimiter(userID, tunnelID)
if err != nil {