package handlers import ( "crypto/rand" "encoding/base32" "github.com/gofiber/fiber/v2" "log/slog" "platform/pkg/u" auth2 "platform/web/auth" "platform/web/core" proxy2 "platform/web/domains/proxy" g "platform/web/globals" "platform/web/globals/orm" m "platform/web/models" q "platform/web/queries" "strings" "time" "gorm.io/gorm/clause" ) // region OnlineProxy type OnlineProxyReq struct { Name string `json:"name" validate:"required"` Version int `json:"version" validate:"required"` } type OnlineProxyResp struct { Id int32 `json:"id"` Secret string `json:"secret"` Permits []ProxyPermit `json:"permits"` } func OnlineProxy(c *fiber.Ctx) (err error) { // 检查接口权限 _, err = auth2.NewProtect(c).Payload( auth2.PayloadInternalServer, ).Do() if err != nil { return err } // 验证请求参数 var req = new(OnlineProxyReq) 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 } 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 []ProxyPermit for _, channel := range channels { if channel.EdgeID == nil { return core.NewBizErr("通道未分配边缘节点") } permit := ProxyPermit{ Id: *channel.EdgeID, Expire: time.Time(channel.Expiration), Whitelists: u.P(strings.Split(u.Z(channel.Whitelists), ",")), Username: channel.Username, Password: channel.Password, } permits = append(permits, permit) } slog.Debug("注册转发服务", "ip", ip, "id", proxy.ID) return c.JSON(&OnlineProxyResp{ Id: proxy.ID, Secret: secret, Permits: permits, }) } // endregion // region OfflineProxy type OfflineProxyReq struct { Name string `json:"name" validate:"required"` } func OfflineProxy(c *fiber.Ctx) (err error) { // 检查接口权限 _, err = auth2.NewProtect(c).Payload( auth2.PayloadInternalServer, ).Do() if err != nil { return err } // 验证请求参数 var req = new(OfflineProxyReq) err = g.Validator.Validate(c, req) if err != nil { return err } // 下线转发服务 _, err = q.Proxy. Where(q.Proxy.Name.Eq(req.Name)). UpdateSimple(q.Proxy.Status.Value(0)) if err != nil { return err } return nil } // endregion // region AssignProxyFwdPort type AssignProxyFwdPortReq struct { Proxy int32 `json:"proxy" validate:"required"` Edge int32 `json:"edge" validate:"required"` Port uint16 `json:"port" validate:"required"` } func AssignProxyFwdPort(c *fiber.Ctx) (err error) { // 检查接口权限 _, err = auth2.NewProtect(c).Payload( auth2.PayloadInternalServer, ).Do() if err != nil { return err } // 验证请求参数 var req = new(AssignProxyFwdPortReq) err = g.Validator.Validate(c, req) if err != nil { return err } // 更新边缘节点端口分配状态 _, err = q.Edge. Where(q.Edge.ID.Eq(req.Edge)). UpdateSimple( q.Edge.ProxyID.Value(req.Proxy), q.Edge.ProxyPort.Value(int32(req.Port)), ) if err != nil { return err } return nil } // endregion type ProxyPermit struct { Id int32 `json:"id"` Expire time.Time `json:"expire"` Whitelists *[]string `json:"whitelists"` Username *string `json:"username"` Password *string `json:"password"` }