228 lines
6.3 KiB
Go
228 lines
6.3 KiB
Go
package models
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type User struct {
|
|
ID uuid.UUID `json:"id"`
|
|
Email string `json:"email"`
|
|
PasswordHash string `json:"-"`
|
|
Name string `json:"name"`
|
|
Role string `json:"role"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
}
|
|
|
|
type Protocol struct {
|
|
ID uuid.UUID `json:"id"`
|
|
Code string `json:"code"`
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Port int `json:"port"`
|
|
Enabled bool `json:"enabled"`
|
|
SortOrder int `json:"sort_order"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
|
|
InstalledOn []NodeProtoRef `json:"installed_on,omitempty"`
|
|
EnabledOn []NodeProtoRef `json:"enabled_on,omitempty"`
|
|
}
|
|
|
|
type NodeProtoRef struct {
|
|
NodeID uuid.UUID `json:"node_id"`
|
|
NodeName string `json:"node_name"`
|
|
Host string `json:"host"`
|
|
Status NodeStatus `json:"status"`
|
|
}
|
|
|
|
type NodeProtocol struct {
|
|
NodeID uuid.UUID `json:"node_id"`
|
|
ProtocolID uuid.UUID `json:"protocol_id"`
|
|
ProtocolCode string `json:"protocol_code"`
|
|
ProtocolName string `json:"protocol_name"`
|
|
Port int `json:"port"`
|
|
Installed bool `json:"installed"`
|
|
Enabled bool `json:"enabled"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
}
|
|
|
|
func (p Protocol) EnabledLabel() string {
|
|
if p.Enabled {
|
|
return "Включён"
|
|
}
|
|
return "Выключен"
|
|
}
|
|
|
|
func (p Protocol) InstallCount() int { return len(p.InstalledOn) }
|
|
func (p Protocol) ActiveCount() int { return len(p.EnabledOn) }
|
|
|
|
|
|
type NodeStatus string
|
|
|
|
const (
|
|
NodeStatusPending NodeStatus = "pending"
|
|
NodeStatusInstalling NodeStatus = "installing"
|
|
NodeStatusOnline NodeStatus = "online"
|
|
NodeStatusOffline NodeStatus = "offline"
|
|
NodeStatusError NodeStatus = "error"
|
|
)
|
|
|
|
type Node struct {
|
|
ID uuid.UUID `json:"id"`
|
|
Name string `json:"name"`
|
|
Host string `json:"host"`
|
|
SSHPort int `json:"ssh_port"`
|
|
SSHUser string `json:"ssh_user"`
|
|
SSHAuthType string `json:"ssh_auth_type"` // password | key
|
|
SSHSecretEnc string `json:"-"`
|
|
NodePort int `json:"node_port"`
|
|
SecretKey string `json:"-"`
|
|
ProfileID *uuid.UUID `json:"profile_id,omitempty"`
|
|
ProfileName string `json:"profile_name,omitempty"`
|
|
Status NodeStatus `json:"status"`
|
|
InstallMode string `json:"install_mode"` // auto | manual
|
|
LastError string `json:"last_error"`
|
|
InstallLog string `json:"install_log"`
|
|
RuntimeLog string `json:"runtime_log"`
|
|
AgentVersion string `json:"agent_version"`
|
|
LastSeenAt *time.Time `json:"last_seen_at,omitempty"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
}
|
|
|
|
func (n Node) StatusLabel() string {
|
|
switch n.Status {
|
|
case NodeStatusOnline:
|
|
return "Online"
|
|
case NodeStatusInstalling:
|
|
return "Установка"
|
|
case NodeStatusOffline:
|
|
return "Offline"
|
|
case NodeStatusError:
|
|
return "Ошибка"
|
|
default:
|
|
return "Ожидание"
|
|
}
|
|
}
|
|
|
|
func (n Node) ProfileIDString() string {
|
|
if n.ProfileID == nil {
|
|
return ""
|
|
}
|
|
return n.ProfileID.String()
|
|
}
|
|
|
|
type ConfigProfile struct {
|
|
ID uuid.UUID `json:"id"`
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
|
|
InboundCount int `json:"inbound_count"`
|
|
NodeCount int `json:"node_count"`
|
|
Inbounds []Inbound `json:"inbounds,omitempty"`
|
|
}
|
|
|
|
type Inbound struct {
|
|
ID uuid.UUID `json:"id"`
|
|
ProfileID uuid.UUID `json:"profile_id"`
|
|
Tag string `json:"tag"`
|
|
ProtocolID uuid.UUID `json:"protocol_id"`
|
|
ProtocolCode string `json:"protocol_code"`
|
|
ProtocolName string `json:"protocol_name"`
|
|
Port int `json:"port"`
|
|
Network string `json:"network"` // tcp, ws, grpc, quic, udp
|
|
Security string `json:"security"` // none, tls, reality
|
|
Listen string `json:"listen"`
|
|
Enabled bool `json:"enabled"` // definition enabled in profile
|
|
SortOrder int `json:"sort_order"`
|
|
Remark string `json:"remark"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
|
|
// Per-node activation when listed under a node
|
|
NodeEnabled bool `json:"node_enabled,omitempty"`
|
|
}
|
|
|
|
type DashboardStats struct {
|
|
ProtocolsTotal int
|
|
ProtocolsEnabled int
|
|
AdminsTotal int
|
|
NodesTotal int
|
|
NodesOnline int
|
|
ProfilesTotal int
|
|
ClientsTotal int
|
|
ClientsActive int
|
|
}
|
|
|
|
type ClientStatus string
|
|
|
|
const (
|
|
ClientStatusActive ClientStatus = "active"
|
|
ClientStatusDisabled ClientStatus = "disabled"
|
|
ClientStatusExpired ClientStatus = "expired"
|
|
)
|
|
|
|
type Client struct {
|
|
ID uuid.UUID `json:"id"`
|
|
Username string `json:"username"`
|
|
Email string `json:"email"`
|
|
UUID uuid.UUID `json:"uuid"` // VLESS/VMess user id
|
|
Status ClientStatus `json:"status"`
|
|
TrafficLimitBytes int64 `json:"traffic_limit_bytes"` // 0 = unlimited
|
|
TrafficUsedBytes int64 `json:"traffic_used_bytes"`
|
|
ExpireAt *time.Time `json:"expire_at,omitempty"`
|
|
SubToken string `json:"sub_token"`
|
|
Note string `json:"note"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
|
|
InboundIDs []uuid.UUID `json:"inbound_ids,omitempty"`
|
|
InboundCount int `json:"inbound_count"`
|
|
}
|
|
|
|
func (c Client) StatusLabel() string {
|
|
switch c.Status {
|
|
case ClientStatusActive:
|
|
return "Активен"
|
|
case ClientStatusDisabled:
|
|
return "Отключён"
|
|
case ClientStatusExpired:
|
|
return "Истёк"
|
|
default:
|
|
return string(c.Status)
|
|
}
|
|
}
|
|
|
|
func (c Client) IsActive() bool {
|
|
if c.Status != ClientStatusActive {
|
|
return false
|
|
}
|
|
if c.ExpireAt != nil && time.Now().After(*c.ExpireAt) {
|
|
return false
|
|
}
|
|
if c.TrafficLimitBytes > 0 && c.TrafficUsedBytes >= c.TrafficLimitBytes {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (c Client) TrafficLimitGB() float64 {
|
|
if c.TrafficLimitBytes <= 0 {
|
|
return 0
|
|
}
|
|
return float64(c.TrafficLimitBytes) / (1024 * 1024 * 1024)
|
|
}
|
|
|
|
func (c Client) HasInbound(id uuid.UUID) bool {
|
|
for _, x := range c.InboundIDs {
|
|
if x == id {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|