2025-09-20 07:35:50 +00:00
// Package model defines the database models and data structures used by the 3x-ui panel.
2023-02-09 19:18:06 +00:00
package model
import (
"fmt"
2024-03-10 21:31:24 +00:00
2025-09-19 08:05:43 +00:00
"github.com/mhsanaei/3x-ui/v2/util/json_util"
"github.com/mhsanaei/3x-ui/v2/xray"
2023-02-09 19:18:06 +00:00
)
2025-09-20 07:35:50 +00:00
// Protocol represents the protocol type for Xray inbounds.
2023-02-09 19:18:06 +00:00
type Protocol string
2025-09-20 07:35:50 +00:00
// Protocol constants for different Xray inbound protocols
2023-02-09 19:18:06 +00:00
const (
2024-08-10 22:47:44 +00:00
VMESS Protocol = "vmess"
2023-02-09 19:18:06 +00:00
VLESS Protocol = "vless"
2025-09-09 11:57:40 +00:00
Tunnel Protocol = "tunnel"
2024-05-28 13:16:29 +00:00
HTTP Protocol = "http"
2023-02-09 19:18:06 +00:00
Trojan Protocol = "trojan"
Shadowsocks Protocol = "shadowsocks"
2025-09-09 11:57:40 +00:00
Mixed Protocol = "mixed"
2024-05-28 13:16:29 +00:00
WireGuard Protocol = "wireguard"
2023-02-09 19:18:06 +00:00
)
2025-09-20 07:35:50 +00:00
// User represents a user account in the 3x-ui panel.
2023-02-09 19:18:06 +00:00
type User struct {
2025-05-08 14:20:58 +00:00
Id int ` json:"id" gorm:"primaryKey;autoIncrement" `
Username string ` json:"username" `
Password string ` json:"password" `
2023-02-09 19:18:06 +00:00
}
2025-09-20 07:35:50 +00:00
// Inbound represents an Xray inbound configuration with traffic statistics and settings.
2023-02-09 19:18:06 +00:00
type Inbound struct {
2025-09-20 07:35:50 +00:00
Id int ` json:"id" form:"id" gorm:"primaryKey;autoIncrement" ` // Unique identifier
UserId int ` json:"-" ` // Associated user ID
Up int64 ` json:"up" form:"up" ` // Upload traffic in bytes
Down int64 ` json:"down" form:"down" ` // Download traffic in bytes
Total int64 ` json:"total" form:"total" ` // Total traffic limit in bytes
AllTime int64 ` json:"allTime" form:"allTime" gorm:"default:0" ` // All-time traffic usage
Remark string ` json:"remark" form:"remark" ` // Human-readable remark
Enable bool ` json:"enable" form:"enable" gorm:"index:idx_enable_traffic_reset,priority:1" ` // Whether the inbound is enabled
ExpiryTime int64 ` json:"expiryTime" form:"expiryTime" ` // Expiration timestamp
TrafficReset string ` json:"trafficReset" form:"trafficReset" gorm:"default:never;index:idx_enable_traffic_reset,priority:2" ` // Traffic reset schedule
LastTrafficResetTime int64 ` json:"lastTrafficResetTime" form:"lastTrafficResetTime" gorm:"default:0" ` // Last traffic reset timestamp
ClientStats [ ] xray . ClientTraffic ` gorm:"foreignKey:InboundId;references:Id" json:"clientStats" form:"clientStats" ` // Client traffic statistics
2023-02-09 19:18:06 +00:00
2025-09-20 07:35:50 +00:00
// Xray configuration fields
2023-02-09 19:18:06 +00:00
Listen string ` json:"listen" form:"listen" `
2024-01-17 12:51:28 +00:00
Port int ` json:"port" form:"port" `
2023-02-09 19:18:06 +00:00
Protocol Protocol ` json:"protocol" form:"protocol" `
Settings string ` json:"settings" form:"settings" `
StreamSettings string ` json:"streamSettings" form:"streamSettings" `
Tag string ` json:"tag" form:"tag" gorm:"unique" `
Sniffing string ` json:"sniffing" form:"sniffing" `
2026-01-05 21:12:53 +00:00
NodeId * int ` json:"nodeId,omitempty" form:"-" gorm:"-" ` // Node ID (not stored in Inbound table, from mapping) - DEPRECATED: kept only for backward compatibility with old clients, use NodeIds instead
NodeIds [ ] int ` json:"nodeIds,omitempty" form:"-" gorm:"-" ` // Node IDs array (not stored in Inbound table, from mapping) - use this for multi-node support
2023-02-09 19:18:06 +00:00
}
2024-01-29 20:37:20 +00:00
2025-09-20 07:35:50 +00:00
// OutboundTraffics tracks traffic statistics for Xray outbound connections.
2024-01-29 20:37:20 +00:00
type OutboundTraffics struct {
Id int ` json:"id" form:"id" gorm:"primaryKey;autoIncrement" `
Tag string ` json:"tag" form:"tag" gorm:"unique" `
Up int64 ` json:"up" form:"up" gorm:"default:0" `
Down int64 ` json:"down" form:"down" gorm:"default:0" `
Total int64 ` json:"total" form:"total" gorm:"default:0" `
}
2025-09-20 07:35:50 +00:00
// InboundClientIps stores IP addresses associated with inbound clients for access control.
2023-02-28 19:54:29 +00:00
type InboundClientIps struct {
2023-04-09 19:43:18 +00:00
Id int ` json:"id" gorm:"primaryKey;autoIncrement" `
2023-02-28 19:54:29 +00:00
ClientEmail string ` json:"clientEmail" form:"clientEmail" gorm:"unique" `
2023-04-09 19:43:18 +00:00
Ips string ` json:"ips" form:"ips" `
2023-02-28 19:54:29 +00:00
}
2023-02-09 19:18:06 +00:00
2025-09-20 07:35:50 +00:00
// HistoryOfSeeders tracks which database seeders have been executed to prevent re-running.
2025-05-03 09:27:53 +00:00
type HistoryOfSeeders struct {
Id int ` json:"id" gorm:"primaryKey;autoIncrement" `
SeederName string ` json:"seederName" `
}
2025-09-20 07:35:50 +00:00
// GenXrayInboundConfig generates an Xray inbound configuration from the Inbound model.
2023-02-09 19:18:06 +00:00
func ( i * Inbound ) GenXrayInboundConfig ( ) * xray . InboundConfig {
listen := i . Listen
2026-01-09 19:22:33 +00:00
// Default to 0.0.0.0 (all interfaces) when listen is empty
// This ensures proper dual-stack IPv4/IPv6 binding in systems where bindv6only=0
if listen == "" {
listen = "0.0.0.0"
2023-02-09 19:18:06 +00:00
}
2026-01-09 19:22:33 +00:00
listen = fmt . Sprintf ( "\"%v\"" , listen )
2023-02-09 19:18:06 +00:00
return & xray . InboundConfig {
Listen : json_util . RawMessage ( listen ) ,
Port : i . Port ,
Protocol : string ( i . Protocol ) ,
Settings : json_util . RawMessage ( i . Settings ) ,
StreamSettings : json_util . RawMessage ( i . StreamSettings ) ,
Tag : i . Tag ,
Sniffing : json_util . RawMessage ( i . Sniffing ) ,
}
}
2025-09-20 07:35:50 +00:00
// Setting stores key-value configuration settings for the 3x-ui panel.
2023-02-09 19:18:06 +00:00
type Setting struct {
Id int ` json:"id" form:"id" gorm:"primaryKey;autoIncrement" `
Key string ` json:"key" form:"key" `
Value string ` json:"value" form:"value" `
}
2023-02-18 12:37:32 +00:00
2025-09-20 07:35:50 +00:00
// Client represents a client configuration for Xray inbounds with traffic limits and settings.
2023-02-09 19:18:06 +00:00
type Client struct {
2025-09-20 07:35:50 +00:00
ID string ` json:"id" ` // Unique client identifier
Security string ` json:"security" ` // Security method (e.g., "auto", "aes-128-gcm")
Password string ` json:"password" ` // Client password
Flow string ` json:"flow" ` // Flow control (XTLS)
Email string ` json:"email" ` // Client email identifier
LimitIP int ` json:"limitIp" ` // IP limit for this client
TotalGB int64 ` json:"totalGB" form:"totalGB" ` // Total traffic limit in GB
ExpiryTime int64 ` json:"expiryTime" form:"expiryTime" ` // Expiration timestamp
Enable bool ` json:"enable" form:"enable" ` // Whether the client is enabled
TgID int64 ` json:"tgId" form:"tgId" ` // Telegram user ID for notifications
SubID string ` json:"subId" form:"subId" ` // Subscription identifier
Comment string ` json:"comment" form:"comment" ` // Client comment
Reset int ` json:"reset" form:"reset" ` // Reset period in days
CreatedAt int64 ` json:"created_at,omitempty" ` // Creation timestamp
UpdatedAt int64 ` json:"updated_at,omitempty" ` // Last update timestamp
2023-02-18 12:37:32 +00:00
}
2026-01-05 21:12:53 +00:00
// Node represents a worker node in multi-node architecture.
type Node struct {
Id int ` json:"id" gorm:"primaryKey;autoIncrement" ` // Unique identifier
Name string ` json:"name" form:"name" ` // Node name/identifier
Address string ` json:"address" form:"address" ` // Node API address (e.g., "http://192.168.1.100:8080")
ApiKey string ` json:"apiKey" form:"apiKey" ` // API key for authentication
Status string ` json:"status" gorm:"default:unknown" ` // Status: online, offline, unknown
LastCheck int64 ` json:"lastCheck" gorm:"default:0" ` // Last health check timestamp
CreatedAt int64 ` json:"createdAt" gorm:"autoCreateTime" ` // Creation timestamp
UpdatedAt int64 ` json:"updatedAt" gorm:"autoUpdateTime" ` // Last update timestamp
}
// InboundNodeMapping maps inbounds to nodes in multi-node mode.
type InboundNodeMapping struct {
Id int ` json:"id" gorm:"primaryKey;autoIncrement" ` // Unique identifier
InboundId int ` json:"inboundId" form:"inboundId" gorm:"uniqueIndex:idx_inbound_node" ` // Inbound ID
NodeId int ` json:"nodeId" form:"nodeId" gorm:"uniqueIndex:idx_inbound_node" ` // Node ID
}