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
+3
View File
@@ -18,6 +18,7 @@ import type {
UserMutationPayload,
NodeMutationPayload,
TunnelMutationPayload,
TunnelQuotaResetPayload,
UserTunnelAssignPayload,
UserTunnelListQuery,
UserTunnelRemovePayload,
@@ -117,6 +118,8 @@ export const getTunnelById = (id: number) =>
Network.post<TunnelApiItem>("/tunnel/get", { id });
export const updateTunnel = (data: TunnelMutationPayload) =>
Network.post("/tunnel/update", data);
export const resetTunnelQuota = (data: TunnelQuotaResetPayload) =>
Network.post("/tunnel/quota/reset", data);
export const deleteTunnel = (id: number) =>
Network.post("/tunnel/delete", { id });
export const diagnoseTunnel = (tunnelId: number) =>
+20
View File
@@ -36,6 +36,19 @@ export interface TunnelApiItem {
name: string;
type: number;
status: number;
flow?: number;
trafficRatio?: number;
inIp?: string;
ipPreference?: string;
inNodeId?: TunnelChainNodePayload[];
outNodeId?: TunnelChainNodePayload[];
chainNodes?: TunnelChainNodePayload[][];
dailyQuotaGB?: number;
monthlyQuotaGB?: number;
dailyUsedBytes?: number;
monthlyUsedBytes?: number;
disabledByQuota?: number;
quotaDisabledAt?: number;
entryNodeId: number;
exitNodeId: number;
inx?: number;
@@ -250,6 +263,8 @@ export interface TunnelMutationPayload {
status?: number;
flow?: number;
trafficRatio?: number;
dailyQuotaGB?: number;
monthlyQuotaGB?: number;
inIp?: string;
ipPreference?: string;
inNodeId?: TunnelChainNodePayload[];
@@ -257,6 +272,11 @@ export interface TunnelMutationPayload {
chainNodes?: TunnelChainNodePayload[][];
}
export interface TunnelQuotaResetPayload {
tunnelId: number;
scope?: "daily" | "monthly" | "all";
}
export interface UserTunnelAssignPayload {
userId?: number;
id?: number;