Initial commit (code only without large binaries)
This commit is contained in:
123
EdgeAdmin/internal/web/actions/default/ns/addPortPopup.go
Normal file
123
EdgeAdmin/internal/web/actions/default/ns/addPortPopup.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package ns
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AddPortPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *AddPortPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *AddPortPopupAction) RunGet(params struct {
|
||||
Protocol string
|
||||
From string
|
||||
SupportRange bool
|
||||
}) {
|
||||
this.Data["from"] = params.From
|
||||
|
||||
var protocols = serverconfigs.FindAllServerProtocols()
|
||||
if len(params.Protocol) > 0 {
|
||||
result := []maps.Map{}
|
||||
for _, p := range protocols {
|
||||
if p.GetString("code") == params.Protocol {
|
||||
result = append(result, p)
|
||||
}
|
||||
}
|
||||
protocols = result
|
||||
}
|
||||
this.Data["protocols"] = protocols
|
||||
|
||||
this.Data["supportRange"] = params.SupportRange
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *AddPortPopupAction) RunPost(params struct {
|
||||
SupportRange bool
|
||||
|
||||
Protocol string
|
||||
Address string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 校验地址
|
||||
var addr = maps.Map{
|
||||
"protocol": params.Protocol,
|
||||
"host": "",
|
||||
"portRange": "",
|
||||
"minPort": 0,
|
||||
"maxPort": 0,
|
||||
}
|
||||
|
||||
var portRegexp = regexp.MustCompile(`^\d+$`)
|
||||
if portRegexp.MatchString(params.Address) { // 单个端口
|
||||
addr["portRange"] = this.checkPort(params.Address)
|
||||
} else if params.SupportRange && regexp.MustCompile(`^\d+\s*-\s*\d+$`).MatchString(params.Address) { // Port1-Port2
|
||||
addr["portRange"], addr["minPort"], addr["maxPort"] = this.checkPortRange(params.Address)
|
||||
} else if strings.Contains(params.Address, ":") { // IP:Port
|
||||
index := strings.LastIndex(params.Address, ":")
|
||||
addr["host"] = strings.TrimSpace(params.Address[:index])
|
||||
port := strings.TrimSpace(params.Address[index+1:])
|
||||
if portRegexp.MatchString(port) {
|
||||
addr["portRange"] = this.checkPort(port)
|
||||
} else if params.SupportRange && regexp.MustCompile(`^\d+\s*-\s*\d+$`).MatchString(port) { // Port1-Port2
|
||||
addr["portRange"], addr["minPort"], addr["maxPort"] = this.checkPortRange(port)
|
||||
} else {
|
||||
this.FailField("address", "请输入正确的端口或者网络地址")
|
||||
}
|
||||
} else {
|
||||
this.FailField("address", "请输入正确的端口或者网络地址")
|
||||
}
|
||||
|
||||
this.Data["address"] = addr
|
||||
this.Success()
|
||||
}
|
||||
|
||||
func (this *AddPortPopupAction) checkPort(port string) (portRange string) {
|
||||
var intPort = types.Int(port)
|
||||
if intPort < 1 {
|
||||
this.FailField("address", "端口号不能小于1")
|
||||
}
|
||||
if intPort > 65535 {
|
||||
this.FailField("address", "端口号不能大于65535")
|
||||
}
|
||||
return port
|
||||
}
|
||||
|
||||
func (this *AddPortPopupAction) checkPortRange(port string) (portRange string, minPort int, maxPort int) {
|
||||
var pieces = strings.Split(port, "-")
|
||||
var piece1 = strings.TrimSpace(pieces[0])
|
||||
var piece2 = strings.TrimSpace(pieces[1])
|
||||
var port1 = types.Int(piece1)
|
||||
var port2 = types.Int(piece2)
|
||||
|
||||
if port1 < 1 {
|
||||
this.FailField("address", "端口号不能小于1")
|
||||
}
|
||||
if port1 > 65535 {
|
||||
this.FailField("address", "端口号不能大于65535")
|
||||
}
|
||||
|
||||
if port2 < 1 {
|
||||
this.FailField("address", "端口号不能小于1")
|
||||
}
|
||||
if port2 > 65535 {
|
||||
this.FailField("address", "端口号不能大于65535")
|
||||
}
|
||||
|
||||
if port1 > port2 {
|
||||
port1, port2 = port2, port1
|
||||
}
|
||||
|
||||
return types.String(port1) + "-" + types.String(port2), port1, port2
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"net"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
RequestId string
|
||||
Keyword string
|
||||
Day string
|
||||
ClusterId int64
|
||||
NodeId int64
|
||||
RecordType string
|
||||
}) {
|
||||
day := strings.ReplaceAll(params.Day, "-", "")
|
||||
if !regexp.MustCompile(`^\d{8}$`).MatchString(day) {
|
||||
day = timeutil.Format("Ymd")
|
||||
}
|
||||
|
||||
this.Data["keyword"] = params.Keyword
|
||||
this.Data["day"] = day[:4] + "-" + day[4:6] + "-" + day[6:]
|
||||
this.Data["path"] = this.Request.URL.Path
|
||||
this.Data["clusterId"] = params.ClusterId
|
||||
this.Data["nodeId"] = params.NodeId
|
||||
this.Data["recordType"] = params.RecordType
|
||||
|
||||
var size = int64(20)
|
||||
|
||||
resp, err := this.RPC().NSAccessLogRPC().ListNSAccessLogs(this.AdminContext(), &pb.ListNSAccessLogsRequest{
|
||||
RequestId: params.RequestId,
|
||||
NsClusterId: params.ClusterId,
|
||||
NsNodeId: params.NodeId,
|
||||
NsDomainId: 0,
|
||||
NsRecordId: 0,
|
||||
RecordType: params.RecordType,
|
||||
Size: size,
|
||||
Day: day,
|
||||
Keyword: params.Keyword,
|
||||
Reverse: false,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var ipList = []string{}
|
||||
var nodeIds = []int64{}
|
||||
var domainIds = []int64{}
|
||||
if len(resp.NsAccessLogs) == 0 {
|
||||
this.Data["accessLogs"] = []interface{}{}
|
||||
} else {
|
||||
this.Data["accessLogs"] = resp.NsAccessLogs
|
||||
for _, accessLog := range resp.NsAccessLogs {
|
||||
// IP
|
||||
if len(accessLog.RemoteAddr) > 0 {
|
||||
// 去掉端口
|
||||
ip, _, err := net.SplitHostPort(accessLog.RemoteAddr)
|
||||
if err == nil {
|
||||
accessLog.RemoteAddr = ip
|
||||
if !lists.ContainsString(ipList, ip) {
|
||||
ipList = append(ipList, ip)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 节点
|
||||
if !lists.ContainsInt64(nodeIds, accessLog.NsNodeId) {
|
||||
nodeIds = append(nodeIds, accessLog.NsNodeId)
|
||||
}
|
||||
|
||||
// 域名
|
||||
if !lists.ContainsInt64(domainIds, accessLog.NsDomainId) {
|
||||
domainIds = append(domainIds, accessLog.NsDomainId)
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["hasMore"] = resp.HasMore
|
||||
this.Data["nextRequestId"] = resp.RequestId
|
||||
|
||||
// 上一个requestId
|
||||
this.Data["hasPrev"] = false
|
||||
this.Data["lastRequestId"] = ""
|
||||
if len(params.RequestId) > 0 {
|
||||
this.Data["hasPrev"] = true
|
||||
prevResp, err := this.RPC().NSAccessLogRPC().ListNSAccessLogs(this.AdminContext(), &pb.ListNSAccessLogsRequest{
|
||||
RequestId: params.RequestId,
|
||||
NsClusterId: params.ClusterId,
|
||||
NsNodeId: params.NodeId,
|
||||
NsDomainId: 0,
|
||||
NsRecordId: 0,
|
||||
RecordType: params.RecordType,
|
||||
Day: day,
|
||||
Keyword: params.Keyword,
|
||||
Size: size,
|
||||
Reverse: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if int64(len(prevResp.NsAccessLogs)) == size {
|
||||
this.Data["lastRequestId"] = prevResp.RequestId
|
||||
}
|
||||
}
|
||||
|
||||
// 根据IP查询区域
|
||||
this.Data["regions"] = iplibrary.LookupIPSummaries(ipList)
|
||||
|
||||
// 节点信息
|
||||
var nodeMap = map[int64]interface{}{} // node id => { ... }
|
||||
for _, nodeId := range nodeIds {
|
||||
nodeResp, err := this.RPC().NSNodeRPC().FindNSNode(this.AdminContext(), &pb.FindNSNodeRequest{NsNodeId: nodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var node = nodeResp.NsNode
|
||||
if node != nil {
|
||||
nodeMap[node.Id] = maps.Map{
|
||||
"id": node.Id,
|
||||
"name": node.Name,
|
||||
"cluster": maps.Map{
|
||||
"id": node.NsCluster.Id,
|
||||
"name": node.NsCluster.Name,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["nodes"] = nodeMap
|
||||
|
||||
// 域名信息
|
||||
var domainMap = map[int64]interface{}{} // domain id => { ... }
|
||||
for _, domainId := range domainIds {
|
||||
domainResp, err := this.RPC().NSDomainRPC().FindNSDomain(this.AdminContext(), &pb.FindNSDomainRequest{NsDomainId: domainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
domain := domainResp.NsDomain
|
||||
if domain != nil {
|
||||
domainMap[domain.Id] = maps.Map{
|
||||
"id": domain.Id,
|
||||
"name": domain.Name,
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["domains"] = domainMap
|
||||
|
||||
// 所有记录类型
|
||||
this.Data["recordTypes"] = dnsconfigs.FindAllRecordTypeDefinitions()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//go:build plus
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeNS)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "accessLog").
|
||||
Prefix("/ns/clusters/accessLogs").
|
||||
Get("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/miekg/dns"
|
||||
"regexp"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type CheckPortsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CheckPortsAction) RunPost(params struct {
|
||||
ClusterId int64
|
||||
Ip []string
|
||||
}) {
|
||||
this.Data["results"] = []maps.Map{}
|
||||
this.Data["port"] = ""
|
||||
|
||||
if len(params.Ip) == 0 {
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
|
||||
// 集群设置
|
||||
clusterResp, err := this.RPC().NSClusterRPC().FindNSCluster(this.AdminContext(), &pb.FindNSClusterRequest{NsClusterId: params.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var cluster = clusterResp.NsCluster
|
||||
if cluster == nil || !cluster.IsOn || !cluster.CheckingPorts {
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
|
||||
// UDP端口设置
|
||||
udpConfigResp, err := this.RPC().NSClusterRPC().FindNSClusterUDPConfig(this.AdminContext(), &pb.FindNSClusterUDPConfigRequest{NsClusterId: params.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var udpJSON = udpConfigResp.UdpJSON
|
||||
if len(udpJSON) == 0 {
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
var udpConfig = &serverconfigs.UDPProtocolConfig{}
|
||||
err = json.Unmarshal(udpJSON, udpConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !udpConfig.IsOn || len(udpConfig.Listen) == 0 {
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
|
||||
var portString = udpConfig.Listen[0].PortRange
|
||||
if !regexp.MustCompile(`^\d+$`).MatchString(portString) {
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
this.Data["port"] = portString
|
||||
|
||||
var client = new(dns.Client)
|
||||
var resultMaps = []maps.Map{}
|
||||
var locker = &sync.Mutex{}
|
||||
|
||||
var wg = sync.WaitGroup{}
|
||||
wg.Add(len(params.Ip))
|
||||
|
||||
for _, ip := range params.Ip {
|
||||
go func(ip string) {
|
||||
defer wg.Done()
|
||||
|
||||
var queryErr error
|
||||
var retries = 2
|
||||
for i := 1; i <= retries; i++ {
|
||||
var questionMsg = new(dns.Msg)
|
||||
var answerMsg *dns.Msg
|
||||
questionMsg.SetQuestion("ping.", dns.TypeA)
|
||||
answerMsg, _, queryErr = client.Exchange(questionMsg, ip+":"+portString)
|
||||
if queryErr == nil {
|
||||
var isValid = false
|
||||
if answerMsg != nil && len(answerMsg.Answer) > 0 {
|
||||
var answer = answerMsg.Answer[0]
|
||||
aAnswer, ok := answer.(*dns.A)
|
||||
if ok && aAnswer.A.String() == "127.0.0.1" {
|
||||
isValid = true
|
||||
} else {
|
||||
queryErr = errors.New("invalid answer: " + answer.String())
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isValid {
|
||||
queryErr = errors.New("invalid answer")
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
locker.Lock()
|
||||
var errorString = ""
|
||||
if queryErr != nil {
|
||||
errorString = queryErr.Error()
|
||||
}
|
||||
resultMaps = append(resultMaps, maps.Map{
|
||||
"ip": ip,
|
||||
"isOk": queryErr == nil,
|
||||
"err": errorString,
|
||||
})
|
||||
locker.Unlock()
|
||||
}(ip)
|
||||
}
|
||||
wg.Wait()
|
||||
this.Data["results"] = resultMaps
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
//go:build plus
|
||||
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// CreateNodeAction 创建节点
|
||||
type CreateNodeAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreateNodeAction) Init() {
|
||||
this.Nav("", "node", "create")
|
||||
this.SecondMenu("nodes")
|
||||
}
|
||||
|
||||
func (this *CreateNodeAction) RunGet(params struct {
|
||||
ClusterId int64
|
||||
}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreateNodeAction) RunPost(params struct {
|
||||
Name string
|
||||
IpAddressesJSON []byte
|
||||
ClusterId int64
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入节点名称")
|
||||
|
||||
if len(params.IpAddressesJSON) == 0 {
|
||||
this.Fail("请至少添加一个IP地址")
|
||||
}
|
||||
|
||||
// 检查cluster
|
||||
if params.ClusterId <= 0 {
|
||||
this.Fail("请选择所在集群")
|
||||
}
|
||||
clusterResp, err := this.RPC().NSClusterRPC().FindNSCluster(this.AdminContext(), &pb.FindNSClusterRequest{NsClusterId: params.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if clusterResp.NsCluster == nil {
|
||||
this.Fail("选择的集群不存在")
|
||||
}
|
||||
|
||||
// IP地址
|
||||
ipAddresses := []maps.Map{}
|
||||
if len(params.IpAddressesJSON) > 0 {
|
||||
err := json.Unmarshal(params.IpAddressesJSON, &ipAddresses)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(ipAddresses) == 0 {
|
||||
this.Fail("请至少输入一个IP地址")
|
||||
}
|
||||
|
||||
// 保存
|
||||
createResp, err := this.RPC().NSNodeRPC().CreateNSNode(this.AdminContext(), &pb.CreateNSNodeRequest{
|
||||
Name: params.Name,
|
||||
NodeClusterId: params.ClusterId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
nodeId := createResp.NsNodeId
|
||||
|
||||
// IP地址
|
||||
for _, addrMap := range ipAddresses {
|
||||
addressId := addrMap.GetInt64("id")
|
||||
if addressId > 0 {
|
||||
_, err = this.RPC().NodeIPAddressRPC().UpdateNodeIPAddressNodeId(this.AdminContext(), &pb.UpdateNodeIPAddressNodeIdRequest{
|
||||
NodeIPAddressId: addressId,
|
||||
NodeId: nodeId,
|
||||
})
|
||||
} else {
|
||||
var ipStrings = addrMap.GetString("ip")
|
||||
result, _ := utils.ExtractIP(ipStrings)
|
||||
|
||||
if len(result) == 1 {
|
||||
// 单个创建
|
||||
_, err = this.RPC().NodeIPAddressRPC().CreateNodeIPAddress(this.AdminContext(), &pb.CreateNodeIPAddressRequest{
|
||||
NodeId: nodeId,
|
||||
Role: nodeconfigs.NodeRoleDNS,
|
||||
Name: addrMap.GetString("name"),
|
||||
Ip: result[0],
|
||||
CanAccess: addrMap.GetBool("canAccess"),
|
||||
IsUp: addrMap.GetBool("isUp"),
|
||||
})
|
||||
} else if len(result) > 1 {
|
||||
// 批量创建
|
||||
_, err = this.RPC().NodeIPAddressRPC().CreateNodeIPAddresses(this.AdminContext(), &pb.CreateNodeIPAddressesRequest{
|
||||
NodeId: nodeId,
|
||||
Role: nodeconfigs.NodeRoleDNS,
|
||||
Name: addrMap.GetString("name"),
|
||||
IpList: result,
|
||||
CanAccess: addrMap.GetBool("canAccess"),
|
||||
IsUp: addrMap.GetBool("isUp"),
|
||||
GroupValue: ipStrings,
|
||||
})
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 创建日志
|
||||
defer this.CreateLogInfo(codes.NSNode_LogCreateNSNode, nodeId)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
//go:build plus
|
||||
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) Init() {
|
||||
this.Nav("", "delete", "index")
|
||||
this.SecondMenu("nodes")
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunGet(params struct {
|
||||
ClusterId int64
|
||||
}) {
|
||||
countResp, err := this.RPC().NSDomainRPC().CountAllNSDomains(this.AdminContext(), &pb.CountAllNSDomainsRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
Status: dnsconfigs.NSDomainStatusVerified,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["countDomains"] = countResp.Count
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
ClusterId int64
|
||||
}) {
|
||||
// 创建日志
|
||||
defer this.CreateLogInfo(codes.NSCluster_LogDeleteNSCluster, params.ClusterId)
|
||||
|
||||
// 删除
|
||||
_, err := this.RPC().NSClusterRPC().DeleteNSCluster(this.AdminContext(), &pb.DeleteNSCluster{NsClusterId: params.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteNodeAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteNodeAction) RunPost(params struct {
|
||||
NodeId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSNode_LogDeleteNSNode, params.NodeId)
|
||||
|
||||
_, err := this.RPC().NSNodeRPC().DeleteNSNode(this.AdminContext(), &pb.DeleteNSNodeRequest{NsNodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"time"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "node", "index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ClusterId int64
|
||||
InstalledState int
|
||||
ActiveState int
|
||||
Keyword string
|
||||
}) {
|
||||
this.Data["installState"] = params.InstalledState
|
||||
this.Data["activeState"] = params.ActiveState
|
||||
this.Data["keyword"] = params.Keyword
|
||||
|
||||
// 最新版本
|
||||
versionResp, err := this.RPC().NSNodeRPC().FindLatestNSNodeVersion(this.AdminContext(), &pb.FindLatestNSNodeVersionRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var latestVersion = versionResp.Version
|
||||
this.Data["latestVersion"] = latestVersion
|
||||
|
||||
countAllResp, err := this.RPC().NSNodeRPC().CountAllNSNodesMatch(this.AdminContext(), &pb.CountAllNSNodesMatchRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["countAll"] = countAllResp.Count
|
||||
|
||||
countResp, err := this.RPC().NSNodeRPC().CountAllNSNodesMatch(this.AdminContext(), &pb.CountAllNSNodesMatchRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
InstallState: types.Int32(params.InstalledState),
|
||||
ActiveState: types.Int32(params.ActiveState),
|
||||
Keyword: params.Keyword,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var page = this.NewPage(countResp.Count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
nodesResp, err := this.RPC().NSNodeRPC().ListNSNodesMatch(this.AdminContext(), &pb.ListNSNodesMatchRequest{
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
NsClusterId: params.ClusterId,
|
||||
InstallState: types.Int32(params.InstalledState),
|
||||
ActiveState: types.Int32(params.ActiveState),
|
||||
Keyword: params.Keyword,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var nodeMaps = []maps.Map{}
|
||||
for _, node := range nodesResp.NsNodes {
|
||||
// 状态
|
||||
status := &nodeconfigs.NodeStatus{}
|
||||
if len(node.StatusJSON) > 0 {
|
||||
err = json.Unmarshal(node.StatusJSON, &status)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
continue
|
||||
}
|
||||
status.IsActive = status.IsActive && time.Now().Unix()-status.UpdatedAt <= 60 // N秒之内认为活跃
|
||||
}
|
||||
|
||||
// IP
|
||||
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledNodeIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledNodeIPAddressesWithNodeIdRequest{
|
||||
NodeId: node.Id,
|
||||
Role: nodeconfigs.NodeRoleDNS,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var ipAddresses = []maps.Map{}
|
||||
for _, addr := range ipAddressesResp.NodeIPAddresses {
|
||||
ipAddresses = append(ipAddresses, maps.Map{
|
||||
"id": addr.Id,
|
||||
"name": addr.Name,
|
||||
"ip": addr.Ip,
|
||||
"canAccess": addr.CanAccess,
|
||||
"isOn": addr.IsOn,
|
||||
"isUp": addr.IsUp,
|
||||
})
|
||||
}
|
||||
|
||||
nodeMaps = append(nodeMaps, maps.Map{
|
||||
"id": node.Id,
|
||||
"name": node.Name,
|
||||
"isInstalled": node.IsInstalled,
|
||||
"isOn": node.IsOn,
|
||||
"isUp": node.IsUp,
|
||||
"installStatus": maps.Map{
|
||||
"isRunning": node.InstallStatus.IsRunning,
|
||||
"isFinished": node.InstallStatus.IsFinished,
|
||||
"isOk": node.InstallStatus.IsOk,
|
||||
"error": node.InstallStatus.Error,
|
||||
},
|
||||
"status": maps.Map{
|
||||
"isActive": node.IsActive,
|
||||
"updatedAt": status.UpdatedAt,
|
||||
"hostname": status.Hostname,
|
||||
"cpuUsage": status.CPUUsage,
|
||||
"cpuUsageText": fmt.Sprintf("%.2f%%", status.CPUUsage*100),
|
||||
"memUsage": status.MemoryUsage,
|
||||
"memUsageText": fmt.Sprintf("%.2f%%", status.MemoryUsage*100),
|
||||
"load1m": numberutils.FormatFloat2(status.Load1m),
|
||||
"load5m": numberutils.FormatFloat2(status.Load5m),
|
||||
"load15m": numberutils.FormatFloat2(status.Load15m),
|
||||
"version": status.BuildVersion,
|
||||
},
|
||||
"ipAddresses": ipAddresses,
|
||||
})
|
||||
}
|
||||
this.Data["nodes"] = nodeMaps
|
||||
|
||||
// 记录最近访问
|
||||
_, err = this.RPC().LatestItemRPC().IncreaseLatestItem(this.AdminContext(), &pb.IncreaseLatestItemRequest{
|
||||
ItemType: "nsCluster",
|
||||
ItemId: params.ClusterId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
//go:build plus
|
||||
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/cluster/node"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeNS)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Helper(new(clusterutils.ClusterHelper)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters/cluster").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/delete", new(DeleteAction)).
|
||||
GetPost("/createNode", new(CreateNodeAction)).
|
||||
Post("/deleteNode", new(DeleteNodeAction)).
|
||||
Get("/upgradeRemote", new(UpgradeRemoteAction)).
|
||||
GetPost("/updateNodeSSH", new(UpdateNodeSSHAction)).
|
||||
Post("/checkPorts", new(CheckPortsAction)).
|
||||
|
||||
// 节点相关
|
||||
Prefix("/ns/clusters/cluster/node").
|
||||
Get("", new(node.IndexAction)).
|
||||
Get("/logs", new(node.LogsAction)).
|
||||
GetPost("/update", new(node.UpdateAction)).
|
||||
GetPost("/install", new(node.InstallAction)).
|
||||
Post("/status", new(node.StatusAction)).
|
||||
Post("/updateInstallStatus", new(node.UpdateInstallStatusAction)).
|
||||
Post("/start", new(node.StartAction)).
|
||||
Post("/stop", new(node.StopAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
//go:build plus
|
||||
|
||||
package node
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants/grantutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "node", "node")
|
||||
this.SecondMenu("nodes")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
NodeId int64
|
||||
}) {
|
||||
this.Data["nodeId"] = params.NodeId
|
||||
|
||||
nodeResp, err := this.RPC().NSNodeRPC().FindNSNode(this.AdminContext(), &pb.FindNSNodeRequest{NsNodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var node = nodeResp.NsNode
|
||||
if node == nil {
|
||||
this.WriteString("找不到要操作的节点")
|
||||
return
|
||||
}
|
||||
|
||||
var clusterMap maps.Map = nil
|
||||
if node.NsCluster != nil {
|
||||
clusterId := node.NsCluster.Id
|
||||
clusterResp, err := this.RPC().NSClusterRPC().FindNSCluster(this.AdminContext(), &pb.FindNSClusterRequest{NsClusterId: clusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
cluster := clusterResp.NsCluster
|
||||
if cluster != nil {
|
||||
clusterMap = maps.Map{
|
||||
"id": cluster.Id,
|
||||
"name": cluster.Name,
|
||||
"installDir": cluster.InstallDir,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IP地址
|
||||
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledNodeIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledNodeIPAddressesWithNodeIdRequest{
|
||||
NodeId: params.NodeId,
|
||||
Role: nodeconfigs.NodeRoleDNS,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var ipAddressMaps = []maps.Map{}
|
||||
for _, addr := range ipAddressesResp.NodeIPAddresses {
|
||||
ipAddressMaps = append(ipAddressMaps, maps.Map{
|
||||
"id": addr.Id,
|
||||
"name": addr.Name,
|
||||
"ip": addr.Ip,
|
||||
"canAccess": addr.CanAccess,
|
||||
"isOn": addr.IsOn,
|
||||
"isUp": addr.IsUp,
|
||||
})
|
||||
}
|
||||
|
||||
// 运行状态
|
||||
this.Data["nodeDatetime"] = ""
|
||||
this.Data["nodeTimeDiff"] = 0
|
||||
var status = &nodeconfigs.NodeStatus{}
|
||||
if len(node.StatusJSON) > 0 {
|
||||
err = json.Unmarshal(node.StatusJSON, &status)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
status.IsActive = status.IsActive && time.Now().Unix()-status.UpdatedAt <= 60 // N秒之内认为活跃
|
||||
if status.Timestamp > 0 {
|
||||
this.Data["nodeDatetime"] = timeutil.FormatTime("Y-m-d H:i:s", status.Timestamp)
|
||||
if status.UpdatedAt > 0 {
|
||||
var diff = status.UpdatedAt - status.Timestamp
|
||||
if diff < 0 {
|
||||
diff = -diff
|
||||
}
|
||||
this.Data["nodeTimeDiff"] = diff
|
||||
}
|
||||
} else if status.UpdatedAt > 0 {
|
||||
this.Data["nodeDatetime"] = timeutil.FormatTime("Y-m-d H:i:s", status.UpdatedAt)
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否有新版本
|
||||
if len(status.OS) > 0 {
|
||||
checkVersionResp, err := this.RPC().NSNodeRPC().CheckNSNodeLatestVersion(this.AdminContext(), &pb.CheckNSNodeLatestVersionRequest{
|
||||
Os: status.OS,
|
||||
Arch: status.Arch,
|
||||
CurrentVersion: status.BuildVersion,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["shouldUpgrade"] = checkVersionResp.HasNewVersion
|
||||
this.Data["newVersion"] = checkVersionResp.NewVersion
|
||||
} else {
|
||||
this.Data["shouldUpgrade"] = false
|
||||
this.Data["newVersion"] = ""
|
||||
}
|
||||
|
||||
// 登录信息
|
||||
var loginMap maps.Map = nil
|
||||
if node.NodeLogin != nil {
|
||||
loginParams := maps.Map{}
|
||||
if len(node.NodeLogin.Params) > 0 {
|
||||
err = json.Unmarshal(node.NodeLogin.Params, &loginParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
grantMap := maps.Map{}
|
||||
grantId := loginParams.GetInt64("grantId")
|
||||
if grantId > 0 {
|
||||
grantResp, err := this.RPC().NodeGrantRPC().FindEnabledNodeGrant(this.AdminContext(), &pb.FindEnabledNodeGrantRequest{NodeGrantId: grantId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if grantResp.NodeGrant != nil {
|
||||
grantMap = maps.Map{
|
||||
"id": grantResp.NodeGrant.Id,
|
||||
"name": grantResp.NodeGrant.Name,
|
||||
"method": grantResp.NodeGrant.Method,
|
||||
"methodName": grantutils.FindGrantMethodName(grantResp.NodeGrant.Method, this.LangCode()),
|
||||
"username": grantResp.NodeGrant.Username,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loginMap = maps.Map{
|
||||
"id": node.NodeLogin.Id,
|
||||
"name": node.NodeLogin.Name,
|
||||
"type": node.NodeLogin.Type,
|
||||
"params": loginParams,
|
||||
"grant": grantMap,
|
||||
}
|
||||
}
|
||||
|
||||
// API节点地址
|
||||
var apiNodeAddrStrings = []string{}
|
||||
var apiNodeAddrs = []*serverconfigs.NetworkAddressConfig{}
|
||||
if len(node.ApiNodeAddrsJSON) > 0 {
|
||||
err = json.Unmarshal(node.ApiNodeAddrsJSON, &apiNodeAddrs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
for _, addr := range apiNodeAddrs {
|
||||
if addr.Init() == nil {
|
||||
apiNodeAddrStrings = append(apiNodeAddrStrings, addr.FullAddresses()...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["node"] = maps.Map{
|
||||
"id": node.Id,
|
||||
"name": node.Name,
|
||||
"ipAddresses": ipAddressMaps,
|
||||
"cluster": clusterMap,
|
||||
"installDir": node.InstallDir,
|
||||
"isInstalled": node.IsInstalled,
|
||||
"uniqueId": node.UniqueId,
|
||||
"secret": node.Secret,
|
||||
"isOn": node.IsOn,
|
||||
"apiNodeAddrs": apiNodeAddrStrings,
|
||||
|
||||
"status": maps.Map{
|
||||
"isActive": node.IsActive && status.IsActive,
|
||||
"updatedAt": status.UpdatedAt,
|
||||
"hostname": status.Hostname,
|
||||
"cpuUsage": status.CPUUsage,
|
||||
"cpuUsageText": fmt.Sprintf("%.2f%%", status.CPUUsage*100),
|
||||
"memUsage": status.MemoryUsage,
|
||||
"memUsageText": fmt.Sprintf("%.2f%%", status.MemoryUsage*100),
|
||||
"connectionCount": status.ConnectionCount,
|
||||
"buildVersion": status.BuildVersion,
|
||||
"cpuPhysicalCount": status.CPUPhysicalCount,
|
||||
"cpuLogicalCount": status.CPULogicalCount,
|
||||
"load1m": fmt.Sprintf("%.2f", status.Load1m),
|
||||
"load5m": fmt.Sprintf("%.2f", status.Load5m),
|
||||
"load15m": fmt.Sprintf("%.2f", status.Load15m),
|
||||
"cacheTotalDiskSize": numberutils.FormatBytes(status.CacheTotalDiskSize),
|
||||
"cacheTotalMemorySize": numberutils.FormatBytes(status.CacheTotalMemorySize),
|
||||
"exePath": status.ExePath,
|
||||
"apiSuccessPercent": status.APISuccessPercent,
|
||||
"apiAvgCostSeconds": status.APIAvgCostSeconds,
|
||||
},
|
||||
|
||||
"login": loginMap,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
//go:build plus
|
||||
|
||||
package node
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// InstallAction 安装节点
|
||||
type InstallAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *InstallAction) Init() {
|
||||
this.Nav("", "node", "install")
|
||||
this.SecondMenu("nodes")
|
||||
}
|
||||
|
||||
func (this *InstallAction) RunGet(params struct {
|
||||
NodeId int64
|
||||
}) {
|
||||
this.Data["nodeId"] = params.NodeId
|
||||
|
||||
// 节点
|
||||
nodeResp, err := this.RPC().NSNodeRPC().FindNSNode(this.AdminContext(), &pb.FindNSNodeRequest{NsNodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var node = nodeResp.NsNode
|
||||
if node == nil {
|
||||
this.WriteString("找不到要操作的节点")
|
||||
return
|
||||
}
|
||||
|
||||
// 安装信息
|
||||
if node.InstallStatus != nil {
|
||||
this.Data["installStatus"] = maps.Map{
|
||||
"isRunning": node.InstallStatus.IsRunning,
|
||||
"isFinished": node.InstallStatus.IsFinished,
|
||||
"isOk": node.InstallStatus.IsOk,
|
||||
"updatedAt": node.InstallStatus.UpdatedAt,
|
||||
"error": node.InstallStatus.Error,
|
||||
}
|
||||
} else {
|
||||
this.Data["installStatus"] = nil
|
||||
}
|
||||
|
||||
// 集群
|
||||
var clusterMap maps.Map = nil
|
||||
if node.NsCluster != nil {
|
||||
var clusterId = node.NsCluster.Id
|
||||
clusterResp, err := this.RPC().NSClusterRPC().FindNSCluster(this.AdminContext(), &pb.FindNSClusterRequest{NsClusterId: clusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var cluster = clusterResp.NsCluster
|
||||
if cluster != nil {
|
||||
clusterMap = maps.Map{
|
||||
"id": cluster.Id,
|
||||
"name": cluster.Name,
|
||||
"installDir": cluster.InstallDir,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// API节点列表
|
||||
apiNodesResp, err := this.RPC().APINodeRPC().FindAllEnabledAPINodes(this.AdminContext(), &pb.FindAllEnabledAPINodesRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var apiNodes = apiNodesResp.ApiNodes
|
||||
var apiEndpoints = []string{}
|
||||
for _, apiNode := range apiNodes {
|
||||
if !apiNode.IsOn {
|
||||
continue
|
||||
}
|
||||
apiEndpoints = append(apiEndpoints, apiNode.AccessAddrs...)
|
||||
}
|
||||
this.Data["apiEndpoints"] = "\"" + strings.Join(apiEndpoints, "\", \"") + "\""
|
||||
|
||||
this.Data["node"] = maps.Map{
|
||||
"id": node.Id,
|
||||
"name": node.Name,
|
||||
"installDir": node.InstallDir,
|
||||
"isInstalled": node.IsInstalled,
|
||||
"uniqueId": node.UniqueId,
|
||||
"secret": node.Secret,
|
||||
"cluster": clusterMap,
|
||||
}
|
||||
|
||||
// SSH主机地址
|
||||
this.Data["sshAddr"] = ""
|
||||
if node.NodeLogin != nil && node.NodeLogin.Type == "ssh" && !utils.JSONIsNull(node.NodeLogin.Params) {
|
||||
var loginParams = maps.Map{}
|
||||
err = json.Unmarshal(node.NodeLogin.Params, &loginParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var host = loginParams.GetString("host")
|
||||
if len(host) > 0 {
|
||||
var port = loginParams.GetString("port")
|
||||
if port == "0" {
|
||||
port = "22"
|
||||
}
|
||||
this.Data["sshAddr"] = configutils.QuoteIP(host) + ":" + port
|
||||
}
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
// RunPost 开始安装
|
||||
func (this *InstallAction) RunPost(params struct {
|
||||
NodeId int64
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 创建日志
|
||||
defer this.CreateLogInfo(codes.NSNode_LogInstallNSNodeRemotely, params.NodeId)
|
||||
|
||||
_, err := this.RPC().NSNodeRPC().InstallNSNode(this.AdminContext(), &pb.InstallNSNodeRequest{
|
||||
NsNodeId: params.NodeId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type LogsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *LogsAction) Init() {
|
||||
this.Nav("", "node", "log")
|
||||
this.SecondMenu("nodes")
|
||||
}
|
||||
|
||||
func (this *LogsAction) RunGet(params struct {
|
||||
NodeId int64
|
||||
DayFrom string
|
||||
DayTo string
|
||||
Keyword string
|
||||
Level string
|
||||
}) {
|
||||
this.Data["nodeId"] = params.NodeId
|
||||
this.Data["dayFrom"] = params.DayFrom
|
||||
this.Data["dayTo"] = params.DayTo
|
||||
this.Data["keyword"] = params.Keyword
|
||||
this.Data["level"] = params.Level
|
||||
|
||||
countResp, err := this.RPC().NodeLogRPC().CountNodeLogs(this.AdminContext(), &pb.CountNodeLogsRequest{
|
||||
Role: nodeconfigs.NodeRoleDNS,
|
||||
NodeId: params.NodeId,
|
||||
DayFrom: params.DayFrom,
|
||||
DayTo: params.DayTo,
|
||||
Keyword: params.Keyword,
|
||||
Level: params.Level,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var count = countResp.Count
|
||||
var page = this.NewPage(count, 20)
|
||||
|
||||
logsResp, err := this.RPC().NodeLogRPC().ListNodeLogs(this.AdminContext(), &pb.ListNodeLogsRequest{
|
||||
NodeId: params.NodeId,
|
||||
Role: nodeconfigs.NodeRoleDNS,
|
||||
DayFrom: params.DayFrom,
|
||||
DayTo: params.DayTo,
|
||||
Keyword: params.Keyword,
|
||||
Level: params.Level,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var logs = []maps.Map{}
|
||||
for _, log := range logsResp.NodeLogs {
|
||||
logs = append(logs, maps.Map{
|
||||
"tag": log.Tag,
|
||||
"description": log.Description,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", log.CreatedAt),
|
||||
"level": log.Level,
|
||||
"isToday": timeutil.FormatTime("Y-m-d", log.CreatedAt) == timeutil.Format("Y-m-d"),
|
||||
"count": log.Count,
|
||||
})
|
||||
}
|
||||
this.Data["logs"] = logs
|
||||
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
// 节点信息
|
||||
nodeResp, err := this.RPC().NSNodeRPC().FindNSNode(this.AdminContext(), &pb.FindNSNodeRequest{NsNodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var node = nodeResp.NsNode
|
||||
if node == nil {
|
||||
this.WriteString("找不到要操作的节点")
|
||||
return
|
||||
}
|
||||
this.Data["node"] = maps.Map{
|
||||
"id": node.Id,
|
||||
"name": node.Name,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
//go:build plus
|
||||
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type StartAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *StartAction) RunPost(params struct {
|
||||
NodeId int64
|
||||
}) {
|
||||
resp, err := this.RPC().NSNodeRPC().StartNSNode(this.AdminContext(), &pb.StartNSNodeRequest{NsNodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建日志
|
||||
defer this.CreateLogInfo(codes.NSNode_LogStartNSNodeRemotely, params.NodeId)
|
||||
|
||||
if resp.IsOk {
|
||||
this.Success()
|
||||
}
|
||||
|
||||
this.Fail("启动失败:" + resp.Error)
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
//go:build plus
|
||||
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// StatusAction 节点状态
|
||||
type StatusAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *StatusAction) RunPost(params struct {
|
||||
NodeId int64
|
||||
}) {
|
||||
// 节点
|
||||
nodeResp, err := this.RPC().NSNodeRPC().FindNSNode(this.AdminContext(), &pb.FindNSNodeRequest{NsNodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
node := nodeResp.NsNode
|
||||
if node == nil {
|
||||
this.WriteString("找不到要操作的节点")
|
||||
return
|
||||
}
|
||||
|
||||
// 安装信息
|
||||
if node.InstallStatus != nil {
|
||||
this.Data["installStatus"] = maps.Map{
|
||||
"isRunning": node.InstallStatus.IsRunning,
|
||||
"isFinished": node.InstallStatus.IsFinished,
|
||||
"isOk": node.InstallStatus.IsOk,
|
||||
"updatedAt": node.InstallStatus.UpdatedAt,
|
||||
"error": node.InstallStatus.Error,
|
||||
"errorCode": node.InstallStatus.ErrorCode,
|
||||
}
|
||||
} else {
|
||||
this.Data["installStatus"] = nil
|
||||
}
|
||||
|
||||
this.Data["isInstalled"] = node.IsInstalled
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
//go:build plus
|
||||
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type StopAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *StopAction) RunPost(params struct {
|
||||
NodeId int64
|
||||
}) {
|
||||
resp, err := this.RPC().NSNodeRPC().StopNSNode(this.AdminContext(), &pb.StopNSNodeRequest{NsNodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建日志
|
||||
defer this.CreateLogInfo(codes.NSNode_LogStopNSNodeRemotely, params.NodeId)
|
||||
|
||||
if resp.IsOk {
|
||||
this.Success()
|
||||
}
|
||||
|
||||
this.Fail("执行失败:" + resp.Error)
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
//go:build plus
|
||||
|
||||
package node
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants/grantutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/ipAddresses/ipaddressutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdateAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateAction) Init() {
|
||||
this.Nav("", "node", "update")
|
||||
this.SecondMenu("nodes")
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunGet(params struct {
|
||||
NodeId int64
|
||||
}) {
|
||||
this.Data["nodeId"] = params.NodeId
|
||||
|
||||
nodeResp, err := this.RPC().NSNodeRPC().FindNSNode(this.AdminContext(), &pb.FindNSNodeRequest{NsNodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
node := nodeResp.NsNode
|
||||
if node == nil {
|
||||
this.WriteString("找不到要操作的节点")
|
||||
return
|
||||
}
|
||||
|
||||
var clusterMap maps.Map = nil
|
||||
if node.NsCluster != nil {
|
||||
clusterMap = maps.Map{
|
||||
"id": node.NsCluster.Id,
|
||||
"name": node.NsCluster.Name,
|
||||
}
|
||||
}
|
||||
|
||||
// IP地址
|
||||
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledNodeIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledNodeIPAddressesWithNodeIdRequest{
|
||||
NodeId: params.NodeId,
|
||||
Role: nodeconfigs.NodeRoleDNS,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
ipAddressMaps := []maps.Map{}
|
||||
for _, addr := range ipAddressesResp.NodeIPAddresses {
|
||||
ipAddressMaps = append(ipAddressMaps, maps.Map{
|
||||
"id": addr.Id,
|
||||
"name": addr.Name,
|
||||
"ip": addr.Ip,
|
||||
"canAccess": addr.CanAccess,
|
||||
"isOn": addr.IsOn,
|
||||
"isUp": addr.IsUp,
|
||||
})
|
||||
}
|
||||
|
||||
// 登录信息
|
||||
var loginMap maps.Map = nil
|
||||
if node.NodeLogin != nil {
|
||||
loginParams := maps.Map{}
|
||||
if len(node.NodeLogin.Params) > 0 {
|
||||
err = json.Unmarshal(node.NodeLogin.Params, &loginParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
grantMap := maps.Map{}
|
||||
grantId := loginParams.GetInt64("grantId")
|
||||
if grantId > 0 {
|
||||
grantResp, err := this.RPC().NodeGrantRPC().FindEnabledNodeGrant(this.AdminContext(), &pb.FindEnabledNodeGrantRequest{NodeGrantId: grantId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if grantResp.NodeGrant != nil {
|
||||
grantMap = maps.Map{
|
||||
"id": grantResp.NodeGrant.Id,
|
||||
"name": grantResp.NodeGrant.Name,
|
||||
"method": grantResp.NodeGrant.Method,
|
||||
"methodName": grantutils.FindGrantMethodName(grantResp.NodeGrant.Method, this.LangCode()),
|
||||
"username": grantResp.NodeGrant.Username,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loginMap = maps.Map{
|
||||
"id": node.NodeLogin.Id,
|
||||
"name": node.NodeLogin.Name,
|
||||
"type": node.NodeLogin.Type,
|
||||
"params": loginParams,
|
||||
"grant": grantMap,
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["node"] = maps.Map{
|
||||
"id": node.Id,
|
||||
"name": node.Name,
|
||||
"ipAddresses": ipAddressMaps,
|
||||
"cluster": clusterMap,
|
||||
"isOn": node.IsOn,
|
||||
"login": loginMap,
|
||||
}
|
||||
|
||||
// 所有集群
|
||||
resp, err := this.RPC().NSClusterRPC().FindAllNSClusters(this.AdminContext(), &pb.FindAllNSClustersRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
clusterMaps := []maps.Map{}
|
||||
for _, cluster := range resp.NsClusters {
|
||||
clusterMaps = append(clusterMaps, maps.Map{
|
||||
"id": cluster.Id,
|
||||
"name": cluster.Name,
|
||||
})
|
||||
}
|
||||
this.Data["clusters"] = clusterMaps
|
||||
|
||||
// API相关
|
||||
apiConfigResp, err := this.RPC().NSNodeRPC().FindNSNodeAPIConfig(this.AdminContext(), &pb.FindNSNodeAPIConfigRequest{NsNodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var apiNodeAddrs = []*serverconfigs.NetworkAddressConfig{}
|
||||
if len(apiConfigResp.ApiNodeAddrsJSON) > 0 {
|
||||
err = json.Unmarshal(apiConfigResp.ApiNodeAddrsJSON, &apiNodeAddrs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
this.Data["apiNodeAddrs"] = apiNodeAddrs
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunPost(params struct {
|
||||
LoginId int64
|
||||
GrantId int64
|
||||
SshHost string
|
||||
SshPort int
|
||||
|
||||
NodeId int64
|
||||
Name string
|
||||
IPAddressesJSON []byte `alias:"ipAddressesJSON"`
|
||||
ClusterId int64
|
||||
IsOn bool
|
||||
|
||||
ApiNodeAddrsJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 创建日志
|
||||
defer this.CreateLogInfo(codes.NSNode_LogUpdateNSNode, params.NodeId)
|
||||
|
||||
if params.NodeId <= 0 {
|
||||
this.Fail("要操作的节点不存在")
|
||||
}
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入节点名称")
|
||||
|
||||
// 检查cluster
|
||||
if params.ClusterId <= 0 {
|
||||
this.Fail("请选择所在集群")
|
||||
}
|
||||
clusterResp, err := this.RPC().NSClusterRPC().FindNSCluster(this.AdminContext(), &pb.FindNSClusterRequest{NsClusterId: params.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if clusterResp.NsCluster == nil {
|
||||
this.Fail("选择的集群不存在")
|
||||
}
|
||||
|
||||
// IP地址
|
||||
ipAddresses := []maps.Map{}
|
||||
if len(params.IPAddressesJSON) > 0 {
|
||||
err := json.Unmarshal(params.IPAddressesJSON, &ipAddresses)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(ipAddresses) == 0 {
|
||||
this.Fail("请至少输入一个IP地址")
|
||||
}
|
||||
|
||||
// TODO 检查登录授权
|
||||
loginInfo := &pb.NodeLogin{
|
||||
Id: params.LoginId,
|
||||
Name: "SSH",
|
||||
Type: "ssh",
|
||||
Params: maps.Map{
|
||||
"grantId": params.GrantId,
|
||||
"host": params.SshHost,
|
||||
"port": params.SshPort,
|
||||
}.AsJSON(),
|
||||
}
|
||||
|
||||
// 保存
|
||||
_, err = this.RPC().NSNodeRPC().UpdateNSNode(this.AdminContext(), &pb.UpdateNSNodeRequest{
|
||||
NsNodeId: params.NodeId,
|
||||
Name: params.Name,
|
||||
NsClusterId: params.ClusterId,
|
||||
IsOn: params.IsOn,
|
||||
NodeLogin: loginInfo,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 禁用老的IP地址
|
||||
_, err = this.RPC().NodeIPAddressRPC().DisableAllNodeIPAddressesWithNodeId(this.AdminContext(), &pb.DisableAllNodeIPAddressesWithNodeIdRequest{
|
||||
NodeId: params.NodeId,
|
||||
Role: nodeconfigs.NodeRoleDNS,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 添加新的IP地址
|
||||
err = ipaddressutils.UpdateNodeIPAddresses(this.Parent(), params.NodeId, nodeconfigs.NodeRoleDNS, params.IPAddressesJSON)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// API节点设置
|
||||
var apiNodeAddrs = []*serverconfigs.NetworkAddressConfig{}
|
||||
if len(params.ApiNodeAddrsJSON) > 0 {
|
||||
err = json.Unmarshal(params.ApiNodeAddrsJSON, &apiNodeAddrs)
|
||||
if err != nil {
|
||||
this.Fail("API节点地址校验错误:" + err.Error())
|
||||
}
|
||||
for _, addr := range apiNodeAddrs {
|
||||
err = addr.Init()
|
||||
if err != nil {
|
||||
this.Fail("API节点地址校验错误:" + err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
_, err = this.RPC().NSNodeRPC().UpdateNSNodeAPIConfig(this.AdminContext(), &pb.UpdateNSNodeAPIConfigRequest{
|
||||
NsNodeId: params.NodeId,
|
||||
ApiNodeAddrsJSON: params.ApiNodeAddrsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
//go:build plus
|
||||
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type UpdateInstallStatusAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateInstallStatusAction) RunPost(params struct {
|
||||
NodeId int64
|
||||
IsInstalled bool
|
||||
}) {
|
||||
// 创建日志
|
||||
defer this.CreateLogInfo(codes.NSNode_LogUpdateNSNodeInstallationStatus, params.NodeId)
|
||||
|
||||
_, err := this.RPC().NSNodeRPC().UpdateNSNodeIsInstalled(this.AdminContext(), &pb.UpdateNSNodeIsInstalledRequest{
|
||||
NsNodeId: params.NodeId,
|
||||
IsInstalled: params.IsInstalled,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package accessLog
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "")
|
||||
this.SecondMenu("accessLog")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ClusterId int64
|
||||
}) {
|
||||
accessLogResp, err := this.RPC().NSClusterRPC().FindNSClusterAccessLog(this.AdminContext(), &pb.FindNSClusterAccessLogRequest{NsClusterId: params.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var accessLogRef = &dnsconfigs.NSAccessLogRef{}
|
||||
if len(accessLogResp.AccessLogJSON) > 0 {
|
||||
err = json.Unmarshal(accessLogResp.AccessLogJSON, accessLogRef)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
this.Data["accessLogRef"] = accessLogRef
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ClusterId int64
|
||||
AccessLogJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSCluster_LogUpdateNSClusterSettingsAccessLog, params.ClusterId)
|
||||
|
||||
var ref = &dnsconfigs.NSAccessLogRef{}
|
||||
err := json.Unmarshal(params.AccessLogJSON, ref)
|
||||
if err != nil {
|
||||
this.Fail("数据格式错误:" + err.Error())
|
||||
}
|
||||
err = ref.Init()
|
||||
if err != nil {
|
||||
this.Fail("数据格式错误:" + err.Error())
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSClusterRPC().UpdateNSClusterAccessLog(this.AdminContext(), &pb.UpdateNSClusterAccessLogRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
AccessLogJSON: params.AccessLogJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//go:build plus
|
||||
|
||||
package accessLog
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeNS)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Helper(new(clusterutils.ClusterHelper)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters/cluster/settings/accessLog").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
//go:build plus
|
||||
|
||||
package answer
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
// IndexAction UDP设置
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("answer")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ClusterId int64
|
||||
}) {
|
||||
this.Data["clusterId"] = params.ClusterId
|
||||
|
||||
answerResp, err := this.RPC().NSClusterRPC().FindNSClusterAnswerConfig(this.AdminContext(), &pb.FindNSClusterAnswerConfigRequest{NsClusterId: params.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var config = dnsconfigs.DefaultNSAnswerConfig()
|
||||
if len(answerResp.AnswerJSON) > 0 {
|
||||
err := json.Unmarshal(answerResp.AnswerJSON, config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["config"] = config
|
||||
|
||||
this.Data["modes"] = dnsconfigs.FindAllNSAnswerModes()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ClusterId int64
|
||||
|
||||
Mode string
|
||||
MaxSize int16
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSCluster_LogUpdateNSClusterSettingsAnswer, params.ClusterId)
|
||||
|
||||
if !dnsconfigs.IsValidNSAnswerMode(params.Mode) {
|
||||
this.Fail("不支持的模式'" + params.Mode + "'")
|
||||
}
|
||||
|
||||
var config = dnsconfigs.DefaultNSAnswerConfig()
|
||||
config.Mode = params.Mode
|
||||
config.MaxSize = params.MaxSize
|
||||
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSClusterRPC().UpdateNSClusterAnswerConfig(this.AdminContext(), &pb.UpdateNSClusterAnswerConfigRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
AnswerJSON: configJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//go:build plus
|
||||
|
||||
package answer
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeNS)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Helper(new(clusterutils.ClusterHelper)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters/cluster/settings/answer").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package ddosProtection
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"net"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "")
|
||||
this.SecondMenu("ddosProtection")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ClusterId int64
|
||||
}) {
|
||||
this.Data["clusterId"] = params.ClusterId
|
||||
|
||||
protectionResp, err := this.RPC().NSClusterRPC().FindNSClusterDDoSProtection(this.AdminContext(), &pb.FindNSClusterDDoSProtectionRequest{NsClusterId: params.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var ddosProtectionConfig = ddosconfigs.DefaultProtectionConfig()
|
||||
if len(protectionResp.DdosProtectionJSON) > 0 {
|
||||
err = json.Unmarshal(protectionResp.DdosProtectionJSON, ddosProtectionConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
this.Data["config"] = ddosProtectionConfig
|
||||
this.Data["defaultConfigs"] = dnsconfigs.DefaultConfigs
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ClusterId int64
|
||||
DdosProtectionJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSCluster_LogUpdateNSClusterSettingsDDoSProtection, params.ClusterId)
|
||||
|
||||
var ddosProtectionConfig = &ddosconfigs.ProtectionConfig{}
|
||||
err := json.Unmarshal(params.DdosProtectionJSON, ddosProtectionConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
err = ddosProtectionConfig.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
}
|
||||
|
||||
// 校验参数
|
||||
if ddosProtectionConfig.TCP != nil {
|
||||
var tcpConfig = ddosProtectionConfig.TCP
|
||||
if tcpConfig.MaxConnectionsPerIP > 0 && tcpConfig.MaxConnectionsPerIP < dnsconfigs.DefaultTCPMinConnectionsPerIP {
|
||||
this.FailField("tcpMaxConnectionsPerIP", "TCP: 单IP TCP最大连接数不能小于"+types.String(dnsconfigs.DefaultTCPMinConnectionsPerIP))
|
||||
}
|
||||
|
||||
if tcpConfig.NewConnectionsMinutelyRate > 0 && tcpConfig.NewConnectionsMinutelyRate < dnsconfigs.DefaultTCPNewConnectionsMinMinutelyRate {
|
||||
this.FailField("tcpNewConnectionsMinutelyRate", "TCP: 单IP连接速率不能小于"+types.String(dnsconfigs.DefaultTCPNewConnectionsMinMinutelyRate))
|
||||
}
|
||||
|
||||
if tcpConfig.NewConnectionsSecondlyRate > 0 && tcpConfig.NewConnectionsSecondlyRate < dnsconfigs.DefaultTCPNewConnectionsMinSecondlyRate {
|
||||
this.FailField("tcpNewConnectionsSecondlyRate", "TCP: 单IP连接速率不能小于"+types.String(dnsconfigs.DefaultTCPNewConnectionsMinSecondlyRate))
|
||||
}
|
||||
|
||||
// Port
|
||||
for _, portConfig := range tcpConfig.Ports {
|
||||
if portConfig.Port > 65535 {
|
||||
this.Fail("端口号" + types.String(portConfig.Port) + "不能大于65535")
|
||||
}
|
||||
}
|
||||
|
||||
// IP
|
||||
for _, ipConfig := range tcpConfig.AllowIPList {
|
||||
if net.ParseIP(ipConfig.IP) == nil {
|
||||
this.Fail("白名单IP '" + ipConfig.IP + "' 格式错误")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSClusterRPC().UpdateNSClusterDDoSProtection(this.AdminContext(), &pb.UpdateNSClusterDDoSProtectionRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
DdosProtectionJSON: params.DdosProtectionJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
//go:build plus
|
||||
|
||||
package ddosProtection
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeNS)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Helper(new(clusterutils.ClusterHelper)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters/cluster/settings/ddos-protection").
|
||||
GetPost("", new(IndexAction)).
|
||||
GetPost("/status", new(StatusAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package ddosProtection
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/nsnodeutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type StatusAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *StatusAction) Init() {
|
||||
this.Nav("", "setting", "")
|
||||
this.SecondMenu("ddosProtection")
|
||||
}
|
||||
|
||||
func (this *StatusAction) RunGet(params struct {
|
||||
ClusterId int64
|
||||
}) {
|
||||
this.Data["clusterId"] = params.ClusterId
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *StatusAction) RunPost(params struct {
|
||||
ClusterId int64
|
||||
}) {
|
||||
results, err := nsnodeutils.SendMessageToNSCluster(this.AdminContext(), params.ClusterId, messageconfigs.MessageCodeCheckLocalFirewall, &messageconfigs.CheckLocalFirewallMessage{
|
||||
Name: "nftables",
|
||||
}, 10)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var resultMaps = []maps.Map{}
|
||||
for _, result := range results {
|
||||
var resultMap = maps.Map{
|
||||
"isOk": result.IsOK,
|
||||
"message": result.Message,
|
||||
"nodeId": result.NodeId,
|
||||
"nodeName": result.NodeName,
|
||||
}
|
||||
|
||||
nodeResp, err := this.RPC().NSNodeRPC().FindNSNodeDDoSProtection(this.AdminContext(), &pb.FindNSNodeDDoSProtectionRequest{NsNodeId: result.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(nodeResp.DdosProtectionJSON) > 0 {
|
||||
var ddosProtection = ddosconfigs.DefaultProtectionConfig()
|
||||
err = json.Unmarshal(nodeResp.DdosProtectionJSON, ddosProtection)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
resultMap["isPrior"] = !ddosProtection.IsPriorEmpty()
|
||||
}
|
||||
resultMaps = append(resultMaps, resultMap)
|
||||
}
|
||||
|
||||
this.Data["results"] = resultMaps
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
//go:build plus
|
||||
|
||||
package doh
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"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/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
// IndexAction DoH设置
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("doh")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ClusterId int64
|
||||
}) {
|
||||
this.Data["clusterId"] = params.ClusterId
|
||||
|
||||
dohResp, err := this.RPC().NSClusterRPC().FindNSClusterDoHConfig(this.AdminContext(), &pb.FindNSClusterDoHConfigRequest{NsClusterId: params.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var dohConfig = dnsconfigs.NewNSDoHConfig()
|
||||
if len(dohResp.DohJSON) > 0 {
|
||||
err := json.Unmarshal(dohResp.DohJSON, dohConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
} else {
|
||||
dohConfig.Listen = []*serverconfigs.NetworkAddressConfig{
|
||||
{
|
||||
Protocol: serverconfigs.ProtocolHTTPS,
|
||||
PortRange: "443",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// SSL配置
|
||||
var sslPolicy *sslconfigs.SSLPolicy
|
||||
if dohConfig.SSLPolicyRef != nil && dohConfig.SSLPolicyRef.SSLPolicyId > 0 {
|
||||
sslPolicyConfigResp, err := this.RPC().SSLPolicyRPC().FindEnabledSSLPolicyConfig(this.AdminContext(), &pb.FindEnabledSSLPolicyConfigRequest{
|
||||
SslPolicyId: dohConfig.SSLPolicyRef.SSLPolicyId,
|
||||
IgnoreData: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var sslPolicyConfigJSON = sslPolicyConfigResp.SslPolicyJSON
|
||||
if len(sslPolicyConfigJSON) > 0 {
|
||||
sslPolicy = &sslconfigs.SSLPolicy{}
|
||||
err = json.Unmarshal(sslPolicyConfigJSON, sslPolicy)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["dohConfig"] = maps.Map{
|
||||
"isOn": dohConfig.IsOn,
|
||||
"listen": dohConfig.Listen,
|
||||
"sslPolicy": sslPolicy,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ClusterId int64
|
||||
IsOn bool
|
||||
Addresses []byte
|
||||
SslPolicyJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSCluster_LogUpdateNSClusterSettingsDoH, params.ClusterId)
|
||||
|
||||
var addresses = []*serverconfigs.NetworkAddressConfig{}
|
||||
err := json.Unmarshal(params.Addresses, &addresses)
|
||||
if err != nil {
|
||||
this.Fail("端口地址解析失败:" + err.Error())
|
||||
}
|
||||
|
||||
// 校验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.AdminContext(), &pb.UpdateSSLPolicyRequest{
|
||||
SslPolicyId: sslPolicyId,
|
||||
Http2Enabled: sslPolicy.HTTP2Enabled,
|
||||
Http3Enabled: sslPolicy.HTTP3Enabled,
|
||||
MinVersion: sslPolicy.MinVersion,
|
||||
SslCertsJSON: certsJSON,
|
||||
HstsJSON: hstsJSON,
|
||||
OcspIsOn: sslPolicy.OCSPIsOn,
|
||||
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.AdminContext(), &pb.CreateSSLPolicyRequest{
|
||||
Http2Enabled: sslPolicy.HTTP2Enabled,
|
||||
Http3Enabled: sslPolicy.HTTP3Enabled,
|
||||
MinVersion: sslPolicy.MinVersion,
|
||||
SslCertsJSON: certsJSON,
|
||||
HstsJSON: hstsJSON,
|
||||
OcspIsOn: sslPolicy.OCSPIsOn,
|
||||
ClientAuthType: types.Int32(sslPolicy.ClientAuthType),
|
||||
ClientCACertsJSON: clientCACertsJSON,
|
||||
CipherSuitesIsOn: sslPolicy.CipherSuitesIsOn,
|
||||
CipherSuites: sslPolicy.CipherSuites,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
sslPolicyId = resp.SslPolicyId
|
||||
}
|
||||
}
|
||||
|
||||
var dohConfig = dnsconfigs.NewNSDoHConfig()
|
||||
dohConfig.IsOn = params.IsOn
|
||||
dohConfig.Listen = addresses
|
||||
|
||||
dohConfig.SSLPolicyRef = &sslconfigs.SSLPolicyRef{
|
||||
IsOn: true,
|
||||
SSLPolicyId: sslPolicyId,
|
||||
}
|
||||
|
||||
configData, err := json.Marshal(dohConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSClusterRPC().UpdateNSClusterDoH(this.AdminContext(), &pb.UpdateNSClusterDoHRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
DohJSON: configData,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//go:build plus
|
||||
|
||||
package doh
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeNS)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Helper(new(clusterutils.ClusterHelper)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters/cluster/settings/doh").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "")
|
||||
this.SecondMenu("basic")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ClusterId int64
|
||||
}) {
|
||||
clusterResp, err := this.RPC().NSClusterRPC().FindNSCluster(this.AdminContext(), &pb.FindNSClusterRequest{NsClusterId: params.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var cluster = clusterResp.NsCluster
|
||||
if cluster == nil {
|
||||
this.NotFound("nsCluster", params.ClusterId)
|
||||
return
|
||||
}
|
||||
|
||||
var hosts = cluster.Hosts
|
||||
if hosts == nil {
|
||||
hosts = []string{}
|
||||
}
|
||||
|
||||
// 时区
|
||||
this.Data["timeZoneGroups"] = nodeconfigs.FindAllTimeZoneGroups()
|
||||
this.Data["timeZoneLocations"] = nodeconfigs.FindAllTimeZoneLocations()
|
||||
|
||||
if len(cluster.TimeZone) == 0 {
|
||||
cluster.TimeZone = nodeconfigs.DefaultTimeZoneLocation
|
||||
}
|
||||
this.Data["timeZoneLocation"] = nodeconfigs.FindTimeZoneLocation(cluster.TimeZone)
|
||||
|
||||
this.Data["cluster"] = maps.Map{
|
||||
"id": cluster.Id,
|
||||
"name": cluster.Name,
|
||||
"email": cluster.Email,
|
||||
"hosts": hosts,
|
||||
"timeZone": cluster.TimeZone,
|
||||
"autoRemoteStart": cluster.AutoRemoteStart,
|
||||
"detectAgents": cluster.DetectAgents,
|
||||
"checkingPorts": cluster.CheckingPorts,
|
||||
"isOn": cluster.IsOn,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ClusterId int64
|
||||
Name string
|
||||
Email string
|
||||
Hosts []string
|
||||
TimeZone string
|
||||
AutoRemoteStart bool
|
||||
DetectAgents bool
|
||||
CheckingPorts bool
|
||||
IsOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSCluster_LogUpdateNSClusterSettingsBasic, params.ClusterId)
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入集群名称").
|
||||
Field("email", params.Email).
|
||||
Require("请输入正确的管理员电子邮箱地址")
|
||||
|
||||
// 校验主机域名
|
||||
var hosts = []string{}
|
||||
for _, host := range params.Hosts {
|
||||
if !domainutils.ValidateDomainFormat(host) {
|
||||
this.Fail("错误的DNS主机地址 '" + host + "'")
|
||||
return
|
||||
}
|
||||
hosts = append(hosts, host)
|
||||
}
|
||||
|
||||
_, err := this.RPC().NSClusterRPC().UpdateNSCluster(this.AdminContext(), &pb.UpdateNSClusterRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
Name: params.Name,
|
||||
Email: params.Email,
|
||||
Hosts: hosts,
|
||||
TimeZone: params.TimeZone,
|
||||
AutoRemoteStart: params.AutoRemoteStart,
|
||||
DetectAgents: params.DetectAgents,
|
||||
CheckingPorts: params.CheckingPorts,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//go:build plus
|
||||
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeNS)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Helper(new(clusterutils.ClusterHelper)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters/cluster/settings").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package recursion
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "")
|
||||
this.SecondMenu("recursion")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ClusterId int64
|
||||
}) {
|
||||
this.Data["clusterId"] = params.ClusterId
|
||||
|
||||
resp, err := this.RPC().NSClusterRPC().FindNSClusterRecursionConfig(this.AdminContext(), &pb.FindNSClusterRecursionConfigRequest{NsClusterId: params.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var config = &dnsconfigs.NSRecursionConfig{}
|
||||
if len(resp.RecursionJSON) > 0 {
|
||||
err = json.Unmarshal(resp.RecursionJSON, config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
config.UseLocalHosts = true
|
||||
}
|
||||
this.Data["config"] = config
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ClusterId int64
|
||||
RecursionJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSCluster_LogUpdateNSClusterSettingsRecursion, params.ClusterId)
|
||||
|
||||
// TODO 校验域名
|
||||
|
||||
_, err := this.RPC().NSClusterRPC().UpdateNSClusterRecursionConfig(this.AdminContext(), &pb.UpdateNSClusterRecursionConfigRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
RecursionJSON: params.RecursionJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//go:build plus
|
||||
|
||||
package recursion
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeNS)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Helper(new(clusterutils.ClusterHelper)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters/cluster/settings/recursion").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
//go:build plus
|
||||
|
||||
package soa
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
// IndexAction UDP设置
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("soa")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ClusterId int64
|
||||
}) {
|
||||
this.Data["clusterId"] = params.ClusterId
|
||||
|
||||
soaResp, err := this.RPC().NSClusterRPC().FindNSClusterSOAConfig(this.AdminContext(), &pb.FindNSClusterSOAConfigRequest{NsClusterId: params.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var config = dnsconfigs.DefaultNSSOAConfig()
|
||||
if len(soaResp.SoaJSON) > 0 {
|
||||
err := json.Unmarshal(soaResp.SoaJSON, config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["config"] = config
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ClusterId int64
|
||||
|
||||
MName string
|
||||
RName string
|
||||
RefreshSeconds uint32
|
||||
RetrySeconds uint32
|
||||
ExpireSeconds uint32
|
||||
MinimumTTL uint32
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSCluster_LogUpdateNSClusterSettingsSOA, params.ClusterId)
|
||||
|
||||
if len(params.MName) > 0 {
|
||||
if !domainutils.ValidateDomainFormat(params.MName) {
|
||||
this.FailField("mName", "请输入正确的主要服务器名称")
|
||||
}
|
||||
}
|
||||
|
||||
if len(params.RName) > 0 {
|
||||
if !utils.ValidateEmail(params.RName) {
|
||||
this.FailField("rName", "请输入正确的管理员电子邮箱地址")
|
||||
}
|
||||
}
|
||||
|
||||
var config = dnsconfigs.DefaultNSSOAConfig()
|
||||
config.MName = params.MName
|
||||
config.RName = params.RName
|
||||
config.RefreshSeconds = params.RefreshSeconds
|
||||
config.RetrySeconds = params.RetrySeconds
|
||||
config.ExpireSeconds = params.ExpireSeconds
|
||||
config.MinimumTTL = params.MinimumTTL
|
||||
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSClusterRPC().UpdateNSClusterSOAConfig(this.AdminContext(), &pb.UpdateNSClusterSOAConfigRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
SoaJSON: configJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//go:build plus
|
||||
|
||||
package soa
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeNS)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Helper(new(clusterutils.ClusterHelper)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters/cluster/settings/soa").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
//go:build plus
|
||||
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
// IndexAction TCP设置
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "")
|
||||
this.SecondMenu("tcp")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ClusterId int64
|
||||
}) {
|
||||
this.Data["clusterId"] = params.ClusterId
|
||||
|
||||
tcpResp, err := this.RPC().NSClusterRPC().FindNSClusterTCPConfig(this.AdminContext(), &pb.FindNSClusterTCPConfigRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var tcpConfig = &serverconfigs.TCPProtocolConfig{}
|
||||
if len(tcpResp.TcpJSON) > 0 {
|
||||
err := json.Unmarshal(tcpResp.TcpJSON, tcpConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
} else {
|
||||
tcpConfig.IsOn = true
|
||||
}
|
||||
|
||||
this.Data["tcpConfig"] = tcpConfig
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ClusterId int64
|
||||
Addresses []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSCluster_LogUpdateNSClusterSettingsTCP, params.ClusterId)
|
||||
|
||||
var addresses = []*serverconfigs.NetworkAddressConfig{}
|
||||
err := json.Unmarshal(params.Addresses, &addresses)
|
||||
if err != nil {
|
||||
this.Fail("端口地址解析失败:" + err.Error())
|
||||
}
|
||||
|
||||
var tcpConfig = &serverconfigs.TCPProtocolConfig{}
|
||||
tcpConfig.IsOn = true
|
||||
tcpConfig.Listen = addresses
|
||||
|
||||
configJSON, err := json.Marshal(tcpConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSClusterRPC().UpdateNSClusterTCP(this.AdminContext(), &pb.UpdateNSClusterTCPRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
TcpJSON: configJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//go:build plus
|
||||
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeNS)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Helper(new(clusterutils.ClusterHelper)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters/cluster/settings/tcp").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
//go:build plus
|
||||
|
||||
package tls
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"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/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 {
|
||||
ClusterId int64
|
||||
}) {
|
||||
this.Data["clusterId"] = params.ClusterId
|
||||
|
||||
tlsResp, err := this.RPC().NSClusterRPC().FindNSClusterTLSConfig(this.AdminContext(), &pb.FindNSClusterTLSConfigRequest{NsClusterId: params.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var tlsConfig = &serverconfigs.TLSProtocolConfig{}
|
||||
if len(tlsResp.TlsJSON) > 0 {
|
||||
err := json.Unmarshal(tlsResp.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.AdminContext(), &pb.FindEnabledSSLPolicyConfigRequest{
|
||||
SslPolicyId: tlsConfig.SSLPolicyRef.SSLPolicyId,
|
||||
IgnoreData: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var sslPolicyConfigJSON = sslPolicyConfigResp.SslPolicyJSON
|
||||
if len(sslPolicyConfigJSON) > 0 {
|
||||
sslPolicy = &sslconfigs.SSLPolicy{}
|
||||
err = json.Unmarshal(sslPolicyConfigJSON, sslPolicy)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["tlsConfig"] = maps.Map{
|
||||
"isOn": tlsConfig.IsOn,
|
||||
"listen": tlsConfig.Listen,
|
||||
"sslPolicy": sslPolicy,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ClusterId int64
|
||||
Addresses []byte
|
||||
|
||||
SslPolicyJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSCluster_LogUpdateNSClusterSettingsTLS, params.ClusterId)
|
||||
|
||||
var addresses = []*serverconfigs.NetworkAddressConfig{}
|
||||
err := json.Unmarshal(params.Addresses, &addresses)
|
||||
if err != nil {
|
||||
this.Fail("端口地址解析失败:" + err.Error())
|
||||
}
|
||||
|
||||
// 校验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.AdminContext(), &pb.UpdateSSLPolicyRequest{
|
||||
SslPolicyId: sslPolicyId,
|
||||
Http2Enabled: sslPolicy.HTTP2Enabled,
|
||||
Http3Enabled: sslPolicy.HTTP3Enabled,
|
||||
MinVersion: sslPolicy.MinVersion,
|
||||
SslCertsJSON: certsJSON,
|
||||
HstsJSON: hstsJSON,
|
||||
OcspIsOn: sslPolicy.OCSPIsOn,
|
||||
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.AdminContext(), &pb.CreateSSLPolicyRequest{
|
||||
Http2Enabled: sslPolicy.HTTP2Enabled,
|
||||
Http3Enabled: sslPolicy.HTTP3Enabled,
|
||||
MinVersion: sslPolicy.MinVersion,
|
||||
SslCertsJSON: certsJSON,
|
||||
HstsJSON: hstsJSON,
|
||||
OcspIsOn: sslPolicy.OCSPIsOn,
|
||||
ClientAuthType: types.Int32(sslPolicy.ClientAuthType),
|
||||
ClientCACertsJSON: clientCACertsJSON,
|
||||
CipherSuitesIsOn: sslPolicy.CipherSuitesIsOn,
|
||||
CipherSuites: sslPolicy.CipherSuites,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
sslPolicyId = resp.SslPolicyId
|
||||
}
|
||||
}
|
||||
|
||||
var tlsConfig = &serverconfigs.TLSProtocolConfig{}
|
||||
tlsConfig.IsOn = true
|
||||
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().NSClusterRPC().UpdateNSClusterTLS(this.AdminContext(), &pb.UpdateNSClusterTLSRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
TlsJSON: configData,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//go:build plus
|
||||
|
||||
package tls
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeNS)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Helper(new(clusterutils.ClusterHelper)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters/cluster/settings/tls").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
//go:build plus
|
||||
|
||||
package udp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
// IndexAction UDP设置
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("udp")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ClusterId int64
|
||||
}) {
|
||||
this.Data["clusterId"] = params.ClusterId
|
||||
|
||||
udpResp, err := this.RPC().NSClusterRPC().FindNSClusterUDPConfig(this.AdminContext(), &pb.FindNSClusterUDPConfigRequest{NsClusterId: params.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var udpConfig = &serverconfigs.UDPProtocolConfig{}
|
||||
if len(udpResp.UdpJSON) > 0 {
|
||||
err := json.Unmarshal(udpResp.UdpJSON, udpConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
} else {
|
||||
udpConfig.IsOn = true
|
||||
}
|
||||
|
||||
this.Data["udpConfig"] = udpConfig
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ClusterId int64
|
||||
Addresses []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSCluster_LogUpdateNSClusterSettingsUDP, params.ClusterId)
|
||||
|
||||
var addresses = []*serverconfigs.NetworkAddressConfig{}
|
||||
err := json.Unmarshal(params.Addresses, &addresses)
|
||||
if err != nil {
|
||||
this.Fail("端口地址解析失败:" + err.Error())
|
||||
}
|
||||
|
||||
var udpConfig = &serverconfigs.UDPProtocolConfig{}
|
||||
udpConfig.IsOn = true
|
||||
udpConfig.Listen = addresses
|
||||
|
||||
configJSON, err := json.Marshal(udpConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSClusterRPC().UpdateNSClusterUDP(this.AdminContext(), &pb.UpdateNSClusterUDPRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
UdpJSON: configJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//go:build plus
|
||||
|
||||
package udp
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeNS)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Helper(new(clusterutils.ClusterHelper)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters/cluster/settings/udp").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
//go:build plus
|
||||
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants/grantutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdateNodeSSHAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateNodeSSHAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdateNodeSSHAction) RunGet(params struct {
|
||||
NodeId int64
|
||||
}) {
|
||||
nodeResp, err := this.RPC().NSNodeRPC().FindNSNode(this.AdminContext(), &pb.FindNSNodeRequest{NsNodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if nodeResp.NsNode == nil {
|
||||
this.NotFound("node", params.NodeId)
|
||||
return
|
||||
}
|
||||
|
||||
node := nodeResp.NsNode
|
||||
this.Data["node"] = maps.Map{
|
||||
"id": node.Id,
|
||||
"name": node.Name,
|
||||
}
|
||||
|
||||
if nodeResp.NsNode.NsCluster != nil {
|
||||
this.Data["clusterId"] = nodeResp.NsNode.NsCluster.Id
|
||||
} else {
|
||||
this.Data["clusterId"] = 0
|
||||
}
|
||||
|
||||
// SSH
|
||||
loginParams := maps.Map{
|
||||
"host": "",
|
||||
"port": "",
|
||||
"grantId": 0,
|
||||
}
|
||||
this.Data["loginId"] = 0
|
||||
if node.NodeLogin != nil {
|
||||
this.Data["loginId"] = node.NodeLogin.Id
|
||||
if len(node.NodeLogin.Params) > 0 {
|
||||
err = json.Unmarshal(node.NodeLogin.Params, &loginParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["params"] = loginParams
|
||||
|
||||
// 认证信息
|
||||
grantId := loginParams.GetInt64("grantId")
|
||||
grantResp, err := this.RPC().NodeGrantRPC().FindEnabledNodeGrant(this.AdminContext(), &pb.FindEnabledNodeGrantRequest{NodeGrantId: grantId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
var grantMap maps.Map = nil
|
||||
if grantResp.NodeGrant != nil {
|
||||
grantMap = maps.Map{
|
||||
"id": grantResp.NodeGrant.Id,
|
||||
"name": grantResp.NodeGrant.Name,
|
||||
"method": grantResp.NodeGrant.Method,
|
||||
"methodName": grantutils.FindGrantMethodName(grantResp.NodeGrant.Method, this.LangCode()),
|
||||
}
|
||||
}
|
||||
this.Data["grant"] = grantMap
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateNodeSSHAction) RunPost(params struct {
|
||||
NodeId int64
|
||||
LoginId int64
|
||||
SshHost string
|
||||
SshPort int
|
||||
GrantId int64
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
params.Must.
|
||||
Field("sshHost", params.SshHost).
|
||||
Require("请输入SSH主机地址").
|
||||
Field("sshPort", params.SshPort).
|
||||
Gt(0, "SSH主机端口需要大于0").
|
||||
Lt(65535, "SSH主机端口需要小于65535")
|
||||
|
||||
if params.GrantId <= 0 {
|
||||
this.Fail("需要选择或填写至少一个认证信息")
|
||||
}
|
||||
|
||||
login := &pb.NodeLogin{
|
||||
Id: params.LoginId,
|
||||
Name: "SSH",
|
||||
Type: "ssh",
|
||||
Params: maps.Map{
|
||||
"grantId": params.GrantId,
|
||||
"host": params.SshHost,
|
||||
"port": params.SshPort,
|
||||
}.AsJSON(),
|
||||
}
|
||||
|
||||
_, err := this.RPC().NSNodeRPC().UpdateNSNodeLogin(this.AdminContext(), &pb.UpdateNSNodeLoginRequest{
|
||||
NsNodeId: params.NodeId,
|
||||
NodeLogin: login,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建日志
|
||||
defer this.CreateLogInfo(codes.NSNodeSSH_LogUpdateNSNodeSSH, params.NodeId)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package cluster
|
||||
|
||||
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
|
||||
type UpgradeRemoteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpgradeRemoteAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpgradeRemoteAction) RunGet(params struct{}) {
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
//go:build plus
|
||||
|
||||
package clusterutils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// ClusterHelper 单个集群的帮助
|
||||
type ClusterHelper struct {
|
||||
helpers.LangHelper
|
||||
}
|
||||
|
||||
func NewClusterHelper() *ClusterHelper {
|
||||
return &ClusterHelper{}
|
||||
}
|
||||
|
||||
func (this *ClusterHelper) BeforeAction(actionPtr actions.ActionWrapper) (goNext bool) {
|
||||
var action = actionPtr.Object()
|
||||
if action.Request.Method != http.MethodGet {
|
||||
return true
|
||||
}
|
||||
|
||||
action.Data["teaMenu"] = "ns"
|
||||
|
||||
selectedTabbar := action.Data.GetString("mainTab")
|
||||
clusterId := action.ParamInt64("clusterId")
|
||||
clusterIdString := strconv.FormatInt(clusterId, 10)
|
||||
action.Data["clusterId"] = clusterId
|
||||
|
||||
if clusterId > 0 {
|
||||
rpcClient, err := rpc.SharedRPC()
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return
|
||||
}
|
||||
clusterResp, err := rpcClient.NSClusterRPC().FindNSCluster(actionPtr.(actionutils.ActionInterface).AdminContext(), &pb.FindNSClusterRequest{
|
||||
NsClusterId: clusterId,
|
||||
})
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return
|
||||
}
|
||||
var cluster = clusterResp.NsCluster
|
||||
if cluster == nil {
|
||||
action.WriteString("can not find ns cluster")
|
||||
return
|
||||
}
|
||||
action.Data["currentCluster"] = maps.Map{
|
||||
"id": cluster.Id,
|
||||
"name": cluster.Name,
|
||||
}
|
||||
|
||||
var nodeId = action.ParamInt64("nodeId")
|
||||
var isInCluster = nodeId <= 0
|
||||
|
||||
var tabbar = actionutils.NewTabbar()
|
||||
{
|
||||
var url = "/ns/clusters"
|
||||
if !isInCluster {
|
||||
url = "/ns/clusters/cluster?clusterId=" + clusterIdString
|
||||
}
|
||||
tabbar.Add("", "", url, "arrow left", false)
|
||||
}
|
||||
{
|
||||
var url = "/ns/clusters/cluster?clusterId=" + clusterIdString
|
||||
var item = tabbar.Add(cluster.Name, "", url, "angle right", true)
|
||||
item.IsTitle = true
|
||||
}
|
||||
{
|
||||
var item = tabbar.Add(this.Lang(action, codes.NSCluster_TabNodes), "", "/ns/clusters/cluster?clusterId="+clusterIdString, "server", selectedTabbar == "node")
|
||||
item.IsDisabled = !isInCluster
|
||||
}
|
||||
{
|
||||
var item = tabbar.Add(this.Lang(action, codes.NSCluster_TabSetting), "", "/ns/clusters/cluster/settings?clusterId="+clusterIdString, "setting", selectedTabbar == "setting")
|
||||
item.IsDisabled = !isInCluster
|
||||
}
|
||||
{
|
||||
var item = tabbar.Add(this.Lang(action, codes.NSCluster_TabDelete), "", "/ns/clusters/cluster/delete?clusterId="+clusterIdString, "trash", selectedTabbar == "delete")
|
||||
item.IsDisabled = !isInCluster
|
||||
}
|
||||
actionutils.SetTabbar(action, tabbar)
|
||||
|
||||
// 左侧菜单
|
||||
secondMenuItem := action.Data.GetString("secondMenuItem")
|
||||
switch selectedTabbar {
|
||||
case "setting":
|
||||
var menuItems = this.createSettingMenu(cluster, secondMenuItem, actionPtr)
|
||||
action.Data["leftMenuItems"] = menuItems
|
||||
|
||||
// 当前菜单
|
||||
action.Data["leftMenuActiveItem"] = nil
|
||||
for _, item := range menuItems {
|
||||
if item.GetBool("isActive") {
|
||||
action.Data["leftMenuActiveItem"] = item
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// 设置菜单
|
||||
func (this *ClusterHelper) createSettingMenu(cluster *pb.NSCluster, selectedItem string, actionPtr actions.ActionWrapper) (items []maps.Map) {
|
||||
var clusterId = types.String(cluster.Id)
|
||||
|
||||
// TCP
|
||||
var tcpConfig = &serverconfigs.TCPProtocolConfig{}
|
||||
if len(cluster.TcpJSON) > 0 {
|
||||
err := json.Unmarshal(cluster.TcpJSON, tcpConfig)
|
||||
if err != nil {
|
||||
// ignore error
|
||||
logs.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TLS
|
||||
var tlsConfig = &serverconfigs.TLSProtocolConfig{}
|
||||
if len(cluster.TlsJSON) > 0 {
|
||||
err := json.Unmarshal(cluster.TlsJSON, tlsConfig)
|
||||
if err != nil {
|
||||
// ignore error
|
||||
logs.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// UDP
|
||||
var udpConfig = &serverconfigs.UDPProtocolConfig{}
|
||||
if len(cluster.UdpJSON) > 0 {
|
||||
err := json.Unmarshal(cluster.UdpJSON, udpConfig)
|
||||
if err != nil {
|
||||
// ignore error
|
||||
logs.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// DoH
|
||||
var dohConfig = dnsconfigs.NewNSDoHConfig()
|
||||
if len(cluster.DohJSON) > 0 {
|
||||
err := json.Unmarshal(cluster.DohJSON, dohConfig)
|
||||
if err != nil {
|
||||
// ignore error
|
||||
logs.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// 应答
|
||||
var answerConfig = dnsconfigs.DefaultNSAnswerConfig()
|
||||
var answerConfigIsChanged = false
|
||||
if len(cluster.AnswerJSON) > 0 {
|
||||
err := json.Unmarshal(cluster.AnswerJSON, answerConfig)
|
||||
if err != nil {
|
||||
// ignore error
|
||||
} else {
|
||||
answerConfigIsChanged = !answerConfig.IsSame(dnsconfigs.DefaultNSAnswerConfig())
|
||||
}
|
||||
}
|
||||
|
||||
// SOA
|
||||
var soaConfig = dnsconfigs.DefaultNSSOAConfig()
|
||||
var soaConfigIsChanged = false
|
||||
if len(cluster.SoaJSON) > 0 {
|
||||
err := json.Unmarshal(cluster.SoaJSON, soaConfig)
|
||||
if err != nil {
|
||||
// ignore error
|
||||
} else {
|
||||
soaConfigIsChanged = !soaConfig.IsSame(dnsconfigs.DefaultNSSOAConfig())
|
||||
}
|
||||
}
|
||||
|
||||
return []maps.Map{
|
||||
{
|
||||
"name": this.Lang(actionPtr, codes.NSCluster_MenuBasic),
|
||||
"url": "/ns/clusters/cluster/settings?clusterId=" + clusterId,
|
||||
"isActive": selectedItem == "basic",
|
||||
},
|
||||
{
|
||||
"name": "-",
|
||||
},
|
||||
{
|
||||
"name": this.Lang(actionPtr, codes.NSCluster_MenuUDP),
|
||||
"url": "/ns/clusters/cluster/settings/udp?clusterId=" + clusterId,
|
||||
"isActive": selectedItem == "udp",
|
||||
"isOn": udpConfig != nil && udpConfig.IsOn,
|
||||
},
|
||||
{
|
||||
"name": this.Lang(actionPtr, codes.NSCluster_MenuTCP),
|
||||
"url": "/ns/clusters/cluster/settings/tcp?clusterId=" + clusterId,
|
||||
"isActive": selectedItem == "tcp",
|
||||
"isOn": tcpConfig != nil && tcpConfig.IsOn,
|
||||
},
|
||||
{
|
||||
"name": this.Lang(actionPtr, codes.NSCluster_MenuTLS),
|
||||
"url": "/ns/clusters/cluster/settings/tls?clusterId=" + clusterId,
|
||||
"isActive": selectedItem == "tls",
|
||||
"isOn": tlsConfig != nil && tlsConfig.IsOn,
|
||||
},
|
||||
{
|
||||
"name": this.Lang(actionPtr, codes.NSCluster_MenuDoH),
|
||||
"url": "/ns/clusters/cluster/settings/doh?clusterId=" + clusterId,
|
||||
"isActive": selectedItem == "doh",
|
||||
"isOn": dohConfig != nil && dohConfig.IsOn,
|
||||
},
|
||||
{
|
||||
"name": "-",
|
||||
},
|
||||
{
|
||||
"name": this.Lang(actionPtr, codes.NSCluster_MenuAccessLogs),
|
||||
"url": "/ns/clusters/cluster/settings/accessLog?clusterId=" + clusterId,
|
||||
"isActive": selectedItem == "accessLog",
|
||||
},
|
||||
{
|
||||
"name": this.Lang(actionPtr, codes.NSCluster_MenuAnswerSetting),
|
||||
"url": "/ns/clusters/cluster/settings/answer?clusterId=" + clusterId,
|
||||
"isActive": selectedItem == "answer",
|
||||
"isOn": answerConfigIsChanged,
|
||||
},
|
||||
{
|
||||
"name": this.Lang(actionPtr, codes.NSCluster_MenuSOA),
|
||||
"url": "/ns/clusters/cluster/settings/soa?clusterId=" + clusterId,
|
||||
"isActive": selectedItem == "soa",
|
||||
"isOn": soaConfigIsChanged,
|
||||
},
|
||||
{
|
||||
"name": this.Lang(actionPtr, codes.NSCluster_MenuDNSRecursion),
|
||||
"url": "/ns/clusters/cluster/settings/recursion?clusterId=" + clusterId,
|
||||
"isActive": selectedItem == "recursion",
|
||||
},
|
||||
{
|
||||
"name": "-",
|
||||
},
|
||||
{
|
||||
"name": this.Lang(actionPtr, codes.NSCluster_MenuDDoSProtection),
|
||||
"url": "/ns/clusters/cluster/settings/ddos-protection?clusterId=" + clusterId,
|
||||
"isActive": selectedItem == "ddosProtection",
|
||||
},
|
||||
}
|
||||
}
|
||||
87
EdgeAdmin/internal/web/actions/default/ns/clusters/create.go
Normal file
87
EdgeAdmin/internal/web/actions/default/ns/clusters/create.go
Normal file
@@ -0,0 +1,87 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package clusters
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type CreateAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreateAction) Init() {
|
||||
this.Nav("", "", "create")
|
||||
}
|
||||
|
||||
func (this *CreateAction) RunGet(params struct{}) {
|
||||
// 默认的访问日志设置
|
||||
this.Data["accessLogRef"] = &dnsconfigs.NSAccessLogRef{
|
||||
IsOn: true,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreateAction) RunPost(params struct {
|
||||
Name string
|
||||
AccessLogJSON []byte
|
||||
Hosts []string
|
||||
Email string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
var clusterId int64
|
||||
defer func() {
|
||||
this.CreateLogInfo(codes.NSCluster_LogCreateNSCluster, clusterId)
|
||||
}()
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入集群名称").
|
||||
Field("email", params.Email).
|
||||
Require("请输入正确的管理员电子邮箱地址")
|
||||
|
||||
// 校验主机域名
|
||||
var hosts = []string{}
|
||||
for _, host := range params.Hosts {
|
||||
if !domainutils.ValidateDomainFormat(host) {
|
||||
this.Fail("错误的DNS主机地址 '" + host + "'")
|
||||
return
|
||||
}
|
||||
hosts = append(hosts, host)
|
||||
}
|
||||
|
||||
// 校验访问日志设置
|
||||
var ref = &dnsconfigs.NSAccessLogRef{}
|
||||
err := json.Unmarshal(params.AccessLogJSON, ref)
|
||||
if err != nil {
|
||||
this.Fail("数据格式错误:" + err.Error())
|
||||
}
|
||||
err = ref.Init()
|
||||
if err != nil {
|
||||
this.Fail("数据格式错误:" + err.Error())
|
||||
}
|
||||
|
||||
resp, err := this.RPC().NSClusterRPC().CreateNSCluster(this.AdminContext(), &pb.CreateNSClusterRequest{
|
||||
Name: params.Name,
|
||||
AccessLogJSON: params.AccessLogJSON,
|
||||
Hosts: hosts,
|
||||
Email: params.Email,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
clusterId = resp.NsClusterId
|
||||
|
||||
this.Success()
|
||||
}
|
||||
90
EdgeAdmin/internal/web/actions/default/ns/clusters/index.go
Normal file
90
EdgeAdmin/internal/web/actions/default/ns/clusters/index.go
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package clusters
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
countResp, err := this.RPC().NSClusterRPC().CountAllNSClusters(this.AdminContext(), &pb.CountAllNSClustersRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var count = countResp.Count
|
||||
var page = this.NewPage(count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
clustersResp, err := this.RPC().NSClusterRPC().ListNSClusters(this.AdminContext(), &pb.ListNSClustersRequest{
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var clusterMaps = []maps.Map{}
|
||||
for _, cluster := range clustersResp.NsClusters {
|
||||
// 全部节点数量
|
||||
countNodesResp, err := this.RPC().NSNodeRPC().CountAllNSNodesMatch(this.AdminContext(), &pb.CountAllNSNodesMatchRequest{NsClusterId: cluster.Id})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 在线节点
|
||||
countActiveNodesResp, err := this.RPC().NSNodeRPC().CountAllNSNodesMatch(this.AdminContext(), &pb.CountAllNSNodesMatchRequest{
|
||||
NsClusterId: cluster.Id,
|
||||
ActiveState: types.Int32(configutils.BoolStateYes),
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 需要升级的节点
|
||||
countUpgradeNodesResp, err := this.RPC().NSNodeRPC().CountAllUpgradeNSNodesWithNSClusterId(this.AdminContext(), &pb.CountAllUpgradeNSNodesWithNSClusterIdRequest{NsClusterId: cluster.Id})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 域名
|
||||
countDomainsResp, err := this.RPC().NSDomainRPC().CountAllNSDomains(this.AdminContext(), &pb.CountAllNSDomainsRequest{
|
||||
NsClusterId: cluster.Id,
|
||||
Status: dnsconfigs.NSDomainStatusVerified,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
clusterMaps = append(clusterMaps, maps.Map{
|
||||
"id": cluster.Id,
|
||||
"name": cluster.Name,
|
||||
"isOn": cluster.IsOn,
|
||||
"countAllNodes": countNodesResp.Count,
|
||||
"countActiveNodes": countActiveNodesResp.Count,
|
||||
"countUpgradeNodes": countUpgradeNodesResp.Count,
|
||||
"countDomains": countDomainsResp.Count,
|
||||
})
|
||||
}
|
||||
this.Data["clusters"] = clusterMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
25
EdgeAdmin/internal/web/actions/default/ns/clusters/init.go
Normal file
25
EdgeAdmin/internal/web/actions/default/ns/clusters/init.go
Normal file
@@ -0,0 +1,25 @@
|
||||
//go:build plus
|
||||
|
||||
package clusters
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeNS)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/create", new(CreateAction)).
|
||||
Post("/options", new(OptionsAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
//go:build plus
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
DayFrom string
|
||||
DayTo string
|
||||
Keyword string
|
||||
Level string
|
||||
}) {
|
||||
this.Data["dayFrom"] = params.DayFrom
|
||||
this.Data["dayTo"] = params.DayTo
|
||||
this.Data["keyword"] = params.Keyword
|
||||
this.Data["level"] = params.Level
|
||||
|
||||
countResp, err := this.RPC().NodeLogRPC().CountNodeLogs(this.AdminContext(), &pb.CountNodeLogsRequest{
|
||||
NodeId: 0,
|
||||
Role: nodeconfigs.NodeRoleDNS,
|
||||
DayFrom: params.DayFrom,
|
||||
DayTo: params.DayTo,
|
||||
Keyword: params.Keyword,
|
||||
Level: params.Level,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var count = countResp.Count
|
||||
var page = this.NewPage(count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
logsResp, err := this.RPC().NodeLogRPC().ListNodeLogs(this.AdminContext(), &pb.ListNodeLogsRequest{
|
||||
NodeId: 0,
|
||||
Role: nodeconfigs.NodeRoleDNS,
|
||||
DayFrom: params.DayFrom,
|
||||
DayTo: params.DayTo,
|
||||
Keyword: params.Keyword,
|
||||
Level: params.Level,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var logs = []maps.Map{}
|
||||
for _, log := range logsResp.NodeLogs {
|
||||
// 节点信息
|
||||
nodeResp, err := this.RPC().NSNodeRPC().FindNSNode(this.AdminContext(), &pb.FindNSNodeRequest{NsNodeId: log.NodeId})
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
node := nodeResp.NsNode
|
||||
if node == nil || node.NsCluster == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
logs = append(logs, maps.Map{
|
||||
"tag": log.Tag,
|
||||
"description": log.Description,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", log.CreatedAt),
|
||||
"level": log.Level,
|
||||
"isToday": timeutil.FormatTime("Y-m-d", log.CreatedAt) == timeutil.Format("Y-m-d"),
|
||||
"count": log.Count,
|
||||
"node": maps.Map{
|
||||
"id": node.Id,
|
||||
"cluster": maps.Map{
|
||||
"id": node.NsCluster.Id,
|
||||
"name": node.NsCluster.Name,
|
||||
},
|
||||
"name": node.Name,
|
||||
},
|
||||
})
|
||||
}
|
||||
this.Data["logs"] = logs
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//go:build plus
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeNS)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "log").
|
||||
Prefix("/ns/clusters/logs").
|
||||
Get("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
//go:build plus
|
||||
|
||||
package clusters
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type OptionsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *OptionsAction) RunPost(params struct{}) {
|
||||
clustersResp, err := this.RPC().NSClusterRPC().FindAllNSClusters(this.AdminContext(), &pb.FindAllNSClustersRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
clusterMaps := []maps.Map{}
|
||||
for _, cluster := range clustersResp.NsClusters {
|
||||
clusterMaps = append(clusterMaps, maps.Map{
|
||||
"id": cluster.Id,
|
||||
"name": cluster.Name,
|
||||
})
|
||||
}
|
||||
this.Data["clusters"] = clusterMaps
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package batch
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CreateRecordsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreateRecordsAction) Init() {
|
||||
this.Nav("", "", "batch")
|
||||
this.SecondMenu("createRecords")
|
||||
}
|
||||
|
||||
func (this *CreateRecordsAction) RunGet(params struct{}) {
|
||||
// 类型
|
||||
this.Data["types"] = dnsconfigs.FindAllUserRecordTypeDefinitions()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreateRecordsAction) RunPost(params struct {
|
||||
Names string
|
||||
UserId int64
|
||||
RecordsJSON []byte
|
||||
RemoveOld bool
|
||||
RemoveAll bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NS_LogCreateNSRecordsBatch)
|
||||
|
||||
// 检查域名是否已经创建
|
||||
var domainNames = []string{}
|
||||
for _, domainName := range strings.Split(params.Names, "\n") {
|
||||
domainName = strings.ToLower(strings.TrimSpace(domainName))
|
||||
if len(domainName) == 0 {
|
||||
continue
|
||||
}
|
||||
if !lists.ContainsString(domainNames, domainName) {
|
||||
domainNames = append(domainNames, domainName)
|
||||
}
|
||||
}
|
||||
|
||||
if len(domainNames) == 0 {
|
||||
this.FailField("names", "请输入域名")
|
||||
}
|
||||
|
||||
duplicateResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.AdminContext(), &pb.ExistNSDomainsRequest{
|
||||
Names: domainNames,
|
||||
UserId: params.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var existingDomainNames = duplicateResp.ExistingNames
|
||||
var notExistingDomainNames = []string{}
|
||||
for _, domainName := range domainNames {
|
||||
if !lists.ContainsString(existingDomainNames, domainName) {
|
||||
notExistingDomainNames = append(notExistingDomainNames, domainName)
|
||||
}
|
||||
}
|
||||
if len(notExistingDomainNames) > 0 {
|
||||
this.FailField("names", "有以下域名不存在:"+strings.Join(notExistingDomainNames, ",")+"。请检查域名是否已删除或用户是否已选择正确。")
|
||||
}
|
||||
|
||||
// 检查记录
|
||||
type record struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Value string `json:"value"`
|
||||
RouteCodes []string `json:"routeCodes"`
|
||||
TTL any `json:"ttl"`
|
||||
}
|
||||
|
||||
var records = []*record{}
|
||||
err = json.Unmarshal(params.RecordsJSON, &records)
|
||||
if err != nil {
|
||||
this.Fail("记录参数格式错误:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if len(records) == 0 {
|
||||
this.Fail("请添加至少一个记录")
|
||||
}
|
||||
|
||||
for _, record := range records {
|
||||
message, ok := domainutils.ValidateRecordValue(record.Type, record.Value)
|
||||
if !ok {
|
||||
this.Fail("记录 '" + record.Name + "' 值校验失败:" + message)
|
||||
}
|
||||
|
||||
// ttl
|
||||
var recordInt = types.Int32(record.TTL)
|
||||
if recordInt <= 0 {
|
||||
recordInt = 600
|
||||
}
|
||||
record.TTL = recordInt
|
||||
}
|
||||
recordsJSON, err := json.Marshal(records)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSRecordRPC().CreateNSRecordsWithDomainNames(this.AdminContext(), &pb.CreateNSRecordsWithDomainNamesRequest{
|
||||
NsDomainNames: domainNames,
|
||||
RecordsJSON: recordsJSON,
|
||||
RemoveOld: params.RemoveOld,
|
||||
RemoveAll: params.RemoveAll,
|
||||
UserId: params.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package batch
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type DeleteDomainsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteDomainsAction) Init() {
|
||||
this.Nav("", "", "batch")
|
||||
this.SecondMenu("deleteDomains")
|
||||
}
|
||||
|
||||
func (this *DeleteDomainsAction) RunGet(params struct{}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *DeleteDomainsAction) RunPost(params struct {
|
||||
Names string
|
||||
UserId int64
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NS_LogDeleteNSDomainsBatch, params.UserId)
|
||||
|
||||
if len(params.Names) == 0 {
|
||||
this.FailField("names", "请输入要删除的域名")
|
||||
}
|
||||
|
||||
var domainNames = []string{}
|
||||
for _, name := range strings.Split(params.Names, "\n") {
|
||||
name = strings.TrimSpace(name)
|
||||
if len(name) == 0 {
|
||||
continue
|
||||
}
|
||||
name = strings.ToLower(name)
|
||||
domainNames = append(domainNames, name)
|
||||
}
|
||||
|
||||
if len(domainNames) == 0 {
|
||||
this.FailField("names", "请输入要删除的域名")
|
||||
}
|
||||
|
||||
// 检查域名是否存在
|
||||
duplicateResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.AdminContext(), &pb.ExistNSDomainsRequest{
|
||||
Names: domainNames,
|
||||
UserId: params.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var existingDomainNames = duplicateResp.ExistingNames
|
||||
var notExistingDomainNames = []string{}
|
||||
for _, domainName := range domainNames {
|
||||
if !lists.ContainsString(existingDomainNames, domainName) {
|
||||
notExistingDomainNames = append(notExistingDomainNames, domainName)
|
||||
}
|
||||
}
|
||||
if len(notExistingDomainNames) > 0 {
|
||||
this.FailField("names", "有以下域名不存在:"+strings.Join(notExistingDomainNames, ",")+"。请检查域名是否已删除或用户是否已选择正确。")
|
||||
}
|
||||
|
||||
// 开始删除
|
||||
_, err = this.RPC().NSDomainRPC().DeleteNSDomains(this.AdminContext(), &pb.DeleteNSDomainsRequest{
|
||||
Names: domainNames,
|
||||
UserId: params.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package batch
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type DeleteRecordsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteRecordsAction) Init() {
|
||||
this.Nav("", "", "batch")
|
||||
this.SecondMenu("deleteRecords")
|
||||
}
|
||||
|
||||
func (this *DeleteRecordsAction) RunGet(params struct{}) {
|
||||
// 类型
|
||||
this.Data["types"] = dnsconfigs.FindAllUserRecordTypeDefinitions()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *DeleteRecordsAction) RunPost(params struct {
|
||||
Names string
|
||||
UserId int64
|
||||
|
||||
SearchName string
|
||||
SearchValue string
|
||||
SearchType string
|
||||
SearchRouteCodes []string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NS_LogDeleteNSRecordsBatch)
|
||||
|
||||
// 检查域名是否已经创建
|
||||
var domainNames = []string{}
|
||||
for _, domainName := range strings.Split(params.Names, "\n") {
|
||||
domainName = strings.ToLower(strings.TrimSpace(domainName))
|
||||
if len(domainName) == 0 {
|
||||
continue
|
||||
}
|
||||
if !lists.ContainsString(domainNames, domainName) {
|
||||
domainNames = append(domainNames, domainName)
|
||||
}
|
||||
}
|
||||
|
||||
if len(domainNames) == 0 {
|
||||
this.FailField("names", "请输入域名")
|
||||
}
|
||||
|
||||
duplicateResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.AdminContext(), &pb.ExistNSDomainsRequest{
|
||||
Names: domainNames,
|
||||
UserId: params.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var existingDomainNames = duplicateResp.ExistingNames
|
||||
var notExistingDomainNames = []string{}
|
||||
for _, domainName := range domainNames {
|
||||
if !lists.ContainsString(existingDomainNames, domainName) {
|
||||
notExistingDomainNames = append(notExistingDomainNames, domainName)
|
||||
}
|
||||
}
|
||||
if len(notExistingDomainNames) > 0 {
|
||||
this.FailField("names", "有以下域名不存在:"+strings.Join(notExistingDomainNames, ",")+"。请检查域名是否已删除或用户是否已选择正确。")
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSRecordRPC().DeleteNSRecordsWithDomainNames(this.AdminContext(), &pb.DeleteNSRecordsWithDomainNamesRequest{
|
||||
NsDomainNames: domainNames,
|
||||
SearchName: params.SearchName,
|
||||
SearchValue: params.SearchValue,
|
||||
SearchType: params.SearchType,
|
||||
SearchNSRouteCodes: params.SearchRouteCodes,
|
||||
UserId: params.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package batch
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type EnableRecordsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *EnableRecordsAction) Init() {
|
||||
this.Nav("", "", "batch")
|
||||
this.SecondMenu("enableRecords")
|
||||
}
|
||||
|
||||
func (this *EnableRecordsAction) RunGet(params struct{}) {
|
||||
// 类型
|
||||
this.Data["types"] = dnsconfigs.FindAllUserRecordTypeDefinitions()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *EnableRecordsAction) RunPost(params struct {
|
||||
Names string
|
||||
UserId int64
|
||||
|
||||
SearchName string
|
||||
SearchValue string
|
||||
SearchType string
|
||||
SearchRouteCodes []string
|
||||
|
||||
IsOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
if params.IsOn {
|
||||
defer this.CreateLogInfo(codes.NS_LogEnableNSRecordsBatch)
|
||||
} else {
|
||||
defer this.CreateLogInfo(codes.NS_LogDisableNSRecordsBatch)
|
||||
}
|
||||
|
||||
// 检查域名是否已经创建
|
||||
var domainNames = []string{}
|
||||
for _, domainName := range strings.Split(params.Names, "\n") {
|
||||
domainName = strings.ToLower(strings.TrimSpace(domainName))
|
||||
if len(domainName) == 0 {
|
||||
continue
|
||||
}
|
||||
if !lists.ContainsString(domainNames, domainName) {
|
||||
domainNames = append(domainNames, domainName)
|
||||
}
|
||||
}
|
||||
|
||||
if len(domainNames) == 0 {
|
||||
this.FailField("names", "请输入域名")
|
||||
}
|
||||
|
||||
duplicateResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.AdminContext(), &pb.ExistNSDomainsRequest{
|
||||
Names: domainNames,
|
||||
UserId: params.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var existingDomainNames = duplicateResp.ExistingNames
|
||||
var notExistingDomainNames = []string{}
|
||||
for _, domainName := range domainNames {
|
||||
if !lists.ContainsString(existingDomainNames, domainName) {
|
||||
notExistingDomainNames = append(notExistingDomainNames, domainName)
|
||||
}
|
||||
}
|
||||
if len(notExistingDomainNames) > 0 {
|
||||
this.FailField("names", "有以下域名不存在:"+strings.Join(notExistingDomainNames, ",")+"。请检查域名是否已删除或用户是否已选择正确。")
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSRecordRPC().UpdateNSRecordsIsOnWithDomainNames(this.AdminContext(), &pb.UpdateNSRecordsIsOnWithDomainNamesRequest{
|
||||
NsDomainNames: domainNames,
|
||||
SearchName: params.SearchName,
|
||||
SearchValue: params.SearchValue,
|
||||
SearchType: params.SearchType,
|
||||
SearchNSRouteCodes: params.SearchRouteCodes,
|
||||
IsOn: params.IsOn,
|
||||
UserId: params.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package batch
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ImportRecordsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *ImportRecordsAction) Init() {
|
||||
this.Nav("", "", "batch")
|
||||
this.SecondMenu("importRecords")
|
||||
}
|
||||
|
||||
func (this *ImportRecordsAction) RunGet(params struct{}) {
|
||||
// 类型
|
||||
this.Data["types"] = dnsconfigs.FindAllUserRecordTypeDefinitions()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *ImportRecordsAction) RunPost(params struct {
|
||||
Records string
|
||||
UserId int64
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NS_LogImportRecordsBatch)
|
||||
|
||||
var allRecordTypes = []string{}
|
||||
for _, t := range dnsconfigs.FindAllUserRecordTypeDefinitions() {
|
||||
allRecordTypes = append(allRecordTypes, t.Type)
|
||||
}
|
||||
|
||||
var pbRecords = []*pb.ImportNSRecordsRequest_Record{}
|
||||
var reg = regexp.MustCompile(`\s+`)
|
||||
var domainNames = []string{}
|
||||
for _, line := range strings.Split(params.Records, "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// 域名 记录名 记录类型 记录值 TTL
|
||||
var pieces = reg.Split(line, -1)
|
||||
if len(pieces) < 4 {
|
||||
this.Fail("'" + line + "' 格式错误,缺少必需项")
|
||||
}
|
||||
|
||||
var domainName = strings.ToLower(strings.TrimSpace(pieces[0]))
|
||||
var recordName = strings.ToLower(strings.TrimSpace(pieces[1]))
|
||||
var recordType = strings.ToUpper(pieces[2])
|
||||
var recordValue = strings.TrimSpace(pieces[3])
|
||||
|
||||
var recordTTLString = ""
|
||||
if len(pieces) > 4 {
|
||||
recordTTLString = pieces[4]
|
||||
}
|
||||
|
||||
// validate
|
||||
if len(domainName) == 0 {
|
||||
this.Fail("'" + line + "' 缺少域名")
|
||||
}
|
||||
if !domainutils.ValidateDomainFormat(domainName) {
|
||||
this.Fail("'" + line + "' 域名格式错误")
|
||||
}
|
||||
|
||||
if !lists.ContainsString(domainNames, domainName) {
|
||||
domainNames = append(domainNames, domainName)
|
||||
}
|
||||
|
||||
if len(recordName) > 0 && !domainutils.ValidateRecordName(recordName) {
|
||||
this.Fail("'" + line + "' 记录名格式错误")
|
||||
}
|
||||
|
||||
if len(recordType) == 0 {
|
||||
this.Fail("'" + line + "' 缺少记录类型")
|
||||
}
|
||||
if !lists.ContainsString(allRecordTypes, recordType) {
|
||||
this.Fail("'" + line + "' 不支持的记录类型 '" + recordType + "'")
|
||||
}
|
||||
|
||||
message, ok := domainutils.ValidateRecordValue(recordType, recordValue)
|
||||
if !ok {
|
||||
this.Fail("'" + line + "' 记录值 '" + recordValue + "' 校验失败:" + message)
|
||||
}
|
||||
|
||||
var recordTTL int32 = 600
|
||||
if len(recordTTLString) > 0 {
|
||||
if !regexp.MustCompile(`^\d+$`).MatchString(recordTTLString) {
|
||||
this.Fail("'" + line + "' 错误的TTL '" + recordTTLString + "'")
|
||||
}
|
||||
recordTTL = types.Int32(recordTTLString)
|
||||
if recordTTL > 10*365*86400 {
|
||||
recordTTL = 10 * 365 * 86400
|
||||
}
|
||||
}
|
||||
pbRecords = append(pbRecords, &pb.ImportNSRecordsRequest_Record{
|
||||
NsDomainName: domainName,
|
||||
Name: recordName,
|
||||
Type: recordType,
|
||||
Value: recordValue,
|
||||
Ttl: recordTTL,
|
||||
})
|
||||
}
|
||||
|
||||
if len(pbRecords) == 0 {
|
||||
this.FailField("records", "请输入要导入的记录")
|
||||
}
|
||||
|
||||
// 检查域名是否存在
|
||||
|
||||
duplicateResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.AdminContext(), &pb.ExistNSDomainsRequest{
|
||||
Names: domainNames,
|
||||
UserId: params.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var existingDomainNames = duplicateResp.ExistingNames
|
||||
var notExistingDomainNames = []string{}
|
||||
for _, domainName := range domainNames {
|
||||
if !lists.ContainsString(existingDomainNames, domainName) {
|
||||
notExistingDomainNames = append(notExistingDomainNames, domainName)
|
||||
}
|
||||
}
|
||||
if len(notExistingDomainNames) > 0 {
|
||||
this.FailField("names", "有以下域名不存在:"+strings.Join(notExistingDomainNames, ",")+"。请检查域名是否已删除或用户是否已选择正确。")
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSRecordRPC().ImportNSRecords(this.AdminContext(), &pb.ImportNSRecordsRequest{
|
||||
NsRecords: pbRecords,
|
||||
UserId: params.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package batch
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "batch")
|
||||
this.SecondMenu("index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
Names string // 如果批量的话
|
||||
ClusterId int64
|
||||
UserId int64
|
||||
GroupId int64
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
var groupIds = []int64{}
|
||||
if params.GroupId > 0 {
|
||||
groupIds = append(groupIds, params.GroupId)
|
||||
}
|
||||
|
||||
defer this.CreateLogInfo(codes.NS_LogCreateNSDomainsBatch)
|
||||
|
||||
params.Must.
|
||||
Field("names", params.Names).
|
||||
Require("请输入域名").
|
||||
Field("clusterId", params.ClusterId).
|
||||
Gt(0, "请选择所属集群")
|
||||
|
||||
var names = []string{}
|
||||
for _, name := range strings.Split(params.Names, "\n") {
|
||||
name = strings.TrimSpace(name)
|
||||
if len(name) == 0 {
|
||||
continue
|
||||
}
|
||||
if !domainutils.ValidateDomainFormat(name) {
|
||||
this.Fail("域名 '" + name + "' 格式不正确")
|
||||
}
|
||||
if !lists.ContainsString(names, name) {
|
||||
names = append(names, name)
|
||||
}
|
||||
}
|
||||
|
||||
if len(names) == 0 {
|
||||
this.FailField("names", "请输入域名")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查域名是否已经存在
|
||||
existResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.AdminContext(), &pb.ExistNSDomainsRequest{
|
||||
Names: names,
|
||||
UserId: params.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(existResp.ExistingNames) > 0 {
|
||||
this.Fail("域名 " + strings.Join(existResp.ExistingNames, ", ") + " 已经存在,无法重复添加")
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSDomainRPC().CreateNSDomains(this.AdminContext(), &pb.CreateNSDomainsRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
UserId: params.UserId,
|
||||
Names: names,
|
||||
NsDomainGroupIds: groupIds,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package batch
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type UpdateRecordsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateRecordsAction) Init() {
|
||||
this.Nav("", "", "batch")
|
||||
this.SecondMenu("updateRecords")
|
||||
}
|
||||
|
||||
func (this *UpdateRecordsAction) RunGet(params struct{}) {
|
||||
// 类型
|
||||
this.Data["types"] = dnsconfigs.FindAllUserRecordTypeDefinitions()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateRecordsAction) RunPost(params struct {
|
||||
Names string
|
||||
UserId int64
|
||||
|
||||
SearchName string
|
||||
SearchValue string
|
||||
SearchType string
|
||||
SearchRouteCodes []string
|
||||
|
||||
NewName string
|
||||
NewValue string
|
||||
NewType string
|
||||
NewRouteCodes []string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NS_LogUpdateNSRecordsBatch)
|
||||
|
||||
// 检查域名是否已经创建
|
||||
var domainNames = []string{}
|
||||
for _, domainName := range strings.Split(params.Names, "\n") {
|
||||
domainName = strings.ToLower(strings.TrimSpace(domainName))
|
||||
if len(domainName) == 0 {
|
||||
continue
|
||||
}
|
||||
if !lists.ContainsString(domainNames, domainName) {
|
||||
domainNames = append(domainNames, domainName)
|
||||
}
|
||||
}
|
||||
|
||||
if len(domainNames) == 0 {
|
||||
this.FailField("names", "请输入域名")
|
||||
}
|
||||
|
||||
duplicateResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.AdminContext(), &pb.ExistNSDomainsRequest{
|
||||
Names: domainNames,
|
||||
UserId: params.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var existingDomainNames = duplicateResp.ExistingNames
|
||||
var notExistingDomainNames = []string{}
|
||||
for _, domainName := range domainNames {
|
||||
if !lists.ContainsString(existingDomainNames, domainName) {
|
||||
notExistingDomainNames = append(notExistingDomainNames, domainName)
|
||||
}
|
||||
}
|
||||
if len(notExistingDomainNames) > 0 {
|
||||
this.FailField("names", "有以下域名不存在:"+strings.Join(notExistingDomainNames, ",")+"。请检查域名是否已删除或用户是否已选择正确。")
|
||||
}
|
||||
|
||||
if len(params.NewValue) > 0 {
|
||||
message, ok := domainutils.ValidateRecordValue(params.NewType, params.NewValue)
|
||||
if !ok {
|
||||
this.Fail("新的记录值 '" + params.NewValue + "' 填写错误:" + message)
|
||||
}
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSRecordRPC().UpdateNSRecordsWithDomainNames(this.AdminContext(), &pb.UpdateNSRecordsWithDomainNamesRequest{
|
||||
NsDomainNames: domainNames,
|
||||
SearchName: params.SearchName,
|
||||
SearchValue: params.SearchValue,
|
||||
SearchType: params.SearchType,
|
||||
SearchNSRouteCodes: params.SearchRouteCodes,
|
||||
NewName: params.NewName,
|
||||
NewValue: params.NewValue,
|
||||
NewType: params.NewType,
|
||||
NewNSRouteCodes: params.NewRouteCodes,
|
||||
UserId: params.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
186
EdgeAdmin/internal/web/actions/default/ns/domains/create.go
Normal file
186
EdgeAdmin/internal/web/actions/default/ns/domains/create.go
Normal file
@@ -0,0 +1,186 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package domains
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CreateAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreateAction) Init() {
|
||||
this.Nav("", "", "create")
|
||||
}
|
||||
|
||||
func (this *CreateAction) RunGet(params struct{}) {
|
||||
// 集群数量
|
||||
countClustersResp, err := this.RPC().NSClusterRPC().CountAllNSClusters(this.AdminContext(), &pb.CountAllNSClustersRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["countClusters"] = countClustersResp.Count
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreateAction) RunPost(params struct {
|
||||
AddingType string
|
||||
|
||||
Name string
|
||||
Names string // 如果批量的话
|
||||
ClusterId int64
|
||||
UserId int64
|
||||
GroupId int64
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
var groupIds = []int64{}
|
||||
if params.GroupId > 0 {
|
||||
groupIds = append(groupIds, params.GroupId)
|
||||
}
|
||||
|
||||
if params.AddingType == "batch" { // 批量添加
|
||||
defer this.CreateLogInfo(codes.NS_LogCreateNSDomainsBatch)
|
||||
|
||||
params.Must.
|
||||
Field("names", params.Names).
|
||||
Require("请输入域名").
|
||||
Field("clusterId", params.ClusterId).
|
||||
Gt(0, "请选择所属集群")
|
||||
|
||||
var names = []string{}
|
||||
for _, name := range strings.Split(params.Names, "\n") {
|
||||
name = strings.TrimSpace(name)
|
||||
if len(name) == 0 {
|
||||
continue
|
||||
}
|
||||
if !domainutils.ValidateDomainFormat(name) {
|
||||
this.Fail("域名 '" + name + "' 格式不正确")
|
||||
}
|
||||
if !lists.ContainsString(names, name) {
|
||||
names = append(names, name)
|
||||
}
|
||||
}
|
||||
|
||||
if len(names) == 0 {
|
||||
this.FailField("names", "请输入域名")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查域名是否已经存在
|
||||
{
|
||||
existResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.AdminContext(), &pb.ExistNSDomainsRequest{
|
||||
Names: names,
|
||||
UserId: params.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(existResp.ExistingNames) > 0 {
|
||||
this.Fail("域名 " + strings.Join(existResp.ExistingNames, ", ") + " 已经存在,无法重复添加")
|
||||
return
|
||||
}
|
||||
}
|
||||
{
|
||||
existResp, err := this.RPC().NSDomainRPC().ExistVerifiedNSDomains(this.AdminContext(), &pb.ExistVerifiedNSDomainsRequest{
|
||||
Names: names,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(existResp.ExistingNames) > 0 {
|
||||
this.Fail("域名 " + strings.Join(existResp.ExistingNames, ", ") + " 已经由别的用户添加,无法重复添加")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
_, err := this.RPC().NSDomainRPC().CreateNSDomains(this.AdminContext(), &pb.CreateNSDomainsRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
UserId: params.UserId,
|
||||
Names: names,
|
||||
NsDomainGroupIds: groupIds,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
} else { // 单个添加
|
||||
var domainId int64
|
||||
defer func() {
|
||||
this.CreateLogInfo(codes.NSDomain_LogCreateNSDomain, domainId)
|
||||
}()
|
||||
|
||||
params.Name = strings.ToLower(params.Name)
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入域名").
|
||||
Expect(func() (message string, success bool) {
|
||||
success = domainutils.ValidateDomainFormat(params.Name)
|
||||
if !success {
|
||||
message = "请输入正确的域名"
|
||||
}
|
||||
return
|
||||
}).
|
||||
Field("clusterId", params.ClusterId).
|
||||
Gt(0, "请选择所属集群")
|
||||
|
||||
// 检查域名是否已经存在
|
||||
{
|
||||
existResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.AdminContext(), &pb.ExistNSDomainsRequest{
|
||||
Names: []string{params.Name},
|
||||
UserId: params.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(existResp.ExistingNames) > 0 {
|
||||
this.Fail("域名 " + strings.Join(existResp.ExistingNames, ", ") + " 已经存在,无法重复添加")
|
||||
return
|
||||
}
|
||||
}
|
||||
{
|
||||
existResp, err := this.RPC().NSDomainRPC().ExistVerifiedNSDomains(this.AdminContext(), &pb.ExistVerifiedNSDomainsRequest{
|
||||
Names: []string{params.Name},
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(existResp.ExistingNames) > 0 {
|
||||
this.Fail("域名 " + strings.Join(existResp.ExistingNames, ", ") + " 已经由别的用户添加,无法重复添加")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().NSDomainRPC().CreateNSDomain(this.AdminContext(), &pb.CreateNSDomainRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
UserId: params.UserId,
|
||||
Name: params.Name,
|
||||
NsDomainGroupIds: groupIds,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
domainId = createResp.NsDomainId
|
||||
|
||||
this.Success()
|
||||
}
|
||||
}
|
||||
28
EdgeAdmin/internal/web/actions/default/ns/domains/delete.go
Normal file
28
EdgeAdmin/internal/web/actions/default/ns/domains/delete.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package domains
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
DomainId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSDomain_LogDeleteNSDomain, params.DomainId)
|
||||
|
||||
_, err := this.RPC().NSDomainRPC().DeleteNSDomain(this.AdminContext(), &pb.DeleteNSDomainRequest{NsDomainId: params.DomainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2024 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package domains
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeletePageAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeletePageAction) RunPost(params struct {
|
||||
DomainIds []int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NS_LogDeleteNSDomainsBatch, this.AdminContext())
|
||||
|
||||
if len(params.DomainIds) == 0 {
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
|
||||
for _, domainId := range params.DomainIds {
|
||||
_, err := this.RPC().NSDomainRPC().DeleteNSDomain(this.AdminContext(), &pb.DeleteNSDomainRequest{
|
||||
NsDomainId: domainId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package domain
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
DomainId int64
|
||||
}) {
|
||||
err := domainutils.InitDomain(this.Parent(), params.DomainId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var countRecords = this.Data.GetMap("domain").GetInt64("countRecords")
|
||||
var countKeys = this.Data.GetMap("domain").GetInt64("countKeys")
|
||||
|
||||
// 域名信息
|
||||
domainResp, err := this.RPC().NSDomainRPC().FindNSDomain(this.AdminContext(), &pb.FindNSDomainRequest{NsDomainId: params.DomainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var domain = domainResp.NsDomain
|
||||
if domain == nil {
|
||||
this.NotFound("nsDomain", params.DomainId)
|
||||
return
|
||||
}
|
||||
|
||||
var clusterMap maps.Map
|
||||
if domain.NsCluster != nil {
|
||||
clusterMap = maps.Map{
|
||||
"id": domain.NsCluster.Id,
|
||||
"name": domain.NsCluster.Name,
|
||||
}
|
||||
}
|
||||
|
||||
// 用户信息
|
||||
var userMap maps.Map
|
||||
if domain.User != nil {
|
||||
userMap = maps.Map{
|
||||
"id": domain.User.Id,
|
||||
"username": domain.User.Username,
|
||||
"fullname": domain.User.Fullname,
|
||||
}
|
||||
}
|
||||
|
||||
// 分组信息
|
||||
var groupMaps = []maps.Map{}
|
||||
for _, group := range domain.NsDomainGroups {
|
||||
groupMaps = append(groupMaps, maps.Map{
|
||||
"id": group.Id,
|
||||
"name": group.Name,
|
||||
"userId": group.UserId,
|
||||
})
|
||||
}
|
||||
|
||||
// 健康检查
|
||||
var healthCheckConfig = dnsconfigs.NewNSRecordsHealthCheckConfig()
|
||||
if len(domain.RecordsHealthCheckJSON) > 0 {
|
||||
err = json.Unmarshal(domain.RecordsHealthCheckJSON, healthCheckConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["domain"] = maps.Map{
|
||||
"id": domain.Id,
|
||||
"name": domain.Name,
|
||||
"isOn": domain.IsOn,
|
||||
"status": domain.Status,
|
||||
"statusName": dnsconfigs.NSDomainStatusName(domain.Status),
|
||||
"cluster": clusterMap,
|
||||
"user": userMap,
|
||||
"groups": groupMaps,
|
||||
"countRecords": countRecords,
|
||||
"countKeys": countKeys,
|
||||
"enableHealthCheck": healthCheckConfig.IsOn,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package domain
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdateStatusPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateStatusPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdateStatusPopupAction) RunGet(params struct {
|
||||
DomainId int64
|
||||
}) {
|
||||
domainResp, err := this.RPC().NSDomainRPC().FindNSDomain(this.AdminContext(), &pb.FindNSDomainRequest{NsDomainId: params.DomainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var domain = domainResp.NsDomain
|
||||
if domain == nil {
|
||||
this.NotFound("NSDomain", params.DomainId)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["domain"] = maps.Map{
|
||||
"id": domain.Id,
|
||||
"name": domain.Name,
|
||||
"status": domain.Status,
|
||||
}
|
||||
|
||||
this.Data["statusList"] = dnsconfigs.FindAllNSDomainStatusList()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateStatusPopupAction) RunPost(params struct {
|
||||
DomainId int64
|
||||
Status string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSDomain_LogUpdateNSDomainStatus, params.DomainId, params.Status)
|
||||
|
||||
_, err := this.RPC().NSDomainRPC().UpdateNSDomainStatus(this.AdminContext(), &pb.UpdateNSDomainStatusRequest{
|
||||
NsDomainId: params.DomainId,
|
||||
Status: params.Status,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package domainutils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
// InitDomain 初始化域名信息
|
||||
func InitDomain(parent *actionutils.ParentAction, domainId int64) error {
|
||||
rpcClient, err := rpc.SharedRPC()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
domainResp, err := rpcClient.NSDomainRPC().FindNSDomain(parent.AdminContext(), &pb.FindNSDomainRequest{NsDomainId: domainId})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var domain = domainResp.NsDomain
|
||||
if domain == nil {
|
||||
return errors.New("InitDomain: can not find domain with id '" + types.String(domainId) + "'")
|
||||
}
|
||||
|
||||
// 记录数量
|
||||
countRecordsResp, err := rpcClient.NSRecordRPC().CountAllNSRecords(parent.AdminContext(), &pb.CountAllNSRecordsRequest{
|
||||
NsDomainId: domainId,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var countRecords = countRecordsResp.Count
|
||||
|
||||
// Key数量
|
||||
countKeysResp, err := rpcClient.NSKeyRPC().CountAllNSKeys(parent.AdminContext(), &pb.CountAllNSKeysRequest{
|
||||
NsDomainId: domainId,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var countKeys = countKeysResp.Count
|
||||
|
||||
// 健康检查
|
||||
var healthCheckConfig = dnsconfigs.NewNSRecordsHealthCheckConfig()
|
||||
if len(domain.RecordsHealthCheckJSON) > 0 {
|
||||
err = json.Unmarshal(domain.RecordsHealthCheckJSON, healthCheckConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
parent.Data["domain"] = maps.Map{
|
||||
"id": domain.Id,
|
||||
"name": domain.Name,
|
||||
"countRecords": countRecords,
|
||||
"countKeys": countKeys,
|
||||
"enableHealthCheck": healthCheckConfig.IsOn,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckHealthCheckPermission 检查是否能够修改健康检查
|
||||
func CheckHealthCheckPermission(rpcClient *rpc.RPCClient, ctx context.Context, domainId int64) (canUpdate bool, err error) {
|
||||
if domainId <= 0 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
domainResp, err := rpcClient.NSDomainRPC().FindNSDomain(ctx, &pb.FindNSDomainRequest{NsDomainId: domainId})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
var domain = domainResp.NsDomain
|
||||
if domain == nil {
|
||||
return false, errors.New("the domain is not found")
|
||||
}
|
||||
if domain.UserId > 0 {
|
||||
// 检查套餐
|
||||
userPlanResp, err := rpcClient.NSUserPlanRPC().FindNSUserPlan(ctx, &pb.FindNSUserPlanRequest{
|
||||
UserId: domain.UserId,
|
||||
NsUserPlanId: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
var userPlan = userPlanResp.NsUserPlan
|
||||
if userPlan == nil || userPlan.NsPlanId == 0 || userPlan.DayTo < timeutil.Format("Ymd") {
|
||||
return checkHealthCheckInUserSetting(rpcClient, ctx)
|
||||
} else {
|
||||
planResp, err := rpcClient.NSPlanRPC().FindNSPlan(ctx, &pb.FindNSPlanRequest{NsPlanId: userPlan.NsPlanId})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if planResp.NsPlan == nil || len(planResp.NsPlan.ConfigJSON) == 0 {
|
||||
return checkHealthCheckInUserSetting(rpcClient, ctx)
|
||||
}
|
||||
var planConfig = dnsconfigs.DefaultNSPlanConfig()
|
||||
err = json.Unmarshal(planResp.NsPlan.ConfigJSON, planConfig)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return planConfig.SupportHealthCheck, nil
|
||||
}
|
||||
} else {
|
||||
return checkHealthCheckInUserSetting(rpcClient, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// 检查用户基础设置
|
||||
func checkHealthCheckInUserSetting(rpcClient *rpc.RPCClient, ctx context.Context) (bool, error) {
|
||||
resp, err := rpcClient.SysSettingRPC().ReadSysSetting(ctx, &pb.ReadSysSettingRequest{
|
||||
Code: systemconfigs.SettingCodeNSUserConfig,
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var config = dnsconfigs.NewNSUserConfig()
|
||||
if len(resp.ValueJSON) > 0 {
|
||||
err = json.Unmarshal(resp.ValueJSON, config)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if config.DefaultPlanConfig == nil {
|
||||
config.DefaultPlanConfig = dnsconfigs.DefaultNSUserPlanConfig()
|
||||
}
|
||||
return config.DefaultPlanConfig.SupportHealthCheck, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package groups
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct {
|
||||
}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
Name string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
var groupId int64 = 0
|
||||
|
||||
defer func() {
|
||||
this.CreateLogInfo(codes.NSDomainGroup_LogCreateNSDomainGroup, groupId)
|
||||
}()
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入分组名称")
|
||||
|
||||
createResp, err := this.RPC().NSDomainGroupRPC().CreateNSDomainGroup(this.AdminContext(), &pb.CreateNSDomainGroupRequest{
|
||||
Name: params.Name,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
groupId = createResp.NsDomainGroupId
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package group
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
GroupId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSDomainGroup_LogDeleteNSDomainGroup, params.GroupId)
|
||||
|
||||
_, err := this.RPC().NSDomainGroupRPC().DeleteNSDomainGroup(this.AdminContext(), &pb.DeleteNSDomainGroupRequest{NsDomainGroupId: params.GroupId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package group
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
GroupId int64
|
||||
}) {
|
||||
groupResp, err := this.RPC().NSDomainGroupRPC().FindNSDomainGroup(this.AdminContext(), &pb.FindNSDomainGroupRequest{NsDomainGroupId: params.GroupId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var group = groupResp.NsDomainGroup
|
||||
if group == nil {
|
||||
this.NotFound("nsDomainGroup", params.GroupId)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["group"] = maps.Map{
|
||||
"id": group.Id,
|
||||
"name": group.Name,
|
||||
"isOn": group.IsOn,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package group
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
GroupId int64
|
||||
}) {
|
||||
groupResp, err := this.RPC().NSDomainGroupRPC().FindNSDomainGroup(this.AdminContext(), &pb.FindNSDomainGroupRequest{NsDomainGroupId: params.GroupId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var group = groupResp.NsDomainGroup
|
||||
if group == nil {
|
||||
this.NotFound("nsDomainGroup", params.GroupId)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["group"] = maps.Map{
|
||||
"id": group.Id,
|
||||
"name": group.Name,
|
||||
"isOn": group.IsOn,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
GroupId int64
|
||||
Name string
|
||||
IsOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSDomainGroup_LogUpdateNSDomainGroup, params.GroupId)
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入分组名称")
|
||||
|
||||
_, err := this.RPC().NSDomainGroupRPC().UpdateNSDomainGroup(this.AdminContext(), &pb.UpdateNSDomainGroupRequest{
|
||||
NsDomainGroupId: params.GroupId,
|
||||
Name: params.Name,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package groups
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
groupsResp, err := this.RPC().NSDomainGroupRPC().FindAllNSDomainGroups(this.AdminContext(), &pb.FindAllNSDomainGroupsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var groupMaps = []maps.Map{}
|
||||
for _, group := range groupsResp.NsDomainGroups {
|
||||
groupMaps = append(groupMaps, maps.Map{
|
||||
"id": group.Id,
|
||||
"name": group.Name,
|
||||
"isOn": group.IsOn,
|
||||
})
|
||||
}
|
||||
this.Data["groups"] = groupMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package groups
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type OptionsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *OptionsAction) RunPost(params struct {
|
||||
UserId int64
|
||||
}) {
|
||||
groupsResp, err := this.RPC().NSDomainGroupRPC().FindAllAvailableNSDomainGroups(this.AdminContext(), &pb.FindAllAvailableNSDomainGroupsRequest{
|
||||
UserId: params.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var groupMaps = []maps.Map{}
|
||||
for _, group := range groupsResp.NsDomainGroups {
|
||||
groupMaps = append(groupMaps, maps.Map{
|
||||
"id": group.Id,
|
||||
"name": group.Name,
|
||||
})
|
||||
}
|
||||
this.Data["groups"] = groupMaps
|
||||
|
||||
this.Success()
|
||||
}
|
||||
103
EdgeAdmin/internal/web/actions/default/ns/domains/healthCheck.go
Normal file
103
EdgeAdmin/internal/web/actions/default/ns/domains/healthCheck.go
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package domains
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type HealthCheckAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *HealthCheckAction) Init() {
|
||||
this.Nav("", "", "healthCheck")
|
||||
}
|
||||
|
||||
func (this *HealthCheckAction) RunGet(params struct {
|
||||
DomainId int64
|
||||
}) {
|
||||
err := domainutils.InitDomain(this.Parent(), params.DomainId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["domainId"] = params.DomainId
|
||||
|
||||
// 检查当前用户权限
|
||||
canUpdate, err := domainutils.CheckHealthCheckPermission(this.RPC(), this.AdminContext(), params.DomainId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["canUpdate"] = canUpdate
|
||||
|
||||
// 健康检查配置
|
||||
healthCheckResp, err := this.RPC().NSDomainRPC().FindNSDomainRecordsHealthCheck(this.AdminContext(), &pb.FindNSDomainRecordsHealthCheckRequest{NsDomainId: params.DomainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var healthCheckConfig = dnsconfigs.NewNSRecordsHealthCheckConfig()
|
||||
if len(healthCheckResp.NsDomainRecordsHealthCheckJSON) > 0 {
|
||||
err = json.Unmarshal(healthCheckResp.NsDomainRecordsHealthCheckJSON, healthCheckConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
this.Data["config"] = healthCheckConfig
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *HealthCheckAction) RunPost(params struct {
|
||||
DomainId int64
|
||||
RecordsHealthCheckJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSDomain_LogUpdateNSDomainHealthCheck, params.DomainId)
|
||||
|
||||
canUpdate, err := domainutils.CheckHealthCheckPermission(this.RPC(), this.AdminContext(), params.DomainId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !canUpdate {
|
||||
this.Fail("当前用户没有权限修改健康检查设置")
|
||||
return
|
||||
}
|
||||
|
||||
var config = dnsconfigs.NewNSRecordsHealthCheckConfig()
|
||||
err = json.Unmarshal(params.RecordsHealthCheckJSON, config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
err = config.Init()
|
||||
if err != nil {
|
||||
this.Fail("校验配置失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSDomainRPC().UpdateNSDomainRecordsHealthCheck(this.AdminContext(), &pb.UpdateNSDomainRecordsHealthCheckRequest{
|
||||
NsDomainId: params.DomainId,
|
||||
NsDomainRecordsHealthCheckJSON: params.RecordsHealthCheckJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
117
EdgeAdmin/internal/web/actions/default/ns/domains/index.go
Normal file
117
EdgeAdmin/internal/web/actions/default/ns/domains/index.go
Normal file
@@ -0,0 +1,117 @@
|
||||
//go:build plus
|
||||
|
||||
package domains
|
||||
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ClusterId int64
|
||||
UserId int64
|
||||
GroupId int64
|
||||
Keyword string
|
||||
}) {
|
||||
if !teaconst.IsPlus {
|
||||
this.RedirectURL("/")
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["clusterId"] = params.ClusterId
|
||||
this.Data["userId"] = params.UserId
|
||||
this.Data["groupId"] = params.GroupId
|
||||
this.Data["keyword"] = params.Keyword
|
||||
|
||||
// 集群数量
|
||||
countClustersResp, err := this.RPC().NSClusterRPC().CountAllNSClusters(this.AdminContext(), &pb.CountAllNSClustersRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["countClusters"] = countClustersResp.Count
|
||||
|
||||
// 分页
|
||||
countResp, err := this.RPC().NSDomainRPC().CountAllNSDomains(this.AdminContext(), &pb.CountAllNSDomainsRequest{
|
||||
UserId: params.UserId,
|
||||
NsDomainGroupId: params.GroupId,
|
||||
NsClusterId: params.ClusterId,
|
||||
Keyword: params.Keyword,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var page = this.NewPage(countResp.Count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
// 列表
|
||||
domainsResp, err := this.RPC().NSDomainRPC().ListNSDomains(this.AdminContext(), &pb.ListNSDomainsRequest{
|
||||
UserId: params.UserId,
|
||||
NsClusterId: params.ClusterId,
|
||||
NsDomainGroupId: params.GroupId,
|
||||
Keyword: params.Keyword,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var domainMaps = []maps.Map{}
|
||||
for _, domain := range domainsResp.NsDomains {
|
||||
// 集群信息
|
||||
var clusterMap maps.Map
|
||||
if domain.NsCluster != nil {
|
||||
clusterMap = maps.Map{
|
||||
"id": domain.NsCluster.Id,
|
||||
"name": domain.NsCluster.Name,
|
||||
}
|
||||
}
|
||||
|
||||
// 用户信息
|
||||
var userMap maps.Map
|
||||
if domain.User != nil {
|
||||
userMap = maps.Map{
|
||||
"id": domain.User.Id,
|
||||
"username": domain.User.Username,
|
||||
"fullname": domain.User.Fullname,
|
||||
}
|
||||
}
|
||||
|
||||
// 分组信息
|
||||
var groupMaps = []maps.Map{}
|
||||
for _, group := range domain.NsDomainGroups {
|
||||
groupMaps = append(groupMaps, maps.Map{
|
||||
"id": group.Id,
|
||||
"name": group.Name,
|
||||
"userId": group.UserId,
|
||||
})
|
||||
}
|
||||
|
||||
domainMaps = append(domainMaps, maps.Map{
|
||||
"id": domain.Id,
|
||||
"name": domain.Name,
|
||||
"status": domain.Status,
|
||||
"statusName": dnsconfigs.NSDomainStatusName(domain.Status),
|
||||
"isOn": domain.IsOn,
|
||||
"cluster": clusterMap,
|
||||
"user": userMap,
|
||||
"groups": groupMaps,
|
||||
})
|
||||
}
|
||||
this.Data["domains"] = domainMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package keys
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct {
|
||||
DomainId int64
|
||||
}) {
|
||||
this.Data["domainId"] = params.DomainId
|
||||
|
||||
// 所有算法
|
||||
var algorithmMaps = []maps.Map{}
|
||||
for _, algo := range dnsconfigs.FindAllKeyAlgorithmTypes() {
|
||||
algorithmMaps = append(algorithmMaps, maps.Map{
|
||||
"name": algo.Name,
|
||||
"code": algo.Code,
|
||||
})
|
||||
}
|
||||
this.Data["algorithms"] = algorithmMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
DomainId int64
|
||||
Name string
|
||||
Algo string
|
||||
Secret string
|
||||
SecretType string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
var keyId int64 = 0
|
||||
defer func() {
|
||||
this.CreateLogInfo(codes.NSKey_LogCreateNSKey, keyId)
|
||||
}()
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入密钥名称").
|
||||
Field("algo", params.Algo).
|
||||
Require("请选择算法").
|
||||
Field("secret", params.Secret).
|
||||
Require("请输入密码")
|
||||
|
||||
// 校验密码
|
||||
if params.SecretType == dnsconfigs.NSKeySecretTypeBase64 {
|
||||
_, err := base64.StdEncoding.DecodeString(params.Secret)
|
||||
if err != nil {
|
||||
this.FailField("secret", "请输入BASE64格式的密码或者选择明文")
|
||||
}
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().NSKeyRPC().CreateNSKey(this.AdminContext(), &pb.CreateNSKeyRequest{
|
||||
NsDomainId: params.DomainId,
|
||||
NsZoneId: 0,
|
||||
Name: params.Name,
|
||||
Algo: params.Algo,
|
||||
Secret: params.Secret,
|
||||
SecretType: params.SecretType,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
keyId = createResp.NsKeyId
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package keys
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
KeyId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSKey_LogDeleteNSKey, params.KeyId)
|
||||
|
||||
_, err := this.RPC().NSKeyRPC().DeleteNSKey(this.AdminContext(), &pb.DeleteNSKeyRequest{NsKeyId: params.KeyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package keys
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
)
|
||||
|
||||
type GenerateSecretAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *GenerateSecretAction) RunPost(params struct {
|
||||
SecretType string
|
||||
}) {
|
||||
switch params.SecretType {
|
||||
case dnsconfigs.NSKeySecretTypeClear:
|
||||
this.Data["secret"] = rands.HexString(128)
|
||||
case dnsconfigs.NSKeySecretTypeBase64:
|
||||
this.Data["secret"] = base64.StdEncoding.EncodeToString([]byte(rands.HexString(128)))
|
||||
default:
|
||||
this.Data["secret"] = rands.HexString(128)
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package keys
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "key")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
DomainId int64
|
||||
}) {
|
||||
// 初始化域名信息
|
||||
err := domainutils.InitDomain(this.Parent(), params.DomainId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 数量
|
||||
countResp, err := this.RPC().NSKeyRPC().CountAllNSKeys(this.AdminContext(), &pb.CountAllNSKeysRequest{
|
||||
NsDomainId: params.DomainId,
|
||||
NsZoneId: 0,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var page = this.NewPage(countResp.Count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
// 列表
|
||||
keysResp, err := this.RPC().NSKeyRPC().ListNSKeys(this.AdminContext(), &pb.ListNSKeysRequest{
|
||||
NsDomainId: params.DomainId,
|
||||
NsZoneId: 0,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var keyMaps = []maps.Map{}
|
||||
for _, key := range keysResp.NsKeys {
|
||||
keyMaps = append(keyMaps, maps.Map{
|
||||
"id": key.Id,
|
||||
"name": key.Name,
|
||||
"secret": key.Secret,
|
||||
"secretTypeName": dnsconfigs.FindKeySecretTypeName(key.SecretType),
|
||||
"algoName": dnsconfigs.FindKeyAlgorithmTypeName(key.Algo),
|
||||
"isOn": key.IsOn,
|
||||
})
|
||||
}
|
||||
this.Data["keys"] = keyMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package keys
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
KeyId int64
|
||||
}) {
|
||||
keyResp, err := this.RPC().NSKeyRPC().FindNSKey(this.AdminContext(), &pb.FindNSKeyRequest{NsKeyId: params.KeyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var key = keyResp.NsKey
|
||||
if key == nil {
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["key"] = maps.Map{
|
||||
"id": key.Id,
|
||||
"name": key.Name,
|
||||
"algo": key.Algo,
|
||||
"secret": key.Secret,
|
||||
"secretType": key.SecretType,
|
||||
"isOn": key.IsOn,
|
||||
}
|
||||
|
||||
// 所有算法
|
||||
var algorithmMaps = []maps.Map{}
|
||||
for _, algo := range dnsconfigs.FindAllKeyAlgorithmTypes() {
|
||||
algorithmMaps = append(algorithmMaps, maps.Map{
|
||||
"name": algo.Name,
|
||||
"code": algo.Code,
|
||||
})
|
||||
}
|
||||
this.Data["algorithms"] = algorithmMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
KeyId int64
|
||||
Name string
|
||||
Algo string
|
||||
Secret string
|
||||
SecretType string
|
||||
IsOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
this.CreateLogInfo(codes.NSKey_LogUpdateNSKey, params.KeyId)
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入密钥名称").
|
||||
Field("algo", params.Algo).
|
||||
Require("请选择算法").
|
||||
Field("secret", params.Secret).
|
||||
Require("请输入密码")
|
||||
|
||||
// 校验密码
|
||||
if params.SecretType == dnsconfigs.NSKeySecretTypeBase64 {
|
||||
_, err := base64.StdEncoding.DecodeString(params.Secret)
|
||||
if err != nil {
|
||||
this.FailField("secret", "请输入BASE64格式的密码或者选择明文")
|
||||
}
|
||||
}
|
||||
|
||||
_, err := this.RPC().NSKeyRPC().UpdateNSKey(this.AdminContext(), &pb.UpdateNSKeyRequest{
|
||||
NsKeyId: params.KeyId,
|
||||
Name: params.Name,
|
||||
Algo: params.Algo,
|
||||
Secret: params.Secret,
|
||||
SecretType: params.SecretType,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package records
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct {
|
||||
DomainId int64
|
||||
}) {
|
||||
// 域名信息
|
||||
domainResp, err := this.RPC().NSDomainRPC().FindNSDomain(this.AdminContext(), &pb.FindNSDomainRequest{NsDomainId: params.DomainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var domain = domainResp.NsDomain
|
||||
if domain == nil {
|
||||
this.NotFound("nsDomain", params.DomainId)
|
||||
return
|
||||
}
|
||||
this.Data["domain"] = maps.Map{
|
||||
"id": domain.Id,
|
||||
"name": domain.Name,
|
||||
}
|
||||
|
||||
// 类型
|
||||
this.Data["types"] = dnsconfigs.FindAllUserRecordTypeDefinitions()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
AddingType string
|
||||
|
||||
DomainId int64
|
||||
|
||||
Name string
|
||||
Names string
|
||||
|
||||
Type string
|
||||
Value string
|
||||
Ttl int32
|
||||
Description string
|
||||
RouteCodes []string
|
||||
Weight int32
|
||||
|
||||
MxPriority int32
|
||||
|
||||
SrvPriority int32
|
||||
SrvWeight int32
|
||||
SrvPort int32
|
||||
|
||||
CaaFlag int32
|
||||
CaaTag string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
domainResp, err := this.RPC().NSDomainRPC().FindNSDomain(this.AdminContext(), &pb.FindNSDomainRequest{NsDomainId: params.DomainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var domain = domainResp.NsDomain
|
||||
if domain == nil {
|
||||
this.Fail("找不到要修改的域名")
|
||||
}
|
||||
var domainName = domain.Name
|
||||
|
||||
if params.AddingType == "batch" { // 批量添加
|
||||
defer this.CreateLogInfo(codes.NS_LogCreateNSRecordsBatch)
|
||||
|
||||
if len(params.Names) == 0 {
|
||||
this.FailField("names", "请输入记录名")
|
||||
}
|
||||
for _, name := range strings.Split(params.Names, "\n") {
|
||||
name = strings.TrimSpace(name)
|
||||
this.CheckType(params.Type, params.DomainId, name)
|
||||
}
|
||||
var names = []string{}
|
||||
for _, name := range strings.Split(params.Names, "\n") {
|
||||
name = strings.TrimSpace(name)
|
||||
if len(name) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if !domainutils.ValidateRecordName(name) {
|
||||
this.FailField("names", "记录名 '"+name+"' 格式不正确,请修改后提交")
|
||||
}
|
||||
|
||||
// 去掉主域名
|
||||
name = strings.TrimSuffix(name, "."+domainName)
|
||||
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
// 校验记录值
|
||||
message, ok := domainutils.ValidateRecordValue(params.Type, params.Value)
|
||||
if !ok {
|
||||
this.FailField("value", "记录值错误:"+message)
|
||||
}
|
||||
|
||||
// SRV
|
||||
if params.Type == dnsconfigs.RecordTypeSRV {
|
||||
if params.SrvPort < 0 || params.SrvPort > 65535 {
|
||||
this.FailField("srvPort", "请输入有效的端口号")
|
||||
}
|
||||
}
|
||||
|
||||
// 校验TTL
|
||||
if params.Ttl <= 0 {
|
||||
this.Fail("请输入正确的TTL")
|
||||
}
|
||||
|
||||
_, err := this.RPC().NSRecordRPC().CreateNSRecords(this.AdminContext(), &pb.CreateNSRecordsRequest{
|
||||
NsDomainId: params.DomainId,
|
||||
Description: params.Description,
|
||||
Names: names,
|
||||
Type: params.Type,
|
||||
Value: params.Value,
|
||||
MxPriority: params.MxPriority,
|
||||
SrvPriority: params.SrvPriority,
|
||||
SrvWeight: params.SrvWeight,
|
||||
SrvPort: params.SrvPort,
|
||||
CaaFlag: params.CaaFlag,
|
||||
CaaTag: params.CaaTag,
|
||||
Ttl: params.Ttl,
|
||||
NsRouteCodes: params.RouteCodes,
|
||||
Weight: params.Weight,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
} else { // 单个添加
|
||||
var recordId int64
|
||||
defer func() {
|
||||
this.CreateLogInfo(codes.NSRecord_LogCreateNSRecord, recordId)
|
||||
}()
|
||||
|
||||
// 校验记录名
|
||||
if !domainutils.ValidateRecordName(params.Name) {
|
||||
this.FailField("name", "请输入正确的记录名")
|
||||
}
|
||||
|
||||
// 校验记录值
|
||||
message, ok := domainutils.ValidateRecordValue(params.Type, params.Value)
|
||||
if !ok {
|
||||
this.FailField("value", "记录值错误:"+message)
|
||||
}
|
||||
|
||||
// SRV
|
||||
if params.Type == dnsconfigs.RecordTypeSRV {
|
||||
if params.SrvPort < 0 || params.SrvPort > 65535 {
|
||||
this.FailField("srvPort", "请输入有效的端口号")
|
||||
}
|
||||
}
|
||||
|
||||
// 校验TTL
|
||||
if params.Ttl <= 0 {
|
||||
this.Fail("请输入正确的TTL")
|
||||
}
|
||||
this.CheckType(params.Type, params.DomainId, params.Name)
|
||||
|
||||
createResp, err := this.RPC().NSRecordRPC().CreateNSRecord(this.AdminContext(), &pb.CreateNSRecordRequest{
|
||||
NsDomainId: params.DomainId,
|
||||
Description: params.Description,
|
||||
Name: params.Name,
|
||||
Type: params.Type,
|
||||
Value: params.Value,
|
||||
MxPriority: params.MxPriority,
|
||||
SrvPort: params.SrvPort,
|
||||
SrvPriority: params.SrvPriority,
|
||||
SrvWeight: params.SrvWeight,
|
||||
CaaFlag: params.CaaFlag,
|
||||
CaaTag: params.CaaTag,
|
||||
Ttl: params.Ttl,
|
||||
NsRouteCodes: params.RouteCodes,
|
||||
Weight: params.Weight,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
recordId = createResp.NsRecordId
|
||||
|
||||
this.Success()
|
||||
}
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) CheckType(recordType dnsconfigs.RecordType, domainId int64, name string) {
|
||||
//A|AAAA记录和cname记录不可以共存
|
||||
if recordType == dnsconfigs.RecordTypeA || recordType == dnsconfigs.RecordTypeAAAA {
|
||||
cnameRecordsCountResp, err := this.RPC().NSRecordRPC().CountAllNSRecordsWithName(this.AdminContext(), &pb.CountAllNSRecordsWithNameRequest{
|
||||
NsDomainId: domainId,
|
||||
Type: dnsconfigs.RecordTypeCNAME,
|
||||
Name: name,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if cnameRecordsCountResp.Count > 0 {
|
||||
this.Fail("已有cname记录,请删除cname记录后在尝试添加A记录")
|
||||
}
|
||||
} else if recordType == dnsconfigs.RecordTypeCNAME {
|
||||
aRecordsCountResp, err := this.RPC().NSRecordRPC().CountAllNSRecordsWithName(this.AdminContext(), &pb.CountAllNSRecordsWithNameRequest{
|
||||
NsDomainId: domainId,
|
||||
Type: dnsconfigs.RecordTypeA,
|
||||
Name: name,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
aaaaRecordsCountResp, err := this.RPC().NSRecordRPC().CountAllNSRecordsWithName(this.AdminContext(), &pb.CountAllNSRecordsWithNameRequest{
|
||||
NsDomainId: domainId,
|
||||
Type: dnsconfigs.RecordTypeAAAA,
|
||||
Name: name,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if aRecordsCountResp.Count+aaaaRecordsCountResp.Count > 0 {
|
||||
this.Fail("已有A记录,请删除A记录后在尝试添加cname记录")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package records
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
RecordId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSRecord_LogDeleteNSRecord, params.RecordId)
|
||||
|
||||
_, err := this.RPC().NSRecordRPC().DeleteNSRecord(this.AdminContext(), &pb.DeleteNSRecordRequest{NsRecordId: params.RecordId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package records
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type HealthCheckPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *HealthCheckPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *HealthCheckPopupAction) RunGet(params struct {
|
||||
RecordId int64
|
||||
}) {
|
||||
// 记录信息
|
||||
recordResp, err := this.RPC().NSRecordRPC().FindNSRecord(this.AdminContext(), &pb.FindNSRecordRequest{NsRecordId: params.RecordId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var record = recordResp.NsRecord
|
||||
if record == nil || record.NsDomain == nil {
|
||||
this.NotFound("nsRecord", params.RecordId)
|
||||
return
|
||||
}
|
||||
|
||||
// 记录健康检查
|
||||
var recordHealthCheckConfig = dnsconfigs.NewNSRecordHealthCheckConfig()
|
||||
if len(record.HealthCheckJSON) > 0 {
|
||||
err = json.Unmarshal(record.HealthCheckJSON, recordHealthCheckConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["record"] = maps.Map{
|
||||
"id": record.Id,
|
||||
"name": record.Name,
|
||||
"type": record.Type,
|
||||
"value": record.Value,
|
||||
"healthCheckConfig": recordHealthCheckConfig,
|
||||
}
|
||||
|
||||
// 域名信息
|
||||
domainResp, err := this.RPC().NSDomainRPC().FindNSDomain(this.AdminContext(), &pb.FindNSDomainRequest{NsDomainId: record.NsDomain.Id})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var domain = domainResp.NsDomain
|
||||
if domain == nil {
|
||||
this.NotFound("nsDomain", record.NsDomain.Id)
|
||||
return
|
||||
}
|
||||
|
||||
// 域名健康检查
|
||||
var domainHealthCheckConfig = dnsconfigs.NewNSRecordsHealthCheckConfig()
|
||||
if len(domain.RecordsHealthCheckJSON) > 0 {
|
||||
err = json.Unmarshal(domain.RecordsHealthCheckJSON, domainHealthCheckConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["domain"] = maps.Map{
|
||||
"name": domain.Name,
|
||||
"healthCheckConfig": domainHealthCheckConfig,
|
||||
}
|
||||
|
||||
// 检查权限
|
||||
canUpdate, err := domainutils.CheckHealthCheckPermission(this.RPC(), this.AdminContext(), record.NsDomain.Id)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !canUpdate {
|
||||
this.Fail("permission denied")
|
||||
return
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *HealthCheckPopupAction) RunPost(params struct {
|
||||
RecordId int64
|
||||
RecordHealthCheckJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSRecord_LogUpdateNSRecordHealthCheck, params.RecordId)
|
||||
|
||||
// 检查权限
|
||||
recordResp, err := this.RPC().NSRecordRPC().FindNSRecord(this.AdminContext(), &pb.FindNSRecordRequest{NsRecordId: params.RecordId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var record = recordResp.NsRecord
|
||||
if record == nil || record.NsDomain == nil {
|
||||
this.Fail("找不到要修改的记录")
|
||||
return
|
||||
}
|
||||
|
||||
canUpdate, err := domainutils.CheckHealthCheckPermission(this.RPC(), this.AdminContext(), record.NsDomain.Id)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !canUpdate {
|
||||
this.Fail("permission denied")
|
||||
return
|
||||
}
|
||||
|
||||
var healthCheckConfig = dnsconfigs.NewNSRecordHealthCheckConfig()
|
||||
err = json.Unmarshal(params.RecordHealthCheckJSON, healthCheckConfig)
|
||||
if err != nil {
|
||||
this.Fail("解析配置失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = healthCheckConfig.Init()
|
||||
if err != nil {
|
||||
this.Fail("校验配置失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSRecordRPC().UpdateNSRecordHealthCheck(this.AdminContext(), &pb.UpdateNSRecordHealthCheckRequest{
|
||||
NsRecordId: params.RecordId,
|
||||
NsRecordHealthCheckJSON: params.RecordHealthCheckJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package records
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "record")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
DomainId int64
|
||||
Type string
|
||||
Keyword string
|
||||
RouteCode string
|
||||
|
||||
NameOrder string
|
||||
TypeOrder string
|
||||
TtlOrder string
|
||||
UpOrder string
|
||||
}) {
|
||||
// 初始化域名信息
|
||||
err := domainutils.InitDomain(this.Parent(), params.DomainId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 去除域名中的域名
|
||||
var domainMap = this.Data.GetMap("domain")
|
||||
if len(domainMap) > 0 {
|
||||
var domainName = domainMap.GetString("name")
|
||||
if len(domainName) > 0 {
|
||||
params.Keyword = strings.TrimSuffix(params.Keyword, "."+domainName)
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["type"] = params.Type
|
||||
this.Data["keyword"] = params.Keyword
|
||||
this.Data["routeCode"] = params.RouteCode
|
||||
|
||||
// 域名的健康检查
|
||||
domainHealthCheckIsEnabled, err := domainutils.CheckHealthCheckPermission(this.RPC(), this.AdminContext(), params.DomainId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var domainHealthCheckIsOn = false
|
||||
if domainHealthCheckIsEnabled {
|
||||
domainHealthCheckResp, err := this.RPC().NSDomainRPC().FindNSDomainRecordsHealthCheck(this.AdminContext(), &pb.FindNSDomainRecordsHealthCheckRequest{NsDomainId: params.DomainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(domainHealthCheckResp.NsDomainRecordsHealthCheckJSON) > 0 {
|
||||
var domainHealthCheckConfig = dnsconfigs.NewNSRecordsHealthCheckConfig()
|
||||
err = json.Unmarshal(domainHealthCheckResp.NsDomainRecordsHealthCheckJSON, domainHealthCheckConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
domainHealthCheckIsOn = domainHealthCheckConfig.IsOn
|
||||
}
|
||||
}
|
||||
this.Data["domainHealthCheckIsOn"] = domainHealthCheckIsOn
|
||||
|
||||
// 记录
|
||||
countResp, err := this.RPC().NSRecordRPC().CountAllNSRecords(this.AdminContext(), &pb.CountAllNSRecordsRequest{
|
||||
NsDomainId: params.DomainId,
|
||||
Type: params.Type,
|
||||
NsRouteCode: params.RouteCode,
|
||||
Keyword: params.Keyword,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var count = countResp.Count
|
||||
var page = this.NewPage(count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
recordsResp, err := this.RPC().NSRecordRPC().ListNSRecords(this.AdminContext(), &pb.ListNSRecordsRequest{
|
||||
NsDomainId: params.DomainId,
|
||||
Type: params.Type,
|
||||
NsRouteCode: params.RouteCode,
|
||||
Keyword: params.Keyword,
|
||||
NameAsc: params.NameOrder == "asc",
|
||||
NameDesc: params.NameOrder == "desc",
|
||||
TypeAsc: params.TypeOrder == "asc",
|
||||
TypeDesc: params.TypeOrder == "desc",
|
||||
TtlAsc: params.TtlOrder == "asc",
|
||||
TtlDesc: params.TtlOrder == "desc",
|
||||
UpAsc: params.UpOrder == "asc",
|
||||
UpDesc: params.UpOrder == "desc",
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var recordMaps = []maps.Map{}
|
||||
|
||||
var recordIds = []int64{}
|
||||
for _, record := range recordsResp.NsRecords {
|
||||
recordIds = append(recordIds, record.Id)
|
||||
}
|
||||
|
||||
// 统计
|
||||
var statMap = map[int64]maps.Map{} // recordId => Map
|
||||
if len(recordIds) > 0 {
|
||||
statsResp, err := this.RPC().NSRecordHourlyStatRPC().FindNSRecordHourlyStatWithRecordIds(this.AdminContext(), &pb.FindNSRecordHourlyStatWithRecordIdsRequest{NsRecordIds: recordIds})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
for _, stat := range statsResp.NsRecordHourlyStats {
|
||||
statMap[stat.NsRecordId] = maps.Map{
|
||||
"bytes": stat.Bytes,
|
||||
"countRequests": stat.CountRequests,
|
||||
"countRequestsFormat": numberutils.FormatCount(stat.CountRequests),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 列表
|
||||
for _, record := range recordsResp.NsRecords {
|
||||
var routeMaps = []maps.Map{}
|
||||
for _, route := range record.NsRoutes {
|
||||
routeMaps = append(routeMaps, maps.Map{
|
||||
"id": route.Id,
|
||||
"name": route.Name,
|
||||
})
|
||||
}
|
||||
|
||||
// 统计
|
||||
recordStatMap, ok := statMap[record.Id]
|
||||
if !ok {
|
||||
recordStatMap = maps.Map{
|
||||
"bytes": 0,
|
||||
"countRequests": 0,
|
||||
"countRequestsFormat": "0",
|
||||
}
|
||||
}
|
||||
|
||||
// 健康检查
|
||||
var recordHealthCheckConfig = dnsconfigs.NewNSRecordHealthCheckConfig()
|
||||
if domainHealthCheckIsOn && len(record.HealthCheckJSON) > 0 {
|
||||
err = json.Unmarshal(record.HealthCheckJSON, recordHealthCheckConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
recordMaps = append(recordMaps, maps.Map{
|
||||
"id": record.Id,
|
||||
"name": record.Name,
|
||||
"type": record.Type,
|
||||
"value": record.Value,
|
||||
"mxPriority": record.MxPriority,
|
||||
"srvPriority": record.SrvPriority,
|
||||
"srvWeight": record.SrvWeight,
|
||||
"srvPort": record.SrvPort,
|
||||
"caaFlag": record.CaaFlag,
|
||||
"caaTag": record.CaaTag,
|
||||
|
||||
"ttl": record.Ttl,
|
||||
"weight": record.Weight,
|
||||
"description": record.Description,
|
||||
"isOn": record.IsOn,
|
||||
"routes": routeMaps,
|
||||
"stat": recordStatMap,
|
||||
|
||||
"healthCheck": recordHealthCheckConfig,
|
||||
"isUp": record.IsUp,
|
||||
})
|
||||
}
|
||||
this.Data["records"] = recordMaps
|
||||
|
||||
// 是否提示可以精准搜索
|
||||
this.Data["enableNameSearch"] = false
|
||||
this.Data["enableValueSearch"] = false
|
||||
this.Data["searchingKeyword"] = params.Keyword
|
||||
if countResp.Count > 0 && len(params.Keyword) > 0 {
|
||||
for _, record := range recordsResp.NsRecords {
|
||||
if record.Name == params.Keyword {
|
||||
this.Data["enableNameSearch"] = true
|
||||
break
|
||||
}
|
||||
if record.Value == params.Keyword {
|
||||
this.Data["enableValueSearch"] = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 所有记录类型
|
||||
this.Data["types"] = dnsconfigs.FindAllUserRecordTypeDefinitions()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package records
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type StatPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *StatPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *StatPopupAction) RunGet(params struct {
|
||||
RecordId int64
|
||||
}) {
|
||||
recordResp, err := this.RPC().NSRecordRPC().FindNSRecord(this.AdminContext(), &pb.FindNSRecordRequest{NsRecordId: params.RecordId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var record = recordResp.NsRecord
|
||||
if record == nil {
|
||||
this.NotFound("nsRecord", params.RecordId)
|
||||
return
|
||||
}
|
||||
|
||||
var routeNames = []string{}
|
||||
for _, route := range record.NsRoutes {
|
||||
routeNames = append(routeNames, route.Name)
|
||||
}
|
||||
|
||||
this.Data["record"] = maps.Map{
|
||||
"id": record.Id,
|
||||
"name": record.Name,
|
||||
"routeNames": routeNames,
|
||||
}
|
||||
|
||||
statsResp, err := this.RPC().NSRecordHourlyStatRPC().FindLatestNSRecordsHourlyStats(this.AdminContext(), &pb.FindLatestNSRecordsHourlyStatsRequest{NsRecordId: params.RecordId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var statMaps = []maps.Map{}
|
||||
for _, stat := range statsResp.NsRecordHourlyStats {
|
||||
statMaps = append(statMaps, maps.Map{
|
||||
"bytes": stat.Bytes,
|
||||
"countRequests": stat.CountRequests,
|
||||
"hour": stat.Hour,
|
||||
})
|
||||
}
|
||||
this.Data["stats"] = statMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package records
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
RecordId int64
|
||||
}) {
|
||||
recordResp, err := this.RPC().NSRecordRPC().FindNSRecord(this.AdminContext(), &pb.FindNSRecordRequest{NsRecordId: params.RecordId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var record = recordResp.NsRecord
|
||||
if record == nil {
|
||||
this.NotFound("nsRecord", params.RecordId)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["record"] = maps.Map{
|
||||
"id": record.Id,
|
||||
"name": record.Name,
|
||||
"type": record.Type,
|
||||
"value": record.Value,
|
||||
"mxPriority": record.MxPriority,
|
||||
"srvPriority": record.SrvPriority,
|
||||
"srvWeight": record.SrvWeight,
|
||||
"srvPort": record.SrvPort,
|
||||
"caaFlag": record.CaaFlag,
|
||||
"caaTag": record.CaaTag,
|
||||
"ttl": record.Ttl,
|
||||
"weight": record.Weight,
|
||||
"description": record.Description,
|
||||
"isOn": record.IsOn,
|
||||
"routes": record.NsRoutes,
|
||||
}
|
||||
|
||||
// 域名信息
|
||||
domainResp, err := this.RPC().NSDomainRPC().FindNSDomain(this.AdminContext(), &pb.FindNSDomainRequest{NsDomainId: record.NsDomain.Id})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
domain := domainResp.NsDomain
|
||||
if domain == nil {
|
||||
this.NotFound("nsDomain", record.NsDomain.Id)
|
||||
return
|
||||
}
|
||||
this.Data["domain"] = maps.Map{
|
||||
"id": domain.Id,
|
||||
"name": domain.Name,
|
||||
}
|
||||
|
||||
// 类型
|
||||
this.Data["types"] = dnsconfigs.FindAllUserRecordTypeDefinitions()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
DomainId int64
|
||||
RecordId int64
|
||||
Name string
|
||||
Type string
|
||||
Value string
|
||||
|
||||
MxPriority int32
|
||||
|
||||
SrvPriority int32
|
||||
SrvWeight int32
|
||||
SrvPort int32
|
||||
|
||||
CaaFlag int32
|
||||
CaaTag string
|
||||
|
||||
Ttl int32
|
||||
Description string
|
||||
IsOn bool
|
||||
RouteCodes []string
|
||||
Weight int32
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
this.CreateLogInfo(codes.NSRecord_LogUpdateNSRecord, params.RecordId)
|
||||
this.CheckType(params.Type, params.DomainId, params.Name)
|
||||
|
||||
// 校验记录名
|
||||
if !domainutils.ValidateRecordName(params.Name) {
|
||||
this.FailField("name", "请输入正确的记录名")
|
||||
}
|
||||
|
||||
// 校验记录值
|
||||
message, ok := domainutils.ValidateRecordValue(params.Type, params.Value)
|
||||
if !ok {
|
||||
this.FailField("value", "记录值错误:"+message)
|
||||
}
|
||||
|
||||
// SRV
|
||||
if params.Type == dnsconfigs.RecordTypeSRV {
|
||||
if params.SrvPort < 0 || params.SrvPort > 65535 {
|
||||
this.FailField("srvPort", "请输入有效的端口号")
|
||||
}
|
||||
}
|
||||
|
||||
// 校验TTL
|
||||
if params.Ttl <= 0 {
|
||||
this.Fail("请输入正确的TTL")
|
||||
}
|
||||
|
||||
_, err := this.RPC().NSRecordRPC().UpdateNSRecord(this.AdminContext(), &pb.UpdateNSRecordRequest{
|
||||
NsRecordId: params.RecordId,
|
||||
Description: params.Description,
|
||||
Name: params.Name,
|
||||
Type: params.Type,
|
||||
Value: params.Value,
|
||||
MxPriority: params.MxPriority,
|
||||
SrvPriority: params.SrvPriority,
|
||||
SrvWeight: params.SrvWeight,
|
||||
SrvPort: params.SrvPort,
|
||||
CaaFlag: params.CaaFlag,
|
||||
CaaTag: params.CaaTag,
|
||||
Ttl: params.Ttl,
|
||||
IsOn: params.IsOn,
|
||||
NsRouteCodes: params.RouteCodes,
|
||||
Weight: params.Weight,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) CheckType(recordType dnsconfigs.RecordType, domainId int64, name string) {
|
||||
//A|AAAA记录和cname记录不可以共存
|
||||
if recordType == dnsconfigs.RecordTypeA || recordType == dnsconfigs.RecordTypeAAAA {
|
||||
cnameRecordsCountResp, err := this.RPC().NSRecordRPC().CountAllNSRecordsWithName(this.AdminContext(), &pb.CountAllNSRecordsWithNameRequest{
|
||||
NsDomainId: domainId,
|
||||
Type: dnsconfigs.RecordTypeCNAME,
|
||||
Name: name,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if cnameRecordsCountResp.Count > 0 {
|
||||
this.Fail("已有cname记录,请删除cname记录后在尝试添加A记录")
|
||||
}
|
||||
} else if recordType == dnsconfigs.RecordTypeCNAME {
|
||||
aRecordsCountResp, err := this.RPC().NSRecordRPC().CountAllNSRecordsWithName(this.AdminContext(), &pb.CountAllNSRecordsWithNameRequest{
|
||||
NsDomainId: domainId,
|
||||
Type: dnsconfigs.RecordTypeA,
|
||||
Name: name,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
aaaaRecordsCountResp, err := this.RPC().NSRecordRPC().CountAllNSRecordsWithName(this.AdminContext(), &pb.CountAllNSRecordsWithNameRequest{
|
||||
NsDomainId: domainId,
|
||||
Type: dnsconfigs.RecordTypeAAAA,
|
||||
Name: name,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if aRecordsCountResp.Count+aaaaRecordsCountResp.Count > 0 {
|
||||
this.Fail("已有A记录,请删除A记录后在尝试添加cname记录")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package records
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type UpdateUpAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateUpAction) RunPost(params struct {
|
||||
RecordId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSRecord_LogUpNSRecord, params.RecordId)
|
||||
|
||||
_, err := this.RPC().NSRecordRPC().UpdateNSRecordIsUp(this.AdminContext(), &pb.UpdateNSRecordIsUpRequest{
|
||||
NsRecordId: params.RecordId,
|
||||
IsUp: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
82
EdgeAdmin/internal/web/actions/default/ns/domains/tsig.go
Normal file
82
EdgeAdmin/internal/web/actions/default/ns/domains/tsig.go
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package domains
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
)
|
||||
|
||||
type TsigAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *TsigAction) Init() {
|
||||
this.Nav("", "", "tsig")
|
||||
}
|
||||
|
||||
func (this *TsigAction) RunGet(params struct {
|
||||
DomainId int64
|
||||
}) {
|
||||
// 初始化域名信息
|
||||
err := domainutils.InitDomain(this.Parent(), params.DomainId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// TSIG信息
|
||||
tsigResp, err := this.RPC().NSDomainRPC().FindNSDomainTSIG(this.AdminContext(), &pb.FindNSDomainTSIGRequest{NsDomainId: params.DomainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var tsigJSON = tsigResp.TsigJSON
|
||||
|
||||
var tsigConfig = &dnsconfigs.NSTSIGConfig{}
|
||||
if len(tsigJSON) > 0 {
|
||||
err = json.Unmarshal(tsigJSON, tsigConfig)
|
||||
if err != nil {
|
||||
// 只是提示错误,仍然允许用户修改
|
||||
logs.Error(err)
|
||||
}
|
||||
}
|
||||
this.Data["tsig"] = tsigConfig
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *TsigAction) RunPost(params struct {
|
||||
DomainId int64
|
||||
IsOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSDomain_LogUpdateNSDomainTSIG, params.DomainId)
|
||||
|
||||
var tsigConfig = &dnsconfigs.NSTSIGConfig{
|
||||
IsOn: params.IsOn,
|
||||
}
|
||||
tsigJSON, err := json.Marshal(tsigConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
_, err = this.RPC().NSDomainRPC().UpdateNSDomainTSIG(this.AdminContext(), &pb.UpdateNSDomainTSIGRequest{
|
||||
NsDomainId: params.DomainId,
|
||||
TsigJSON: tsigJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Success()
|
||||
}
|
||||
144
EdgeAdmin/internal/web/actions/default/ns/domains/update.go
Normal file
144
EdgeAdmin/internal/web/actions/default/ns/domains/update.go
Normal file
@@ -0,0 +1,144 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package domains
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdateAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateAction) Init() {
|
||||
this.Nav("", "", "update")
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunGet(params struct {
|
||||
DomainId int64
|
||||
}) {
|
||||
// 初始化域名信息
|
||||
err := domainutils.InitDomain(this.Parent(), params.DomainId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var countRecords = this.Data.GetMap("domain").GetInt64("countRecords")
|
||||
var countKeys = this.Data.GetMap("domain").GetInt64("countKeys")
|
||||
|
||||
// 域名信息
|
||||
domainResp, err := this.RPC().NSDomainRPC().FindNSDomain(this.AdminContext(), &pb.FindNSDomainRequest{NsDomainId: params.DomainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var domain = domainResp.NsDomain
|
||||
if domain == nil {
|
||||
this.NotFound("nsDomain", params.DomainId)
|
||||
return
|
||||
}
|
||||
|
||||
var clusterId = int64(0)
|
||||
if domain.NsCluster != nil {
|
||||
clusterId = domain.NsCluster.Id
|
||||
}
|
||||
|
||||
// 用户信息
|
||||
var userId = int64(0)
|
||||
if domain.User != nil {
|
||||
userId = domain.User.Id
|
||||
}
|
||||
|
||||
// 分组信息
|
||||
var groupId int64
|
||||
if len(domain.NsDomainGroups) > 0 {
|
||||
groupId = domain.NsDomainGroups[0].Id
|
||||
}
|
||||
|
||||
// 健康检查
|
||||
var healthCheckConfig = dnsconfigs.NewNSRecordsHealthCheckConfig()
|
||||
if len(domain.RecordsHealthCheckJSON) > 0 {
|
||||
err = json.Unmarshal(domain.RecordsHealthCheckJSON, healthCheckConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["domain"] = maps.Map{
|
||||
"id": domain.Id,
|
||||
"name": domain.Name,
|
||||
"isOn": domain.IsOn,
|
||||
"clusterId": clusterId,
|
||||
"userId": userId,
|
||||
"countRecords": countRecords,
|
||||
"countKeys": countKeys,
|
||||
"groupId": groupId,
|
||||
"enableHealthCheck": healthCheckConfig.IsOn,
|
||||
}
|
||||
|
||||
// DNS服务器
|
||||
if domain.NsCluster == nil || domain.NsCluster.Id <= 0 {
|
||||
this.WriteString("当前域名(" + domain.Name + ")所在集群已被删除,请删除当前域名后重新添加")
|
||||
return
|
||||
}
|
||||
|
||||
hostsResp, err := this.RPC().NSClusterRPC().FindNSClusterHosts(this.AdminContext(), &pb.FindNSClusterHostsRequest{
|
||||
NsClusterId: domain.NsCluster.Id,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var hosts = hostsResp.Hosts
|
||||
if hosts == nil {
|
||||
hosts = []string{}
|
||||
}
|
||||
this.Data["dnsHosts"] = hosts
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunPost(params struct {
|
||||
DomainId int64
|
||||
ClusterId int64
|
||||
UserId int64
|
||||
GroupId int64
|
||||
IsOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSDomain_LogUpdateNSDomain, params.DomainId)
|
||||
|
||||
params.Must.
|
||||
Field("clusterId", params.ClusterId).
|
||||
Gt(0, "请选择所属集群")
|
||||
|
||||
var groupIds = []int64{}
|
||||
if params.GroupId > 0 {
|
||||
groupIds = append(groupIds, params.GroupId)
|
||||
}
|
||||
|
||||
_, err := this.RPC().NSDomainRPC().UpdateNSDomain(this.AdminContext(), &pb.UpdateNSDomainRequest{
|
||||
NsDomainId: params.DomainId,
|
||||
NsClusterId: params.ClusterId,
|
||||
UserId: params.UserId,
|
||||
NsDomainGroupIds: groupIds,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
155
EdgeAdmin/internal/web/actions/default/ns/index.go
Normal file
155
EdgeAdmin/internal/web/actions/default/ns/index.go
Normal file
@@ -0,0 +1,155 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package ns
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "ns")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
this.Data["board"] = maps.Map{
|
||||
"countDomains": 0,
|
||||
"countRecords": 0,
|
||||
"countClusters": 0,
|
||||
"countNodes": 0,
|
||||
"countOfflineNodes": 0,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct{}) {
|
||||
resp, err := this.RPC().NSRPC().ComposeNSBoard(this.AdminContext(), &pb.ComposeNSBoardRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["board"] = maps.Map{
|
||||
"countDomains": resp.CountNSDomains,
|
||||
"countRecords": resp.CountNSRecords,
|
||||
"countClusters": resp.CountNSClusters,
|
||||
"countNodes": resp.CountNSNodes,
|
||||
"countOfflineNodes": resp.CountOfflineNSNodes,
|
||||
}
|
||||
|
||||
// 流量排行
|
||||
{
|
||||
var statMaps = []maps.Map{}
|
||||
for _, stat := range resp.HourlyTrafficStats {
|
||||
statMaps = append(statMaps, maps.Map{
|
||||
"day": stat.Hour[4:6] + "月" + stat.Hour[6:8] + "日",
|
||||
"hour": stat.Hour[8:],
|
||||
"countRequests": stat.CountRequests,
|
||||
"bytes": stat.Bytes,
|
||||
})
|
||||
}
|
||||
this.Data["hourlyStats"] = statMaps
|
||||
}
|
||||
|
||||
{
|
||||
var statMaps = []maps.Map{}
|
||||
for _, stat := range resp.DailyTrafficStats {
|
||||
statMaps = append(statMaps, maps.Map{
|
||||
"day": stat.Day[4:6] + "月" + stat.Day[6:] + "日",
|
||||
"countRequests": stat.CountRequests,
|
||||
"bytes": stat.Bytes,
|
||||
})
|
||||
}
|
||||
this.Data["dailyStats"] = statMaps
|
||||
}
|
||||
|
||||
// 域名排行
|
||||
{
|
||||
var statMaps = []maps.Map{}
|
||||
for _, stat := range resp.TopNSDomainStats {
|
||||
statMaps = append(statMaps, maps.Map{
|
||||
"domainId": stat.NsDomainId,
|
||||
"domainName": stat.NsDomainName,
|
||||
"countRequests": stat.CountRequests,
|
||||
"bytes": stat.Bytes,
|
||||
})
|
||||
}
|
||||
this.Data["topDomainStats"] = statMaps
|
||||
}
|
||||
|
||||
// 节点排行
|
||||
{
|
||||
var statMaps = []maps.Map{}
|
||||
for _, stat := range resp.TopNSNodeStats {
|
||||
statMaps = append(statMaps, maps.Map{
|
||||
"clusterId": stat.NsClusterId,
|
||||
"nodeId": stat.NsNodeId,
|
||||
"nodeName": stat.NsNodeName,
|
||||
"countRequests": stat.CountRequests,
|
||||
"bytes": stat.Bytes,
|
||||
})
|
||||
}
|
||||
this.Data["topNodeStats"] = statMaps
|
||||
}
|
||||
|
||||
// CPU
|
||||
{
|
||||
var statMaps = []maps.Map{}
|
||||
for _, stat := range resp.CpuNodeValues {
|
||||
var valueMap = maps.Map{}
|
||||
err = json.Unmarshal(stat.ValueJSON, &valueMap)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
statMaps = append(statMaps, maps.Map{
|
||||
"time": timeutil.FormatTime("H:i", stat.CreatedAt),
|
||||
"value": valueMap.GetFloat32("usage"),
|
||||
})
|
||||
}
|
||||
this.Data["cpuValues"] = statMaps
|
||||
}
|
||||
|
||||
// Memory
|
||||
{
|
||||
var statMaps = []maps.Map{}
|
||||
for _, stat := range resp.MemoryNodeValues {
|
||||
var valueMap = maps.Map{}
|
||||
err = json.Unmarshal(stat.ValueJSON, &valueMap)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
statMaps = append(statMaps, maps.Map{
|
||||
"time": timeutil.FormatTime("H:i", stat.CreatedAt),
|
||||
"value": valueMap.GetFloat32("usage"),
|
||||
})
|
||||
}
|
||||
this.Data["memoryValues"] = statMaps
|
||||
}
|
||||
|
||||
// Load
|
||||
{
|
||||
var statMaps = []maps.Map{}
|
||||
for _, stat := range resp.LoadNodeValues {
|
||||
var valueMap = maps.Map{}
|
||||
err = json.Unmarshal(stat.ValueJSON, &valueMap)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
statMaps = append(statMaps, maps.Map{
|
||||
"time": timeutil.FormatTime("H:i", stat.CreatedAt),
|
||||
"value": valueMap.GetFloat32("load1m"),
|
||||
})
|
||||
}
|
||||
this.Data["loadValues"] = statMaps
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
119
EdgeAdmin/internal/web/actions/default/ns/init.go
Normal file
119
EdgeAdmin/internal/web/actions/default/ns/init.go
Normal file
@@ -0,0 +1,119 @@
|
||||
//go:build plus
|
||||
|
||||
package ns
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/batch"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domain"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/groups"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/groups/group"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/keys"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/records"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/plans"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/plans/plan"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/settings"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/userPlans"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/userPlans/userPlan"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeNS)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Data("teaMenu", "ns").
|
||||
Prefix("/ns").
|
||||
GetPost("", new(IndexAction)).
|
||||
GetPost("/addPortPopup", new(AddPortPopupAction)).
|
||||
|
||||
// 域名列表
|
||||
Prefix("/ns/domains").
|
||||
Data("teaSubMenu", "domain").
|
||||
Get("", new(domains.IndexAction)).
|
||||
GetPost("/create", new(domains.CreateAction)).
|
||||
Post("/delete", new(domains.DeleteAction)).
|
||||
Post("/deletePage", new(domains.DeletePageAction)).
|
||||
GetPost("/update", new(domains.UpdateAction)).
|
||||
GetPost("/tsig", new(domains.TsigAction)).
|
||||
GetPost("/healthCheck", new(domains.HealthCheckAction)).
|
||||
|
||||
// 单个域名
|
||||
Prefix("/ns/domains/domain").
|
||||
Data("teaSubMenu", "domain").
|
||||
Get("", new(domain.IndexAction)).
|
||||
GetPost("/updateStatusPopup", new(domain.UpdateStatusPopupAction)).
|
||||
|
||||
// 域名批量操作
|
||||
Prefix("/ns/domains/batch").
|
||||
Data("teaSubMenu", "domainBatch").
|
||||
GetPost("", new(batch.IndexAction)).
|
||||
GetPost("/createRecords", new(batch.CreateRecordsAction)).
|
||||
GetPost("/deleteDomains", new(batch.DeleteDomainsAction)).
|
||||
GetPost("/updateRecords", new(batch.UpdateRecordsAction)).
|
||||
GetPost("/enableRecords", new(batch.EnableRecordsAction)).
|
||||
GetPost("/importRecords", new(batch.ImportRecordsAction)).
|
||||
GetPost("/deleteRecords", new(batch.DeleteRecordsAction)).
|
||||
|
||||
// 域名密钥
|
||||
Prefix("/ns/domains/keys").
|
||||
Data("teaSubMenu", "domain").
|
||||
Get("", new(keys.IndexAction)).
|
||||
GetPost("/createPopup", new(keys.CreatePopupAction)).
|
||||
GetPost("/updatePopup", new(keys.UpdatePopupAction)).
|
||||
Post("/delete", new(keys.DeleteAction)).
|
||||
Post("/generateSecret", new(keys.GenerateSecretAction)).
|
||||
|
||||
// 记录相关
|
||||
Prefix("/ns/domains/records").
|
||||
Get("", new(records.IndexAction)).
|
||||
GetPost("/createPopup", new(records.CreatePopupAction)).
|
||||
GetPost("/updatePopup", new(records.UpdatePopupAction)).
|
||||
Post("/delete", new(records.DeleteAction)).
|
||||
GetPost("/statPopup", new(records.StatPopupAction)).
|
||||
GetPost("/healthCheckPopup", new(records.HealthCheckPopupAction)).
|
||||
Post("/updateUp", new(records.UpdateUpAction)).
|
||||
|
||||
// 域名分组列表
|
||||
Prefix("/ns/domains/groups").
|
||||
Data("teaSubMenu", "domainGroup").
|
||||
Get("", new(groups.IndexAction)).
|
||||
GetPost("/createPopup", new(groups.CreatePopupAction)).
|
||||
Post("/options", new(groups.OptionsAction)).
|
||||
|
||||
// 域名分组
|
||||
Prefix("/ns/domains/groups/group").
|
||||
Data("teaSubMenu", "domainGroup").
|
||||
Get("", new(group.IndexAction)).
|
||||
GetPost("/updatePopup", new(group.UpdatePopupAction)).
|
||||
Post("/delete", new(group.DeleteAction)).
|
||||
|
||||
// 设置
|
||||
Prefix("/ns/settings").
|
||||
Get("", new(settings.IndexAction)).
|
||||
|
||||
// 套餐管理
|
||||
Prefix("/ns/plans").
|
||||
Data("teaSubMenu", "plan").
|
||||
Get("", new(plans.IndexAction)).
|
||||
Post("/sort", new(plans.SortAction)).
|
||||
GetPost("/createPopup", new(plans.CreatePopupAction)).
|
||||
GetPost("/plan/updatePopup", new(plan.UpdatePopupAction)).
|
||||
Post("/plan/delete", new(plan.DeleteAction)).
|
||||
|
||||
// 用户套餐
|
||||
Prefix("/ns/userPlans").
|
||||
Data("teaSubMenu", "userPlan").
|
||||
Get("", new(userPlans.IndexAction)).
|
||||
GetPost("/createPopup", new(userPlans.CreatePopupAction)).
|
||||
GetPost("/userPlan/updatePopup", new(userPlan.UpdatePopupAction)).
|
||||
Post("/userPlan/delete", new(userPlan.DeleteAction)).
|
||||
|
||||
//
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
173
EdgeAdmin/internal/web/actions/default/ns/nsnodeutils/utils.go
Normal file
173
EdgeAdmin/internal/web/actions/default/ns/nsnodeutils/utils.go
Normal file
@@ -0,0 +1,173 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package nsnodeutils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"sort"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// MessageResult 和节点消息通讯结果定义
|
||||
type MessageResult struct {
|
||||
NodeId int64 `json:"nodeId"`
|
||||
NodeName string `json:"nodeName"`
|
||||
IsOK bool `json:"isOk"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// SendMessageToNSCluster 向NS集群发送命令消息
|
||||
func SendMessageToNSCluster(ctx context.Context, clusterId int64, code string, msg interface{}, timeoutSeconds int32) (results []*MessageResult, err error) {
|
||||
results = []*MessageResult{}
|
||||
|
||||
msgJSON, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return results, err
|
||||
}
|
||||
|
||||
defaultRPCClient, err := rpc.SharedRPC()
|
||||
if err != nil {
|
||||
return results, err
|
||||
}
|
||||
|
||||
// 获取所有节点
|
||||
nodesResp, err := defaultRPCClient.NSNodeRPC().FindAllNSNodesWithNSClusterId(ctx, &pb.FindAllNSNodesWithNSClusterIdRequest{
|
||||
NsClusterId: clusterId,
|
||||
})
|
||||
if err != nil {
|
||||
return results, err
|
||||
}
|
||||
var nodes = nodesResp.NsNodes
|
||||
if len(nodes) == 0 {
|
||||
return results, nil
|
||||
}
|
||||
|
||||
var rpcMap = map[int64]*rpc.RPCClient{} // apiNodeId => RPCClient
|
||||
var locker = &sync.Mutex{}
|
||||
|
||||
var wg = &sync.WaitGroup{}
|
||||
wg.Add(len(nodes))
|
||||
|
||||
for _, node := range nodes {
|
||||
// TODO 检查是否在线
|
||||
|
||||
if len(node.ConnectedAPINodeIds) == 0 {
|
||||
locker.Lock()
|
||||
results = append(results, &MessageResult{
|
||||
NodeId: node.Id,
|
||||
NodeName: node.Name,
|
||||
IsOK: false,
|
||||
Message: "节点尚未连接到API",
|
||||
})
|
||||
locker.Unlock()
|
||||
wg.Done()
|
||||
continue
|
||||
}
|
||||
|
||||
// 获取API节点信息
|
||||
apiNodeId := node.ConnectedAPINodeIds[0]
|
||||
rpcClient, ok := rpcMap[apiNodeId]
|
||||
if !ok {
|
||||
apiNodeResp, err := defaultRPCClient.APINodeRPC().FindEnabledAPINode(ctx, &pb.FindEnabledAPINodeRequest{ApiNodeId: apiNodeId})
|
||||
if err != nil {
|
||||
locker.Lock()
|
||||
results = append(results, &MessageResult{
|
||||
NodeId: node.Id,
|
||||
NodeName: node.Name,
|
||||
IsOK: false,
|
||||
Message: "无法读取对应的API节点信息:" + err.Error(),
|
||||
})
|
||||
locker.Unlock()
|
||||
wg.Done()
|
||||
continue
|
||||
}
|
||||
|
||||
if apiNodeResp.ApiNode == nil {
|
||||
locker.Lock()
|
||||
results = append(results, &MessageResult{
|
||||
NodeId: node.Id,
|
||||
NodeName: node.Name,
|
||||
IsOK: false,
|
||||
Message: "无法读取对应的API节点信息:API节点ID:" + strconv.FormatInt(apiNodeId, 10),
|
||||
})
|
||||
locker.Unlock()
|
||||
wg.Done()
|
||||
continue
|
||||
}
|
||||
apiNode := apiNodeResp.ApiNode
|
||||
|
||||
apiRPCClient, err := rpc.NewRPCClient(&configs.APIConfig{
|
||||
RPCEndpoints: apiNode.AccessAddrs,
|
||||
NodeId: apiNode.UniqueId,
|
||||
Secret: apiNode.Secret,
|
||||
}, false)
|
||||
if err != nil {
|
||||
locker.Lock()
|
||||
results = append(results, &MessageResult{
|
||||
NodeId: node.Id,
|
||||
NodeName: node.Name,
|
||||
IsOK: false,
|
||||
Message: "初始化API节点错误:API节点ID:" + strconv.FormatInt(apiNodeId, 10) + ":" + err.Error(),
|
||||
})
|
||||
locker.Unlock()
|
||||
wg.Done()
|
||||
continue
|
||||
}
|
||||
rpcMap[apiNodeId] = apiRPCClient
|
||||
rpcClient = apiRPCClient
|
||||
}
|
||||
|
||||
// 发送消息
|
||||
go func(node *pb.NSNode) {
|
||||
defer wg.Done()
|
||||
|
||||
result, err := rpcClient.NSNodeRPC().SendCommandToNSNode(ctx, &pb.NSNodeStreamMessage{
|
||||
NsNodeId: node.Id,
|
||||
TimeoutSeconds: timeoutSeconds,
|
||||
Code: code,
|
||||
DataJSON: msgJSON,
|
||||
})
|
||||
if err != nil {
|
||||
locker.Lock()
|
||||
results = append(results, &MessageResult{
|
||||
NodeId: node.Id,
|
||||
NodeName: node.Name,
|
||||
IsOK: false,
|
||||
Message: "API返回错误:" + err.Error(),
|
||||
})
|
||||
locker.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
locker.Lock()
|
||||
results = append(results, &MessageResult{
|
||||
NodeId: node.Id,
|
||||
NodeName: node.Name,
|
||||
IsOK: result.IsOk,
|
||||
Message: result.Message,
|
||||
})
|
||||
locker.Unlock()
|
||||
}(node)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
// 对结果进行排序
|
||||
if len(results) > 0 {
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].NodeId < results[j].NodeId
|
||||
})
|
||||
}
|
||||
|
||||
// 关闭RPC
|
||||
for _, rpcClient := range rpcMap {
|
||||
_ = rpcClient.Close()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package plans
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
Name string
|
||||
MonthlyPrice float32
|
||||
YearlyPrice float32
|
||||
SupportCountryRoutes bool
|
||||
SupportChinaProvinceRoutes bool
|
||||
SupportISPRoutes bool
|
||||
SupportAgentRoutes bool
|
||||
SupportPublicRoutes bool
|
||||
|
||||
SupportHealthCheck bool
|
||||
|
||||
MinTTL int32
|
||||
MaxDomains int32
|
||||
MaxRecordsPerDomain int32
|
||||
MaxLoadBalanceRecordsPerRecord int32
|
||||
MaxCustomRoutes int32
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
var planId int64
|
||||
defer func() {
|
||||
this.CreateLogInfo(codes.NSPlan_LogCreateNSPlan, planId)
|
||||
}()
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入套餐名称").
|
||||
Field("monthlyPrice", params.MonthlyPrice).
|
||||
Gt(0, "请输入按月价格").
|
||||
Field("yearlyPrice", params.YearlyPrice).
|
||||
Gt(0, "请输入按年价格")
|
||||
|
||||
var config = dnsconfigs.DefaultNSPlanConfig()
|
||||
config.SupportCountryRoutes = params.SupportCountryRoutes
|
||||
config.SupportChinaProvinceRoutes = params.SupportChinaProvinceRoutes
|
||||
config.SupportISPRoutes = params.SupportISPRoutes
|
||||
config.SupportAgentRoutes = params.SupportAgentRoutes
|
||||
config.SupportPublicRoutes = params.SupportPublicRoutes
|
||||
|
||||
config.SupportHealthCheck = params.SupportHealthCheck
|
||||
|
||||
config.MinTTL = params.MinTTL
|
||||
config.MaxDomains = params.MaxDomains
|
||||
config.MaxRecordsPerDomain = params.MaxRecordsPerDomain
|
||||
config.MaxLoadBalanceRecordsPerRecord = params.MaxLoadBalanceRecordsPerRecord
|
||||
config.MaxCustomRoutes = params.MaxCustomRoutes
|
||||
err := config.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
}
|
||||
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().NSPlanRPC().CreateNSPlan(this.AdminContext(), &pb.CreateNSPlanRequest{
|
||||
Name: params.Name,
|
||||
MonthlyPrice: params.MonthlyPrice,
|
||||
YearlyPrice: params.YearlyPrice,
|
||||
ConfigJSON: configJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
planId = createResp.NsPlanId
|
||||
|
||||
this.Success()
|
||||
}
|
||||
54
EdgeAdmin/internal/web/actions/default/ns/plans/index.go
Normal file
54
EdgeAdmin/internal/web/actions/default/ns/plans/index.go
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package plans
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
// 当前所有套餐
|
||||
plansResp, err := this.RPC().NSPlanRPC().FindAllNSPlans(this.AdminContext(), &pb.FindAllNSPlansRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var planMaps = []maps.Map{}
|
||||
for _, plan := range plansResp.NsPlans {
|
||||
var config = dnsconfigs.DefaultNSPlanConfig()
|
||||
if len(plan.ConfigJSON) > 0 {
|
||||
err = json.Unmarshal(plan.ConfigJSON, config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
planMaps = append(planMaps, maps.Map{
|
||||
"id": plan.Id,
|
||||
"name": plan.Name,
|
||||
"isOn": plan.IsOn,
|
||||
"monthlyPriceFormat": fmt.Sprintf("%.2f", plan.MonthlyPrice),
|
||||
"yearlyPriceFormat": fmt.Sprintf("%.2f", plan.YearlyPrice),
|
||||
"config": config,
|
||||
})
|
||||
}
|
||||
this.Data["plans"] = planMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package plan
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
PlanId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSPlan_LogDeleteNSPlan, params.PlanId)
|
||||
|
||||
// 检查是否有用户在使用
|
||||
countResp, err := this.RPC().NSUserPlanRPC().CountNSUserPlans(this.AdminContext(), &pb.CountNSUserPlansRequest{
|
||||
NsPlanId: params.PlanId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if countResp.Count > 0 {
|
||||
this.Fail("有" + types.String(countResp.Count) + "个用户正在使用此套餐,请转移用户套餐后再删除")
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSPlanRPC().DeleteNSPlan(this.AdminContext(), &pb.DeleteNSPlanRequest{NsPlanId: params.PlanId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package plan
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
PlanId int64
|
||||
}) {
|
||||
planResp, err := this.RPC().NSPlanRPC().FindNSPlan(this.AdminContext(), &pb.FindNSPlanRequest{NsPlanId: params.PlanId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var plan = planResp.NsPlan
|
||||
|
||||
if plan == nil {
|
||||
this.NotFound("NSPlan", params.PlanId)
|
||||
return
|
||||
}
|
||||
|
||||
var config = dnsconfigs.DefaultNSPlanConfig()
|
||||
if len(plan.ConfigJSON) > 0 {
|
||||
err = json.Unmarshal(plan.ConfigJSON, config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["plan"] = maps.Map{
|
||||
"id": plan.Id,
|
||||
"name": plan.Name,
|
||||
"isOn": plan.IsOn,
|
||||
"monthlyPrice": plan.MonthlyPrice,
|
||||
"yearlyPrice": plan.YearlyPrice,
|
||||
"config": config,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
PlanId int64
|
||||
|
||||
Name string
|
||||
MonthlyPrice float32
|
||||
YearlyPrice float32
|
||||
SupportCountryRoutes bool
|
||||
SupportChinaProvinceRoutes bool
|
||||
SupportISPRoutes bool
|
||||
SupportAgentRoutes bool
|
||||
SupportPublicRoutes bool
|
||||
|
||||
SupportHealthCheck bool
|
||||
|
||||
MinTTL int32
|
||||
MaxDomains int32
|
||||
MaxRecordsPerDomain int32
|
||||
MaxLoadBalanceRecordsPerRecord int32
|
||||
MaxCustomRoutes int32
|
||||
|
||||
IsOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSPlan_LogUpdateNSPlan, params.PlanId)
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入套餐名称").
|
||||
Field("monthlyPrice", params.MonthlyPrice).
|
||||
Gt(0, "请输入按月价格").
|
||||
Field("yearlyPrice", params.YearlyPrice).
|
||||
Gt(0, "请输入按年价格")
|
||||
|
||||
var config = dnsconfigs.DefaultNSPlanConfig()
|
||||
config.SupportCountryRoutes = params.SupportCountryRoutes
|
||||
config.SupportChinaProvinceRoutes = params.SupportChinaProvinceRoutes
|
||||
config.SupportISPRoutes = params.SupportISPRoutes
|
||||
config.SupportAgentRoutes = params.SupportAgentRoutes
|
||||
config.SupportPublicRoutes = params.SupportPublicRoutes
|
||||
|
||||
config.SupportHealthCheck = params.SupportHealthCheck
|
||||
|
||||
config.MinTTL = params.MinTTL
|
||||
config.MaxDomains = params.MaxDomains
|
||||
config.MaxRecordsPerDomain = params.MaxRecordsPerDomain
|
||||
config.MaxLoadBalanceRecordsPerRecord = params.MaxLoadBalanceRecordsPerRecord
|
||||
config.MaxCustomRoutes = params.MaxCustomRoutes
|
||||
err := config.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
}
|
||||
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSPlanRPC().UpdateNSPlan(this.AdminContext(), &pb.UpdateNSPlanRequest{
|
||||
NsPlanId: params.PlanId,
|
||||
Name: params.Name,
|
||||
MonthlyPrice: params.MonthlyPrice,
|
||||
YearlyPrice: params.YearlyPrice,
|
||||
ConfigJSON: configJSON,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
28
EdgeAdmin/internal/web/actions/default/ns/plans/sort.go
Normal file
28
EdgeAdmin/internal/web/actions/default/ns/plans/sort.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package plans
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type SortAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *SortAction) RunPost(params struct {
|
||||
Ids []int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSPlan_LogSortNSPlans)
|
||||
|
||||
_, err := this.RPC().NSPlanRPC().SortNSPlanOrders(this.AdminContext(), &pb.SortNSPlansRequest{NsPlanIds: params.Ids})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package category
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
CategoryId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSRouteCategory_LogDeleteNSRouteCategory, params.CategoryId)
|
||||
|
||||
_, err := this.RPC().NSRouteCategoryRPC().DeleteNSRouteCategory(this.AdminContext(), &pb.DeleteNSRouteCategoryRequest{NsRouteCategoryId: params.CategoryId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package category
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
CategoryId int64
|
||||
}) {
|
||||
categoryResp, err := this.RPC().NSRouteCategoryRPC().FindNSRouteCategory(this.AdminContext(), &pb.FindNSRouteCategoryRequest{NsRouteCategoryId: params.CategoryId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var category = categoryResp.NsRouteCategory
|
||||
if category == nil {
|
||||
this.NotFound("NSRouteCategory", params.CategoryId)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["category"] = maps.Map{
|
||||
"id": category.Id,
|
||||
"name": category.Name,
|
||||
"isOn": category.IsOn,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
CategoryId int64
|
||||
Name string
|
||||
IsOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSRouteCategory_LogUpdateNSRouteCategory, params.CategoryId)
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入分类名称")
|
||||
|
||||
_, err := this.RPC().NSRouteCategoryRPC().UpdateNSRouteCategory(this.AdminContext(), &pb.UpdateNSRouteCategoryRequest{
|
||||
NsRouteCategoryId: params.CategoryId,
|
||||
Name: params.Name,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package categories
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
Name string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
var categoryId int64
|
||||
defer func() {
|
||||
this.CreateLogInfo(codes.NSRouteCategory_LogCreateNSRouteCategory, categoryId)
|
||||
}()
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入分类名称")
|
||||
|
||||
createResp, err := this.RPC().NSRouteCategoryRPC().CreateNSRouteCategory(this.AdminContext(), &pb.CreateNSRouteCategoryRequest{Name: params.Name})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
categoryId = createResp.NsRouteCategoryId
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package categories
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "category")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
categoriesResp, err := this.RPC().NSRouteCategoryRPC().FindAllNSRouteCategories(this.AdminContext(), &pb.FindAllNSRouteCategoriesRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var categoryMaps = []maps.Map{}
|
||||
for _, category := range categoriesResp.NsRouteCategories {
|
||||
categoryMaps = append(categoryMaps, maps.Map{
|
||||
"id": category.Id,
|
||||
"name": category.Name,
|
||||
"isOn": category.IsOn,
|
||||
})
|
||||
}
|
||||
this.Data["categories"] = categoryMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
//go:build plus
|
||||
|
||||
package categories
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/routes/categories/category"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeNS)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "route").
|
||||
Prefix("/ns/routes/categories").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/createPopup", new(CreatePopupAction)).
|
||||
Post("/sort", new(SortAction)).
|
||||
|
||||
//
|
||||
GetPost("/category/updatePopup", new(category.UpdatePopupAction)).
|
||||
Post("/category/delete", new(category.DeleteAction)).
|
||||
|
||||
//
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package categories
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type SortAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *SortAction) RunPost(params struct {
|
||||
CategoryIds []int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSRouteCategory_LogSortNSRouteCategories)
|
||||
|
||||
_, err := this.RPC().NSRouteCategoryRPC().UpdateNSRouteCategoryOrders(this.AdminContext(), &pb.UpdateNSRouteCategoryOrders{NsRouteCategoryIds: params.CategoryIds})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package routes
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct {
|
||||
ClusterId int64
|
||||
DomainId int64
|
||||
UserId int64
|
||||
}) {
|
||||
this.Data["clusterId"] = params.ClusterId
|
||||
this.Data["domainId"] = params.DomainId
|
||||
this.Data["userId"] = params.UserId
|
||||
|
||||
this.Data["rangeTypes"] = dnsconfigs.AllNSRouteRangeTypes()
|
||||
|
||||
// 所有分类
|
||||
categoriesResp, err := this.RPC().NSRouteCategoryRPC().FindAllNSRouteCategories(this.AdminContext(), &pb.FindAllNSRouteCategoriesRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var categoryMaps = []maps.Map{}
|
||||
for _, category := range categoriesResp.NsRouteCategories {
|
||||
categoryMaps = append(categoryMaps, maps.Map{
|
||||
"id": category.Id,
|
||||
"name": category.Name,
|
||||
})
|
||||
}
|
||||
this.Data["categories"] = categoryMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
ClusterId int64
|
||||
DomainId int64
|
||||
UserId int64
|
||||
|
||||
Name string
|
||||
RangesJSON []byte
|
||||
IsPublic bool
|
||||
CategoryId int64
|
||||
Priority int32
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
var routeId = int64(0)
|
||||
defer func() {
|
||||
this.CreateLogInfo(codes.NSRoute_LogCreateNSRoute, routeId)
|
||||
}()
|
||||
|
||||
params.Must.Field("name", params.Name).
|
||||
Require("请输入线路名称")
|
||||
|
||||
ranges, err := dnsconfigs.InitNSRangesFromJSON(params.RangesJSON)
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
}
|
||||
|
||||
if len(ranges) == 0 {
|
||||
this.Fail("请添加线路范围")
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().NSRouteRPC().CreateNSRoute(this.AdminContext(), &pb.CreateNSRouteRequest{
|
||||
NsClusterId: params.ClusterId,
|
||||
NsDomainId: params.DomainId,
|
||||
UserId: params.UserId,
|
||||
Name: params.Name,
|
||||
RangesJSON: params.RangesJSON,
|
||||
IsPublic: params.IsPublic,
|
||||
NsRouteCategoryId: params.CategoryId,
|
||||
Priority: params.Priority,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
routeId = createResp.NsRouteId
|
||||
|
||||
this.Success()
|
||||
}
|
||||
28
EdgeAdmin/internal/web/actions/default/ns/routes/delete.go
Normal file
28
EdgeAdmin/internal/web/actions/default/ns/routes/delete.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package routes
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
RouteId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSRoute_LogDeleteNSRoute, params.RouteId)
|
||||
|
||||
_, err := this.RPC().NSRouteRPC().DeleteNSRoute(this.AdminContext(), &pb.DeleteNSRouteRequest{NsRouteId: params.RouteId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package routes
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type ExportAgentIPsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *ExportAgentIPsAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *ExportAgentIPsAction) RunGet(params struct{}) {
|
||||
var lastId int64 = 0
|
||||
var agentIPMaps = []maps.Map{}
|
||||
for {
|
||||
resp, err := this.RPC().ClientAgentIPRPC().ListClientAgentIPsAfterId(this.AdminContext(), &pb.ListClientAgentIPsAfterIdRequest{
|
||||
Id: lastId,
|
||||
Size: 10000,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var agentIPs = resp.ClientAgentIPs
|
||||
if len(agentIPs) == 0 {
|
||||
break
|
||||
}
|
||||
for _, agentIP := range agentIPs {
|
||||
if lastId < agentIP.Id {
|
||||
lastId = agentIP.Id
|
||||
}
|
||||
if agentIP.ClientAgent == nil {
|
||||
continue
|
||||
}
|
||||
agentIPMaps = append(agentIPMaps, maps.Map{
|
||||
"ip": agentIP.Ip,
|
||||
"ptr": agentIP.Ptr,
|
||||
"agentCode": agentIP.ClientAgent.Code,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
agentIPsJSON, err := json.Marshal(agentIPMaps)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.AddHeader("Content-Disposition", "attachment; filename=\"AGENT-IP-LIST.json\";")
|
||||
this.AddHeader("Content-Length", strconv.Itoa(len(agentIPsJSON)))
|
||||
_, _ = this.Write(agentIPsJSON)
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package routes
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"net"
|
||||
)
|
||||
|
||||
type ImportAgentIPsPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *ImportAgentIPsPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *ImportAgentIPsPopupAction) RunGet(params struct {
|
||||
}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *ImportAgentIPsPopupAction) RunPost(params struct {
|
||||
File *actions.File
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
if params.File == nil {
|
||||
this.Fail("请选择要导入的文件")
|
||||
return
|
||||
}
|
||||
|
||||
data, err := params.File.Read()
|
||||
if err != nil {
|
||||
this.Fail("读文件失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var ipMaps = []maps.Map{}
|
||||
err = json.Unmarshal(data, &ipMaps)
|
||||
if err != nil {
|
||||
this.Fail("解析文件失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var pbIPs = []*pb.CreateClientAgentIPsRequest_AgentIPInfo{}
|
||||
for _, ipMap := range ipMaps {
|
||||
var ip = ipMap.GetString("ip")
|
||||
var ptr = ipMap.GetString("ptr")
|
||||
var agentCode = ipMap.GetString("agentCode")
|
||||
if len(ip) == 0 || len(agentCode) == 0 || net.ParseIP(ip) == nil {
|
||||
continue
|
||||
}
|
||||
pbIPs = append(pbIPs, &pb.CreateClientAgentIPsRequest_AgentIPInfo{
|
||||
AgentCode: agentCode,
|
||||
Ip: ip,
|
||||
Ptr: ptr,
|
||||
})
|
||||
}
|
||||
|
||||
if len(pbIPs) == 0 {
|
||||
this.Fail("文件中没有包含有效的数据")
|
||||
return
|
||||
}
|
||||
|
||||
var size = 10000
|
||||
for {
|
||||
var pbIPList []*pb.CreateClientAgentIPsRequest_AgentIPInfo
|
||||
var isEnd = false
|
||||
if len(pbIPs) > size {
|
||||
pbIPList = pbIPs[:size]
|
||||
pbIPs = pbIPs[size:]
|
||||
} else {
|
||||
pbIPList = pbIPs
|
||||
isEnd = true
|
||||
}
|
||||
|
||||
_, err = this.RPC().ClientAgentIPRPC().CreateClientAgentIPs(this.AdminContext(), &pb.CreateClientAgentIPsRequest{AgentIPs: pbIPList})
|
||||
if err != nil {
|
||||
this.Fail("导入失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if isEnd {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user