model.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // Package model defines the database models and data structures used by the 3x-ui panel.
  2. package model
  3. import (
  4. "fmt"
  5. "github.com/mhsanaei/3x-ui/v3/util/json_util"
  6. "github.com/mhsanaei/3x-ui/v3/xray"
  7. )
  8. // Protocol represents the protocol type for Xray inbounds.
  9. type Protocol string
  10. // Protocol constants for different Xray inbound protocols
  11. const (
  12. VMESS Protocol = "vmess"
  13. VLESS Protocol = "vless"
  14. Tunnel Protocol = "tunnel"
  15. HTTP Protocol = "http"
  16. Trojan Protocol = "trojan"
  17. Shadowsocks Protocol = "shadowsocks"
  18. Mixed Protocol = "mixed"
  19. WireGuard Protocol = "wireguard"
  20. Hysteria Protocol = "hysteria"
  21. Hysteria2 Protocol = "hysteria2"
  22. )
  23. // IsHysteria returns true for both "hysteria" and "hysteria2".
  24. // Use instead of a bare ==model.Hysteria check: a v2 inbound stored
  25. // with the literal v2 string would otherwise fall through (#4081).
  26. func IsHysteria(p Protocol) bool {
  27. return p == Hysteria || p == Hysteria2
  28. }
  29. // User represents a user account in the 3x-ui panel.
  30. type User struct {
  31. Id int `json:"id" gorm:"primaryKey;autoIncrement"`
  32. Username string `json:"username"`
  33. Password string `json:"password"`
  34. LoginEpoch int64 `json:"-" gorm:"default:0"`
  35. }
  36. // Inbound represents an Xray inbound configuration with traffic statistics and settings.
  37. type Inbound struct {
  38. Id int `json:"id" form:"id" gorm:"primaryKey;autoIncrement"` // Unique identifier
  39. UserId int `json:"-"` // Associated user ID
  40. Up int64 `json:"up" form:"up"` // Upload traffic in bytes
  41. Down int64 `json:"down" form:"down"` // Download traffic in bytes
  42. Total int64 `json:"total" form:"total"` // Total traffic limit in bytes
  43. AllTime int64 `json:"allTime" form:"allTime" gorm:"default:0"` // All-time traffic usage
  44. Remark string `json:"remark" form:"remark"` // Human-readable remark
  45. Enable bool `json:"enable" form:"enable" gorm:"index:idx_enable_traffic_reset,priority:1"` // Whether the inbound is enabled
  46. ExpiryTime int64 `json:"expiryTime" form:"expiryTime"` // Expiration timestamp
  47. TrafficReset string `json:"trafficReset" form:"trafficReset" gorm:"default:never;index:idx_enable_traffic_reset,priority:2"` // Traffic reset schedule
  48. LastTrafficResetTime int64 `json:"lastTrafficResetTime" form:"lastTrafficResetTime" gorm:"default:0"` // Last traffic reset timestamp
  49. ClientStats []xray.ClientTraffic `gorm:"foreignKey:InboundId;references:Id" json:"clientStats" form:"clientStats"` // Client traffic statistics
  50. // Xray configuration fields
  51. Listen string `json:"listen" form:"listen"`
  52. Port int `json:"port" form:"port"`
  53. Protocol Protocol `json:"protocol" form:"protocol"`
  54. Settings string `json:"settings" form:"settings"`
  55. StreamSettings string `json:"streamSettings" form:"streamSettings"`
  56. Tag string `json:"tag" form:"tag" gorm:"unique"`
  57. Sniffing string `json:"sniffing" form:"sniffing"`
  58. NodeID *int `json:"nodeId,omitempty" form:"nodeId" gorm:"index"`
  59. }
  60. // OutboundTraffics tracks traffic statistics for Xray outbound connections.
  61. type OutboundTraffics struct {
  62. Id int `json:"id" form:"id" gorm:"primaryKey;autoIncrement"`
  63. Tag string `json:"tag" form:"tag" gorm:"unique"`
  64. Up int64 `json:"up" form:"up" gorm:"default:0"`
  65. Down int64 `json:"down" form:"down" gorm:"default:0"`
  66. Total int64 `json:"total" form:"total" gorm:"default:0"`
  67. }
  68. // InboundClientIps stores IP addresses associated with inbound clients for access control.
  69. type InboundClientIps struct {
  70. Id int `json:"id" gorm:"primaryKey;autoIncrement"`
  71. ClientEmail string `json:"clientEmail" form:"clientEmail" gorm:"unique"`
  72. Ips string `json:"ips" form:"ips"`
  73. }
  74. // HistoryOfSeeders tracks which database seeders have been executed to prevent re-running.
  75. type HistoryOfSeeders struct {
  76. Id int `json:"id" gorm:"primaryKey;autoIncrement"`
  77. SeederName string `json:"seederName"`
  78. }
  79. // GenXrayInboundConfig generates an Xray inbound configuration from the Inbound model.
  80. func (i *Inbound) GenXrayInboundConfig() *xray.InboundConfig {
  81. listen := i.Listen
  82. // Default to 0.0.0.0 (all interfaces) when listen is empty
  83. // This ensures proper dual-stack IPv4/IPv6 binding in systems where bindv6only=0
  84. if listen == "" {
  85. listen = "0.0.0.0"
  86. }
  87. listen = fmt.Sprintf("\"%v\"", listen)
  88. return &xray.InboundConfig{
  89. Listen: json_util.RawMessage(listen),
  90. Port: i.Port,
  91. Protocol: string(i.Protocol),
  92. Settings: json_util.RawMessage(i.Settings),
  93. StreamSettings: json_util.RawMessage(i.StreamSettings),
  94. Tag: i.Tag,
  95. Sniffing: json_util.RawMessage(i.Sniffing),
  96. }
  97. }
  98. // Setting stores key-value configuration settings for the 3x-ui panel.
  99. type Setting struct {
  100. Id int `json:"id" form:"id" gorm:"primaryKey;autoIncrement"`
  101. Key string `json:"key" form:"key"`
  102. Value string `json:"value" form:"value"`
  103. }
  104. // Node represents a remote 3x-ui panel registered with the central panel.
  105. // The central panel polls each node's existing /panel/api/server/status
  106. // endpoint over HTTP using the per-node ApiToken to populate the runtime
  107. // status fields below.
  108. type Node struct {
  109. Id int `json:"id" form:"id" gorm:"primaryKey;autoIncrement"`
  110. Name string `json:"name" form:"name" gorm:"uniqueIndex"`
  111. Remark string `json:"remark" form:"remark"`
  112. Scheme string `json:"scheme" form:"scheme"`
  113. Address string `json:"address" form:"address"`
  114. Port int `json:"port" form:"port"`
  115. BasePath string `json:"basePath" form:"basePath"`
  116. ApiToken string `json:"apiToken" form:"apiToken"`
  117. Enable bool `json:"enable" form:"enable" gorm:"default:true"`
  118. AllowPrivateAddress bool `json:"allowPrivateAddress" form:"allowPrivateAddress" gorm:"default:false"`
  119. // Heartbeat-updated fields. UpdatedAt advances on every probe even when
  120. // the row is otherwise unchanged so the UI's "last seen" tooltip is
  121. // truthful without us having to read LastHeartbeat separately.
  122. Status string `json:"status" gorm:"default:unknown"` // online|offline|unknown
  123. LastHeartbeat int64 `json:"lastHeartbeat"` // unix seconds, 0 = never
  124. LatencyMs int `json:"latencyMs"`
  125. XrayVersion string `json:"xrayVersion"`
  126. CpuPct float64 `json:"cpuPct"`
  127. MemPct float64 `json:"memPct"`
  128. UptimeSecs uint64 `json:"uptimeSecs"`
  129. LastError string `json:"lastError"`
  130. CreatedAt int64 `json:"createdAt" gorm:"autoCreateTime"`
  131. UpdatedAt int64 `json:"updatedAt" gorm:"autoUpdateTime"`
  132. }
  133. type CustomGeoResource struct {
  134. Id int `json:"id" gorm:"primaryKey;autoIncrement"`
  135. Type string `json:"type" gorm:"not null;uniqueIndex:idx_custom_geo_type_alias;column:geo_type"`
  136. Alias string `json:"alias" gorm:"not null;uniqueIndex:idx_custom_geo_type_alias"`
  137. Url string `json:"url" gorm:"not null"`
  138. LocalPath string `json:"localPath" gorm:"column:local_path"`
  139. LastUpdatedAt int64 `json:"lastUpdatedAt" gorm:"default:0;column:last_updated_at"`
  140. LastModified string `json:"lastModified" gorm:"column:last_modified"`
  141. CreatedAt int64 `json:"createdAt" gorm:"autoCreateTime;column:created_at"`
  142. UpdatedAt int64 `json:"updatedAt" gorm:"autoUpdateTime;column:updated_at"`
  143. }
  144. type ClientReverse struct {
  145. Tag string `json:"tag"`
  146. }
  147. // Client represents a client configuration for Xray inbounds with traffic limits and settings.
  148. type Client struct {
  149. ID string `json:"id,omitempty"` // Unique client identifier
  150. Security string `json:"security"` // Security method (e.g., "auto", "aes-128-gcm")
  151. Password string `json:"password,omitempty"` // Client password
  152. Flow string `json:"flow,omitempty"` // Flow control (XTLS)
  153. Reverse *ClientReverse `json:"reverse,omitempty"` // VLESS simple reverse proxy settings
  154. Auth string `json:"auth,omitempty"` // Auth password (Hysteria)
  155. Email string `json:"email"` // Client email identifier
  156. LimitIP int `json:"limitIp"` // IP limit for this client
  157. TotalGB int64 `json:"totalGB" form:"totalGB"` // Total traffic limit in GB
  158. ExpiryTime int64 `json:"expiryTime" form:"expiryTime"` // Expiration timestamp
  159. Enable bool `json:"enable" form:"enable"` // Whether the client is enabled
  160. TgID int64 `json:"tgId" form:"tgId"` // Telegram user ID for notifications
  161. SubID string `json:"subId" form:"subId"` // Subscription identifier
  162. Comment string `json:"comment" form:"comment"` // Client comment
  163. Reset int `json:"reset" form:"reset"` // Reset period in days
  164. CreatedAt int64 `json:"created_at,omitempty"` // Creation timestamp
  165. UpdatedAt int64 `json:"updated_at,omitempty"` // Last update timestamp
  166. }