优化与代理服务的密钥存储与传递方式;更新套餐,账单查询对长效套餐的支持,新增长效套餐分页查询接口
This commit is contained in:
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"gorm.io/gen/field"
|
||||
"log/slog"
|
||||
"math"
|
||||
@@ -52,7 +51,7 @@ func (s *channelService) RemoveChannels(ctx context.Context, authCtx *auth.Conte
|
||||
// 检查权限,如果为用户操作的话,则只能删除自己的通道
|
||||
for _, channel := range channels {
|
||||
if authCtx.Payload.Type == auth.PayloadUser && authCtx.Payload.Id != channel.UserID {
|
||||
return fiber.NewError(fiber.StatusForbidden)
|
||||
return ErrRemoveForbidden
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,13 +227,14 @@ func (s *channelService) CreateChannel(
|
||||
AuthIp: authType == ChannelAuthTypeIp,
|
||||
Whitelists: whitelist,
|
||||
AuthPass: authType == ChannelAuthTypePass,
|
||||
Expiration: now.Add(time.Duration(resource.Live) * time.Second),
|
||||
}
|
||||
|
||||
switch resource2.Type(resource.Type) {
|
||||
switch resource.Type {
|
||||
case resource2.TypeShort:
|
||||
config.Expiration = now.Add(time.Duration(resource.Live) * time.Second)
|
||||
channels, err = assignShortChannels(q, authCtx.Payload.Id, count, config, filter, now)
|
||||
case resource2.TypeLong:
|
||||
config.Expiration = now.Add(time.Duration(resource.Live) * time.Hour)
|
||||
channels, err = assignLongChannels(q, authCtx.Payload.Id, count, config, filter)
|
||||
}
|
||||
if err != nil {
|
||||
@@ -260,8 +260,8 @@ func findResource(q *q.Query, resourceId int32, userId int32, count int, now tim
|
||||
|
||||
resource, err := q.Resource.
|
||||
Preload(
|
||||
q.Resource.Short.On(q.Resource.Type.Eq(int32(resource2.TypeShort))),
|
||||
q.Resource.Long.On(q.Resource.Type.Eq(int32(resource2.TypeLong))),
|
||||
q.Resource.Short,
|
||||
q.Resource.Long,
|
||||
).
|
||||
Where(
|
||||
q.Resource.ID.Eq(resourceId),
|
||||
@@ -560,9 +560,22 @@ func assignLongChannels(q *q.Query, userId int32, count int, config ChannelCreat
|
||||
// 查询符合条件的节点,根据 channel 统计使用次数
|
||||
var edges = make([]struct {
|
||||
m.Edge
|
||||
Count int
|
||||
Host string
|
||||
Count int
|
||||
Host string
|
||||
Secret string
|
||||
}, 0)
|
||||
|
||||
do := q.Edge.Where(q.Edge.Status.Eq(1))
|
||||
if filter.Prov != "" {
|
||||
do = do.Where(q.Edge.Prov.Eq(filter.Prov))
|
||||
}
|
||||
if filter.City != "" {
|
||||
do = do.Where(q.Edge.City.Eq(filter.City))
|
||||
}
|
||||
if filter.Isp != "" {
|
||||
do = do.Where(q.Edge.Isp.Eq(int32(edge2.ISPFromStr(filter.Isp))))
|
||||
}
|
||||
|
||||
err := q.Edge.
|
||||
LeftJoin(q.Channel, q.Channel.EdgeID.EqCol(q.Edge.ID)).
|
||||
LeftJoin(q.Proxy, q.Proxy.ID.EqCol(q.Edge.ProxyID)).
|
||||
@@ -570,20 +583,19 @@ func assignLongChannels(q *q.Query, userId int32, count int, config ChannelCreat
|
||||
q.Edge.ALL,
|
||||
q.Channel.ALL.Count().As("count"),
|
||||
q.Proxy.Host,
|
||||
q.Proxy.Secret,
|
||||
).
|
||||
Group(q.Edge.ID).
|
||||
Where(
|
||||
q.Edge.Prov.Eq(filter.Prov),
|
||||
q.Edge.City.Eq(filter.City),
|
||||
q.Edge.Isp.Eq(int32(edge2.ISPFromStr(filter.Isp))),
|
||||
q.Edge.Status.Eq(1),
|
||||
).
|
||||
Group(q.Edge.ID, q.Proxy.Host, q.Proxy.Secret).
|
||||
Where(do).
|
||||
Order(field.NewField("", "count").Asc()).
|
||||
Scan(edges)
|
||||
Limit(count).
|
||||
Scan(&edges)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("edges: %v\n", edges)
|
||||
if len(edges) == 0 {
|
||||
return nil, ErrEdgesNoAvailable
|
||||
}
|
||||
|
||||
// 计算分配负载(考虑去重,维护一个节点使用记录表,优先分配未使用节点,达到算法额定负载后再选择负载最少的节点)
|
||||
var total = count
|
||||
@@ -593,8 +605,17 @@ func assignLongChannels(q *q.Query, userId int32, count int, config ChannelCreat
|
||||
var avg = int(math.Ceil(float64(total) / float64(len(edges))))
|
||||
|
||||
var channels = make([]*m.Channel, 0, count)
|
||||
var reqs = make(map[string][]*g.ProxyPermitConfig)
|
||||
var proxies = make(map[int32]*m.Proxy)
|
||||
var reqs = make(map[int32][]*g.ProxyPermitConfig)
|
||||
for _, edge := range edges {
|
||||
if _, ok := proxies[edge.ProxyID]; !ok {
|
||||
proxies[edge.ProxyID] = &m.Proxy{
|
||||
ID: edge.ProxyID,
|
||||
Host: edge.Host,
|
||||
Secret: edge.Secret,
|
||||
}
|
||||
}
|
||||
|
||||
prev := edge.Count
|
||||
next := int(math.Max(float64(prev), float64(int(math.Min(float64(avg), float64(total))))))
|
||||
total -= next
|
||||
@@ -613,6 +634,8 @@ func assignLongChannels(q *q.Query, userId int32, count int, config ChannelCreat
|
||||
AuthIP: config.AuthIp,
|
||||
AuthPass: config.AuthPass,
|
||||
Expiration: orm.LocalDateTime(config.Expiration),
|
||||
ProxyHost: edge.Host,
|
||||
ProxyPort: edge.ProxyPort,
|
||||
}
|
||||
if config.AuthPass {
|
||||
username, password := genPassPair()
|
||||
@@ -634,15 +657,17 @@ func assignLongChannels(q *q.Query, userId int32, count int, config ChannelCreat
|
||||
req.Username = &channel.Username
|
||||
req.Password = &channel.Password
|
||||
}
|
||||
reqs[edge.Host] = append(reqs[edge.Host], req)
|
||||
|
||||
reqs[edge.ProxyID] = append(reqs[edge.ProxyID], req)
|
||||
}
|
||||
}
|
||||
|
||||
// 发送配置到网关
|
||||
if env.DebugExternalChange {
|
||||
var step = time.Now()
|
||||
for host, reqs := range reqs {
|
||||
err := g.Proxy.Permit(host, reqs)
|
||||
for id, reqs := range reqs {
|
||||
proxy := proxies[id]
|
||||
err := g.Proxy.Permit(proxy.Host, proxy.Secret, reqs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -654,6 +679,9 @@ func assignLongChannels(q *q.Query, userId int32, count int, config ChannelCreat
|
||||
}
|
||||
|
||||
func saveAssigns(q *q.Query, resource *ResourceInfo, channels []*m.Channel, now time.Time) (err error) {
|
||||
if len(channels) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 缓存通道数据
|
||||
pipe := g.Redis.TxPipeline()
|
||||
@@ -687,7 +715,7 @@ func saveAssigns(q *q.Query, resource *ResourceInfo, channels []*m.Channel, now
|
||||
|
||||
// 更新套餐使用记录
|
||||
var count = len(channels)
|
||||
var last = time.Time(resource.DailyLast)
|
||||
var last = resource.DailyLast
|
||||
var dailyUsed int32
|
||||
if now.Year() != last.Year() || now.Month() != last.Month() || now.Day() != last.Day() {
|
||||
dailyUsed = int32(count)
|
||||
@@ -695,7 +723,7 @@ func saveAssigns(q *q.Query, resource *ResourceInfo, channels []*m.Channel, now
|
||||
dailyUsed = resource.DailyUsed + int32(count)
|
||||
}
|
||||
|
||||
switch resource2.Type(resource.Type) {
|
||||
switch resource.Type {
|
||||
case resource2.TypeShort:
|
||||
_, err = q.ResourceShort.
|
||||
Where(q.ResourceShort.ResourceID.Eq(resource.Id)).
|
||||
@@ -788,4 +816,6 @@ const (
|
||||
ErrResourceExhausted = ChannelServiceErr("套餐已用完")
|
||||
ErrResourceExpired = ChannelServiceErr("套餐已过期")
|
||||
ErrResourceDailyLimit = ChannelServiceErr("套餐每日配额已用完")
|
||||
ErrRemoveForbidden = ChannelServiceErr("删除通道失败,当前用户没有权限")
|
||||
ErrEdgesNoAvailable = ChannelServiceErr("没有可用的节点")
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user