Initial commit (code only without large binaries)

This commit is contained in:
robin
2026-02-15 18:58:44 +08:00
commit 35df75498f
9442 changed files with 1495866 additions and 0 deletions

View File

@@ -0,0 +1,135 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package batch
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/types"
"strings"
)
type CreateRecordsAction struct {
actionutils.ParentAction
}
func (this *CreateRecordsAction) Init() {
this.Nav("", "", "batch")
this.SecondMenu("createRecords")
}
func (this *CreateRecordsAction) RunGet(params struct{}) {
// 类型
this.Data["types"] = dnsconfigs.FindAllUserRecordTypeDefinitions()
this.Show()
}
func (this *CreateRecordsAction) RunPost(params struct {
Names string
UserId int64
RecordsJSON []byte
RemoveOld bool
RemoveAll bool
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo(codes.NS_LogCreateNSRecordsBatch)
// 检查域名是否已经创建
var domainNames = []string{}
for _, domainName := range strings.Split(params.Names, "\n") {
domainName = strings.ToLower(strings.TrimSpace(domainName))
if len(domainName) == 0 {
continue
}
if !lists.ContainsString(domainNames, domainName) {
domainNames = append(domainNames, domainName)
}
}
if len(domainNames) == 0 {
this.FailField("names", "请输入域名")
}
duplicateResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.AdminContext(), &pb.ExistNSDomainsRequest{
Names: domainNames,
UserId: params.UserId,
})
if err != nil {
this.ErrorPage(err)
return
}
var existingDomainNames = duplicateResp.ExistingNames
var notExistingDomainNames = []string{}
for _, domainName := range domainNames {
if !lists.ContainsString(existingDomainNames, domainName) {
notExistingDomainNames = append(notExistingDomainNames, domainName)
}
}
if len(notExistingDomainNames) > 0 {
this.FailField("names", "有以下域名不存在:"+strings.Join(notExistingDomainNames, "")+"。请检查域名是否已删除或用户是否已选择正确。")
}
// 检查记录
type record struct {
Name string `json:"name"`
Type string `json:"type"`
Value string `json:"value"`
RouteCodes []string `json:"routeCodes"`
TTL any `json:"ttl"`
}
var records = []*record{}
err = json.Unmarshal(params.RecordsJSON, &records)
if err != nil {
this.Fail("记录参数格式错误:" + err.Error())
return
}
if len(records) == 0 {
this.Fail("请添加至少一个记录")
}
for _, record := range records {
message, ok := domainutils.ValidateRecordValue(record.Type, record.Value)
if !ok {
this.Fail("记录 '" + record.Name + "' 值校验失败:" + message)
}
// ttl
var recordInt = types.Int32(record.TTL)
if recordInt <= 0 {
recordInt = 600
}
record.TTL = recordInt
}
recordsJSON, err := json.Marshal(records)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().NSRecordRPC().CreateNSRecordsWithDomainNames(this.AdminContext(), &pb.CreateNSRecordsWithDomainNamesRequest{
NsDomainNames: domainNames,
RecordsJSON: recordsJSON,
RemoveOld: params.RemoveOld,
RemoveAll: params.RemoveAll,
UserId: params.UserId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,87 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package batch
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"strings"
)
type DeleteDomainsAction struct {
actionutils.ParentAction
}
func (this *DeleteDomainsAction) Init() {
this.Nav("", "", "batch")
this.SecondMenu("deleteDomains")
}
func (this *DeleteDomainsAction) RunGet(params struct{}) {
this.Show()
}
func (this *DeleteDomainsAction) RunPost(params struct {
Names string
UserId int64
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo(codes.NS_LogDeleteNSDomainsBatch, params.UserId)
if len(params.Names) == 0 {
this.FailField("names", "请输入要删除的域名")
}
var domainNames = []string{}
for _, name := range strings.Split(params.Names, "\n") {
name = strings.TrimSpace(name)
if len(name) == 0 {
continue
}
name = strings.ToLower(name)
domainNames = append(domainNames, name)
}
if len(domainNames) == 0 {
this.FailField("names", "请输入要删除的域名")
}
// 检查域名是否存在
duplicateResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.AdminContext(), &pb.ExistNSDomainsRequest{
Names: domainNames,
UserId: params.UserId,
})
if err != nil {
this.ErrorPage(err)
return
}
var existingDomainNames = duplicateResp.ExistingNames
var notExistingDomainNames = []string{}
for _, domainName := range domainNames {
if !lists.ContainsString(existingDomainNames, domainName) {
notExistingDomainNames = append(notExistingDomainNames, domainName)
}
}
if len(notExistingDomainNames) > 0 {
this.FailField("names", "有以下域名不存在:"+strings.Join(notExistingDomainNames, "")+"。请检查域名是否已删除或用户是否已选择正确。")
}
// 开始删除
_, err = this.RPC().NSDomainRPC().DeleteNSDomains(this.AdminContext(), &pb.DeleteNSDomainsRequest{
Names: domainNames,
UserId: params.UserId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,96 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package batch
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"strings"
)
type DeleteRecordsAction struct {
actionutils.ParentAction
}
func (this *DeleteRecordsAction) Init() {
this.Nav("", "", "batch")
this.SecondMenu("deleteRecords")
}
func (this *DeleteRecordsAction) RunGet(params struct{}) {
// 类型
this.Data["types"] = dnsconfigs.FindAllUserRecordTypeDefinitions()
this.Show()
}
func (this *DeleteRecordsAction) RunPost(params struct {
Names string
UserId int64
SearchName string
SearchValue string
SearchType string
SearchRouteCodes []string
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo(codes.NS_LogDeleteNSRecordsBatch)
// 检查域名是否已经创建
var domainNames = []string{}
for _, domainName := range strings.Split(params.Names, "\n") {
domainName = strings.ToLower(strings.TrimSpace(domainName))
if len(domainName) == 0 {
continue
}
if !lists.ContainsString(domainNames, domainName) {
domainNames = append(domainNames, domainName)
}
}
if len(domainNames) == 0 {
this.FailField("names", "请输入域名")
}
duplicateResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.AdminContext(), &pb.ExistNSDomainsRequest{
Names: domainNames,
UserId: params.UserId,
})
if err != nil {
this.ErrorPage(err)
return
}
var existingDomainNames = duplicateResp.ExistingNames
var notExistingDomainNames = []string{}
for _, domainName := range domainNames {
if !lists.ContainsString(existingDomainNames, domainName) {
notExistingDomainNames = append(notExistingDomainNames, domainName)
}
}
if len(notExistingDomainNames) > 0 {
this.FailField("names", "有以下域名不存在:"+strings.Join(notExistingDomainNames, "")+"。请检查域名是否已删除或用户是否已选择正确。")
}
_, err = this.RPC().NSRecordRPC().DeleteNSRecordsWithDomainNames(this.AdminContext(), &pb.DeleteNSRecordsWithDomainNamesRequest{
NsDomainNames: domainNames,
SearchName: params.SearchName,
SearchValue: params.SearchValue,
SearchType: params.SearchType,
SearchNSRouteCodes: params.SearchRouteCodes,
UserId: params.UserId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,103 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package batch
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"strings"
)
type EnableRecordsAction struct {
actionutils.ParentAction
}
func (this *EnableRecordsAction) Init() {
this.Nav("", "", "batch")
this.SecondMenu("enableRecords")
}
func (this *EnableRecordsAction) RunGet(params struct{}) {
// 类型
this.Data["types"] = dnsconfigs.FindAllUserRecordTypeDefinitions()
this.Show()
}
func (this *EnableRecordsAction) RunPost(params struct {
Names string
UserId int64
SearchName string
SearchValue string
SearchType string
SearchRouteCodes []string
IsOn bool
Must *actions.Must
CSRF *actionutils.CSRF
}) {
if params.IsOn {
defer this.CreateLogInfo(codes.NS_LogEnableNSRecordsBatch)
} else {
defer this.CreateLogInfo(codes.NS_LogDisableNSRecordsBatch)
}
// 检查域名是否已经创建
var domainNames = []string{}
for _, domainName := range strings.Split(params.Names, "\n") {
domainName = strings.ToLower(strings.TrimSpace(domainName))
if len(domainName) == 0 {
continue
}
if !lists.ContainsString(domainNames, domainName) {
domainNames = append(domainNames, domainName)
}
}
if len(domainNames) == 0 {
this.FailField("names", "请输入域名")
}
duplicateResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.AdminContext(), &pb.ExistNSDomainsRequest{
Names: domainNames,
UserId: params.UserId,
})
if err != nil {
this.ErrorPage(err)
return
}
var existingDomainNames = duplicateResp.ExistingNames
var notExistingDomainNames = []string{}
for _, domainName := range domainNames {
if !lists.ContainsString(existingDomainNames, domainName) {
notExistingDomainNames = append(notExistingDomainNames, domainName)
}
}
if len(notExistingDomainNames) > 0 {
this.FailField("names", "有以下域名不存在:"+strings.Join(notExistingDomainNames, "")+"。请检查域名是否已删除或用户是否已选择正确。")
}
_, err = this.RPC().NSRecordRPC().UpdateNSRecordsIsOnWithDomainNames(this.AdminContext(), &pb.UpdateNSRecordsIsOnWithDomainNamesRequest{
NsDomainNames: domainNames,
SearchName: params.SearchName,
SearchValue: params.SearchValue,
SearchType: params.SearchType,
SearchNSRouteCodes: params.SearchRouteCodes,
IsOn: params.IsOn,
UserId: params.UserId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,157 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package batch
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/types"
"regexp"
"strings"
)
type ImportRecordsAction struct {
actionutils.ParentAction
}
func (this *ImportRecordsAction) Init() {
this.Nav("", "", "batch")
this.SecondMenu("importRecords")
}
func (this *ImportRecordsAction) RunGet(params struct{}) {
// 类型
this.Data["types"] = dnsconfigs.FindAllUserRecordTypeDefinitions()
this.Show()
}
func (this *ImportRecordsAction) RunPost(params struct {
Records string
UserId int64
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo(codes.NS_LogImportRecordsBatch)
var allRecordTypes = []string{}
for _, t := range dnsconfigs.FindAllUserRecordTypeDefinitions() {
allRecordTypes = append(allRecordTypes, t.Type)
}
var pbRecords = []*pb.ImportNSRecordsRequest_Record{}
var reg = regexp.MustCompile(`\s+`)
var domainNames = []string{}
for _, line := range strings.Split(params.Records, "\n") {
line = strings.TrimSpace(line)
if len(line) == 0 {
continue
}
// 域名 记录名 记录类型 记录值 TTL
var pieces = reg.Split(line, -1)
if len(pieces) < 4 {
this.Fail("'" + line + "' 格式错误,缺少必需项")
}
var domainName = strings.ToLower(strings.TrimSpace(pieces[0]))
var recordName = strings.ToLower(strings.TrimSpace(pieces[1]))
var recordType = strings.ToUpper(pieces[2])
var recordValue = strings.TrimSpace(pieces[3])
var recordTTLString = ""
if len(pieces) > 4 {
recordTTLString = pieces[4]
}
// validate
if len(domainName) == 0 {
this.Fail("'" + line + "' 缺少域名")
}
if !domainutils.ValidateDomainFormat(domainName) {
this.Fail("'" + line + "' 域名格式错误")
}
if !lists.ContainsString(domainNames, domainName) {
domainNames = append(domainNames, domainName)
}
if len(recordName) > 0 && !domainutils.ValidateRecordName(recordName) {
this.Fail("'" + line + "' 记录名格式错误")
}
if len(recordType) == 0 {
this.Fail("'" + line + "' 缺少记录类型")
}
if !lists.ContainsString(allRecordTypes, recordType) {
this.Fail("'" + line + "' 不支持的记录类型 '" + recordType + "'")
}
message, ok := domainutils.ValidateRecordValue(recordType, recordValue)
if !ok {
this.Fail("'" + line + "' 记录值 '" + recordValue + "' 校验失败:" + message)
}
var recordTTL int32 = 600
if len(recordTTLString) > 0 {
if !regexp.MustCompile(`^\d+$`).MatchString(recordTTLString) {
this.Fail("'" + line + "' 错误的TTL '" + recordTTLString + "'")
}
recordTTL = types.Int32(recordTTLString)
if recordTTL > 10*365*86400 {
recordTTL = 10 * 365 * 86400
}
}
pbRecords = append(pbRecords, &pb.ImportNSRecordsRequest_Record{
NsDomainName: domainName,
Name: recordName,
Type: recordType,
Value: recordValue,
Ttl: recordTTL,
})
}
if len(pbRecords) == 0 {
this.FailField("records", "请输入要导入的记录")
}
// 检查域名是否存在
duplicateResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.AdminContext(), &pb.ExistNSDomainsRequest{
Names: domainNames,
UserId: params.UserId,
})
if err != nil {
this.ErrorPage(err)
return
}
var existingDomainNames = duplicateResp.ExistingNames
var notExistingDomainNames = []string{}
for _, domainName := range domainNames {
if !lists.ContainsString(existingDomainNames, domainName) {
notExistingDomainNames = append(notExistingDomainNames, domainName)
}
}
if len(notExistingDomainNames) > 0 {
this.FailField("names", "有以下域名不存在:"+strings.Join(notExistingDomainNames, "")+"。请检查域名是否已删除或用户是否已选择正确。")
}
_, err = this.RPC().NSRecordRPC().ImportNSRecords(this.AdminContext(), &pb.ImportNSRecordsRequest{
NsRecords: pbRecords,
UserId: params.UserId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,97 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package batch
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"strings"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "batch")
this.SecondMenu("index")
}
func (this *IndexAction) RunGet(params struct{}) {
this.Show()
}
func (this *IndexAction) RunPost(params struct {
Names string // 如果批量的话
ClusterId int64
UserId int64
GroupId int64
Must *actions.Must
CSRF *actionutils.CSRF
}) {
var groupIds = []int64{}
if params.GroupId > 0 {
groupIds = append(groupIds, params.GroupId)
}
defer this.CreateLogInfo(codes.NS_LogCreateNSDomainsBatch)
params.Must.
Field("names", params.Names).
Require("请输入域名").
Field("clusterId", params.ClusterId).
Gt(0, "请选择所属集群")
var names = []string{}
for _, name := range strings.Split(params.Names, "\n") {
name = strings.TrimSpace(name)
if len(name) == 0 {
continue
}
if !domainutils.ValidateDomainFormat(name) {
this.Fail("域名 '" + name + "' 格式不正确")
}
if !lists.ContainsString(names, name) {
names = append(names, name)
}
}
if len(names) == 0 {
this.FailField("names", "请输入域名")
return
}
// 检查域名是否已经存在
existResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.AdminContext(), &pb.ExistNSDomainsRequest{
Names: names,
UserId: params.UserId,
})
if err != nil {
this.ErrorPage(err)
return
}
if len(existResp.ExistingNames) > 0 {
this.Fail("域名 " + strings.Join(existResp.ExistingNames, ", ") + " 已经存在,无法重复添加")
return
}
_, err = this.RPC().NSDomainRPC().CreateNSDomains(this.AdminContext(), &pb.CreateNSDomainsRequest{
NsClusterId: params.ClusterId,
UserId: params.UserId,
Names: names,
NsDomainGroupIds: groupIds,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,113 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package batch
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"strings"
)
type UpdateRecordsAction struct {
actionutils.ParentAction
}
func (this *UpdateRecordsAction) Init() {
this.Nav("", "", "batch")
this.SecondMenu("updateRecords")
}
func (this *UpdateRecordsAction) RunGet(params struct{}) {
// 类型
this.Data["types"] = dnsconfigs.FindAllUserRecordTypeDefinitions()
this.Show()
}
func (this *UpdateRecordsAction) RunPost(params struct {
Names string
UserId int64
SearchName string
SearchValue string
SearchType string
SearchRouteCodes []string
NewName string
NewValue string
NewType string
NewRouteCodes []string
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo(codes.NS_LogUpdateNSRecordsBatch)
// 检查域名是否已经创建
var domainNames = []string{}
for _, domainName := range strings.Split(params.Names, "\n") {
domainName = strings.ToLower(strings.TrimSpace(domainName))
if len(domainName) == 0 {
continue
}
if !lists.ContainsString(domainNames, domainName) {
domainNames = append(domainNames, domainName)
}
}
if len(domainNames) == 0 {
this.FailField("names", "请输入域名")
}
duplicateResp, err := this.RPC().NSDomainRPC().ExistNSDomains(this.AdminContext(), &pb.ExistNSDomainsRequest{
Names: domainNames,
UserId: params.UserId,
})
if err != nil {
this.ErrorPage(err)
return
}
var existingDomainNames = duplicateResp.ExistingNames
var notExistingDomainNames = []string{}
for _, domainName := range domainNames {
if !lists.ContainsString(existingDomainNames, domainName) {
notExistingDomainNames = append(notExistingDomainNames, domainName)
}
}
if len(notExistingDomainNames) > 0 {
this.FailField("names", "有以下域名不存在:"+strings.Join(notExistingDomainNames, "")+"。请检查域名是否已删除或用户是否已选择正确。")
}
if len(params.NewValue) > 0 {
message, ok := domainutils.ValidateRecordValue(params.NewType, params.NewValue)
if !ok {
this.Fail("新的记录值 '" + params.NewValue + "' 填写错误:" + message)
}
}
_, err = this.RPC().NSRecordRPC().UpdateNSRecordsWithDomainNames(this.AdminContext(), &pb.UpdateNSRecordsWithDomainNamesRequest{
NsDomainNames: domainNames,
SearchName: params.SearchName,
SearchValue: params.SearchValue,
SearchType: params.SearchType,
SearchNSRouteCodes: params.SearchRouteCodes,
NewName: params.NewName,
NewValue: params.NewValue,
NewType: params.NewType,
NewNSRouteCodes: params.NewRouteCodes,
UserId: params.UserId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}