This commit is contained in:
unknown
2026-02-04 20:27:13 +08:00
commit 3b042d1dad
9410 changed files with 1488147 additions and 0 deletions

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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()
}

View 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()
}

View File

@@ -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()
}

View 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()
}
}

View 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()
}

View File

@@ -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()
}

View File

@@ -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))
}

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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
}

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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()
}

View 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()
}

View 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()
}

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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()
}
}

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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()
}

View 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()
}

View 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()
}

View File

@@ -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()
}