mirror of
				https://github.com/TeaOSLab/EdgeAPI.git
				synced 2025-11-04 16:00:24 +08:00 
			
		
		
		
	增加服务之间拷贝配置的API(开源版本只有定义,没有完全实现)
This commit is contained in:
		@@ -96,6 +96,27 @@ func (this *HTTPAuthPolicyDAO) UpdateHTTPAuthPolicy(tx *dbs.Tx, policyId int64,
 | 
			
		||||
	return this.NotifyUpdate(tx, policyId)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CloneAuthPolicy 复制策略
 | 
			
		||||
func (this *HTTPAuthPolicyDAO) CloneAuthPolicy(tx *dbs.Tx, fromPolicyId int64) (int64, error) {
 | 
			
		||||
	policyOne, err := this.Query(tx).
 | 
			
		||||
		Pk(fromPolicyId).
 | 
			
		||||
		Find()
 | 
			
		||||
	if err != nil || policyOne == nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	var policy = policyOne.(*HTTPAuthPolicy)
 | 
			
		||||
 | 
			
		||||
	var op = NewHTTPAuthPolicyOperator()
 | 
			
		||||
	op.IsOn = policy.IsOn
 | 
			
		||||
	op.Name = policy.Name
 | 
			
		||||
	op.Type = policy.Type
 | 
			
		||||
	if len(policy.Params) > 0 {
 | 
			
		||||
		op.Params = policy.Params
 | 
			
		||||
	}
 | 
			
		||||
	op.State = policy.State
 | 
			
		||||
	return this.SaveInt64(tx, op)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ComposePolicyConfig 组合配置
 | 
			
		||||
func (this *HTTPAuthPolicyDAO) ComposePolicyConfig(tx *dbs.Tx, policyId int64, cacheMap *utils.CacheMap) (*serverconfigs.HTTPAuthPolicy, error) {
 | 
			
		||||
	if cacheMap == nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -133,6 +133,32 @@ func (this *HTTPPageDAO) UpdatePage(tx *dbs.Tx, pageId int64, statusList []strin
 | 
			
		||||
	return this.NotifyUpdate(tx, pageId)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ClonePage 克隆页面
 | 
			
		||||
func (this *HTTPPageDAO) ClonePage(tx *dbs.Tx, fromPageId int64) (newPageId int64, err error) {
 | 
			
		||||
	if fromPageId <= 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	pageOne, err := this.Query(tx).
 | 
			
		||||
		Pk(fromPageId).
 | 
			
		||||
		Find()
 | 
			
		||||
	if err != nil || pageOne == nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	var page = pageOne.(*HTTPPage)
 | 
			
		||||
 | 
			
		||||
	var op = NewHTTPPageOperator()
 | 
			
		||||
	op.IsOn = page.IsOn
 | 
			
		||||
	if len(page.StatusList) > 0 {
 | 
			
		||||
		op.StatusList = page.StatusList
 | 
			
		||||
	}
 | 
			
		||||
	op.Url = page.Url
 | 
			
		||||
	op.NewStatus = page.NewStatus
 | 
			
		||||
	op.Body = page.Body
 | 
			
		||||
	op.BodyType = page.BodyType
 | 
			
		||||
	op.State = page.State
 | 
			
		||||
	return this.SaveInt64(tx, op)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ComposePageConfig 组合配置
 | 
			
		||||
func (this *HTTPPageDAO) ComposePageConfig(tx *dbs.Tx, pageId int64, cacheMap *utils.CacheMap) (*serverconfigs.HTTPPageConfig, error) {
 | 
			
		||||
	if cacheMap == nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -732,32 +732,6 @@ func (this *HTTPWebDAO) UpdateWebStat(tx *dbs.Tx, webId int64, statJSON []byte)
 | 
			
		||||
	return this.NotifyUpdate(tx, webId)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CopyWebStats 拷贝统计配置
 | 
			
		||||
func (this *HTTPWebDAO) CopyWebStats(tx *dbs.Tx, fromWebId int64, toWebIds []int64) error {
 | 
			
		||||
	if fromWebId <= 0 || len(toWebIds) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	statJSON, err := this.Query(tx).
 | 
			
		||||
		Pk(fromWebId).
 | 
			
		||||
		Result("stat").
 | 
			
		||||
		FindJSONCol()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 暂时不处理
 | 
			
		||||
	if len(statJSON) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return this.Query(tx).
 | 
			
		||||
		Pk(toWebIds).
 | 
			
		||||
		Reuse(false).
 | 
			
		||||
		Set("stat", statJSON).
 | 
			
		||||
		UpdateQuickly()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateWebCache 更改缓存配置
 | 
			
		||||
func (this *HTTPWebDAO) UpdateWebCache(tx *dbs.Tx, webId int64, cacheJSON []byte) error {
 | 
			
		||||
	if webId <= 0 {
 | 
			
		||||
@@ -1182,8 +1156,6 @@ func (this *HTTPWebDAO) UpdateWebHostRedirects(tx *dbs.Tx, webId int64, hostRedi
 | 
			
		||||
	return this.NotifyUpdate(tx, webId)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 通用设置
 | 
			
		||||
 | 
			
		||||
// FindWebHostRedirects 查找主机跳转
 | 
			
		||||
func (this *HTTPWebDAO) FindWebHostRedirects(tx *dbs.Tx, webId int64) ([]byte, error) {
 | 
			
		||||
	col, err := this.Query(tx).
 | 
			
		||||
 
 | 
			
		||||
@@ -159,6 +159,31 @@ func (this *HTTPWebsocketDAO) UpdateWebsocket(tx *dbs.Tx, websocketId int64, han
 | 
			
		||||
	return this.NotifyUpdate(tx, websocketId)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CloneWebsocket 复制配置
 | 
			
		||||
func (this *HTTPWebsocketDAO) CloneWebsocket(tx *dbs.Tx, fromWebsocketId int64) (newWebsocketId int64, err error) {
 | 
			
		||||
	websocketOne, err := this.Query(tx).
 | 
			
		||||
		Pk(fromWebsocketId).
 | 
			
		||||
		Find()
 | 
			
		||||
	if err != nil || websocketOne == nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	var websocket = websocketOne.(*HTTPWebsocket)
 | 
			
		||||
 | 
			
		||||
	var op = NewHTTPWebsocketOperator()
 | 
			
		||||
	op.State = websocket.State
 | 
			
		||||
	op.IsOn = websocket.IsOn
 | 
			
		||||
	if len(websocket.HandshakeTimeout) > 0 {
 | 
			
		||||
		op.HandshakeTimeout = websocket.HandshakeTimeout
 | 
			
		||||
	}
 | 
			
		||||
	op.AllowAllOrigins = websocket.AllowAllOrigins
 | 
			
		||||
	if len(websocket.AllowedOrigins) > 0 {
 | 
			
		||||
		op.AllowedOrigins = websocket.AllowedOrigins
 | 
			
		||||
	}
 | 
			
		||||
	op.RequestSameOrigin = websocket.RequestSameOrigin
 | 
			
		||||
	op.RequestOrigin = websocket.RequestOrigin
 | 
			
		||||
	return this.SaveInt64(tx, op)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NotifyUpdate 通知更新
 | 
			
		||||
func (this *HTTPWebsocketDAO) NotifyUpdate(tx *dbs.Tx, websocketId int64) error {
 | 
			
		||||
	webId, err := SharedHTTPWebDAO.FindEnabledWebIdWithWebsocketId(tx, websocketId)
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@ package models
 | 
			
		||||
 | 
			
		||||
import "github.com/iwind/TeaGo/dbs"
 | 
			
		||||
 | 
			
		||||
// Websocket设置
 | 
			
		||||
// HTTPWebsocket Websocket设置
 | 
			
		||||
type HTTPWebsocket struct {
 | 
			
		||||
	Id                uint32   `field:"id"`                // ID
 | 
			
		||||
	AdminId           uint32   `field:"adminId"`           // 管理员ID
 | 
			
		||||
@@ -15,20 +15,22 @@ type HTTPWebsocket struct {
 | 
			
		||||
	AllowedOrigins    dbs.JSON `field:"allowedOrigins"`    // 支持的源域名列表
 | 
			
		||||
	RequestSameOrigin uint8    `field:"requestSameOrigin"` // 是否请求一样的Origin
 | 
			
		||||
	RequestOrigin     string   `field:"requestOrigin"`     // 请求Origin
 | 
			
		||||
	WebId             uint64   `field:"webId"`             // Web
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type HTTPWebsocketOperator struct {
 | 
			
		||||
	Id                interface{} // ID
 | 
			
		||||
	AdminId           interface{} // 管理员ID
 | 
			
		||||
	UserId            interface{} // 用户ID
 | 
			
		||||
	CreatedAt         interface{} // 创建时间
 | 
			
		||||
	State             interface{} // 状态
 | 
			
		||||
	IsOn              interface{} // 是否启用
 | 
			
		||||
	HandshakeTimeout  interface{} // 握手超时时间
 | 
			
		||||
	AllowAllOrigins   interface{} // 是否支持所有源
 | 
			
		||||
	AllowedOrigins    interface{} // 支持的源域名列表
 | 
			
		||||
	RequestSameOrigin interface{} // 是否请求一样的Origin
 | 
			
		||||
	RequestOrigin     interface{} // 请求Origin
 | 
			
		||||
	Id                any // ID
 | 
			
		||||
	AdminId           any // 管理员ID
 | 
			
		||||
	UserId            any // 用户ID
 | 
			
		||||
	CreatedAt         any // 创建时间
 | 
			
		||||
	State             any // 状态
 | 
			
		||||
	IsOn              any // 是否启用
 | 
			
		||||
	HandshakeTimeout  any // 握手超时时间
 | 
			
		||||
	AllowAllOrigins   any // 是否支持所有源
 | 
			
		||||
	AllowedOrigins    any // 支持的源域名列表
 | 
			
		||||
	RequestSameOrigin any // 是否请求一样的Origin
 | 
			
		||||
	RequestOrigin     any // 请求Origin
 | 
			
		||||
	WebId             any // Web
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewHTTPWebsocketOperator() *HTTPWebsocketOperator {
 | 
			
		||||
 
 | 
			
		||||
@@ -275,6 +275,64 @@ func (this *OriginDAO) UpdateOrigin(tx *dbs.Tx,
 | 
			
		||||
	return this.NotifyUpdate(tx, originId)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CloneOrigin 复制源站
 | 
			
		||||
func (this *OriginDAO) CloneOrigin(tx *dbs.Tx, fromOriginId int64) (newOriginId int64, err error) {
 | 
			
		||||
	if fromOriginId <= 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	originOne, err := this.Find(tx, fromOriginId)
 | 
			
		||||
	if err != nil || originOne == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	var origin = originOne.(*Origin)
 | 
			
		||||
	var op = NewOriginOperator()
 | 
			
		||||
	op.IsOn = origin.IsOn
 | 
			
		||||
	op.Name = origin.Name
 | 
			
		||||
	op.Version = origin.Version
 | 
			
		||||
	if IsNotNull(origin.Addr) {
 | 
			
		||||
		op.Addr = origin.Addr
 | 
			
		||||
	}
 | 
			
		||||
	op.Description = origin.Description
 | 
			
		||||
	op.Code = origin.Code
 | 
			
		||||
	op.Weight = origin.Weight
 | 
			
		||||
	if IsNotNull(origin.ConnTimeout) {
 | 
			
		||||
		op.ConnTimeout = origin.ConnTimeout
 | 
			
		||||
	}
 | 
			
		||||
	if IsNotNull(origin.ReadTimeout) {
 | 
			
		||||
		op.ReadTimeout = origin.ReadTimeout
 | 
			
		||||
	}
 | 
			
		||||
	if IsNotNull(origin.IdleTimeout) {
 | 
			
		||||
		op.IdleTimeout = origin.IdleTimeout
 | 
			
		||||
	}
 | 
			
		||||
	op.MaxFails = origin.MaxFails
 | 
			
		||||
	op.MaxConns = origin.MaxConns
 | 
			
		||||
	op.MaxIdleConns = origin.MaxIdleConns
 | 
			
		||||
	op.HttpRequestURI = origin.HttpRequestURI
 | 
			
		||||
	if IsNotNull(origin.HttpRequestHeader) {
 | 
			
		||||
		op.HttpRequestHeader = origin.HttpRequestHeader
 | 
			
		||||
	}
 | 
			
		||||
	if IsNotNull(origin.HttpResponseHeader) {
 | 
			
		||||
		op.HttpResponseHeader = origin.HttpResponseHeader
 | 
			
		||||
	}
 | 
			
		||||
	op.Host = origin.Host
 | 
			
		||||
	if IsNotNull(origin.HealthCheck) {
 | 
			
		||||
		op.HealthCheck = origin.HealthCheck
 | 
			
		||||
	}
 | 
			
		||||
	if IsNotNull(origin.Cert) {
 | 
			
		||||
		// TODO 需要Clone证书
 | 
			
		||||
		op.Cert = origin.Cert
 | 
			
		||||
	}
 | 
			
		||||
	if IsNotNull(origin.Ftp) {
 | 
			
		||||
		op.Ftp = origin.Ftp
 | 
			
		||||
	}
 | 
			
		||||
	if IsNotNull(origin.Domains) {
 | 
			
		||||
		op.Domains = origin.Domains
 | 
			
		||||
	}
 | 
			
		||||
	op.FollowPort = origin.FollowPort
 | 
			
		||||
	op.State = origin.State
 | 
			
		||||
	return this.SaveInt64(tx, op)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ComposeOriginConfig 将源站信息转换为配置
 | 
			
		||||
func (this *OriginDAO) ComposeOriginConfig(tx *dbs.Tx, originId int64, dataMap *shared.DataMap, cacheMap *utils.CacheMap) (*serverconfigs.OriginConfig, error) {
 | 
			
		||||
	if cacheMap == nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -243,6 +243,115 @@ func (this *ReverseProxyDAO) CreateReverseProxy(tx *dbs.Tx, adminId int64, userI
 | 
			
		||||
	return types.Int64(op.Id), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CloneReverseProxy 复制反向代理
 | 
			
		||||
func (this *ReverseProxyDAO) CloneReverseProxy(tx *dbs.Tx, fromReverseProxyId int64) (newReverseProxyId int64, err error) {
 | 
			
		||||
	if fromReverseProxyId <= 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	reverseProxyOne, err := this.Query(tx).
 | 
			
		||||
		Pk(fromReverseProxyId).
 | 
			
		||||
		State(ReverseProxyStateEnabled).
 | 
			
		||||
		Find()
 | 
			
		||||
	if err != nil || reverseProxyOne == nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	var reverseProxy = reverseProxyOne.(*ReverseProxy)
 | 
			
		||||
	var op = NewReverseProxyOperator()
 | 
			
		||||
	op.TemplateId = reverseProxy.TemplateId
 | 
			
		||||
	op.IsOn = reverseProxy.IsOn
 | 
			
		||||
	if IsNotNull(reverseProxy.Scheduling) {
 | 
			
		||||
		op.Scheduling = reverseProxy.Scheduling
 | 
			
		||||
	}
 | 
			
		||||
	if IsNotNull(reverseProxy.PrimaryOrigins) {
 | 
			
		||||
		var originRefs = []*serverconfigs.OriginRef{}
 | 
			
		||||
		err = json.Unmarshal(reverseProxy.PrimaryOrigins, &originRefs)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var newRefs = []*serverconfigs.OriginRef{}
 | 
			
		||||
		for _, originRef := range originRefs {
 | 
			
		||||
			if originRef.OriginId > 0 {
 | 
			
		||||
				newOriginId, err := SharedOriginDAO.CloneOrigin(tx, originRef.OriginId)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return 0, err
 | 
			
		||||
				}
 | 
			
		||||
				if newOriginId > 0 {
 | 
			
		||||
					newRef, err := utils.JSONClone[*serverconfigs.OriginRef](originRef)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return 0, err
 | 
			
		||||
					}
 | 
			
		||||
					newRef.OriginId = newOriginId
 | 
			
		||||
					newRefs = append(newRefs, newRef)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		newRefsJSON, err := json.Marshal(newRefs)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
		op.PrimaryOrigins = newRefsJSON
 | 
			
		||||
	}
 | 
			
		||||
	if IsNotNull(reverseProxy.BackupOrigins) {
 | 
			
		||||
		var originRefs = []*serverconfigs.OriginRef{}
 | 
			
		||||
		err = json.Unmarshal(reverseProxy.BackupOrigins, &originRefs)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var newRefs = []*serverconfigs.OriginRef{}
 | 
			
		||||
		for _, originRef := range originRefs {
 | 
			
		||||
			if originRef.OriginId > 0 {
 | 
			
		||||
				newOriginId, err := SharedOriginDAO.CloneOrigin(tx, originRef.OriginId)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return 0, err
 | 
			
		||||
				}
 | 
			
		||||
				if newOriginId > 0 {
 | 
			
		||||
					newRef, err := utils.JSONClone[*serverconfigs.OriginRef](originRef)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return 0, err
 | 
			
		||||
					}
 | 
			
		||||
					newRef.OriginId = newOriginId
 | 
			
		||||
					newRefs = append(newRefs, newRef)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		newRefsJSON, err := json.Marshal(newRefs)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
		op.BackupOrigins = newRefsJSON
 | 
			
		||||
	}
 | 
			
		||||
	op.StripPrefix = reverseProxy.StripPrefix
 | 
			
		||||
	op.RequestHostType = reverseProxy.RequestHostType
 | 
			
		||||
	op.RequestHost = reverseProxy.RequestHost
 | 
			
		||||
	op.RequestHostExcludingPort = reverseProxy.RequestHostExcludingPort
 | 
			
		||||
	op.RequestURI = reverseProxy.RequestURI
 | 
			
		||||
	op.AutoFlush = reverseProxy.AutoFlush
 | 
			
		||||
	if IsNotNull(reverseProxy.AddHeaders) {
 | 
			
		||||
		// TODO 复制Header
 | 
			
		||||
		op.AddHeaders = reverseProxy.AddHeaders
 | 
			
		||||
	}
 | 
			
		||||
	op.State = reverseProxy.State
 | 
			
		||||
	if IsNotNull(reverseProxy.ConnTimeout) {
 | 
			
		||||
		op.ConnTimeout = reverseProxy.ConnTimeout
 | 
			
		||||
	}
 | 
			
		||||
	if IsNotNull(reverseProxy.ReadTimeout) {
 | 
			
		||||
		op.ReadTimeout = reverseProxy.ReadTimeout
 | 
			
		||||
	}
 | 
			
		||||
	if IsNotNull(reverseProxy.IdleTimeout) {
 | 
			
		||||
		op.IdleTimeout = reverseProxy.IdleTimeout
 | 
			
		||||
	}
 | 
			
		||||
	op.MaxConns = reverseProxy.MaxConns
 | 
			
		||||
	op.MaxIdleConns = reverseProxy.MaxIdleConns
 | 
			
		||||
	if IsNotNull(reverseProxy.ProxyProtocol) {
 | 
			
		||||
		op.ProxyProtocol = reverseProxy.ProxyProtocol
 | 
			
		||||
	}
 | 
			
		||||
	op.FollowRedirects = reverseProxy.FollowRedirects
 | 
			
		||||
 | 
			
		||||
	return this.SaveInt64(tx, op)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateReverseProxyScheduling 修改反向代理调度算法
 | 
			
		||||
func (this *ReverseProxyDAO) UpdateReverseProxyScheduling(tx *dbs.Tx, reverseProxyId int64, schedulingJSON []byte) error {
 | 
			
		||||
	if reverseProxyId <= 0 {
 | 
			
		||||
 
 | 
			
		||||
@@ -126,7 +126,7 @@ func (this *ServerDAO) FindEnabledServerBasic(tx *dbs.Tx, serverId int64) (*Serv
 | 
			
		||||
	result, err := this.Query(tx).
 | 
			
		||||
		Pk(serverId).
 | 
			
		||||
		State(ServerStateEnabled).
 | 
			
		||||
		Result("id", "name", "description", "isOn", "type", "clusterId", "userId").
 | 
			
		||||
		Result("id", "name", "description", "isOn", "type", "clusterId", "userId", "groupIds").
 | 
			
		||||
		Find()
 | 
			
		||||
	if result == nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
 
 | 
			
		||||
@@ -1,173 +0,0 @@
 | 
			
		||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
 | 
			
		||||
 | 
			
		||||
package models
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
			
		||||
	"github.com/iwind/TeaGo/dbs"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// 服务基本信息
 | 
			
		||||
type clusterServerList struct {
 | 
			
		||||
	clusterId int64
 | 
			
		||||
	serverIds []int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CopyServerConfigToServers 拷贝服务配置到一组服务
 | 
			
		||||
func (this *ServerDAO) CopyServerConfigToServers(tx *dbs.Tx, fromServerId int64, toServerIds []int64, configCode serverconfigs.ConfigCode) error {
 | 
			
		||||
	if fromServerId <= 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if len(toServerIds) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	webId, err := SharedServerDAO.FindServerWebId(tx, fromServerId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	clusterServers, toWebIds, err := this.findServerClusterIdsAndWebIds(tx, toServerIds)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if len(clusterServers) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch configCode {
 | 
			
		||||
	case serverconfigs.ConfigCodeStat: // 统计
 | 
			
		||||
		if webId <= 0 {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		err = SharedHTTPWebDAO.CopyWebStats(tx, webId, toWebIds)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 通知更新
 | 
			
		||||
	for _, serverList := range clusterServers {
 | 
			
		||||
		err = SharedUpdatingServerListDAO.CreateList(tx, serverList.clusterId, serverList.serverIds)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		err = SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, serverList.clusterId, 0, 0,  NodeTaskTypeUpdatingServers)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 查找一组服务的集群和WebId信息
 | 
			
		||||
func (this *ServerDAO) findServerClusterIdsAndWebIds(tx *dbs.Tx, serverIds []int64) (clusterServers []*clusterServerList, webIds []int64, err error) {
 | 
			
		||||
	if len(serverIds) == 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ones, err := this.Query(tx).
 | 
			
		||||
		Result("id", "webId", "clusterId").
 | 
			
		||||
		Pk(serverIds).
 | 
			
		||||
		Reuse(false).
 | 
			
		||||
		FindAll()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var clusterMap = map[int64]*clusterServerList{} // clusterId => servers
 | 
			
		||||
 | 
			
		||||
	for _, one := range ones {
 | 
			
		||||
		var server = one.(*Server)
 | 
			
		||||
		var clusterId = int64(server.ClusterId)
 | 
			
		||||
		if clusterId <= 0 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		serverList, ok := clusterMap[clusterId]
 | 
			
		||||
		if ok {
 | 
			
		||||
			serverList.serverIds = append(serverList.serverIds, int64(server.Id))
 | 
			
		||||
		} else {
 | 
			
		||||
			clusterMap[clusterId] = &clusterServerList{
 | 
			
		||||
				clusterId: clusterId,
 | 
			
		||||
				serverIds: []int64{int64(server.Id)},
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var webId = int64(server.WebId)
 | 
			
		||||
		if webId > 0 {
 | 
			
		||||
			webIds = append(webIds, webId)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, serverList := range clusterMap {
 | 
			
		||||
		clusterServers = append(clusterServers, serverList)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CopyServerConfigToGroups 拷贝服务配置到分组
 | 
			
		||||
func (this *ServerDAO) CopyServerConfigToGroups(tx *dbs.Tx, fromServerId int64, groupIds []int64, configCode string) error {
 | 
			
		||||
	if len(groupIds) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var serverIds = []int64{}
 | 
			
		||||
	for _, groupId := range groupIds {
 | 
			
		||||
		ones, err := this.Query(tx).
 | 
			
		||||
			ResultPk().
 | 
			
		||||
			State(ServerStateEnabled).
 | 
			
		||||
			Where("JSON_CONTAINS(groupIds, :groupId)").
 | 
			
		||||
			Param("groupId", groupId).
 | 
			
		||||
			FindAll()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		for _, one := range ones {
 | 
			
		||||
			serverIds = append(serverIds, int64(one.(*Server).Id))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return this.CopyServerConfigToServers(tx, fromServerId, serverIds, configCode)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CopyServerConfigToCluster 拷贝服务配置到集群
 | 
			
		||||
func (this *ServerDAO) CopyServerConfigToCluster(tx *dbs.Tx, fromServerId int64, clusterId int64, configCode string) error {
 | 
			
		||||
	ones, err := this.Query(tx).
 | 
			
		||||
		ResultPk().
 | 
			
		||||
		State(ServerStateEnabled).
 | 
			
		||||
		Attr("clusterId", clusterId).
 | 
			
		||||
		UseIndex("clusterId").
 | 
			
		||||
		FindAll()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	var serverIds = []int64{}
 | 
			
		||||
	for _, one := range ones {
 | 
			
		||||
		serverIds = append(serverIds, int64(one.(*Server).Id))
 | 
			
		||||
	}
 | 
			
		||||
	return this.CopyServerConfigToServers(tx, fromServerId, serverIds, configCode)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CopyServerConfigToUser 拷贝服务配置到用户
 | 
			
		||||
func (this *ServerDAO) CopyServerConfigToUser(tx *dbs.Tx, fromServerId int64, userId int64, configCode string) error {
 | 
			
		||||
	ones, err := this.Query(tx).
 | 
			
		||||
		ResultPk().
 | 
			
		||||
		State(ServerStateEnabled).
 | 
			
		||||
		Attr("userId", userId).
 | 
			
		||||
		UseIndex("userId").
 | 
			
		||||
		FindAll()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	var serverIds = []int64{}
 | 
			
		||||
	for _, one := range ones {
 | 
			
		||||
		serverIds = append(serverIds, int64(one.(*Server).Id))
 | 
			
		||||
	}
 | 
			
		||||
	return this.CopyServerConfigToServers(tx, fromServerId, serverIds, configCode)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								internal/db/models/server_dao_copy_ext.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								internal/db/models/server_dao_copy_ext.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
 | 
			
		||||
//go:build !plus
 | 
			
		||||
 | 
			
		||||
package models
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
			
		||||
	"github.com/iwind/TeaGo/dbs"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CopyServerConfigToServers 拷贝服务配置到一组服务
 | 
			
		||||
func (this *ServerDAO) CopyServerConfigToServers(tx *dbs.Tx, fromServerId int64, toServerIds []int64, configCode serverconfigs.ConfigCode) error {
 | 
			
		||||
	return errors.New("not implemented")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CopyServerConfigToGroups 拷贝服务配置到分组
 | 
			
		||||
func (this *ServerDAO) CopyServerConfigToGroups(tx *dbs.Tx, fromServerId int64, groupIds []int64, configCode string) error {
 | 
			
		||||
	return errors.New("not implemented")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CopyServerConfigToCluster 拷贝服务配置到集群
 | 
			
		||||
func (this *ServerDAO) CopyServerConfigToCluster(tx *dbs.Tx, fromServerId int64, clusterId int64, configCode string) error {
 | 
			
		||||
	return errors.New("not implemented")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CopyServerConfigToUser 拷贝服务配置到用户
 | 
			
		||||
func (this *ServerDAO) CopyServerConfigToUser(tx *dbs.Tx, fromServerId int64, userId int64, configCode string) error {
 | 
			
		||||
	return errors.New("not implemented")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CopyServerUAMConfigs 复制UAM设置
 | 
			
		||||
func (this *ServerDAO) CopyServerUAMConfigs(tx *dbs.Tx, fromServerId int64, toServerIds []int64) error {
 | 
			
		||||
	return errors.New("not implemented")
 | 
			
		||||
}
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
 | 
			
		||||
 | 
			
		||||
package models_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAPI/internal/db/models"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
			
		||||
	"github.com/iwind/TeaGo/dbs"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestServerDAO_CopyServerConfigToServers(t *testing.T) {
 | 
			
		||||
	dbs.NotifyReady()
 | 
			
		||||
 | 
			
		||||
	var tx *dbs.Tx
 | 
			
		||||
	var dao = models.NewServerDAO()
 | 
			
		||||
 | 
			
		||||
	err := dao.CopyServerConfigToServers(tx, 10170, []int64{23, 10171}, serverconfigs.ConfigCodeStat)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -424,6 +424,18 @@ func (this *ServerGroupDAO) ExistsGroup(tx *dbs.Tx, groupId int64) (bool, error)
 | 
			
		||||
		Exist()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FindGroupUserId 读取分组所属用户
 | 
			
		||||
func (this *ServerGroupDAO) FindGroupUserId(tx *dbs.Tx, groupId int64) (userId int64, err error) {
 | 
			
		||||
	if groupId <= 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	return this.Query(tx).
 | 
			
		||||
		Pk(groupId).
 | 
			
		||||
		State(ServerGroupStateEnabled).
 | 
			
		||||
		Result("userId").
 | 
			
		||||
		FindInt64Col(0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NotifyUpdate 通知更新
 | 
			
		||||
func (this *ServerGroupDAO) NotifyUpdate(tx *dbs.Tx, groupId int64) error {
 | 
			
		||||
	serverIds, err := SharedServerDAO.FindAllEnabledServerIdsWithGroupId(tx, groupId)
 | 
			
		||||
 
 | 
			
		||||
@@ -1299,6 +1299,16 @@ func (this *ServerService) CountAllEnabledServersWithServerGroupId(ctx context.C
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tx = this.NullTx()
 | 
			
		||||
	if userId <= 0 {
 | 
			
		||||
		// 指定用户ID可以加快查询速度
 | 
			
		||||
		groupUserId, err := models.SharedServerGroupDAO.FindGroupUserId(tx, req.ServerGroupId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if groupUserId > 0 {
 | 
			
		||||
			userId = groupUserId
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	count, err := models.SharedServerDAO.CountAllEnabledServersWithGroupId(tx, req.ServerGroupId, userId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -1562,11 +1572,29 @@ func (this *ServerService) FindEnabledUserServerBasic(ctx context.Context, req *
 | 
			
		||||
		return &pb.FindEnabledUserServerBasicResponse{Server: nil}, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 集群
 | 
			
		||||
	clusterName, err := models.SharedNodeClusterDAO.FindNodeClusterName(tx, int64(server.ClusterId))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 分组
 | 
			
		||||
	var pbGroups = []*pb.ServerGroup{}
 | 
			
		||||
	for _, groupId := range server.DecodeGroupIds() {
 | 
			
		||||
		group, err := models.SharedServerGroupDAO.FindEnabledServerGroup(tx, groupId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if group == nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		pbGroups = append(pbGroups, &pb.ServerGroup{
 | 
			
		||||
			Id:     groupId,
 | 
			
		||||
			Name:   group.Name,
 | 
			
		||||
			UserId: int64(group.UserId),
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &pb.FindEnabledUserServerBasicResponse{Server: &pb.Server{
 | 
			
		||||
		Id:          int64(server.Id),
 | 
			
		||||
		Name:        server.Name,
 | 
			
		||||
@@ -1578,6 +1606,7 @@ func (this *ServerService) FindEnabledUserServerBasic(ctx context.Context, req *
 | 
			
		||||
			Id:   int64(server.ClusterId),
 | 
			
		||||
			Name: clusterName,
 | 
			
		||||
		},
 | 
			
		||||
		ServerGroups: pbGroups,
 | 
			
		||||
	}}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -85,21 +85,26 @@ func (this *ServerGroupService) DeleteServerGroup(ctx context.Context, req *pb.D
 | 
			
		||||
// FindAllEnabledServerGroups 查询所有分组
 | 
			
		||||
func (this *ServerGroupService) FindAllEnabledServerGroups(ctx context.Context, req *pb.FindAllEnabledServerGroupsRequest) (*pb.FindAllEnabledServerGroupsResponse, error) {
 | 
			
		||||
	// 校验请求
 | 
			
		||||
	_, userId, err := this.ValidateAdminAndUser(ctx, true)
 | 
			
		||||
	adminId, userId, err := this.ValidateAdminAndUser(ctx, true)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if adminId > 0 {
 | 
			
		||||
		userId = req.UserId
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tx = this.NullTx()
 | 
			
		||||
 | 
			
		||||
	groups, err := models.SharedServerGroupDAO.FindAllEnabledGroups(tx, userId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	result := []*pb.ServerGroup{}
 | 
			
		||||
	var result = []*pb.ServerGroup{}
 | 
			
		||||
	for _, group := range groups {
 | 
			
		||||
		result = append(result, &pb.ServerGroup{
 | 
			
		||||
			Id:   int64(group.Id),
 | 
			
		||||
			IsOn: group.IsOn,
 | 
			
		||||
			Name: group.Name,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
@@ -153,6 +158,7 @@ func (this *ServerGroupService) FindEnabledServerGroup(ctx context.Context, req
 | 
			
		||||
	return &pb.FindEnabledServerGroupResponse{
 | 
			
		||||
		ServerGroup: &pb.ServerGroup{
 | 
			
		||||
			Id:   int64(group.Id),
 | 
			
		||||
			IsOn: group.IsOn,
 | 
			
		||||
			Name: group.Name,
 | 
			
		||||
		},
 | 
			
		||||
	}, nil
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										45
									
								
								internal/utils/json.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								internal/utils/json.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
 | 
			
		||||
 | 
			
		||||
package utils
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"reflect"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// JSONClone 使用JSON协议克隆对象
 | 
			
		||||
func JSONClone[T any](ptr T) (newPtr T, err error) {
 | 
			
		||||
	var ptrType = reflect.TypeOf(ptr)
 | 
			
		||||
	var kind = ptrType.Kind()
 | 
			
		||||
	if kind != reflect.Ptr && kind != reflect.Slice {
 | 
			
		||||
		err = errors.New("JSONClone: input must be a ptr or slice")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	var jsonData []byte
 | 
			
		||||
	jsonData, err = json.Marshal(ptr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return ptr, errors.New("JSONClone: marshal failed: " + err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var newValue any
 | 
			
		||||
	switch kind {
 | 
			
		||||
	case reflect.Ptr:
 | 
			
		||||
		newValue = reflect.New(ptrType.Elem()).Interface()
 | 
			
		||||
	case reflect.Slice:
 | 
			
		||||
		newValue = reflect.New(reflect.SliceOf(ptrType.Elem())).Interface()
 | 
			
		||||
	default:
 | 
			
		||||
		return ptr, errors.New("JSONClone: unknown data type")
 | 
			
		||||
	}
 | 
			
		||||
	err = json.Unmarshal(jsonData, newValue)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		err = errors.New("JSONClone: unmarshal failed: " + err.Error())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if kind == reflect.Slice {
 | 
			
		||||
		newValue = reflect.Indirect(reflect.ValueOf(newValue)).Interface()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return newValue.(T), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								internal/utils/json_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								internal/utils/json_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
 | 
			
		||||
 | 
			
		||||
package utils_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAPI/internal/utils"
 | 
			
		||||
	"github.com/iwind/TeaGo/logs"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestJSONClone(t *testing.T) {
 | 
			
		||||
	type user struct {
 | 
			
		||||
		Name string
 | 
			
		||||
		Age  int
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var u = &user{
 | 
			
		||||
		Name: "Jack",
 | 
			
		||||
		Age:  20,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	newU, err := utils.JSONClone[*user](u)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	t.Logf("%#v", newU)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestJSONClone_Slice(t *testing.T) {
 | 
			
		||||
	type user struct {
 | 
			
		||||
		Name string
 | 
			
		||||
		Age  int
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var u = []*user{
 | 
			
		||||
		{
 | 
			
		||||
			Name: "Jack",
 | 
			
		||||
			Age:  20,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Name: "Lily",
 | 
			
		||||
			Age:  18,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	newU, err := utils.JSONClone[[]*user](u)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	logs.PrintAsJSON(newU, t)
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user