Initial commit (code only without large binaries)
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package batch
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/ns/nsutils"
|
||||
"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()
|
||||
|
||||
defaultTTL, err := nsutils.FindDefaultTTL(this.UserContext())
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["defaultTTL"] = defaultTTL
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreateRecordsAction) RunPost(params struct {
|
||||
Names string
|
||||
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.UserContext(), &pb.ExistNSDomainsRequest{
|
||||
Names: domainNames,
|
||||
})
|
||||
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("请添加至少一个记录")
|
||||
}
|
||||
|
||||
var recordCountsMap = map[string]int32{} // record name_type = count
|
||||
for _, record := range records {
|
||||
recordCountsMap[record.Name+"_____"+record.Type]++
|
||||
}
|
||||
|
||||
// 检查限额
|
||||
for _, domainName := range domainNames {
|
||||
domainResp, err := this.RPC().NSDomainRPC().FindNSDomainWithName(this.UserContext(), &pb.FindNSDomainWithNameRequest{Name: domainName})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if domainResp.NsDomain == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
_, canCreate, err := nsutils.CheckRecordsQuota(this.UserContext(), domainResp.NsDomain.Id, int32(len(records)))
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !canCreate {
|
||||
this.Fail("域名 '" + domainName + "' 记录数已超出限额,请购买套餐后重试")
|
||||
}
|
||||
|
||||
// 检查负载均衡限额
|
||||
if !params.RemoveOld && !params.RemoveAll {
|
||||
for recordString, recordCount := range recordCountsMap {
|
||||
var recordPieces = strings.Split(recordString, "_____")
|
||||
var recordName = recordPieces[0]
|
||||
var recordType = recordPieces[1]
|
||||
|
||||
_, canCreate, err = nsutils.CheckLoadBalanceRecordsQuota(this.UserContext(), domainResp.NsDomain.Id, recordName, recordType, recordCount)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !canCreate {
|
||||
this.Fail("域名 '" + domainName + "' 记录 '" + recordName + "' 负载均衡数已超出限额,请购买套餐后重试")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 最小TTL
|
||||
minTTL, err := nsutils.FindMinTTL(this.UserContext())
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// 检查最小TTL
|
||||
if recordInt < minTTL {
|
||||
this.Fail("TTL不能小于" + types.String(minTTL) + "秒")
|
||||
}
|
||||
}
|
||||
recordsJSON, err := json.Marshal(records)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSRecordRPC().CreateNSRecordsWithDomainNames(this.UserContext(), &pb.CreateNSRecordsWithDomainNamesRequest{
|
||||
NsDomainNames: domainNames,
|
||||
RecordsJSON: recordsJSON,
|
||||
RemoveOld: params.RemoveOld,
|
||||
RemoveAll: params.RemoveAll,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package batch
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"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
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NS_LogDeleteNSDomainsBatch, this.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.UserContext(), &pb.ExistNSDomainsRequest{
|
||||
Names: domainNames,
|
||||
})
|
||||
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.UserContext(), &pb.DeleteNSDomainsRequest{
|
||||
Names: domainNames,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package batch
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"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
|
||||
|
||||
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.UserContext(), &pb.ExistNSDomainsRequest{
|
||||
Names: domainNames,
|
||||
})
|
||||
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.UserContext(), &pb.DeleteNSRecordsWithDomainNamesRequest{
|
||||
NsDomainNames: domainNames,
|
||||
SearchName: params.SearchName,
|
||||
SearchValue: params.SearchValue,
|
||||
SearchType: params.SearchType,
|
||||
SearchNSRouteCodes: params.SearchRouteCodes,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package batch
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"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
|
||||
|
||||
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.UserContext(), &pb.ExistNSDomainsRequest{
|
||||
Names: domainNames,
|
||||
})
|
||||
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.UserContext(), &pb.UpdateNSRecordsIsOnWithDomainNamesRequest{
|
||||
NsDomainNames: domainNames,
|
||||
SearchName: params.SearchName,
|
||||
SearchValue: params.SearchValue,
|
||||
SearchType: params.SearchType,
|
||||
SearchNSRouteCodes: params.SearchRouteCodes,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package batch
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/ns/nsutils"
|
||||
"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
|
||||
|
||||
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{}
|
||||
|
||||
minTTL, err := nsutils.FindMinTTL(this.UserContext())
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if recordTTL < minTTL {
|
||||
this.Fail("TTL不能小于" + types.String(minTTL) + "秒")
|
||||
}
|
||||
}
|
||||
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.UserContext(), &pb.ExistNSDomainsRequest{
|
||||
Names: domainNames,
|
||||
})
|
||||
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, ",")+"。请检查域名是否已删除或用户是否已选择正确。")
|
||||
}
|
||||
|
||||
// 检查限额
|
||||
for _, domainName := range domainNames {
|
||||
domainResp, err := this.RPC().NSDomainRPC().FindNSDomainWithName(this.UserContext(), &pb.FindNSDomainWithNameRequest{Name: domainName})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if domainResp.NsDomain == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var countRecords int32 = 0
|
||||
for _, record := range pbRecords {
|
||||
if record.NsDomainName == domainName {
|
||||
countRecords++
|
||||
}
|
||||
}
|
||||
if countRecords == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
_, canCreate, err := nsutils.CheckRecordsQuota(this.UserContext(), domainResp.NsDomain.Id, countRecords)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !canCreate {
|
||||
this.Fail("域名 '" + domainName + "' 记录数已超出限额,请购买套餐后重试")
|
||||
}
|
||||
|
||||
// 检查负载均衡限额
|
||||
var recordCountsMap = map[string]int32{} // record name_type = count
|
||||
for _, record := range pbRecords {
|
||||
if record.NsDomainName == domainName {
|
||||
recordCountsMap[record.Name+"_____"+record.Type]++
|
||||
}
|
||||
}
|
||||
|
||||
for recordString, recordCount := range recordCountsMap {
|
||||
var recordPieces = strings.Split(recordString, "_____")
|
||||
var recordName = recordPieces[0]
|
||||
var recordType = recordPieces[1]
|
||||
|
||||
_, canCreate, err = nsutils.CheckLoadBalanceRecordsQuota(this.UserContext(), domainResp.NsDomain.Id, recordName, recordType, recordCount)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !canCreate {
|
||||
this.Fail("域名 '" + domainName + "' 记录 '" + recordName + "' 负载均衡数已超出限额,请购买套餐后重试")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSRecordRPC().ImportNSRecords(this.UserContext(), &pb.ImportNSRecordsRequest{
|
||||
NsRecords: pbRecords,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
102
EdgeUser/internal/web/actions/default/ns/domains/batch/index.go
Normal file
102
EdgeUser/internal/web/actions/default/ns/domains/batch/index.go
Normal file
@@ -0,0 +1,102 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package batch
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/ns/nsutils"
|
||||
"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 // 如果批量的话
|
||||
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_LogCreateNSRecordsBatch)
|
||||
|
||||
params.Must.
|
||||
Field("names", params.Names).
|
||||
Require("请输入域名")
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// 检查限额
|
||||
_, canCreate, err := nsutils.CheckDomainsQuote(this.UserContext(), int32(len(names)))
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !canCreate {
|
||||
this.Fail("域名数已超出限额,请购买套餐后重试")
|
||||
}
|
||||
|
||||
// 检查域名是否已经存在
|
||||
{
|
||||
existResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.UserContext(), &pb.ExistNSDomainsRequest{
|
||||
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.UserContext(), &pb.CreateNSDomainsRequest{
|
||||
Names: names,
|
||||
NsDomainGroupIds: groupIds,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package batch
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/dns/domains/domainutils"
|
||||
"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
|
||||
|
||||
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.UserContext(), &pb.ExistNSDomainsRequest{
|
||||
Names: domainNames,
|
||||
})
|
||||
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.UserContext(), &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,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
187
EdgeUser/internal/web/actions/default/ns/domains/create.go
Normal file
187
EdgeUser/internal/web/actions/default/ns/domains/create.go
Normal file
@@ -0,0 +1,187 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package domains
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"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/systemconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/ns/nsutils"
|
||||
"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{}) {
|
||||
userConfigResp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.UserContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeNSUserConfig})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["configIsValid"] = false
|
||||
if len(userConfigResp.ValueJSON) > 0 {
|
||||
var config = &dnsconfigs.NSUserConfig{}
|
||||
err = json.Unmarshal(userConfigResp.ValueJSON, config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if config.DefaultClusterId > 0 {
|
||||
this.Data["configIsValid"] = true
|
||||
}
|
||||
}
|
||||
|
||||
// 套餐限制
|
||||
maxDomains, canCreate, err := nsutils.CheckDomainsQuote(this.UserContext(), 1)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["quotaMaxDomains"] = maxDomains
|
||||
this.Data["quotaCanCreate"] = canCreate
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreateAction) RunPost(params struct {
|
||||
AddingType string
|
||||
|
||||
Name string
|
||||
Names string // 如果批量的话
|
||||
UserId int64
|
||||
GroupId int64
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
// 检查套餐限制
|
||||
_, canCreate, err := nsutils.CheckDomainsQuote(this.UserContext(), 1)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !canCreate {
|
||||
this.Fail("域名个数已超出最大限额")
|
||||
}
|
||||
|
||||
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("请输入域名")
|
||||
|
||||
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.UserContext(), &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.UserContext(), &pb.CreateNSDomainsRequest{
|
||||
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
|
||||
})
|
||||
|
||||
// 检查域名是否已经存在
|
||||
{
|
||||
existResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.UserContext(), &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
|
||||
}
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().NSDomainRPC().CreateNSDomain(this.UserContext(), &pb.CreateNSDomainRequest{
|
||||
UserId: params.UserId,
|
||||
Name: params.Name,
|
||||
NsDomainGroupIds: groupIds,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
domainId = createResp.NsDomainId
|
||||
|
||||
this.Success()
|
||||
}
|
||||
}
|
||||
27
EdgeUser/internal/web/actions/default/ns/domains/delete.go
Normal file
27
EdgeUser/internal/web/actions/default/ns/domains/delete.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package domains
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
DomainId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSDomain_LogDeleteNSDomain, params.DomainId)
|
||||
|
||||
_, err := this.RPC().NSDomainRPC().DeleteNSDomain(this.UserContext(), &pb.DeleteNSDomainRequest{NsDomainId: params.DomainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package domains
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type DeletePageAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeletePageAction) RunPost(params struct {
|
||||
DomainIds []int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NS_LogDeleteNSDomainsBatch, this.UserId())
|
||||
|
||||
if len(params.DomainIds) == 0 {
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
|
||||
for _, domainId := range params.DomainIds {
|
||||
_, err := this.RPC().NSDomainRPC().DeleteNSDomain(this.UserContext(), &pb.DeleteNSDomainRequest{
|
||||
NsDomainId: domainId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package domain
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
DomainId int64
|
||||
}) {
|
||||
this.RedirectURL("/ns/domains/records?domainId=" + types.String(params.DomainId))
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package domain
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"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.UserContext(), &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.UserContext(), &pb.UpdateNSDomainStatusRequest{
|
||||
NsDomainId: params.DomainId,
|
||||
Status: params.Status,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package domain
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/ns/domains/domainutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type VerifyPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *VerifyPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *VerifyPopupAction) RunGet(params struct {
|
||||
DomainId int64
|
||||
}) {
|
||||
domainResp, err := this.RPC().NSDomainRPC().FindNSDomain(this.UserContext(), &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,
|
||||
}
|
||||
|
||||
// 当前用户可以使用的DNS Hosts
|
||||
if domain.NsCluster == nil || domain.NsCluster.Id <= 0 {
|
||||
this.WriteString("当前域名(" + domain.Name + ")所在集群已被删除,请删除当前域名后重新添加")
|
||||
return
|
||||
}
|
||||
|
||||
var hosts []string
|
||||
hostsResp, err := this.RPC().NSClusterRPC().FindNSClusterHosts(this.UserContext(), &pb.FindNSClusterHostsRequest{
|
||||
NsClusterId: domain.NsCluster.Id,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
hosts = hostsResp.Hosts
|
||||
|
||||
if hosts == nil {
|
||||
hosts = []string{}
|
||||
}
|
||||
this.Data["hosts"] = hosts
|
||||
|
||||
// TXT记录
|
||||
txtResp, err := this.RPC().NSDomainRPC().FindNSDomainVerifyingInfo(this.UserContext(), &pb.FindNSDomainVerifyingInfoRequest{NsDomainId: params.DomainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["requireTXT"] = txtResp.RequireTXT
|
||||
this.Data["txt"] = txtResp.Txt
|
||||
this.Data["txtExpiresTime"] = timeutil.FormatTime("Y-m-d H:i:s", txtResp.ExpiresAt)
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *VerifyPopupAction) RunPost(params struct {
|
||||
DomainId int64
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
domainResp, err := this.RPC().NSDomainRPC().FindNSDomain(this.UserContext(), &pb.FindNSDomainRequest{NsDomainId: params.DomainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["isOk"] = false
|
||||
this.Data["message"] = ""
|
||||
this.Data["rawErrorMessage"] = ""
|
||||
|
||||
var domain = domainResp.NsDomain
|
||||
if domain == nil {
|
||||
this.NotFound("nsDomain", params.DomainId)
|
||||
return
|
||||
}
|
||||
|
||||
if domain.Status == dnsconfigs.NSDomainStatusVerified {
|
||||
this.Data["message"] = "已验证"
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
|
||||
if domain.Status != dnsconfigs.NSDomainStatusNone {
|
||||
this.Data["message"] = "当前状态为:" + dnsconfigs.NSDomainStatusName(domain.Status) + ",不允许验证"
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
|
||||
// 提交验证
|
||||
verifyResp, err := this.RPC().NSDomainRPC().VerifyNSDomain(this.UserContext(), &pb.VerifyNSDomainRequest{NsDomainId: params.DomainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !verifyResp.IsOk {
|
||||
var message = domainutils.VerifyMessageWithCode(verifyResp.ErrorCode)
|
||||
if len(verifyResp.CurrentTXTValues) > 0 {
|
||||
message += ",当前TXT解析结果为:" + strings.Join(verifyResp.CurrentTXTValues, ", ")
|
||||
} else if len(verifyResp.CurrentNSValues) > 0 {
|
||||
message += ",当前NS解析结果为:" + strings.Join(verifyResp.CurrentNSValues, ", ")
|
||||
}
|
||||
message += "。"
|
||||
|
||||
this.Data["message"] = message
|
||||
this.Data["rawErrorMessage"] = verifyResp.ErrorMessage
|
||||
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["isOk"] = true
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package domainutils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/rpc"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"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.UserContext(), &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.UserContext(), &pb.CountAllNSRecordsRequest{
|
||||
NsDomainId: domainId,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var countRecords = countRecordsResp.Count
|
||||
|
||||
// Key数量
|
||||
countKeysResp, err := rpcClient.NSKeyRPC().CountAllNSKeys(parent.UserContext(), &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
|
||||
}
|
||||
|
||||
// VerifyMessageWithCode 通过代号获取验证消息
|
||||
func VerifyMessageWithCode(code string) string {
|
||||
var message = ""
|
||||
switch code {
|
||||
case "DomainNotFound":
|
||||
message = "无法找到域名"
|
||||
case "InvalidStatus":
|
||||
message = "在当前域名状态下无法提交验证"
|
||||
case "InvalidDNSHosts":
|
||||
message = "没有设置正确的DNS主机地址或者NS记录尚未生效"
|
||||
case "TXTNotFound":
|
||||
message = "没有找到TXT记录或者TXT记录尚未生效"
|
||||
case "InvalidTXT":
|
||||
message = "没有设置正确的TXT记录或者TXT记录尚未生效"
|
||||
case "TXTExpired":
|
||||
message = "验证信息已失效,请刷新后重试"
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
// 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,51 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package groups
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"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.UserContext(), &pb.CreateNSDomainGroupRequest{
|
||||
Name: params.Name,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
groupId = createResp.NsDomainGroupId
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package group
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
GroupId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSDomainGroup_LogDeleteNSDomainGroup, params.GroupId)
|
||||
|
||||
_, err := this.RPC().NSDomainGroupRPC().DeleteNSDomainGroup(this.UserContext(), &pb.DeleteNSDomainGroupRequest{NsDomainGroupId: params.GroupId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package group
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"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.UserContext(), &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,69 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package group
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"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.UserContext(), &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.UserContext(), &pb.UpdateNSDomainGroupRequest{
|
||||
NsDomainGroupId: params.GroupId,
|
||||
Name: params.Name,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package groups
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"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.UserContext(), &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,35 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package groups
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"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.UserContext(), &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
EdgeUser/internal/web/actions/default/ns/domains/healthCheck.go
Normal file
103
EdgeUser/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/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/ns/domains/domainutils"
|
||||
"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.UserContext(), params.DomainId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["canUpdate"] = canUpdate
|
||||
|
||||
// 健康检查配置
|
||||
healthCheckResp, err := this.RPC().NSDomainRPC().FindNSDomainRecordsHealthCheck(this.UserContext(), &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.UserContext(), 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.UserContext(), &pb.UpdateNSDomainRecordsHealthCheckRequest{
|
||||
NsDomainId: params.DomainId,
|
||||
NsDomainRecordsHealthCheckJSON: params.RecordsHealthCheckJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
72
EdgeUser/internal/web/actions/default/ns/domains/index.go
Normal file
72
EdgeUser/internal/web/actions/default/ns/domains/index.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package domains
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
GroupId int64
|
||||
Keyword string
|
||||
}) {
|
||||
this.Data["groupId"] = params.GroupId
|
||||
this.Data["keyword"] = params.Keyword
|
||||
|
||||
// 分页
|
||||
countResp, err := this.RPC().NSDomainRPC().CountAllNSDomains(this.UserContext(), &pb.CountAllNSDomainsRequest{
|
||||
NsDomainGroupId: params.GroupId,
|
||||
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.UserContext(), &pb.ListNSDomainsRequest{
|
||||
Keyword: params.Keyword,
|
||||
NsDomainGroupId: params.GroupId,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var domainMaps = []maps.Map{}
|
||||
for _, domain := range domainsResp.NsDomains {
|
||||
// 分组信息
|
||||
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,
|
||||
"groups": groupMaps,
|
||||
})
|
||||
}
|
||||
this.Data["domains"] = domainMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package keys
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"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.UserContext(), &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,27 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package keys
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
KeyId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSKey_LogDeleteNSKey, params.KeyId)
|
||||
|
||||
_, err := this.RPC().NSKeyRPC().DeleteNSKey(this.UserContext(), &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/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"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,68 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package keys
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/ns/domains/domainutils"
|
||||
"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.UserContext(), &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.UserContext(), &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,101 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package keys
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"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.UserContext(), &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.UserContext(), &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,246 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package records
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/ns/nsutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"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.UserContext(), &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()
|
||||
|
||||
// 检查限额
|
||||
maxRecords, canCreate, err := nsutils.CheckRecordsQuota(this.UserContext(), params.DomainId, 1)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["quotaMaxRecords"] = maxRecords
|
||||
this.Data["quotaCanCreate"] = canCreate
|
||||
|
||||
defaultTTL, err := nsutils.FindDefaultTTL(this.UserContext())
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["defaultTTL"] = defaultTTL
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
AddingType string
|
||||
|
||||
DomainId int64
|
||||
|
||||
Name string
|
||||
Names string
|
||||
|
||||
Type string
|
||||
Value string
|
||||
|
||||
MxPriority int32
|
||||
|
||||
SrvPriority int32
|
||||
SrvWeight int32
|
||||
SrvPort int32
|
||||
|
||||
CaaFlag int32
|
||||
CaaTag string
|
||||
|
||||
Ttl int32
|
||||
Description string
|
||||
RouteCodes []string
|
||||
Weight int32
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
// 检查限额
|
||||
maxRecords, canCreate, err := nsutils.CheckRecordsQuota(this.UserContext(), params.DomainId, 1)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !canCreate {
|
||||
this.Fail("当前域名记录数已超出最大限额(" + types.String(maxRecords) + "个)")
|
||||
}
|
||||
|
||||
maxLoadBalanceRecords, canCreate, err := nsutils.CheckLoadBalanceRecordsQuota(this.UserContext(), params.DomainId, params.Name, params.Type, 1)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !canCreate {
|
||||
this.Fail("当前记录 '" + params.Name + "' 负载均衡数已超出最大限额(" + types.String(maxLoadBalanceRecords) + "个)")
|
||||
}
|
||||
|
||||
domainResp, err := this.RPC().NSDomainRPC().FindNSDomain(this.UserContext(), &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.NSRecord_LogCreateNSRecordsBatch)
|
||||
|
||||
if len(params.Names) == 0 {
|
||||
this.FailField("names", "请输入记录名")
|
||||
}
|
||||
|
||||
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
|
||||
minTTL, err := nsutils.FindMinTTL(this.UserContext())
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if params.Ttl < minTTL {
|
||||
this.Fail("TTL不能小于" + types.String(minTTL) + "秒")
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSRecordRPC().CreateNSRecords(this.UserContext(), &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)
|
||||
}
|
||||
|
||||
// 检查TTL
|
||||
minTTL, err := nsutils.FindMinTTL(this.UserContext())
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if params.Ttl < minTTL {
|
||||
this.Fail("TTL不能小于" + types.String(minTTL) + "秒")
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().NSRecordRPC().CreateNSRecord(this.UserContext(), &pb.CreateNSRecordRequest{
|
||||
NsDomainId: params.DomainId,
|
||||
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,
|
||||
NsRouteCodes: params.RouteCodes,
|
||||
Weight: params.Weight,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
recordId = createResp.NsRecordId
|
||||
|
||||
this.Success()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package records
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
RecordId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSRecord_LogDeleteNSRecord, params.RecordId)
|
||||
|
||||
_, err := this.RPC().NSRecordRPC().DeleteNSRecord(this.UserContext(), &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/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/ns/domains/domainutils"
|
||||
"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.UserContext(), &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.UserContext(), &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.UserContext(), 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.UserContext(), &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.UserContext(), 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.UserContext(), &pb.UpdateNSRecordHealthCheckRequest{
|
||||
NsRecordId: params.RecordId,
|
||||
NsRecordHealthCheckJSON: params.RecordHealthCheckJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package records
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/ns/domains/domainutils"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
this.Data["type"] = params.Type
|
||||
this.Data["keyword"] = params.Keyword
|
||||
this.Data["routeCode"] = params.RouteCode
|
||||
|
||||
// 域名的健康检查
|
||||
domainHealthCheckIsEnabled, err := domainutils.CheckHealthCheckPermission(this.RPC(), this.UserContext(), params.DomainId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var domainHealthCheckIsOn = false
|
||||
if domainHealthCheckIsEnabled {
|
||||
domainHealthCheckResp, err := this.RPC().NSDomainRPC().FindNSDomainRecordsHealthCheck(this.UserContext(), &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.UserContext(), &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.UserContext(), &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.UserContext(), &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,
|
||||
"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,60 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package records
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"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.UserContext(), &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.UserContext(), &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,187 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package records
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/ns/nsutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
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.UserContext(), &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.UserContext(), &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()
|
||||
|
||||
// TTL
|
||||
defaultTTL, err := nsutils.FindDefaultTTL(this.UserContext())
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["defaultTTL"] = defaultTTL
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
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_LogUpdateNSRecordHealthCheck, params.RecordId)
|
||||
|
||||
// 校验记录名
|
||||
if !domainutils.ValidateRecordName(params.Name) {
|
||||
this.FailField("name", "请输入正确的记录名")
|
||||
}
|
||||
|
||||
// 名称是否有改变
|
||||
recordResp, err := this.RPC().NSRecordRPC().FindNSRecord(this.UserContext(), &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
|
||||
}
|
||||
if record.Name != params.Name {
|
||||
// 检查限额
|
||||
maxLoadBalanceRecords, canCreate, err := nsutils.CheckLoadBalanceRecordsQuota(this.UserContext(), record.NsDomain.Id, params.Name, params.Type, 1)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !canCreate {
|
||||
this.Fail("当前记录 '" + params.Name + "' 负载均衡数已超出最大限额(" + types.String(maxLoadBalanceRecords) + "个)")
|
||||
}
|
||||
}
|
||||
|
||||
// 校验记录值
|
||||
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
|
||||
minTTL, err := nsutils.FindMinTTL(this.UserContext())
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if params.Ttl < minTTL {
|
||||
this.Fail("TTL不能小于" + types.String(minTTL) + "秒")
|
||||
}
|
||||
|
||||
_, err = this.RPC().NSRecordRPC().UpdateNSRecord(this.UserContext(), &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()
|
||||
}
|
||||
@@ -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/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
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.UserContext(), &pb.UpdateNSRecordIsUpRequest{
|
||||
NsRecordId: params.RecordId,
|
||||
IsUp: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
81
EdgeUser/internal/web/actions/default/ns/domains/tsig.go
Normal file
81
EdgeUser/internal/web/actions/default/ns/domains/tsig.go
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package domains
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/ns/domains/domainutils"
|
||||
"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.UserContext(), &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.UserContext(), &pb.UpdateNSDomainTSIGRequest{
|
||||
NsDomainId: params.DomainId,
|
||||
TsigJSON: tsigJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Success()
|
||||
}
|
||||
122
EdgeUser/internal/web/actions/default/ns/domains/update.go
Normal file
122
EdgeUser/internal/web/actions/default/ns/domains/update.go
Normal file
@@ -0,0 +1,122 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package domains
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/ns/domains/domainutils"
|
||||
"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.UserContext(), &pb.FindNSDomainRequest{NsDomainId: params.DomainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
this.Data["domain"] = maps.Map{
|
||||
"id": domain.Id,
|
||||
"name": domain.Name,
|
||||
"isOn": domain.IsOn,
|
||||
"clusterId": clusterId,
|
||||
"userId": userId,
|
||||
"countRecords": countRecords,
|
||||
"countKeys": countKeys,
|
||||
"groupId": groupId,
|
||||
}
|
||||
|
||||
// DNS服务器
|
||||
if domain.NsCluster == nil || domain.NsCluster.Id <= 0 {
|
||||
this.WriteString("当前域名(" + domain.Name + ")所在集群已被删除,请删除当前域名后重新添加")
|
||||
return
|
||||
}
|
||||
|
||||
hostsResp, err := this.RPC().NSClusterRPC().FindNSClusterHosts(this.UserContext(), &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
|
||||
GroupId int64
|
||||
IsOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSDomain_LogUpdateNSDomain, params.DomainId)
|
||||
|
||||
var groupIds = []int64{}
|
||||
if params.GroupId > 0 {
|
||||
groupIds = append(groupIds, params.GroupId)
|
||||
}
|
||||
|
||||
_, err := this.RPC().NSDomainRPC().UpdateNSDomain(this.UserContext(), &pb.UpdateNSDomainRequest{
|
||||
NsDomainId: params.DomainId,
|
||||
NsDomainGroupIds: groupIds,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package domains
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/ns/domains/domainutils"
|
||||
)
|
||||
|
||||
type VerifyPageAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *VerifyPageAction) RunPost(params struct {
|
||||
DomainIds []int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NSDomain_LogValidateNSDomains)
|
||||
|
||||
if len(params.DomainIds) == 0 {
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
|
||||
for _, domainId := range params.DomainIds {
|
||||
// 检查域名信息
|
||||
domainResp, err := this.RPC().NSDomainRPC().FindNSDomain(this.UserContext(), &pb.FindNSDomainRequest{NsDomainId: domainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var domain = domainResp.NsDomain
|
||||
if domain == nil || domain.Status != dnsconfigs.NSDomainStatusNone {
|
||||
continue
|
||||
}
|
||||
|
||||
verifyResp, err := this.RPC().NSDomainRPC().VerifyNSDomain(this.UserContext(), &pb.VerifyNSDomainRequest{NsDomainId: domainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !verifyResp.IsOk {
|
||||
var message = domainutils.VerifyMessageWithCode(verifyResp.ErrorCode)
|
||||
if len(message) > 0 {
|
||||
this.Fail("域名 '" + domain.Name + "' 验证失败:" + message)
|
||||
return
|
||||
}
|
||||
this.Fail("域名 '" + domain.Name + "' 验证失败")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
Reference in New Issue
Block a user