优化表结构,重构模型,重新实现基于白银网关的提取节点流程

This commit is contained in:
2025-11-24 18:44:06 +08:00
parent 9a574f55cb
commit cb2a963a37
142 changed files with 6528 additions and 5808 deletions

View File

@@ -1,26 +1,9 @@
package handlers
import (
"crypto/rand"
"encoding/base32"
"fmt"
"log/slog"
"platform/pkg/u"
auth2 "platform/web/auth"
"platform/web/core"
edge2 "platform/web/domains/edge"
proxy2 "platform/web/domains/proxy"
g "platform/web/globals"
"platform/web/globals/orm"
m "platform/web/models"
q "platform/web/queries"
"strings"
"time"
"github.com/gofiber/fiber/v2"
"gorm.io/gen/field"
"gorm.io/gorm/clause"
)
// region 报告上线
@@ -38,103 +21,106 @@ type ProxyReportOnlineResp struct {
}
func ProxyReportOnline(c *fiber.Ctx) (err error) {
// 检查接口权限
_, err = auth2.GetAuthCtx(c).PermitSecretClient()
if err != nil {
return err
}
// 验证请求参数
var req = new(ProxyReportOnlineReq)
err = g.Validator.Validate(c, req)
if err != nil {
return err
}
// 创建代理
var ip = c.Context().RemoteIP()
var secretBytes = make([]byte, 16)
if _, err := rand.Read(secretBytes); err != nil {
return err
}
var secret = base32.StdEncoding.
WithPadding(base32.NoPadding).
EncodeToString(secretBytes)
slog.Debug("生成随机密钥", "ip", ip, "secret", secret)
var proxy = &m.Proxy{
Name: req.Name,
Version: int32(req.Version),
Type: int32(proxy2.TypeSelfHosted),
Host: ip.String(),
Secret: &secret,
Status: 1,
}
err = q.Proxy.
Clauses(clause.OnConflict{
UpdateAll: true,
Columns: []clause.Column{
{Name: q.Proxy.Name.ColumnName().String()},
},
}).
Create(proxy)
if err != nil {
return err
}
// 获取边缘节点信息
data, err := q.Edge.Where(
q.Edge.ProxyID.Eq(proxy.ID),
).Find()
if err != nil {
return err
}
edges := make([]*ProxyEdge, len(data))
for i, edge := range data {
edges[i] = &ProxyEdge{
Id: edge.ID,
Port: edge.ProxyPort,
Prov: &edge.Prov,
City: &edge.City,
Isp: u.P(edge2.ISP(edge.Isp).String()),
Status: &edge.Status,
Loss: edge.Loss,
Rtt: edge.Rtt,
}
}
// 获取许可配置
channels, err := q.Channel.Where(
q.Channel.ProxyID.Eq(proxy.ID),
q.Channel.Expiration.Gt(orm.LocalDateTime(time.Now())),
).Find()
if err != nil {
return err
}
var permits = make([]*ProxyPermit, len(channels))
for i, channel := range channels {
if channel.EdgeID == nil {
return core.NewBizErr(fmt.Sprintf("权限解析异常通道缺少边缘节点ID %d", channel.ID))
}
permits[i] = &ProxyPermit{
Id: *channel.EdgeID,
Expire: time.Time(channel.Expiration),
Whitelists: u.P(strings.Split(u.Z(channel.Whitelists), ",")),
Username: channel.Username,
Password: channel.Password,
}
}
slog.Debug("注册转发服务", "ip", ip, "id", proxy.ID)
return c.JSON(&ProxyReportOnlineResp{
Id: proxy.ID,
Secret: secret,
Edges: edges,
Permits: permits,
return c.JSON(map[string]any{
"error": "接口暂不可用",
})
// // 检查接口权限
// _, err = auth2.GetAuthCtx(c).PermitSecretClient()
// if err != nil {
// return err
// }
// // 验证请求参数
// var req = new(ProxyReportOnlineReq)
// err = g.Validator.Validate(c, req)
// if err != nil {
// return err
// }
// // 创建代理
// var ip = c.Context().RemoteIP()
// var secretBytes = make([]byte, 16)
// if _, err := rand.Read(secretBytes); err != nil {
// return err
// }
// var secret = base32.StdEncoding.
// WithPadding(base32.NoPadding).
// EncodeToString(secretBytes)
// slog.Debug("生成随机密钥", "ip", ip, "secret", secret)
// var proxy = &m.Proxy{
// Mac: req.Name,
// Version: int32(req.Version),
// Type: m.ProxyTypeSelfHosted,
// IP: ip,
// Secret: &secret,
// Status: 1,
// }
// err = q.Proxy.
// Clauses(clause.OnConflict{
// UpdateAll: true,
// Columns: []clause.Column{
// {Name: q.Proxy.Mac.ColumnName().String()},
// },
// }).
// Create(proxy)
// if err != nil {
// return err
// }
// // 获取边缘节点信息
// data, err := q.Edge.Where(
// q.Edge.ProxyID.Eq(proxy.ID),
// ).Find()
// if err != nil {
// return err
// }
// edges := make([]*ProxyEdge, len(data))
// for i, edge := range data {
// edges[i] = &ProxyEdge{
// Id: edge.ID,
// Port: edge.ProxyPort,
// Prov: &edge.Prov,
// City: &edge.City,
// Isp: u.P(edge2.ISP(edge.Isp).String()),
// Status: &edge.Status,
// Loss: edge.Loss,
// Rtt: edge.Rtt,
// }
// }
// // 获取许可配置
// channels, err := q.Channel.Where(
// q.Channel.ProxyID.Eq(proxy.ID),
// q.Channel.Expiration.Gt(orm.LocalDateTime(time.Now())),
// ).Find()
// if err != nil {
// return err
// }
// var permits = make([]*ProxyPermit, len(channels))
// for i, channel := range channels {
// if channel.EdgeID == nil {
// return core.NewBizErr(fmt.Sprintf("权限解析异常通道缺少边缘节点ID %d", channel.ID))
// }
// permits[i] = &ProxyPermit{
// Id: *channel.EdgeID,
// Expire: time.Time(channel.Expiration),
// Whitelists: u.P(strings.Split(u.Z(channel.Whitelists), ",")),
// Username: channel.Username,
// Password: channel.Password,
// }
// }
// slog.Debug("注册转发服务", "ip", ip, "id", proxy.ID)
// return c.JSON(&ProxyReportOnlineResp{
// Id: proxy.ID,
// Secret: secret,
// Edges: edges,
// Permits: permits,
// })
}
// endregion
@@ -146,36 +132,40 @@ type ProxyReportOfflineReq struct {
}
func ProxyReportOffline(c *fiber.Ctx) (err error) {
// 检查接口权限
_, err = auth2.GetAuthCtx(c).PermitSecretClient()
if err != nil {
return err
}
return c.JSON(map[string]any{
"error": "接口暂不可用",
})
// 验证请求参数
var req = new(ProxyReportOfflineReq)
err = g.Validator.Validate(c, req)
if err != nil {
return err
}
// // 检查接口权限
// _, err = auth2.GetAuthCtx(c).PermitSecretClient()
// if err != nil {
// return err
// }
// 下线转发服务
_, err = q.Proxy.
Where(q.Proxy.ID.Eq(req.Id)).
UpdateSimple(q.Proxy.Status.Value(0))
if err != nil {
return err
}
// // 验证请求参数
// var req = new(ProxyReportOfflineReq)
// err = g.Validator.Validate(c, req)
// if err != nil {
// return err
// }
// 下线所有相关的边缘节点
_, err = q.Edge.
Where(q.Edge.ProxyID.Eq(req.Id)).
UpdateSimple(q.Edge.Status.Value(0))
if err != nil {
return err
}
// // 下线转发服务
// _, err = q.Proxy.
// Where(q.Proxy.ID.Eq(req.Id)).
// UpdateSimple(q.Proxy.Status.Value(0))
// if err != nil {
// return err
// }
return nil
// // 下线所有相关的边缘节点
// _, err = q.Edge.
// Where(q.Edge.ProxyID.Eq(req.Id)).
// UpdateSimple(q.Edge.Status.Value(0))
// if err != nil {
// return err
// }
// return nil
}
// endregion
@@ -188,157 +178,161 @@ type ProxyReportUpdateReq struct {
}
func ProxyReportUpdate(c *fiber.Ctx) (err error) {
// 检查接口权限
_, err = auth2.GetAuthCtx(c).PermitSecretClient()
if err != nil {
return err
}
// 验证请求参数
var req = new(ProxyReportUpdateReq)
err = g.Validator.Validate(c, req)
if err != nil {
return err
}
// 更新节点信息
var idsActive = make([]int32, 0, len(req.Edges))
var idsInactive = make([]int32, 0, len(req.Edges))
var idsIspUnknown = make([]int32, 0, len(req.Edges))
var idsIspTelecom = make([]int32, 0, len(req.Edges))
var idsIspUnicom = make([]int32, 0, len(req.Edges))
var idsIspMobile = make([]int32, 0, len(req.Edges))
var otherEdges = make([]*ProxyEdge, 0, len(req.Edges))
for _, edge := range req.Edges {
// 检查更新ISP
if edge.Isp != nil {
switch edge2.ISPFromStr(*edge.Isp) {
case edge2.IspUnknown:
idsIspUnknown = append(idsIspUnknown, edge.Id)
case edge2.IspChinaTelecom:
idsIspTelecom = append(idsIspTelecom, edge.Id)
case edge2.IspChinaUnicom:
idsIspUnicom = append(idsIspUnicom, edge.Id)
case edge2.IspChinaMobile:
idsIspMobile = append(idsIspMobile, edge.Id)
}
}
// 检查更新状态
if edge.Status != nil {
if *edge.Status == 1 {
idsActive = append(idsActive, edge.Id)
} else {
idsInactive = append(idsInactive, edge.Id)
}
}
// 无法分类更新
if edge.Host != nil || edge.Port != nil || edge.Prov != nil || edge.City != nil {
otherEdges = append(otherEdges, edge)
continue
}
}
slog.Debug("更新边缘节点信息",
"active", len(idsActive),
"inactive", len(idsInactive),
"isp_unknown", len(idsIspUnknown),
"isp_telecom", len(idsIspTelecom),
"isp_unicom", len(idsIspUnicom),
"isp_mobile", len(idsIspMobile),
"other_edges", len(otherEdges),
)
err = q.Q.Transaction(func(q *q.Query) error {
// 更新边缘节点状态
if len(idsActive) > 0 {
_, err = q.Edge.Debug().
Where(q.Edge.ID.In(idsActive...)).
UpdateSimple(q.Edge.Status.Value(1))
if err != nil {
return err
}
}
if len(idsInactive) > 0 {
_, err = q.Edge.Debug().
Where(q.Edge.ID.In(idsInactive...)).
UpdateSimple(q.Edge.Status.Value(0))
if err != nil {
return err
}
}
// 更新边缘节点ISP
if len(idsIspUnknown) > 0 {
_, err = q.Edge.Debug().
Where(q.Edge.ID.In(idsIspUnknown...)).
UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspUnknown)))
if err != nil {
return err
}
}
if len(idsIspTelecom) > 0 {
_, err = q.Edge.Debug().
Where(q.Edge.ID.In(idsIspTelecom...)).
UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspChinaTelecom)))
if err != nil {
return err
}
}
if len(idsIspUnicom) > 0 {
_, err = q.Edge.Debug().
Where(q.Edge.ID.In(idsIspUnicom...)).
UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspChinaUnicom)))
if err != nil {
return err
}
}
if len(idsIspMobile) > 0 {
_, err = q.Edge.Debug().
Where(q.Edge.ID.In(idsIspMobile...)).
UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspChinaMobile)))
if err != nil {
return err
}
}
// 更新其他边缘节点信息
for _, edge := range otherEdges {
do := q.Edge.Debug().Where(q.Edge.ID.Eq(edge.Id))
var assigns = make([]field.AssignExpr, 0, 5)
if edge.Host != nil {
assigns = append(assigns, q.Edge.Host.Value(*edge.Host))
}
if edge.Port != nil {
assigns = append(assigns, q.Edge.ProxyPort.Value(*edge.Port))
}
if edge.Prov != nil {
assigns = append(assigns, q.Edge.Prov.Value(*edge.Prov))
}
if edge.City != nil {
assigns = append(assigns, q.Edge.City.Value(*edge.City))
}
// 更新边缘节点
_, err := do.UpdateSimple(assigns...)
if err != nil {
return fmt.Errorf("更新边缘节点 %d 失败: %w", edge.Id, err)
}
}
return nil
return c.JSON(map[string]any{
"error": "接口暂不可用",
})
if err != nil {
return err
}
return nil
// // 检查接口权限
// _, err = auth2.GetAuthCtx(c).PermitSecretClient()
// if err != nil {
// return err
// }
// // 验证请求参数
// var req = new(ProxyReportUpdateReq)
// err = g.Validator.Validate(c, req)
// if err != nil {
// return err
// }
// // 更新节点信息
// var idsActive = make([]int32, 0, len(req.Edges))
// var idsInactive = make([]int32, 0, len(req.Edges))
// var idsIspUnknown = make([]int32, 0, len(req.Edges))
// var idsIspTelecom = make([]int32, 0, len(req.Edges))
// var idsIspUnicom = make([]int32, 0, len(req.Edges))
// var idsIspMobile = make([]int32, 0, len(req.Edges))
// var otherEdges = make([]*ProxyEdge, 0, len(req.Edges))
// for _, edge := range req.Edges {
// // 检查更新ISP
// if edge.Isp != nil {
// switch edge2.ISPFromStr(*edge.Isp) {
// case edge2.IspUnknown:
// idsIspUnknown = append(idsIspUnknown, edge.Id)
// case edge2.IspChinaTelecom:
// idsIspTelecom = append(idsIspTelecom, edge.Id)
// case edge2.IspChinaUnicom:
// idsIspUnicom = append(idsIspUnicom, edge.Id)
// case edge2.IspChinaMobile:
// idsIspMobile = append(idsIspMobile, edge.Id)
// }
// }
// // 检查更新状态
// if edge.Status != nil {
// if *edge.Status == 1 {
// idsActive = append(idsActive, edge.Id)
// } else {
// idsInactive = append(idsInactive, edge.Id)
// }
// }
// // 无法分类更新
// if edge.Host != nil || edge.Port != nil || edge.Prov != nil || edge.City != nil {
// otherEdges = append(otherEdges, edge)
// continue
// }
// }
// slog.Debug("更新边缘节点信息",
// "active", len(idsActive),
// "inactive", len(idsInactive),
// "isp_unknown", len(idsIspUnknown),
// "isp_telecom", len(idsIspTelecom),
// "isp_unicom", len(idsIspUnicom),
// "isp_mobile", len(idsIspMobile),
// "other_edges", len(otherEdges),
// )
// err = q.Q.Transaction(func(q *q.Query) error {
// // 更新边缘节点状态
// if len(idsActive) > 0 {
// _, err = q.Edge.Debug().
// Where(q.Edge.ID.In(idsActive...)).
// UpdateSimple(q.Edge.Status.Value(1))
// if err != nil {
// return err
// }
// }
// if len(idsInactive) > 0 {
// _, err = q.Edge.Debug().
// Where(q.Edge.ID.In(idsInactive...)).
// UpdateSimple(q.Edge.Status.Value(0))
// if err != nil {
// return err
// }
// }
// // 更新边缘节点ISP
// if len(idsIspUnknown) > 0 {
// _, err = q.Edge.Debug().
// Where(q.Edge.ID.In(idsIspUnknown...)).
// UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspUnknown)))
// if err != nil {
// return err
// }
// }
// if len(idsIspTelecom) > 0 {
// _, err = q.Edge.Debug().
// Where(q.Edge.ID.In(idsIspTelecom...)).
// UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspChinaTelecom)))
// if err != nil {
// return err
// }
// }
// if len(idsIspUnicom) > 0 {
// _, err = q.Edge.Debug().
// Where(q.Edge.ID.In(idsIspUnicom...)).
// UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspChinaUnicom)))
// if err != nil {
// return err
// }
// }
// if len(idsIspMobile) > 0 {
// _, err = q.Edge.Debug().
// Where(q.Edge.ID.In(idsIspMobile...)).
// UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspChinaMobile)))
// if err != nil {
// return err
// }
// }
// // 更新其他边缘节点信息
// for _, edge := range otherEdges {
// do := q.Edge.Debug().Where(q.Edge.ID.Eq(edge.Id))
// var assigns = make([]field.AssignExpr, 0, 5)
// if edge.Host != nil {
// assigns = append(assigns, q.Edge.Host.Value(*edge.Host))
// }
// if edge.Port != nil {
// assigns = append(assigns, q.Edge.ProxyPort.Value(*edge.Port))
// }
// if edge.Prov != nil {
// assigns = append(assigns, q.Edge.Prov.Value(*edge.Prov))
// }
// if edge.City != nil {
// assigns = append(assigns, q.Edge.City.Value(*edge.City))
// }
// // 更新边缘节点
// _, err := do.UpdateSimple(assigns...)
// if err != nil {
// return fmt.Errorf("更新边缘节点 %d 失败: %w", edge.Id, err)
// }
// }
// return nil
// })
// if err != nil {
// return err
// }
// return nil
}
// endregion