Apply inbounds on nodes via Xray with Reality settings and client sync.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/lib/pq"
|
||||
|
||||
"github.com/orohi/vpn-panel/internal/models"
|
||||
)
|
||||
@@ -310,15 +311,45 @@ ORDER BY p.sort_order`, nodeID)
|
||||
if !in.NodeEnabled || !in.Enabled {
|
||||
continue
|
||||
}
|
||||
clients, err := ListActiveClientsForInbound(db, in.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var clientList []map[string]any
|
||||
for _, c := range clients {
|
||||
clientList = append(clientList, map[string]any{
|
||||
"id": c.ID.String(),
|
||||
"uuid": c.UUID.String(),
|
||||
"email": c.Email,
|
||||
"username": c.Username,
|
||||
})
|
||||
}
|
||||
if clientList == nil {
|
||||
clientList = []map[string]any{}
|
||||
}
|
||||
inList = append(inList, map[string]any{
|
||||
"id": in.ID.String(),
|
||||
"tag": in.Tag,
|
||||
"protocol": in.ProtocolCode,
|
||||
"port": in.Port,
|
||||
"network": in.Network,
|
||||
"security": in.Security,
|
||||
"listen": in.Listen,
|
||||
"remark": in.Remark,
|
||||
"id": in.ID.String(),
|
||||
"tag": in.Tag,
|
||||
"protocol": in.ProtocolCode,
|
||||
"port": in.Port,
|
||||
"network": in.Network,
|
||||
"security": in.Security,
|
||||
"listen": in.Listen,
|
||||
"remark": in.Remark,
|
||||
"path": in.Path,
|
||||
"host": in.Host,
|
||||
"sni": in.SNI,
|
||||
"fingerprint": in.Fingerprint,
|
||||
"flow": in.Flow,
|
||||
"alpn": in.ALPN,
|
||||
"reality_dest": in.RealityDest,
|
||||
"reality_server_names": in.RealityServerNames,
|
||||
"reality_private_key": in.RealityPrivateKey,
|
||||
"reality_public_key": in.RealityPublicKey,
|
||||
"reality_short_id": in.RealityShortID,
|
||||
"ss_method": in.SSMethod,
|
||||
"password": in.Password,
|
||||
"clients": clientList,
|
||||
})
|
||||
}
|
||||
if inList == nil {
|
||||
@@ -329,3 +360,60 @@ ORDER BY p.sort_order`, nodeID)
|
||||
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
// ListActiveClientsForInbound returns active non-expired clients assigned to an inbound.
|
||||
func ListActiveClientsForInbound(db *sql.DB, inboundID uuid.UUID) ([]models.Client, error) {
|
||||
rows, err := db.Query(`
|
||||
SELECT c.id, c.username, c.email, c.uuid, c.status,
|
||||
c.traffic_limit_bytes, c.traffic_used_bytes, c.expire_at, c.sub_token, c.note,
|
||||
c.created_at, c.updated_at, 0
|
||||
FROM clients c
|
||||
JOIN client_inbounds ci ON ci.client_id = c.id AND ci.inbound_id = $1
|
||||
WHERE c.status = 'active'
|
||||
AND (c.expire_at IS NULL OR c.expire_at > NOW())
|
||||
AND (c.traffic_limit_bytes = 0 OR c.traffic_used_bytes < c.traffic_limit_bytes)
|
||||
ORDER BY c.username ASC`, inboundID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var list []models.Client
|
||||
for rows.Next() {
|
||||
c, err := scanClient(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list = append(list, *c)
|
||||
}
|
||||
return list, rows.Err()
|
||||
}
|
||||
|
||||
// ListOnlineNodesByInboundIDs returns online nodes that have any of the inbounds enabled.
|
||||
func ListOnlineNodesByInboundIDs(db *sql.DB, inboundIDs []uuid.UUID) ([]models.Node, error) {
|
||||
if len(inboundIDs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
ids := make([]string, len(inboundIDs))
|
||||
for i, id := range inboundIDs {
|
||||
ids[i] = id.String()
|
||||
}
|
||||
rows, err := db.Query(`
|
||||
SELECT DISTINCT `+nodeColumns+`
|
||||
FROM nodes n
|
||||
JOIN node_inbounds ni ON ni.node_id = n.id AND ni.enabled = TRUE
|
||||
LEFT JOIN config_profiles cp ON cp.id = n.profile_id
|
||||
WHERE n.status = 'online' AND ni.inbound_id = ANY($1)`, pq.Array(ids))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var list []models.Node
|
||||
for rows.Next() {
|
||||
n, err := scanNode(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list = append(list, *n)
|
||||
}
|
||||
return list, rows.Err()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user