Initial commit (code only without large binaries)
This commit is contained in:
547
EdgeUser/internal/web/actions/default/lb/create.go
Normal file
547
EdgeUser/internal/web/actions/default/lb/create.go
Normal file
@@ -0,0 +1,547 @@
|
||||
package lb
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type CreateAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreateAction) Init() {
|
||||
this.Nav("", "", "create")
|
||||
}
|
||||
|
||||
func (this *CreateAction) RunGet(params struct{}) {
|
||||
var supportTCP = this.ValidateFeature(userconfigs.UserFeatureCodeServerTCP, 0)
|
||||
var supportUDP = this.ValidateFeature(userconfigs.UserFeatureCodeServerUDP, 0)
|
||||
|
||||
if !supportTCP && !supportUDP {
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["supportTCP"] = supportTCP
|
||||
this.Data["supportUDP"] = supportUDP
|
||||
|
||||
// 服务类型
|
||||
var serverTypes = []maps.Map{}
|
||||
if supportTCP {
|
||||
serverTypes = append(serverTypes, maps.Map{
|
||||
"name": "TCP负载均衡",
|
||||
"code": serverconfigs.ServerTypeTCPProxy,
|
||||
})
|
||||
}
|
||||
if supportUDP {
|
||||
serverTypes = append(serverTypes, maps.Map{
|
||||
"name": "UDP负载均衡",
|
||||
"code": serverconfigs.ServerTypeUDPProxy,
|
||||
})
|
||||
}
|
||||
this.Data["serverTypes"] = serverTypes
|
||||
|
||||
this.Data["canSpecifyTCPPort"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerTCPPort, 0)
|
||||
this.Data["canSpecifyUDPPort"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerUDPPort, 0)
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreateAction) RunPost(params struct {
|
||||
Name string
|
||||
ServerType string
|
||||
Protocols []string
|
||||
CertIdsJSON []byte
|
||||
OriginsJSON []byte
|
||||
TcpPorts []int
|
||||
TlsPorts []int
|
||||
UdpPorts []int
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
// 检查ServerType
|
||||
var serverType = params.ServerType
|
||||
if !lists.ContainsString([]string{serverconfigs.ServerTypeTCPProxy, serverconfigs.ServerTypeUDPProxy}, serverType) {
|
||||
this.Fail("请选择正确的服务类型")
|
||||
}
|
||||
|
||||
// 检查用户所在集群
|
||||
clusterIdResp, err := this.RPC().UserRPC().FindUserNodeClusterId(this.UserContext(), &pb.FindUserNodeClusterIdRequest{UserId: this.UserId()})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
clusterId := clusterIdResp.NodeClusterId
|
||||
if clusterId == 0 {
|
||||
this.Fail("当前用户没有指定集群,不能使用此服务")
|
||||
}
|
||||
|
||||
// 检查是否有TCP权限
|
||||
if lists.ContainsString(params.Protocols, "tcp") && !this.ValidateFeature(userconfigs.UserFeatureCodeServerTCP, 0) {
|
||||
this.Fail("你没有权限使用TCP负载均衡功能")
|
||||
}
|
||||
|
||||
// 检查是否有UDP权限
|
||||
if lists.ContainsString(params.Protocols, "udp") && !this.ValidateFeature(userconfigs.UserFeatureCodeServerUDP, 0) {
|
||||
this.Fail("你没有权限使用UDP负载均衡功能")
|
||||
}
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入服务名称")
|
||||
|
||||
// 协议
|
||||
if len(params.Protocols) == 0 {
|
||||
this.Fail("请选择至少一个协议")
|
||||
}
|
||||
|
||||
// TCP
|
||||
canSpecifyTCPPort := this.ValidateFeature(userconfigs.UserFeatureCodeServerTCPPort, 0)
|
||||
if serverType == serverconfigs.ServerTypeTCPProxy {
|
||||
// 检查TCP端口
|
||||
if canSpecifyTCPPort {
|
||||
if lists.Contains(params.Protocols, "tcp") {
|
||||
if len(params.TcpPorts) == 0 {
|
||||
this.Fail("需要至少指定一个TCP监听端口")
|
||||
}
|
||||
for _, port := range params.TcpPorts {
|
||||
if port < 1024 || port > 65534 {
|
||||
this.Fail("端口 '" + strconv.Itoa(port) + "' 范围错误")
|
||||
}
|
||||
|
||||
// 检查是否被使用
|
||||
resp, err := this.RPC().NodeClusterRPC().CheckPortIsUsingInNodeCluster(this.UserContext(), &pb.CheckPortIsUsingInNodeClusterRequest{
|
||||
Port: types.Int32(port),
|
||||
NodeClusterId: clusterId,
|
||||
ProtocolFamily: "tcp",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if resp.IsUsing {
|
||||
this.Fail("端口 '" + strconv.Itoa(port) + "' 正在被别的服务使用,请换一个")
|
||||
}
|
||||
}
|
||||
}
|
||||
if lists.Contains(params.Protocols, "tls") {
|
||||
if len(params.TlsPorts) == 0 {
|
||||
this.Fail("需要至少指定一个TLS监听端口")
|
||||
}
|
||||
for _, port := range params.TlsPorts {
|
||||
if port < 1024 || port > 65534 {
|
||||
this.Fail("端口 '" + strconv.Itoa(port) + "' 范围错误")
|
||||
}
|
||||
if lists.ContainsInt(params.TcpPorts, port) {
|
||||
this.Fail("TLS端口 '" + strconv.Itoa(port) + "' 已经被TCP端口使用,不能重复使用")
|
||||
}
|
||||
|
||||
// 检查是否被使用
|
||||
resp, err := this.RPC().NodeClusterRPC().CheckPortIsUsingInNodeCluster(this.UserContext(), &pb.CheckPortIsUsingInNodeClusterRequest{
|
||||
Port: types.Int32(port),
|
||||
NodeClusterId: clusterId,
|
||||
ProtocolFamily: "tcp",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if resp.IsUsing {
|
||||
this.Fail("端口 '" + strconv.Itoa(port) + "' 正在被别的服务使用,请换一个")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UDP
|
||||
canSpecifyUDPPort := this.ValidateFeature(userconfigs.UserFeatureCodeServerUDPPort, 0)
|
||||
if serverType == serverconfigs.ServerTypeUDPProxy {
|
||||
// 检查UDP端口
|
||||
if canSpecifyUDPPort {
|
||||
if lists.Contains(params.Protocols, "udp") {
|
||||
if len(params.UdpPorts) == 0 {
|
||||
this.Fail("需要至少指定一个UDP监听端口")
|
||||
}
|
||||
for _, port := range params.UdpPorts {
|
||||
if port < 1024 || port > 65534 {
|
||||
this.Fail("端口 '" + strconv.Itoa(port) + "' 范围错误")
|
||||
}
|
||||
|
||||
// 检查是否被使用
|
||||
resp, err := this.RPC().NodeClusterRPC().CheckPortIsUsingInNodeCluster(this.UserContext(), &pb.CheckPortIsUsingInNodeClusterRequest{
|
||||
Port: types.Int32(port),
|
||||
NodeClusterId: clusterId,
|
||||
ProtocolFamily: "udp",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if resp.IsUsing {
|
||||
this.Fail("端口 '" + strconv.Itoa(port) + "' 正在被别的服务使用,请换一个")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 先加锁
|
||||
lockerKey := "create_tcp_server"
|
||||
lockResp, err := this.RPC().SysLockerRPC().SysLockerLock(this.UserContext(), &pb.SysLockerLockRequest{
|
||||
Key: lockerKey,
|
||||
TimeoutSeconds: 30,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !lockResp.Ok {
|
||||
this.Fail("操作繁忙,请稍后再试")
|
||||
}
|
||||
defer func() {
|
||||
_, err := this.RPC().SysLockerRPC().SysLockerUnlock(this.UserContext(), &pb.SysLockerUnlockRequest{Key: lockerKey})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
tcpConfig := &serverconfigs.TCPProtocolConfig{}
|
||||
tlsConfig := &serverconfigs.TLSProtocolConfig{}
|
||||
udpConfig := &serverconfigs.UDPProtocolConfig{}
|
||||
|
||||
if serverType == serverconfigs.ServerTypeTCPProxy {
|
||||
// TCP
|
||||
ports := []int{}
|
||||
if lists.ContainsString(params.Protocols, "tcp") {
|
||||
tcpConfig.IsOn = true
|
||||
|
||||
if canSpecifyTCPPort {
|
||||
for _, port := range params.TcpPorts {
|
||||
tcpConfig.Listen = append(tcpConfig.Listen, &serverconfigs.NetworkAddressConfig{
|
||||
Protocol: serverconfigs.ProtocolTCP,
|
||||
Host: "",
|
||||
PortRange: strconv.Itoa(port),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// 获取随机端口
|
||||
portResp, err := this.RPC().NodeClusterRPC().FindFreePortInNodeCluster(this.UserContext(), &pb.FindFreePortInNodeClusterRequest{
|
||||
NodeClusterId: clusterId,
|
||||
ProtocolFamily: "tcp",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
port := int(portResp.Port)
|
||||
ports = append(ports, port)
|
||||
tcpConfig.Listen = []*serverconfigs.NetworkAddressConfig{
|
||||
{
|
||||
Protocol: serverconfigs.ProtocolTCP,
|
||||
Host: "",
|
||||
PortRange: strconv.Itoa(port),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TLS
|
||||
if lists.ContainsString(params.Protocols, "tls") {
|
||||
tlsConfig.IsOn = true
|
||||
|
||||
if canSpecifyTCPPort {
|
||||
for _, port := range params.TlsPorts {
|
||||
tlsConfig.Listen = append(tlsConfig.Listen, &serverconfigs.NetworkAddressConfig{
|
||||
Protocol: serverconfigs.ProtocolTLS,
|
||||
Host: "",
|
||||
PortRange: strconv.Itoa(port),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
var port int
|
||||
|
||||
// 尝试N次
|
||||
for i := 0; i < 5; i++ {
|
||||
// 获取随机端口
|
||||
portResp, err := this.RPC().NodeClusterRPC().FindFreePortInNodeCluster(this.UserContext(), &pb.FindFreePortInNodeClusterRequest{
|
||||
NodeClusterId: clusterId,
|
||||
ProtocolFamily: "tcp",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
p := int(portResp.Port)
|
||||
if !lists.ContainsInt(ports, p) {
|
||||
port = p
|
||||
break
|
||||
}
|
||||
}
|
||||
if port == 0 {
|
||||
this.Fail("无法找到可用的端口,请稍后重试")
|
||||
}
|
||||
tlsConfig.Listen = []*serverconfigs.NetworkAddressConfig{
|
||||
{
|
||||
Protocol: serverconfigs.ProtocolTLS,
|
||||
Host: "",
|
||||
PortRange: strconv.Itoa(port),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if len(params.CertIdsJSON) == 0 {
|
||||
this.Fail("请选择或者上传TLS证书")
|
||||
}
|
||||
certIds := []int64{}
|
||||
err := json.Unmarshal(params.CertIdsJSON, &certIds)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(certIds) == 0 {
|
||||
this.Fail("请选择或者上传TLS证书")
|
||||
}
|
||||
|
||||
certRefs := []*sslconfigs.SSLCertRef{}
|
||||
for _, certId := range certIds {
|
||||
certRefs = append(certRefs, &sslconfigs.SSLCertRef{
|
||||
IsOn: true,
|
||||
CertId: certId,
|
||||
})
|
||||
}
|
||||
certRefsJSON, err := json.Marshal(certRefs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建策略
|
||||
sslPolicyIdResp, err := this.RPC().SSLPolicyRPC().CreateSSLPolicy(this.UserContext(), &pb.CreateSSLPolicyRequest{
|
||||
Http2Enabled: false,
|
||||
Http3Enabled: false,
|
||||
MinVersion: "TLS 1.1",
|
||||
SslCertsJSON: certRefsJSON,
|
||||
HstsJSON: nil,
|
||||
ClientAuthType: 0,
|
||||
ClientCACertsJSON: nil,
|
||||
CipherSuites: nil,
|
||||
CipherSuitesIsOn: false,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
tlsConfig.SSLPolicyRef = &sslconfigs.SSLPolicyRef{
|
||||
IsOn: true,
|
||||
SSLPolicyId: sslPolicyIdResp.SslPolicyId,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UDP
|
||||
if serverType == serverconfigs.ServerTypeUDPProxy {
|
||||
if lists.ContainsString(params.Protocols, "udp") {
|
||||
udpConfig.IsOn = true
|
||||
|
||||
if canSpecifyUDPPort {
|
||||
for _, port := range params.UdpPorts {
|
||||
udpConfig.Listen = append(udpConfig.Listen, &serverconfigs.NetworkAddressConfig{
|
||||
Protocol: serverconfigs.ProtocolUDP,
|
||||
Host: "",
|
||||
PortRange: strconv.Itoa(port),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// 获取随机端口
|
||||
portResp, err := this.RPC().NodeClusterRPC().FindFreePortInNodeCluster(this.UserContext(), &pb.FindFreePortInNodeClusterRequest{
|
||||
NodeClusterId: clusterId,
|
||||
ProtocolFamily: "udp",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
port := int(portResp.Port)
|
||||
udpConfig.Listen = []*serverconfigs.NetworkAddressConfig{
|
||||
{
|
||||
Protocol: serverconfigs.ProtocolUDP,
|
||||
Host: "",
|
||||
PortRange: strconv.Itoa(port),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 源站信息
|
||||
originMaps := []maps.Map{}
|
||||
if len(params.OriginsJSON) == 0 {
|
||||
this.Fail("请输入源站信息")
|
||||
}
|
||||
err = json.Unmarshal(params.OriginsJSON, &originMaps)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(originMaps) == 0 {
|
||||
this.Fail("请输入源站信息")
|
||||
}
|
||||
primaryOriginRefs := []*serverconfigs.OriginRef{}
|
||||
backupOriginRefs := []*serverconfigs.OriginRef{}
|
||||
for _, originMap := range originMaps {
|
||||
host := originMap.GetString("host")
|
||||
isPrimary := originMap.GetBool("isPrimary")
|
||||
scheme := originMap.GetString("scheme")
|
||||
|
||||
if len(host) == 0 {
|
||||
this.Fail("源站地址不能为空")
|
||||
}
|
||||
addrHost, addrPort, err := net.SplitHostPort(host)
|
||||
if err != nil {
|
||||
this.Fail("源站地址'" + host + "'格式错误")
|
||||
}
|
||||
|
||||
if (serverType == serverconfigs.ServerTypeTCPProxy && scheme != "tcp" && scheme != "tls") ||
|
||||
(serverType == serverconfigs.ServerTypeUDPProxy && scheme != "udp") {
|
||||
this.Fail("错误的源站协议")
|
||||
}
|
||||
|
||||
originIdResp, err := this.RPC().OriginRPC().CreateOrigin(this.UserContext(), &pb.CreateOriginRequest{
|
||||
Name: "",
|
||||
Addr: &pb.NetworkAddress{
|
||||
Protocol: scheme,
|
||||
Host: addrHost,
|
||||
PortRange: addrPort,
|
||||
},
|
||||
Description: "",
|
||||
Weight: 10,
|
||||
IsOn: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if isPrimary {
|
||||
primaryOriginRefs = append(primaryOriginRefs, &serverconfigs.OriginRef{
|
||||
IsOn: true,
|
||||
OriginId: originIdResp.OriginId,
|
||||
})
|
||||
} else {
|
||||
backupOriginRefs = append(backupOriginRefs, &serverconfigs.OriginRef{
|
||||
IsOn: true,
|
||||
OriginId: originIdResp.OriginId,
|
||||
})
|
||||
}
|
||||
}
|
||||
primaryOriginsJSON, err := json.Marshal(primaryOriginRefs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
backupOriginsJSON, err := json.Marshal(backupOriginRefs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
scheduling := &serverconfigs.SchedulingConfig{
|
||||
Code: "random",
|
||||
Options: nil,
|
||||
}
|
||||
schedulingJSON, err := json.Marshal(scheduling)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 反向代理
|
||||
reverseProxyResp, err := this.RPC().ReverseProxyRPC().CreateReverseProxy(this.UserContext(), &pb.CreateReverseProxyRequest{
|
||||
SchedulingJSON: schedulingJSON,
|
||||
PrimaryOriginsJSON: primaryOriginsJSON,
|
||||
BackupOriginsJSON: backupOriginsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
reverseProxyId := reverseProxyResp.ReverseProxyId
|
||||
reverseProxyRef := &serverconfigs.ReverseProxyRef{
|
||||
IsPrior: false,
|
||||
IsOn: true,
|
||||
ReverseProxyId: reverseProxyId,
|
||||
}
|
||||
reverseProxyRefJSON, err := json.Marshal(reverseProxyRef)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 开始保存
|
||||
var tcpJSON []byte
|
||||
var tlsJSON []byte
|
||||
var udpJSON []byte
|
||||
if tcpConfig.IsOn {
|
||||
tcpJSON, err = tcpConfig.AsJSON()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if tlsConfig.IsOn {
|
||||
tlsJSON, err = tlsConfig.AsJSON()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if udpConfig.IsOn {
|
||||
udpJSON, err = udpConfig.AsJSON()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().ServerRPC().CreateServer(this.UserContext(), &pb.CreateServerRequest{
|
||||
UserId: this.UserId(),
|
||||
AdminId: 0,
|
||||
Type: serverType,
|
||||
Name: params.Name,
|
||||
Description: "",
|
||||
ServerNamesJSON: []byte("[]"),
|
||||
HttpJSON: nil,
|
||||
HttpsJSON: nil,
|
||||
TcpJSON: tcpJSON,
|
||||
TlsJSON: tlsJSON,
|
||||
UdpJSON: udpJSON,
|
||||
WebId: 0,
|
||||
ReverseProxyJSON: reverseProxyRefJSON,
|
||||
ServerGroupIds: nil,
|
||||
NodeClusterId: clusterId,
|
||||
IncludeNodesJSON: nil,
|
||||
ExcludeNodesJSON: nil,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
serverId := createResp.ServerId
|
||||
|
||||
defer this.CreateLogInfo(codes.Server_LogCreateServer, serverId)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
25
EdgeUser/internal/web/actions/default/lb/delete.go
Normal file
25
EdgeUser/internal/web/actions/default/lb/delete.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package lb
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.Server_LogDeleteServer, params.ServerId)
|
||||
|
||||
_, err := this.RPC().ServerRPC().DeleteServer(this.UserContext(), &pb.DeleteServerRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
213
EdgeUser/internal/web/actions/default/lb/index.go
Normal file
213
EdgeUser/internal/web/actions/default/lb/index.go
Normal file
@@ -0,0 +1,213 @@
|
||||
package lb
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
// 更新用户可用状态
|
||||
stateResp, err := this.RPC().UserRPC().RenewUserServersState(this.UserContext(), &pb.RenewUserServersStateRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["serversIsEnabled"] = stateResp.IsEnabled
|
||||
|
||||
// 提醒有逾期未支付的账单
|
||||
this.Data["countUnpaidBills"] = 0
|
||||
priceConfig, _ := configloaders.LoadCacheableUserPriceConfig()
|
||||
if priceConfig != nil && priceConfig.IsOn && priceConfig.UnpaidBillPolicy.IsOn && (priceConfig.UnpaidBillPolicy.MinDailyBillDays > 0 || priceConfig.UnpaidBillPolicy.MinMonthlyBillDays > 0) {
|
||||
countResp, err := this.RPC().UserBillRPC().CountAllUserBills(this.UserContext(), &pb.CountAllUserBillsRequest{
|
||||
PaidFlag: 0,
|
||||
UserId: this.UserId(),
|
||||
Month: "",
|
||||
TrafficRelated: true,
|
||||
MinDailyBillDays: priceConfig.UnpaidBillPolicy.MinDailyBillDays,
|
||||
MinMonthlyBillDays: priceConfig.UnpaidBillPolicy.MinMonthlyBillDays,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["countUnpaidBills"] = countResp.Count
|
||||
}
|
||||
|
||||
var supportTCP = this.ValidateFeature(userconfigs.UserFeatureCodeServerTCP, 0)
|
||||
var supportUDP = this.ValidateFeature(userconfigs.UserFeatureCodeServerUDP, 0)
|
||||
if !supportTCP && !supportUDP {
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["supportTCP"] = supportTCP
|
||||
this.Data["supportUDP"] = supportUDP
|
||||
|
||||
var protocols = []string{}
|
||||
if supportTCP {
|
||||
protocols = append(protocols, "tcp")
|
||||
}
|
||||
if supportUDP {
|
||||
protocols = append(protocols, "udp")
|
||||
}
|
||||
|
||||
countResp, err := this.RPC().ServerRPC().CountAllEnabledServersMatch(this.UserContext(), &pb.CountAllEnabledServersMatchRequest{
|
||||
ServerGroupId: 0,
|
||||
Keyword: "",
|
||||
UserId: this.UserId(),
|
||||
ProtocolFamily: strings.Join(protocols, ","),
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var count = countResp.Count
|
||||
var page = this.NewPage(count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
serversResp, err := this.RPC().ServerRPC().ListEnabledServersMatch(this.UserContext(), &pb.ListEnabledServersMatchRequest{
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
ServerGroupId: 0,
|
||||
Keyword: "",
|
||||
ProtocolFamily: strings.Join(protocols, ","),
|
||||
UserId: this.UserId(),
|
||||
IgnoreSSLCerts: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var serverMaps = []maps.Map{}
|
||||
for _, server := range serversResp.Servers {
|
||||
// CNAME
|
||||
var cname = ""
|
||||
if server.NodeCluster != nil {
|
||||
clusterId := server.NodeCluster.Id
|
||||
if clusterId > 0 {
|
||||
dnsInfoResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeClusterDNS(this.UserContext(), &pb.FindEnabledNodeClusterDNSRequest{NodeClusterId: clusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if dnsInfoResp.Domain != nil {
|
||||
cname = server.DnsName + "." + dnsInfoResp.Domain.Name + "."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TCP
|
||||
var tcpPorts = []string{}
|
||||
if len(server.TcpJSON) > 0 {
|
||||
config, err := serverconfigs.NewTCPProtocolConfigFromJSON(server.TcpJSON)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if config.IsOn {
|
||||
for _, listen := range config.Listen {
|
||||
tcpPorts = append(tcpPorts, listen.PortRange)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TLS
|
||||
var tlsPorts = []string{}
|
||||
if len(server.TlsJSON) > 0 {
|
||||
config, err := serverconfigs.NewTLSProtocolConfigFromJSON(server.TlsJSON)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if config.IsOn {
|
||||
for _, listen := range config.Listen {
|
||||
tlsPorts = append(tlsPorts, listen.PortRange)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UDP
|
||||
var udpPorts = []string{}
|
||||
if len(server.UdpJSON) > 0 {
|
||||
config, err := serverconfigs.NewUDPProtocolConfigFromJSON(server.UdpJSON)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if config.IsOn {
|
||||
for _, listen := range config.Listen {
|
||||
udpPorts = append(udpPorts, listen.PortRange)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 套餐
|
||||
var userPlanMap = maps.Map{"id": 0}
|
||||
if server.UserPlanId > 0 {
|
||||
userPlanResp, err := this.RPC().UserPlanRPC().FindEnabledUserPlan(this.UserContext(), &pb.FindEnabledUserPlanRequest{
|
||||
UserPlanId: server.UserPlanId,
|
||||
})
|
||||
if err != nil {
|
||||
if !utils.IsNotFound(err) {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
var userPlan = userPlanResp.UserPlan
|
||||
if userPlan != nil && userPlan.Plan != nil {
|
||||
if len(userPlan.Name) == 0 {
|
||||
userPlan.Name = userPlan.Plan.Name
|
||||
}
|
||||
userPlanMap = maps.Map{
|
||||
"id": userPlan.Id,
|
||||
"name": userPlan.Name,
|
||||
"dayTo": userPlan.DayTo,
|
||||
"isExpired": userPlan.DayTo <= timeutil.Format("Y-m-d"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 域名和限流状态
|
||||
var trafficLimitStatus *serverconfigs.TrafficLimitStatus
|
||||
if len(server.Config) > 0 {
|
||||
var serverConfig = &serverconfigs.ServerConfig{}
|
||||
err = json.Unmarshal(server.Config, serverConfig)
|
||||
if err == nil {
|
||||
if serverConfig.TrafficLimitStatus != nil && serverConfig.TrafficLimitStatus.IsValid() {
|
||||
trafficLimitStatus = serverConfig.TrafficLimitStatus
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serverMaps = append(serverMaps, maps.Map{
|
||||
"id": server.Id,
|
||||
"name": server.Name,
|
||||
"cname": cname,
|
||||
"tcpPorts": tcpPorts,
|
||||
"tlsPorts": tlsPorts,
|
||||
"udpPorts": udpPorts,
|
||||
"isOn": server.IsOn,
|
||||
"userPlan": userPlanMap,
|
||||
"trafficLimitStatus": trafficLimitStatus,
|
||||
})
|
||||
}
|
||||
this.Data["servers"] = serverMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
21
EdgeUser/internal/web/actions/default/lb/init.go
Normal file
21
EdgeUser/internal/web/actions/default/lb/init.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package lb
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Data("teaMenu", "lb").
|
||||
Prefix("/lb").
|
||||
GetPost("", new(IndexAction)).
|
||||
GetPost("/create", new(CreateAction)).
|
||||
Post("/updateOn", new(UpdateOnAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
Get("/server", new(ServerAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
21
EdgeUser/internal/web/actions/default/lb/server.go
Normal file
21
EdgeUser/internal/web/actions/default/lb/server.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package lb
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type ServerAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *ServerAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *ServerAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
// TODO 先跳转到设置页面,将来实现日志查看、统计看板等
|
||||
this.RedirectURL("/lb/server/settings/basic?serverId=" + numberutils.FormatInt64(params.ServerId))
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("basic")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
resp, err := this.RPC().ServerRPC().FindEnabledUserServerBasic(this.UserContext(), &pb.FindEnabledUserServerBasicRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
server := resp.Server
|
||||
if server == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["name"] = server.Name
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
Name string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入服务名称")
|
||||
|
||||
_, err := this.RPC().ServerRPC().UpdateEnabledUserServerBasic(this.UserContext(), &pb.UpdateEnabledUserServerBasicRequest{
|
||||
ServerId: params.ServerId,
|
||||
Name: params.Name,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/lb/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/lb/server/settings/basic").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("dns")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
dnsInfoResp, err := this.RPC().ServerRPC().FindEnabledServerDNS(this.UserContext(), &pb.FindEnabledServerDNSRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["dnsName"] = dnsInfoResp.DnsName
|
||||
if dnsInfoResp.Domain != nil {
|
||||
this.Data["dnsDomain"] = dnsInfoResp.Domain.Name
|
||||
} else {
|
||||
this.Data["dnsDomain"] = ""
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/lb/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/lb/server/settings/dns").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package plan
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// DataAction 套餐相关数据
|
||||
type DataAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DataAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
UserPlanId int64
|
||||
}) {
|
||||
userPlanResp, err := this.RPC().UserPlanRPC().FindEnabledUserPlan(this.UserContext(), &pb.FindEnabledUserPlanRequest{UserPlanId: params.UserPlanId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var userPlan = userPlanResp.UserPlan
|
||||
if userPlan == nil || userPlan.Plan == nil {
|
||||
this.NotFound("userPlan", params.UserPlanId)
|
||||
return
|
||||
}
|
||||
var plan = userPlan.Plan
|
||||
|
||||
// 网站数
|
||||
countServersResp, err := this.RPC().ServerRPC().CountAllUserServers(this.UserContext(), &pb.CountAllUserServersRequest{
|
||||
UserPlanId: params.UserPlanId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["servers"] = maps.Map{
|
||||
"current": countServersResp.Count,
|
||||
"max": plan.TotalServers,
|
||||
"isValid": plan.TotalServers <= 0 || countServersResp.Count+1 <= int64(plan.TotalServers),
|
||||
}
|
||||
|
||||
// 当前网站域名数
|
||||
countServerNamesResp, err := this.RPC().ServerRPC().CountServerNames(this.UserContext(), &pb.CountServerNamesRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["serverNames"] = maps.Map{
|
||||
"current": countServerNamesResp.Count,
|
||||
"max": plan.TotalServerNamesPerServer,
|
||||
"isValid": plan.TotalServerNamesPerServer <= 0 || countServerNamesResp.Count <= int64(plan.TotalServerNamesPerServer),
|
||||
}
|
||||
|
||||
// 总域名数
|
||||
countAllServerNamesResp, err := this.RPC().ServerRPC().CountAllServerNamesWithUserId(this.UserContext(), &pb.CountAllServerNamesWithUserIdRequest{
|
||||
UserPlanId: params.UserPlanId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["allServerNames"] = maps.Map{
|
||||
"current": countAllServerNamesResp.Count,
|
||||
"max": plan.TotalServerNames,
|
||||
"isValid": plan.TotalServerNames <= 0 || countAllServerNamesResp.Count+countServerNamesResp.Count <= int64(plan.TotalServerNames),
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package plan
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("plan")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
if !this.ValidateFeature(userconfigs.UserFeatureCodePlan, params.ServerId) {
|
||||
return
|
||||
}
|
||||
|
||||
// 所有可选套餐
|
||||
userPlansResp, err := this.RPC().UserPlanRPC().FindAllEnabledUserPlansForServer(this.UserContext(), &pb.FindAllEnabledUserPlansForServerRequest{
|
||||
UserId: this.UserId(),
|
||||
ServerId: params.ServerId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var userPlanMaps = []maps.Map{}
|
||||
for _, userPlan := range userPlansResp.UserPlans {
|
||||
if userPlan.Plan == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var name = userPlan.Plan.Name
|
||||
if len(userPlan.Name) > 0 {
|
||||
name += "-" + userPlan.Name
|
||||
}
|
||||
|
||||
userPlanMaps = append(userPlanMaps, maps.Map{
|
||||
"id": userPlan.Id,
|
||||
"name": name,
|
||||
"dayTo": userPlan.DayTo,
|
||||
"totalServers": userPlan.Plan.TotalServers,
|
||||
"totalServerNames": userPlan.Plan.TotalServerNames,
|
||||
"totalServerNamesPerServer": userPlan.Plan.TotalServerNamesPerServer,
|
||||
})
|
||||
}
|
||||
this.Data["userPlans"] = userPlanMaps
|
||||
|
||||
// 当前使用的套餐
|
||||
userPlanResp, err := this.RPC().ServerRPC().FindServerUserPlan(this.UserContext(), &pb.FindServerUserPlanRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 用户套餐信息
|
||||
var userPlanMap = maps.Map{"id": 0}
|
||||
var userPlan = userPlanResp.UserPlan
|
||||
this.Data["hasTrafficLimit"] = false
|
||||
if userPlan != nil {
|
||||
userPlanMap = maps.Map{
|
||||
"id": userPlan.Id,
|
||||
"dayTo": userPlan.DayTo,
|
||||
"isExpired": timeutil.Format("Y-m-d") > userPlan.DayTo,
|
||||
"name": userPlan.Name,
|
||||
"plan": nil,
|
||||
}
|
||||
|
||||
var plan = userPlan.Plan
|
||||
if plan != nil {
|
||||
// 流量限制
|
||||
var trafficLimit = &serverconfigs.TrafficLimitConfig{}
|
||||
if len(plan.TrafficLimitJSON) > 0 {
|
||||
err = json.Unmarshal(plan.TrafficLimitJSON, trafficLimit)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
userPlanMap["plan"] = maps.Map{
|
||||
"id": plan.Id,
|
||||
"name": plan.Name,
|
||||
"trafficLimit": trafficLimit,
|
||||
}
|
||||
|
||||
if !trafficLimit.IsEmpty() {
|
||||
this.Data["hasTrafficLimit"] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["userPlan"] = userPlanMap
|
||||
|
||||
// 当前网站流量
|
||||
{
|
||||
trafficStatResp, err := this.RPC().ServerDailyRPC().SumServerDailyStats(this.UserContext(), &pb.SumServerDailyStatsRequest{
|
||||
ServerId: params.ServerId,
|
||||
Day: timeutil.Format("Ymd"),
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var trafficDailyBytes int64 = 0
|
||||
if trafficStatResp.ServerDailyStat != nil {
|
||||
trafficDailyBytes = trafficStatResp.ServerDailyStat.Bytes
|
||||
}
|
||||
this.Data["trafficDailyFormat"] = numberutils.FormatBytes(trafficDailyBytes)
|
||||
}
|
||||
|
||||
{
|
||||
trafficStatResp, err := this.RPC().ServerDailyRPC().SumServerMonthlyStats(this.UserContext(), &pb.SumServerMonthlyStatsRequest{
|
||||
ServerId: params.ServerId,
|
||||
Month: timeutil.Format("Ym"),
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var trafficMonthlyBytes int64 = 0
|
||||
if trafficStatResp.ServerMonthlyStat != nil {
|
||||
trafficMonthlyBytes = trafficStatResp.ServerMonthlyStat.Bytes
|
||||
}
|
||||
this.Data["trafficMonthlyFormat"] = numberutils.FormatBytes(trafficMonthlyBytes)
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
|
||||
IsChanged bool
|
||||
UserPlanId int64
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
if !params.IsChanged {
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
|
||||
if params.UserPlanId <= 0 { // 取消绑定
|
||||
defer this.CreateLogInfo(codes.UserPlan_LogCancelUserPlanFromServer, params.ServerId)
|
||||
} else { // 变更绑定
|
||||
defer this.CreateLogInfo(codes.UserPlan_LogBindUserPlanToServer, params.ServerId, params.UserPlanId)
|
||||
}
|
||||
|
||||
// 前后套餐是否一致
|
||||
oldUserPlanResp, err := this.RPC().ServerRPC().FindServerUserPlan(this.UserContext(), &pb.FindServerUserPlanRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if oldUserPlanResp.UserPlan != nil && oldUserPlanResp.UserPlan.Id == params.UserPlanId {
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
|
||||
// 检查套餐
|
||||
if params.UserPlanId > 0 {
|
||||
userPlanResp, err := this.RPC().UserPlanRPC().FindEnabledUserPlan(this.UserContext(), &pb.FindEnabledUserPlanRequest{UserPlanId: params.UserPlanId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var userPlan = userPlanResp.UserPlan
|
||||
if userPlan == nil || userPlan.Plan == nil {
|
||||
this.NotFound("userPlan", params.UserPlanId)
|
||||
return
|
||||
}
|
||||
var plan = userPlan.Plan
|
||||
|
||||
// server
|
||||
if plan.TotalServers > 0 {
|
||||
countServersResp, err := this.RPC().ServerRPC().CountAllUserServers(this.UserContext(), &pb.CountAllUserServersRequest{
|
||||
UserPlanId: params.UserPlanId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if countServersResp.Count+1 > int64(plan.TotalServers) {
|
||||
this.Fail("已绑定网站数超出当前套餐限制")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
countServerNamesResp, err := this.RPC().ServerRPC().CountServerNames(this.UserContext(), &pb.CountServerNamesRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if plan.TotalServerNamesPerServer > 0 {
|
||||
if countServerNamesResp.Count > int64(plan.TotalServerNamesPerServer) {
|
||||
this.Fail("当前网站域名数超出当前套餐限制")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if plan.TotalServerNames > 0 {
|
||||
countAllServerNamesResp, err := this.RPC().ServerRPC().CountAllServerNamesWithUserId(this.UserContext(), &pb.CountAllServerNamesWithUserIdRequest{
|
||||
UserPlanId: params.UserPlanId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if countAllServerNamesResp.Count+countServerNamesResp.Count > int64(plan.TotalServerNames) {
|
||||
this.Fail("已绑定域名数超出当前套餐限制")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 提交修改
|
||||
_, err = this.RPC().ServerRPC().UpdateServerUserPlan(this.UserContext(), &pb.UpdateServerUserPlanRequest{
|
||||
ServerId: params.ServerId,
|
||||
UserPlanId: params.UserPlanId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package plan
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/lb/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/lb/server/settings/plan").
|
||||
GetPost("", new(IndexAction)).
|
||||
Post("/data", new(DataAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package reverseProxy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// IndexAction 源站列表
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.FirstMenu("index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
serverTypeResp, err := this.RPC().ServerRPC().FindEnabledServerType(this.UserContext(), &pb.FindEnabledServerTypeRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var serverType = serverTypeResp.Type
|
||||
|
||||
reverseProxyResp, err := this.RPC().ServerRPC().FindAndInitServerReverseProxyConfig(this.UserContext(), &pb.FindAndInitServerReverseProxyConfigRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var reverseProxyRef = &serverconfigs.ReverseProxyRef{}
|
||||
err = json.Unmarshal(reverseProxyResp.ReverseProxyRefJSON, reverseProxyRef)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["reverseProxyRef"] = reverseProxyRef
|
||||
|
||||
reverseProxy := &serverconfigs.ReverseProxyConfig{}
|
||||
err = json.Unmarshal(reverseProxyResp.ReverseProxyJSON, reverseProxy)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["reverseProxyConfig"] = reverseProxy
|
||||
|
||||
this.Data["serverType"] = serverType
|
||||
|
||||
var primaryOriginMaps = []maps.Map{}
|
||||
backupOriginMaps := []maps.Map{}
|
||||
for _, originConfig := range reverseProxy.PrimaryOrigins {
|
||||
var domains = originConfig.Domains
|
||||
if len(domains) == 0 {
|
||||
domains = []string{}
|
||||
}
|
||||
|
||||
var m = maps.Map{
|
||||
"id": originConfig.Id,
|
||||
"weight": originConfig.Weight,
|
||||
"addr": originConfig.AddrSummary(),
|
||||
"isOSS": originConfig.IsOSS(),
|
||||
"name": originConfig.Name,
|
||||
"isOn": originConfig.IsOn,
|
||||
"hasCert": originConfig.Cert != nil,
|
||||
"host": originConfig.RequestHost,
|
||||
"followPort": originConfig.FollowPort,
|
||||
"http2Enabled": originConfig.HTTP2Enabled,
|
||||
"domains": domains,
|
||||
}
|
||||
primaryOriginMaps = append(primaryOriginMaps, m)
|
||||
}
|
||||
for _, originConfig := range reverseProxy.BackupOrigins {
|
||||
var domains = originConfig.Domains
|
||||
if len(domains) == 0 {
|
||||
domains = []string{}
|
||||
}
|
||||
|
||||
var m = maps.Map{
|
||||
"id": originConfig.Id,
|
||||
"weight": originConfig.Weight,
|
||||
"addr": originConfig.AddrSummary(),
|
||||
"isOSS": originConfig.IsOSS(),
|
||||
"name": originConfig.Name,
|
||||
"isOn": originConfig.IsOn,
|
||||
"hasCert": originConfig.Cert != nil,
|
||||
"host": originConfig.RequestHost,
|
||||
"followPort": originConfig.FollowPort,
|
||||
"http2Enabled": originConfig.HTTP2Enabled,
|
||||
"domains": domains,
|
||||
}
|
||||
backupOriginMaps = append(backupOriginMaps, m)
|
||||
}
|
||||
this.Data["primaryOrigins"] = primaryOriginMaps
|
||||
this.Data["backupOrigins"] = backupOriginMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package reverseProxy
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/lb/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Data("mainTab", "setting").
|
||||
Data("secondMenuItem", "reverseProxy").
|
||||
Prefix("/lb/server/settings/reverseProxy").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/scheduling", new(SchedulingAction)).
|
||||
GetPost("/updateSchedulingPopup", new(UpdateSchedulingPopupAction)).
|
||||
GetPost("/setting", new(SettingAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package reverseProxy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/schedulingconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type SchedulingAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *SchedulingAction) Init() {
|
||||
this.FirstMenu("scheduling")
|
||||
}
|
||||
|
||||
func (this *SchedulingAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
reverseProxyResp, err := this.RPC().ServerRPC().FindAndInitServerReverseProxyConfig(this.UserContext(), &pb.FindAndInitServerReverseProxyConfigRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
reverseProxy := &serverconfigs.ReverseProxyConfig{}
|
||||
err = json.Unmarshal(reverseProxyResp.ReverseProxyJSON, reverseProxy)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["reverseProxyId"] = reverseProxy.Id
|
||||
|
||||
schedulingCode := reverseProxy.FindSchedulingConfig().Code
|
||||
schedulingMap := schedulingconfigs.FindSchedulingType(schedulingCode)
|
||||
if schedulingMap == nil {
|
||||
this.ErrorPage(errors.New("invalid scheduling code '" + schedulingCode + "'"))
|
||||
return
|
||||
}
|
||||
this.Data["scheduling"] = schedulingMap
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package reverseProxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type SettingAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *SettingAction) Init() {
|
||||
this.FirstMenu("setting")
|
||||
}
|
||||
|
||||
func (this *SettingAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
reverseProxyResp, err := this.RPC().ServerRPC().FindAndInitServerReverseProxyConfig(this.UserContext(), &pb.FindAndInitServerReverseProxyConfigRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
reverseProxyRef := &serverconfigs.ReverseProxyRef{}
|
||||
err = json.Unmarshal(reverseProxyResp.ReverseProxyRefJSON, reverseProxyRef)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
reverseProxy := &serverconfigs.ReverseProxyConfig{}
|
||||
err = json.Unmarshal(reverseProxyResp.ReverseProxyJSON, reverseProxy)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["reverseProxyRef"] = reverseProxyRef
|
||||
this.Data["reverseProxyConfig"] = reverseProxy
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *SettingAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
ReverseProxyRefJSON []byte
|
||||
ReverseProxyJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.ServerReverseProxy_LogUpdateServerReverseProxySettings, params.ServerId)
|
||||
|
||||
var reverseProxyConfig = &serverconfigs.ReverseProxyConfig{}
|
||||
err := json.Unmarshal(params.ReverseProxyJSON, reverseProxyConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
err = reverseProxyConfig.Init(context.TODO())
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
}
|
||||
|
||||
// 设置是否启用
|
||||
_, err = this.RPC().ServerRPC().UpdateServerReverseProxy(this.UserContext(), &pb.UpdateServerReverseProxyRequest{
|
||||
ServerId: params.ServerId,
|
||||
ReverseProxyJSON: params.ReverseProxyRefJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// PROXY Protocol
|
||||
var proxyProtocolJSON = []byte{}
|
||||
if reverseProxyConfig.ProxyProtocol != nil {
|
||||
proxyProtocolJSON, err = json.Marshal(reverseProxyConfig.ProxyProtocol)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 设置反向代理相关信息
|
||||
_, err = this.RPC().ReverseProxyRPC().UpdateReverseProxy(this.UserContext(), &pb.UpdateReverseProxyRequest{
|
||||
ReverseProxyId: reverseProxyConfig.Id,
|
||||
RequestHostType: types.Int32(reverseProxyConfig.RequestHostType),
|
||||
RequestHost: reverseProxyConfig.RequestHost,
|
||||
RequestURI: reverseProxyConfig.RequestURI,
|
||||
StripPrefix: reverseProxyConfig.StripPrefix,
|
||||
AutoFlush: reverseProxyConfig.AutoFlush,
|
||||
ProxyProtocolJSON: proxyProtocolJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package reverseProxy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/schedulingconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
// 修改调度算法
|
||||
type UpdateSchedulingPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateSchedulingPopupAction) Init() {
|
||||
}
|
||||
|
||||
func (this *UpdateSchedulingPopupAction) RunGet(params struct {
|
||||
Type string
|
||||
ServerId int64
|
||||
ReverseProxyId int64
|
||||
}) {
|
||||
serverConfig, err := dao.SharedServerDAO.FindEnabledServerConfig(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if serverConfig == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["dataType"] = params.Type
|
||||
this.Data["serverId"] = params.ServerId
|
||||
this.Data["reverseProxyId"] = params.ReverseProxyId
|
||||
|
||||
reverseProxyResp, err := this.RPC().ReverseProxyRPC().FindEnabledReverseProxyConfig(this.UserContext(), &pb.FindEnabledReverseProxyConfigRequest{
|
||||
ReverseProxyId: params.ReverseProxyId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
configData := reverseProxyResp.ReverseProxyJSON
|
||||
|
||||
reverseProxyConfig := &serverconfigs.ReverseProxyConfig{}
|
||||
err = json.Unmarshal(configData, reverseProxyConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
schedulingObject := &serverconfigs.SchedulingConfig{
|
||||
Code: "random",
|
||||
Options: nil,
|
||||
}
|
||||
if reverseProxyConfig.Scheduling != nil {
|
||||
schedulingObject = reverseProxyConfig.Scheduling
|
||||
}
|
||||
this.Data["scheduling"] = schedulingObject
|
||||
|
||||
// 调度类型
|
||||
schedulingTypes := []maps.Map{}
|
||||
for _, m := range schedulingconfigs.AllSchedulingTypes() {
|
||||
networks, ok := m["networks"]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if !types.IsSlice(networks) {
|
||||
continue
|
||||
}
|
||||
if (serverConfig.IsHTTPFamily() && lists.Contains(networks, "http")) ||
|
||||
(serverConfig.IsTCPFamily() && lists.Contains(networks, "tcp")) ||
|
||||
(serverConfig.IsUDPFamily() && lists.Contains(networks, "udp")) {
|
||||
schedulingTypes = append(schedulingTypes, m)
|
||||
}
|
||||
}
|
||||
this.Data["schedulingTypes"] = schedulingTypes
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateSchedulingPopupAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
ReverseProxyId int64
|
||||
|
||||
Type string
|
||||
HashKey string
|
||||
StickyType string
|
||||
StickyParam string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.ReverseProxy_LogUpdateReverseProxyScheduling, params.ReverseProxyId)
|
||||
|
||||
reverseProxyResp, err := this.RPC().ReverseProxyRPC().FindEnabledReverseProxyConfig(this.UserContext(), &pb.FindEnabledReverseProxyConfigRequest{ReverseProxyId: params.ReverseProxyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
configData := reverseProxyResp.ReverseProxyJSON
|
||||
reverseProxy := &serverconfigs.ReverseProxyConfig{}
|
||||
err = json.Unmarshal(configData, reverseProxy)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if reverseProxy.Scheduling == nil {
|
||||
reverseProxy.FindSchedulingConfig()
|
||||
}
|
||||
|
||||
options := maps.Map{}
|
||||
if params.Type == "hash" {
|
||||
params.Must.
|
||||
Field("hashKey", params.HashKey).
|
||||
Require("请输入Key")
|
||||
|
||||
options["key"] = params.HashKey
|
||||
} else if params.Type == "sticky" {
|
||||
params.Must.
|
||||
Field("stickyType", params.StickyType).
|
||||
Require("请选择参数类型").
|
||||
Field("stickyParam", params.StickyParam).
|
||||
Require("请输入参数名").
|
||||
Match("^[a-zA-Z0-9]+$", "参数名只能是英文字母和数字的组合").
|
||||
MaxCharacters(50, "参数名长度不能超过50位")
|
||||
|
||||
options["type"] = params.StickyType
|
||||
options["param"] = params.StickyParam
|
||||
}
|
||||
|
||||
if schedulingconfigs.FindSchedulingType(params.Type) == nil {
|
||||
this.Fail("不支持此种算法")
|
||||
}
|
||||
|
||||
reverseProxy.Scheduling.Code = params.Type
|
||||
reverseProxy.Scheduling.Options = options
|
||||
|
||||
schedulingData, err := json.Marshal(reverseProxy.Scheduling)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().ReverseProxyRPC().UpdateReverseProxyScheduling(this.UserContext(), &pb.UpdateReverseProxySchedulingRequest{
|
||||
ReverseProxyId: params.ReverseProxyId,
|
||||
SchedulingJSON: schedulingData,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
// IndexAction TCP设置
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("tcp")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.Data["canSpecifyPort"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerTCPPort, params.ServerId)
|
||||
|
||||
server, err := dao.SharedServerDAO.FindEnabledServer(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if server == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
tcpConfig := &serverconfigs.TCPProtocolConfig{}
|
||||
if len(server.TcpJSON) > 0 {
|
||||
err := json.Unmarshal(server.TcpJSON, tcpConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
} else {
|
||||
tcpConfig.IsOn = true
|
||||
}
|
||||
|
||||
this.Data["serverType"] = server.Type
|
||||
this.Data["tcpConfig"] = tcpConfig
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
ServerType string
|
||||
Addresses string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.ServerTCP_LogUpdateTCPSettings, params.ServerId)
|
||||
|
||||
canSpecifyPort := this.ValidateFeature(userconfigs.UserFeatureCodeServerTCPPort, params.ServerId)
|
||||
|
||||
server, err := dao.SharedServerDAO.FindEnabledServer(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if server == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
|
||||
addresses := []*serverconfigs.NetworkAddressConfig{}
|
||||
err = json.Unmarshal([]byte(params.Addresses), &addresses)
|
||||
if err != nil {
|
||||
this.Fail("端口地址解析失败:" + err.Error())
|
||||
}
|
||||
|
||||
// 检查端口是否被使用
|
||||
clusterIdResp, err := this.RPC().UserRPC().FindUserNodeClusterId(this.UserContext(), &pb.FindUserNodeClusterIdRequest{UserId: this.UserId()})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
clusterId := clusterIdResp.NodeClusterId
|
||||
if clusterId == 0 {
|
||||
this.Fail("当前用户没有指定集群,不能使用此服务")
|
||||
}
|
||||
for _, address := range addresses {
|
||||
port := types.Int32(address.PortRange)
|
||||
if port < 1024 || port > 65534 {
|
||||
this.Fail("'" + address.PortRange + "' 端口范围错误")
|
||||
}
|
||||
resp, err := this.RPC().NodeClusterRPC().CheckPortIsUsingInNodeCluster(this.UserContext(), &pb.CheckPortIsUsingInNodeClusterRequest{
|
||||
Port: port,
|
||||
NodeClusterId: clusterId,
|
||||
ExcludeServerId: params.ServerId,
|
||||
ExcludeProtocol: "tcp",
|
||||
ProtocolFamily: "tcp",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if resp.IsUsing {
|
||||
this.Fail("端口 '" + fmt.Sprintf("%d", port) + "' 正在被别的服务或者同服务其他网络协议使用,请换一个")
|
||||
}
|
||||
}
|
||||
|
||||
tcpConfig := &serverconfigs.TCPProtocolConfig{}
|
||||
if len(server.TcpJSON) > 0 {
|
||||
err := json.Unmarshal(server.TcpJSON, tcpConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
} else {
|
||||
tcpConfig.IsOn = true
|
||||
}
|
||||
if canSpecifyPort {
|
||||
tcpConfig.Listen = addresses
|
||||
}
|
||||
|
||||
configData, err := json.Marshal(tcpConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().ServerRPC().UpdateServerTCP(this.UserContext(), &pb.UpdateServerTCPRequest{
|
||||
ServerId: params.ServerId,
|
||||
TcpJSON: configData,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/lb/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/lb/server/settings/tcp").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
package tls
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
// IndexAction TLS设置
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("tls")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.Data["canSpecifyPort"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerTCPPort, params.ServerId)
|
||||
|
||||
server, err := dao.SharedServerDAO.FindEnabledServer(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if server == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
tlsConfig := &serverconfigs.TLSProtocolConfig{}
|
||||
if len(server.TlsJSON) > 0 {
|
||||
err := json.Unmarshal(server.TlsJSON, tlsConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
} else {
|
||||
tlsConfig.IsOn = true
|
||||
}
|
||||
|
||||
// SSL配置
|
||||
var sslPolicy *sslconfigs.SSLPolicy
|
||||
if tlsConfig.SSLPolicyRef != nil && tlsConfig.SSLPolicyRef.SSLPolicyId > 0 {
|
||||
sslPolicyConfigResp, err := this.RPC().SSLPolicyRPC().FindEnabledSSLPolicyConfig(this.UserContext(), &pb.FindEnabledSSLPolicyConfigRequest{
|
||||
SslPolicyId: tlsConfig.SSLPolicyRef.SSLPolicyId,
|
||||
IgnoreData: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
sslPolicyConfigJSON := sslPolicyConfigResp.SslPolicyJSON
|
||||
if len(sslPolicyConfigJSON) > 0 {
|
||||
sslPolicy = &sslconfigs.SSLPolicy{}
|
||||
err = json.Unmarshal(sslPolicyConfigJSON, sslPolicy)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["serverType"] = server.Type
|
||||
this.Data["tlsConfig"] = maps.Map{
|
||||
"isOn": tlsConfig.IsOn,
|
||||
"listen": tlsConfig.Listen,
|
||||
"sslPolicy": sslPolicy,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
ServerType string
|
||||
Addresses string
|
||||
|
||||
SslPolicyJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.ServerTLS_LogUpdateTLSSettings, params.ServerId)
|
||||
|
||||
canSpecifyPort := this.ValidateFeature(userconfigs.UserFeatureCodeServerTCPPort, params.ServerId)
|
||||
|
||||
server, err := dao.SharedServerDAO.FindEnabledServer(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if server == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
|
||||
addresses := []*serverconfigs.NetworkAddressConfig{}
|
||||
err = json.Unmarshal([]byte(params.Addresses), &addresses)
|
||||
if err != nil {
|
||||
this.Fail("端口地址解析失败:" + err.Error())
|
||||
}
|
||||
|
||||
// 检查端口是否被使用
|
||||
clusterIdResp, err := this.RPC().UserRPC().FindUserNodeClusterId(this.UserContext(), &pb.FindUserNodeClusterIdRequest{UserId: this.UserId()})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
clusterId := clusterIdResp.NodeClusterId
|
||||
if clusterId == 0 {
|
||||
this.Fail("当前用户没有指定集群,不能使用此服务")
|
||||
}
|
||||
for _, address := range addresses {
|
||||
port := types.Int32(address.PortRange)
|
||||
if port < 1024 || port > 65534 {
|
||||
this.Fail("'" + address.PortRange + "' 端口范围错误")
|
||||
}
|
||||
resp, err := this.RPC().NodeClusterRPC().CheckPortIsUsingInNodeCluster(this.UserContext(), &pb.CheckPortIsUsingInNodeClusterRequest{
|
||||
Port: port,
|
||||
NodeClusterId: clusterId,
|
||||
ExcludeServerId: params.ServerId,
|
||||
ExcludeProtocol: "tls",
|
||||
ProtocolFamily: "tcp",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if resp.IsUsing {
|
||||
this.Fail("端口 '" + fmt.Sprintf("%d", port) + "' 正在被别的服务或者同服务其他网络协议使用,请换一个")
|
||||
}
|
||||
}
|
||||
|
||||
// 校验SSL
|
||||
var sslPolicyId = int64(0)
|
||||
if params.SslPolicyJSON != nil {
|
||||
sslPolicy := &sslconfigs.SSLPolicy{}
|
||||
err = json.Unmarshal(params.SslPolicyJSON, sslPolicy)
|
||||
if err != nil {
|
||||
this.ErrorPage(errors.New("解析SSL配置时发生了错误:" + err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
sslPolicyId = sslPolicy.Id
|
||||
|
||||
certsJSON, err := json.Marshal(sslPolicy.CertRefs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
hstsJSON, err := json.Marshal(sslPolicy.HSTS)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
clientCACertsJSON, err := json.Marshal(sslPolicy.ClientCARefs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if sslPolicyId > 0 {
|
||||
_, err := this.RPC().SSLPolicyRPC().UpdateSSLPolicy(this.UserContext(), &pb.UpdateSSLPolicyRequest{
|
||||
SslPolicyId: sslPolicyId,
|
||||
Http2Enabled: sslPolicy.HTTP2Enabled,
|
||||
Http3Enabled: sslPolicy.HTTP3Enabled,
|
||||
MinVersion: sslPolicy.MinVersion,
|
||||
SslCertsJSON: certsJSON,
|
||||
HstsJSON: hstsJSON,
|
||||
ClientAuthType: types.Int32(sslPolicy.ClientAuthType),
|
||||
ClientCACertsJSON: clientCACertsJSON,
|
||||
CipherSuitesIsOn: sslPolicy.CipherSuitesIsOn,
|
||||
CipherSuites: sslPolicy.CipherSuites,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
resp, err := this.RPC().SSLPolicyRPC().CreateSSLPolicy(this.UserContext(), &pb.CreateSSLPolicyRequest{
|
||||
Http2Enabled: sslPolicy.HTTP2Enabled,
|
||||
Http3Enabled: sslPolicy.HTTP3Enabled,
|
||||
MinVersion: sslPolicy.MinVersion,
|
||||
SslCertsJSON: certsJSON,
|
||||
HstsJSON: hstsJSON,
|
||||
ClientAuthType: types.Int32(sslPolicy.ClientAuthType),
|
||||
ClientCACertsJSON: clientCACertsJSON,
|
||||
CipherSuitesIsOn: sslPolicy.CipherSuitesIsOn,
|
||||
CipherSuites: sslPolicy.CipherSuites,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
sslPolicyId = resp.SslPolicyId
|
||||
}
|
||||
}
|
||||
|
||||
tlsConfig := &serverconfigs.TLSProtocolConfig{}
|
||||
if len(server.TlsJSON) > 0 {
|
||||
err := json.Unmarshal(server.TlsJSON, tlsConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
} else {
|
||||
tlsConfig.IsOn = true
|
||||
}
|
||||
if canSpecifyPort {
|
||||
tlsConfig.Listen = addresses
|
||||
}
|
||||
|
||||
tlsConfig.SSLPolicyRef = &sslconfigs.SSLPolicyRef{
|
||||
IsOn: true,
|
||||
SSLPolicyId: sslPolicyId,
|
||||
}
|
||||
|
||||
configData, err := json.Marshal(tlsConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().ServerRPC().UpdateServerTLS(this.UserContext(), &pb.UpdateServerTLSRequest{
|
||||
ServerId: params.ServerId,
|
||||
TlsJSON: configData,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package tls
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/lb/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/lb/server/settings/tls").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package udp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
// IndexAction UDP设置
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("udp")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.Data["canSpecifyPort"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerUDPPort, params.ServerId)
|
||||
|
||||
server, err := dao.SharedServerDAO.FindEnabledServer(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if server == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
|
||||
udpConfig := &serverconfigs.UDPProtocolConfig{}
|
||||
if len(server.UdpJSON) > 0 {
|
||||
err := json.Unmarshal(server.UdpJSON, udpConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
} else {
|
||||
udpConfig.IsOn = true
|
||||
}
|
||||
|
||||
this.Data["serverType"] = server.Type
|
||||
this.Data["udpConfig"] = udpConfig
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
ServerType string
|
||||
Addresses string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.ServerUDP_LogUpdateUDPSettings, params.ServerId)
|
||||
|
||||
canSpecifyPort := this.ValidateFeature(userconfigs.UserFeatureCodeServerUDPPort, params.ServerId)
|
||||
|
||||
server, err := dao.SharedServerDAO.FindEnabledServer(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if server == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
|
||||
addresses := []*serverconfigs.NetworkAddressConfig{}
|
||||
err = json.Unmarshal([]byte(params.Addresses), &addresses)
|
||||
if err != nil {
|
||||
this.Fail("端口地址解析失败:" + err.Error())
|
||||
}
|
||||
|
||||
// 检查端口是否被使用
|
||||
clusterIdResp, err := this.RPC().UserRPC().FindUserNodeClusterId(this.UserContext(), &pb.FindUserNodeClusterIdRequest{UserId: this.UserId()})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
clusterId := clusterIdResp.NodeClusterId
|
||||
if clusterId == 0 {
|
||||
this.Fail("当前用户没有指定集群,不能使用此服务")
|
||||
}
|
||||
for _, address := range addresses {
|
||||
port := types.Int32(address.PortRange)
|
||||
if port < 1024 || port > 65534 {
|
||||
this.Fail("'" + address.PortRange + "' 端口范围错误")
|
||||
}
|
||||
resp, err := this.RPC().NodeClusterRPC().CheckPortIsUsingInNodeCluster(this.UserContext(), &pb.CheckPortIsUsingInNodeClusterRequest{
|
||||
Port: port,
|
||||
NodeClusterId: clusterId,
|
||||
ExcludeServerId: params.ServerId,
|
||||
ProtocolFamily: "udp",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if resp.IsUsing {
|
||||
this.Fail("端口 '" + fmt.Sprintf("%d", port) + "' 正在被别的服务或者同服务其他网络协议使用,请换一个")
|
||||
}
|
||||
}
|
||||
|
||||
udpConfig := &serverconfigs.UDPProtocolConfig{}
|
||||
if len(server.UdpJSON) > 0 {
|
||||
err := json.Unmarshal(server.UdpJSON, udpConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
} else {
|
||||
udpConfig.IsOn = true
|
||||
}
|
||||
|
||||
if canSpecifyPort {
|
||||
udpConfig.Listen = addresses
|
||||
}
|
||||
|
||||
configData, err := json.Marshal(udpConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().ServerRPC().UpdateServerUDP(this.UserContext(), &pb.UpdateServerUDPRequest{
|
||||
ServerId: params.ServerId,
|
||||
UdpJSON: configData,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package udp
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/lb/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/lb/server/settings/udp").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
package serverutils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/rpc"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type ServerHelper struct {
|
||||
}
|
||||
|
||||
func NewServerHelper() *ServerHelper {
|
||||
return &ServerHelper{}
|
||||
}
|
||||
|
||||
func (this *ServerHelper) BeforeAction(action *actions.ActionObject) {
|
||||
if action.Request.Method != http.MethodGet {
|
||||
return
|
||||
}
|
||||
|
||||
action.Data["teaMenu"] = "lb"
|
||||
|
||||
// 左侧菜单
|
||||
this.createLeftMenu(action)
|
||||
}
|
||||
|
||||
func (this *ServerHelper) createLeftMenu(action *actions.ActionObject) {
|
||||
// 初始化
|
||||
if !action.Data.Has("leftMenuItemIsDisabled") {
|
||||
action.Data["leftMenuItemIsDisabled"] = false
|
||||
}
|
||||
action.Data["leftMenuItems"] = []maps.Map{}
|
||||
var mainTab = action.Data["mainTab"]
|
||||
var secondMenuItem = action.Data["secondMenuItem"]
|
||||
|
||||
serverId := action.ParamInt64("serverId")
|
||||
if serverId == 0 {
|
||||
return
|
||||
}
|
||||
serverIdString := strconv.FormatInt(serverId, 10)
|
||||
action.Data["serverId"] = serverId
|
||||
|
||||
// 读取server信息
|
||||
rpcClient, err := rpc.SharedRPC()
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
userId := action.Context.GetInt64("userId")
|
||||
ctx := rpcClient.Context(userId)
|
||||
serverResp, err := rpcClient.ServerRPC().FindEnabledServer(ctx, &pb.FindEnabledServerRequest{
|
||||
ServerId: serverId,
|
||||
IgnoreSSLCerts: true,
|
||||
})
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return
|
||||
}
|
||||
server := serverResp.Server
|
||||
if server == nil {
|
||||
logs.Error(errors.New("can not find the server"))
|
||||
return
|
||||
}
|
||||
|
||||
// 服务管理
|
||||
serverConfig := &serverconfigs.ServerConfig{}
|
||||
err = json.Unmarshal(server.Config, serverConfig)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 协议簇
|
||||
var family = ""
|
||||
if serverConfig.IsHTTPFamily() {
|
||||
family = "http"
|
||||
} else if serverConfig.IsTCPFamily() {
|
||||
family = "tcp"
|
||||
} else if serverConfig.IsUDPFamily() {
|
||||
family = "udp"
|
||||
}
|
||||
action.Data["serverFamily"] = family
|
||||
|
||||
// TABBAR
|
||||
var selectedTabbar = action.Data["mainTab"]
|
||||
tabbar := actionutils.NewTabbar()
|
||||
tabbar.Add("网站列表", "", "/lb", "", false)
|
||||
//tabbar.Add("看板", "", "/servers/server/board?serverId="+serverIdString, "dashboard", selectedTabbar == "board")
|
||||
//tabbar.Add("日志", "", "/servers/server/log?serverId="+serverIdString, "history", selectedTabbar == "log")
|
||||
//tabbar.Add("统计", "", "/servers/server/stat?serverId="+serverIdString, "chart area", selectedTabbar == "stat")
|
||||
tabbar.Add("设置", "", "/lb/server?serverId="+serverIdString, "setting", selectedTabbar == "setting")
|
||||
//tabbar.Add("删除", "", "/servers/server/delete?serverId="+serverIdString, "trash", selectedTabbar == "delete")
|
||||
|
||||
actionutils.SetTabbar(action, tabbar)
|
||||
|
||||
// 左侧操作子菜单
|
||||
switch types.String(mainTab) {
|
||||
case "board":
|
||||
action.Data["leftMenuItems"] = this.createBoardMenu(types.String(secondMenuItem), serverIdString, serverConfig)
|
||||
case "log":
|
||||
action.Data["leftMenuItems"] = this.createLogMenu(types.String(secondMenuItem), serverIdString, serverConfig)
|
||||
case "stat":
|
||||
action.Data["leftMenuItems"] = this.createStatMenu(types.String(secondMenuItem), serverIdString, serverConfig)
|
||||
case "setting":
|
||||
action.Data["leftMenuItems"] = this.createSettingsMenu(action, types.String(secondMenuItem), serverIdString, serverConfig)
|
||||
case "delete":
|
||||
action.Data["leftMenuItems"] = this.createDeleteMenu(action, types.String(secondMenuItem), serverIdString, serverConfig)
|
||||
}
|
||||
}
|
||||
|
||||
// 看板菜单
|
||||
func (this *ServerHelper) createBoardMenu(secondMenuItem string, serverIdString string, serverConfig *serverconfigs.ServerConfig) []maps.Map {
|
||||
menuItems := []maps.Map{}
|
||||
menuItems = append(menuItems, maps.Map{
|
||||
"name": "看板",
|
||||
"url": "/servers/server/board?serverId=" + serverIdString,
|
||||
"isActive": secondMenuItem == "index",
|
||||
})
|
||||
return menuItems
|
||||
}
|
||||
|
||||
// 日志菜单
|
||||
func (this *ServerHelper) createLogMenu(secondMenuItem string, serverIdString string, serverConfig *serverconfigs.ServerConfig) []maps.Map {
|
||||
menuItems := []maps.Map{}
|
||||
menuItems = append(menuItems, maps.Map{
|
||||
"name": "实时",
|
||||
"url": "/servers/server/log?serverId=" + serverIdString,
|
||||
"isActive": secondMenuItem == "index",
|
||||
})
|
||||
menuItems = append(menuItems, maps.Map{
|
||||
"name": "今天",
|
||||
"url": "/servers/server/log/today?serverId=" + serverIdString,
|
||||
"isActive": secondMenuItem == "today",
|
||||
})
|
||||
menuItems = append(menuItems, maps.Map{
|
||||
"name": "历史",
|
||||
"url": "/servers/server/log/history?serverId=" + serverIdString,
|
||||
"isActive": secondMenuItem == "history",
|
||||
})
|
||||
return menuItems
|
||||
}
|
||||
|
||||
// 统计菜单
|
||||
func (this *ServerHelper) createStatMenu(secondMenuItem string, serverIdString string, serverConfig *serverconfigs.ServerConfig) []maps.Map {
|
||||
menuItems := []maps.Map{}
|
||||
menuItems = append(menuItems, maps.Map{
|
||||
"name": "统计",
|
||||
"url": "/servers/server/stat?serverId=" + serverIdString,
|
||||
"isActive": secondMenuItem == "index",
|
||||
})
|
||||
return menuItems
|
||||
}
|
||||
|
||||
// 设置菜单
|
||||
func (this *ServerHelper) createSettingsMenu(action *actions.ActionObject, secondMenuItem string, serverIdString string, serverConfig *serverconfigs.ServerConfig) (items []maps.Map) {
|
||||
menuItems := []maps.Map{
|
||||
{
|
||||
"name": "基本信息",
|
||||
"url": "/lb/server/settings/basic?serverId=" + serverIdString,
|
||||
"isActive": secondMenuItem == "basic",
|
||||
"isOff": !serverConfig.IsOn,
|
||||
},
|
||||
{
|
||||
"name": "DNS",
|
||||
"url": "/lb/server/settings/dns?serverId=" + serverIdString,
|
||||
"isActive": secondMenuItem == "dns",
|
||||
},
|
||||
}
|
||||
|
||||
// 是否有权限使用套餐
|
||||
rpcClient, err := rpc.SharedRPC()
|
||||
var supportPlan = false
|
||||
if err == nil {
|
||||
userId := action.Context.GetInt64("userId")
|
||||
ctx := rpcClient.Context(userId)
|
||||
|
||||
userFeatureResp, err := rpcClient.UserRPC().FindUserFeatures(ctx, &pb.FindUserFeaturesRequest{UserId: userId})
|
||||
if err == nil {
|
||||
userFeatureCodes := []string{}
|
||||
for _, feature := range userFeatureResp.Features {
|
||||
userFeatureCodes = append(userFeatureCodes, feature.Code)
|
||||
}
|
||||
|
||||
supportPlan = lists.ContainsString(userFeatureCodes, userconfigs.UserFeatureCodePlan)
|
||||
}
|
||||
}
|
||||
|
||||
if serverConfig.IsTCPFamily() {
|
||||
menuItems = append(menuItems, maps.Map{
|
||||
"name": "TCP",
|
||||
"url": "/lb/server/settings/tcp?serverId=" + serverIdString,
|
||||
"isActive": secondMenuItem == "tcp",
|
||||
"isOn": serverConfig.TCP != nil && serverConfig.TCP.IsOn && len(serverConfig.TCP.Listen) > 0,
|
||||
})
|
||||
menuItems = append(menuItems, maps.Map{
|
||||
"name": "TLS",
|
||||
"url": "/lb/server/settings/tls?serverId=" + serverIdString,
|
||||
"isActive": secondMenuItem == "tls",
|
||||
"isOn": serverConfig.TLS != nil && serverConfig.TLS.IsOn && len(serverConfig.TLS.Listen) > 0,
|
||||
})
|
||||
if supportPlan {
|
||||
var planName = ""
|
||||
if serverConfig.UserPlan != nil && serverConfig.UserPlan.PlanId > 0 {
|
||||
planName = this.findPlanName(serverConfig.UserPlan.PlanId)
|
||||
}
|
||||
|
||||
menuItems = append(menuItems, maps.Map{
|
||||
"name": "套餐",
|
||||
"subName": planName,
|
||||
"url": "/lb/server/settings/plan?serverId=" + serverIdString,
|
||||
"isActive": secondMenuItem == "plan",
|
||||
"isOn": serverConfig.UserPlan != nil && serverConfig.UserPlan.IsAvailable(),
|
||||
})
|
||||
}
|
||||
menuItems = append(menuItems, maps.Map{
|
||||
"name": "源站",
|
||||
"url": "/lb/server/settings/reverseProxy?serverId=" + serverIdString,
|
||||
"isActive": secondMenuItem == "reverseProxy",
|
||||
"isOn": serverConfig.ReverseProxyRef != nil && serverConfig.ReverseProxyRef.IsOn,
|
||||
})
|
||||
} else if serverConfig.IsUDPFamily() {
|
||||
menuItems = append(menuItems, maps.Map{
|
||||
"name": "UDP",
|
||||
"url": "/lb/server/settings/udp?serverId=" + serverIdString,
|
||||
"isActive": secondMenuItem == "udp",
|
||||
"isOn": serverConfig.UDP != nil && serverConfig.UDP.IsOn && len(serverConfig.UDP.Listen) > 0,
|
||||
})
|
||||
|
||||
if supportPlan {
|
||||
var planName = ""
|
||||
if serverConfig.UserPlan != nil && serverConfig.UserPlan.PlanId > 0 {
|
||||
planName = this.findPlanName(serverConfig.UserPlan.PlanId)
|
||||
}
|
||||
|
||||
menuItems = append(menuItems, maps.Map{
|
||||
"name": "套餐",
|
||||
"subName": planName,
|
||||
"url": "/lb/server/settings/plan?serverId=" + serverIdString,
|
||||
"isActive": secondMenuItem == "plan",
|
||||
"isOn": serverConfig.UserPlan != nil && serverConfig.UserPlan.IsAvailable(),
|
||||
})
|
||||
}
|
||||
|
||||
menuItems = append(menuItems, maps.Map{
|
||||
"name": "源站",
|
||||
"url": "/lb/server/settings/reverseProxy?serverId=" + serverIdString,
|
||||
"isActive": secondMenuItem == "reverseProxy",
|
||||
"isOn": serverConfig.ReverseProxyRef != nil && serverConfig.ReverseProxyRef.IsOn,
|
||||
})
|
||||
}
|
||||
|
||||
return menuItems
|
||||
}
|
||||
|
||||
// 删除菜单
|
||||
func (this *ServerHelper) createDeleteMenu(action *actions.ActionObject, secondMenuItem string, serverIdString string, serverConfig *serverconfigs.ServerConfig) []maps.Map {
|
||||
var menuItems = []maps.Map{}
|
||||
menuItems = append(menuItems, maps.Map{
|
||||
"name": "删除",
|
||||
"url": "/servers/server/delete?serverId=" + serverIdString,
|
||||
"isActive": secondMenuItem == "index",
|
||||
})
|
||||
return menuItems
|
||||
}
|
||||
|
||||
// 查找套餐名称
|
||||
func (this *ServerHelper) findPlanName(planId int64) string {
|
||||
if planId <= 0 {
|
||||
return ""
|
||||
}
|
||||
rpcClient, err := rpc.SharedRPC()
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return ""
|
||||
}
|
||||
planResp, err := rpcClient.PlanRPC().FindBasicPlan(rpcClient.Context(0), &pb.FindBasicPlanRequest{PlanId: planId})
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return ""
|
||||
}
|
||||
if planResp.Plan == nil {
|
||||
return ""
|
||||
}
|
||||
return planResp.Plan.Name
|
||||
}
|
||||
33
EdgeUser/internal/web/actions/default/lb/updateOn.go
Normal file
33
EdgeUser/internal/web/actions/default/lb/updateOn.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package lb
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type UpdateOnAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateOnAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
IsOn bool
|
||||
}) {
|
||||
if params.IsOn {
|
||||
defer this.CreateLogInfo(codes.Server_LogEnableServer, params.ServerId)
|
||||
} else {
|
||||
defer this.CreateLogInfo(codes.Server_LogDisableServer, params.ServerId)
|
||||
}
|
||||
|
||||
_, err := this.RPC().ServerRPC().UpdateServerIsOn(this.UserContext(), &pb.UpdateServerIsOnRequest{
|
||||
ServerId: params.ServerId,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
Reference in New Issue
Block a user