mirror of
				https://github.com/TeaOSLab/EdgeAdmin.git
				synced 2025-11-04 05:00:25 +08:00 
			
		
		
		
	DNS服务支持密钥管理/“域名服务”改为“自建DNS”
This commit is contained in:
		@@ -15,7 +15,7 @@ func main() {
 | 
			
		||||
	app := apps.NewAppCmd().
 | 
			
		||||
		Version(teaconst.Version).
 | 
			
		||||
		Product(teaconst.ProductName).
 | 
			
		||||
		Usage(teaconst.ProcessName+" [-v|start|stop|restart|service|daemon|reset|recover]").
 | 
			
		||||
		Usage(teaconst.ProcessName+" [-v|start|stop|restart|service|daemon|reset|recover|demo]").
 | 
			
		||||
		Option("-h", "show this help").
 | 
			
		||||
		Option("-v", "show version").
 | 
			
		||||
		Option("start", "start the service").
 | 
			
		||||
 
 | 
			
		||||
@@ -182,7 +182,7 @@ func AllModuleMaps() []maps.Map {
 | 
			
		||||
	}
 | 
			
		||||
	if teaconst.IsPlus {
 | 
			
		||||
		m = append(m, maps.Map{
 | 
			
		||||
			"name": "域名服务",
 | 
			
		||||
			"name": "自建DNS",
 | 
			
		||||
			"code": AdminModuleCodeNS,
 | 
			
		||||
			"url":  "/ns",
 | 
			
		||||
		})
 | 
			
		||||
 
 | 
			
		||||
@@ -388,6 +388,10 @@ func (this *RPCClient) NSRecordRPC() pb.NSRecordServiceClient {
 | 
			
		||||
	return pb.NewNSRecordServiceClient(this.pickConn())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *RPCClient) NSKeyRPC() pb.NSKeyServiceClient {
 | 
			
		||||
	return pb.NewNSKeyServiceClient(this.pickConn())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *RPCClient) NSRouteRPC() pb.NSRouteServiceClient {
 | 
			
		||||
	return pb.NewNSRouteServiceClient(this.pickConn())
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ package domains
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domainutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
)
 | 
			
		||||
@@ -19,6 +20,14 @@ func (this *DomainAction) Init() {
 | 
			
		||||
func (this *DomainAction) 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().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: params.DomainId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -55,6 +64,8 @@ func (this *DomainAction) RunGet(params struct {
 | 
			
		||||
		"isOn":         domain.IsOn,
 | 
			
		||||
		"cluster":      clusterMap,
 | 
			
		||||
		"user":         userMap,
 | 
			
		||||
		"countRecords": countRecords,
 | 
			
		||||
		"countKeys":    countKeys,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										55
									
								
								internal/web/actions/default/ns/domains/domainutils/utils.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								internal/web/actions/default/ns/domains/domainutils/utils.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package domainutils
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
	"github.com/iwind/TeaGo/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// InitDomain 初始化域名信息
 | 
			
		||||
func InitDomain(parent *actionutils.ParentAction, domainId int64) error {
 | 
			
		||||
	rpcClient, err := rpc.SharedRPC()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	domainResp, err := rpcClient.NSDomainRPC().FindEnabledNSDomain(parent.AdminContext(), &pb.FindEnabledNSDomainRequest{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().CountAllEnabledNSRecords(parent.AdminContext(), &pb.CountAllEnabledNSRecordsRequest{
 | 
			
		||||
		NsDomainId: domainId,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	var countRecords = countRecordsResp.Count
 | 
			
		||||
 | 
			
		||||
	// Key数量
 | 
			
		||||
	countKeysResp, err := rpcClient.NSKeyRPC().CountAllEnabledNSKeys(parent.AdminContext(), &pb.CountAllEnabledNSKeysRequest{
 | 
			
		||||
		NsDomainId: domainId,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	var countKeys = countKeysResp.Count
 | 
			
		||||
 | 
			
		||||
	parent.Data["domain"] = maps.Map{
 | 
			
		||||
		"id":           domain.Id,
 | 
			
		||||
		"name":         domain.Name,
 | 
			
		||||
		"countRecords": countRecords,
 | 
			
		||||
		"countKeys":    countKeys,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										86
									
								
								internal/web/actions/default/ns/domains/keys/createPopup.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								internal/web/actions/default/ns/domains/keys/createPopup.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package keys
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/iwind/TeaGo/actions"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type CreatePopupAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *CreatePopupAction) Init() {
 | 
			
		||||
	this.Nav("", "", "")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *CreatePopupAction) RunGet(params struct {
 | 
			
		||||
	DomainId int64
 | 
			
		||||
}) {
 | 
			
		||||
	this.Data["domainId"] = params.DomainId
 | 
			
		||||
 | 
			
		||||
	// 所有算法
 | 
			
		||||
	var algorithmMaps = []maps.Map{}
 | 
			
		||||
	for _, algo := range dnsconfigs.FindAllKeyAlgorithmTypes() {
 | 
			
		||||
		algorithmMaps = append(algorithmMaps, maps.Map{
 | 
			
		||||
			"name": algo.Name,
 | 
			
		||||
			"code": algo.Code,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	this.Data["algorithms"] = algorithmMaps
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *CreatePopupAction) RunPost(params struct {
 | 
			
		||||
	DomainId   int64
 | 
			
		||||
	Name       string
 | 
			
		||||
	Algo       string
 | 
			
		||||
	Secret     string
 | 
			
		||||
	SecretType string
 | 
			
		||||
 | 
			
		||||
	Must *actions.Must
 | 
			
		||||
	CSRF *actionutils.CSRF
 | 
			
		||||
}) {
 | 
			
		||||
	var keyId int64 = 0
 | 
			
		||||
	defer func() {
 | 
			
		||||
		this.CreateLogInfo("创建DNS密钥 %d", keyId)
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	params.Must.
 | 
			
		||||
		Field("name", params.Name).
 | 
			
		||||
		Require("请输入密钥名称").
 | 
			
		||||
		Field("algo", params.Algo).
 | 
			
		||||
		Require("请选择算法").
 | 
			
		||||
		Field("secret", params.Secret).
 | 
			
		||||
		Require("请输入密码")
 | 
			
		||||
 | 
			
		||||
	// 校验密码
 | 
			
		||||
	if params.SecretType == dnsconfigs.NSKeySecretTypeBase64 {
 | 
			
		||||
		_, err := base64.StdEncoding.DecodeString(params.Secret)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			this.FailField("secret", "请输入BASE64格式的密码或者选择明文")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	createResp, err := this.RPC().NSKeyRPC().CreateNSKey(this.AdminContext(), &pb.CreateNSKeyRequest{
 | 
			
		||||
		NsDomainId: params.DomainId,
 | 
			
		||||
		NsZoneId:   0,
 | 
			
		||||
		Name:       params.Name,
 | 
			
		||||
		Algo:       params.Algo,
 | 
			
		||||
		Secret:     params.Secret,
 | 
			
		||||
		SecretType: params.SecretType,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	keyId = createResp.NsKeyId
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								internal/web/actions/default/ns/domains/keys/delete.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								internal/web/actions/default/ns/domains/keys/delete.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package keys
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type DeleteAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *DeleteAction) RunPost(params struct {
 | 
			
		||||
	KeyId int64
 | 
			
		||||
}) {
 | 
			
		||||
	defer this.CreateLogInfo("删除DNS密钥 %d", params.KeyId)
 | 
			
		||||
 | 
			
		||||
	_, err := this.RPC().NSKeyRPC().DeleteNSKey(this.AdminContext(), &pb.DeleteNSKeyRequest{NsKeyId: params.KeyId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,29 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package keys
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
 | 
			
		||||
	"github.com/iwind/TeaGo/rands"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type GenerateSecretAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *GenerateSecretAction) RunPost(params struct {
 | 
			
		||||
	SecretType string
 | 
			
		||||
}) {
 | 
			
		||||
	switch params.SecretType {
 | 
			
		||||
	case dnsconfigs.NSKeySecretTypeClear:
 | 
			
		||||
		this.Data["secret"] = rands.HexString(128)
 | 
			
		||||
	case dnsconfigs.NSKeySecretTypeBase64:
 | 
			
		||||
		this.Data["secret"] = base64.StdEncoding.EncodeToString([]byte(rands.HexString(128)))
 | 
			
		||||
	default:
 | 
			
		||||
		this.Data["secret"] = rands.HexString(128)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										68
									
								
								internal/web/actions/default/ns/domains/keys/index.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								internal/web/actions/default/ns/domains/keys/index.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package keys
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domainutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type IndexAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *IndexAction) Init() {
 | 
			
		||||
	this.Nav("", "", "key")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *IndexAction) RunGet(params struct {
 | 
			
		||||
	DomainId int64
 | 
			
		||||
}) {
 | 
			
		||||
	// 初始化域名信息
 | 
			
		||||
	err := domainutils.InitDomain(this.Parent(), params.DomainId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 数量
 | 
			
		||||
	countResp, err := this.RPC().NSKeyRPC().CountAllEnabledNSKeys(this.AdminContext(), &pb.CountAllEnabledNSKeysRequest{
 | 
			
		||||
		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().ListEnabledNSKeys(this.AdminContext(), &pb.ListEnabledNSKeysRequest{
 | 
			
		||||
		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()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										100
									
								
								internal/web/actions/default/ns/domains/keys/updatePopup.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								internal/web/actions/default/ns/domains/keys/updatePopup.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package keys
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/iwind/TeaGo/actions"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type UpdatePopupAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *UpdatePopupAction) Init() {
 | 
			
		||||
	this.Nav("", "", "")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *UpdatePopupAction) RunGet(params struct {
 | 
			
		||||
	KeyId int64
 | 
			
		||||
}) {
 | 
			
		||||
	keyResp, err := this.RPC().NSKeyRPC().FindEnabledNSKey(this.AdminContext(), &pb.FindEnabledNSKeyRequest{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("修改DNS密钥 %d", params.KeyId)
 | 
			
		||||
 | 
			
		||||
	params.Must.
 | 
			
		||||
		Field("name", params.Name).
 | 
			
		||||
		Require("请输入密钥名称").
 | 
			
		||||
		Field("algo", params.Algo).
 | 
			
		||||
		Require("请选择算法").
 | 
			
		||||
		Field("secret", params.Secret).
 | 
			
		||||
		Require("请输入密码")
 | 
			
		||||
 | 
			
		||||
	// 校验密码
 | 
			
		||||
	if params.SecretType == dnsconfigs.NSKeySecretTypeBase64 {
 | 
			
		||||
		_, err := base64.StdEncoding.DecodeString(params.Secret)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			this.FailField("secret", "请输入BASE64格式的密码或者选择明文")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err := this.RPC().NSKeyRPC().UpdateNSKey(this.AdminContext(), &pb.UpdateNSKeyRequest{
 | 
			
		||||
		NsKeyId:    params.KeyId,
 | 
			
		||||
		Name:       params.Name,
 | 
			
		||||
		Algo:       params.Algo,
 | 
			
		||||
		Secret:     params.Secret,
 | 
			
		||||
		SecretType: params.SecretType,
 | 
			
		||||
		IsOn:       params.IsOn,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
@@ -4,6 +4,7 @@ package records
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domainutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
@@ -23,25 +24,16 @@ func (this *IndexAction) RunGet(params struct {
 | 
			
		||||
	Keyword  string
 | 
			
		||||
	RouteId  int64
 | 
			
		||||
}) {
 | 
			
		||||
	this.Data["type"] = params.Type
 | 
			
		||||
	this.Data["keyword"] = params.Keyword
 | 
			
		||||
	this.Data["routeId"] = params.RouteId
 | 
			
		||||
 | 
			
		||||
	// 域名信息
 | 
			
		||||
	domainResp, err := this.RPC().NSDomainRPC().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: params.DomainId})
 | 
			
		||||
	// 初始化域名信息
 | 
			
		||||
	err := domainutils.InitDomain(this.Parent(), params.DomainId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	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["type"] = params.Type
 | 
			
		||||
	this.Data["keyword"] = params.Keyword
 | 
			
		||||
	this.Data["routeId"] = params.RouteId
 | 
			
		||||
 | 
			
		||||
	// 记录
 | 
			
		||||
	countResp, err := this.RPC().NSRecordRPC().CountAllEnabledNSRecords(this.AdminContext(), &pb.CountAllEnabledNSRecordsRequest{
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ package domains
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/domainutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/iwind/TeaGo/actions"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
@@ -20,6 +21,15 @@ func (this *UpdateAction) Init() {
 | 
			
		||||
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().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: params.DomainId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -49,6 +59,8 @@ func (this *UpdateAction) RunGet(params struct {
 | 
			
		||||
		"isOn":         domain.IsOn,
 | 
			
		||||
		"clusterId":    clusterId,
 | 
			
		||||
		"userId":       userId,
 | 
			
		||||
		"countRecords": countRecords,
 | 
			
		||||
		"countKeys":    countKeys,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ package ns
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/keys"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/records"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
 | 
			
		||||
	"github.com/iwind/TeaGo"
 | 
			
		||||
@@ -23,6 +24,14 @@ func init() {
 | 
			
		||||
			Get("/domain", new(domains.DomainAction)).
 | 
			
		||||
			GetPost("/update", new(domains.UpdateAction)).
 | 
			
		||||
 | 
			
		||||
			// 域名密钥
 | 
			
		||||
			Prefix("/ns/domains/keys").
 | 
			
		||||
			Get("", new(keys.IndexAction)).
 | 
			
		||||
			GetPost("/createPopup", new(keys.CreatePopupAction)).
 | 
			
		||||
			GetPost("/updatePopup", new(keys.UpdatePopupAction)).
 | 
			
		||||
			Post("/delete", new(keys.DeleteAction)).
 | 
			
		||||
			Post("/generateSecret", new(keys.GenerateSecretAction)).
 | 
			
		||||
 | 
			
		||||
			// 记录相关
 | 
			
		||||
			Prefix("/ns/domains/records").
 | 
			
		||||
			Get("", new(records.IndexAction)).
 | 
			
		||||
 
 | 
			
		||||
@@ -257,7 +257,7 @@ func (this *userMustAuth) modules(adminId int64) []maps.Map {
 | 
			
		||||
		{
 | 
			
		||||
			"code":     "ns",
 | 
			
		||||
			"module":   configloaders.AdminModuleCodeNS,
 | 
			
		||||
			"name":     "域名服务",
 | 
			
		||||
			"name":     "自建DNS",
 | 
			
		||||
			"subtitle": "域名列表",
 | 
			
		||||
			"icon":     "cubes",
 | 
			
		||||
			"isOn":     teaconst.IsPlus,
 | 
			
		||||
 
 | 
			
		||||
@@ -215,6 +215,10 @@ window.teaweb = {
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	popup: function (url, options) {
 | 
			
		||||
		if (url != null && url.length > 0 && url.substring(0, 1) == '.') {
 | 
			
		||||
			url = Tea.url(url)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (options == null) {
 | 
			
		||||
			options = {};
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
    <menu-item href="/ns">所有域名</menu-item>
 | 
			
		||||
    <span class="item disabled">|</span>
 | 
			
		||||
    <menu-item :href="'/ns/domains/domain?domainId=' + domain.id" code="index">详情<span class="grey small">({{domain.name}})</span></menu-item>
 | 
			
		||||
    <menu-item :href="'/ns/domains/records?domainId=' + domain.id" code="record">记录</menu-item>
 | 
			
		||||
    <menu-item :href="'/ns/domains/records?domainId=' + domain.id" code="record">记录({{domain.countRecords}})</menu-item>
 | 
			
		||||
    <menu-item :href="'/ns/domains/keys?domainId=' + domain.id" code="key">密钥({{domain.countKeys}})</menu-item>
 | 
			
		||||
    <menu-item :href="'/ns/domains/update?domainId=' + domain.id" code="update">修改</menu-item>
 | 
			
		||||
</first-menu>
 | 
			
		||||
							
								
								
									
										40
									
								
								web/views/@default/ns/domains/keys/createPopup.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								web/views/@default/ns/domains/keys/createPopup.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
{$layout "layout_popup"}
 | 
			
		||||
 | 
			
		||||
<h3>创建密钥</h3>
 | 
			
		||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
 | 
			
		||||
    <csrf-token></csrf-token>
 | 
			
		||||
    <input type="hidden" name="domainId" :value="domainId"/>
 | 
			
		||||
    <table class="ui table definition selectable">
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td class="title">密钥名称 *</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <input type="text" name="name" ref="focus"/>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td>算法 *</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <select class="ui dropdown auto-width" name="algo">
 | 
			
		||||
                    <option value="">[选择算法]</option>
 | 
			
		||||
                    <option v-for="algo in algorithms" :value="algo.code">{{algo.name}}</option>
 | 
			
		||||
                </select>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td>密码 *</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <div style="margin-bottom: 1em">
 | 
			
		||||
                    <radio name="secretType" value="clear" :v-value="'clear'" v-model="secretType">明文密码</radio>
 | 
			
		||||
                       
 | 
			
		||||
                    <radio name="secretType" value="base64" :v-value="'base64'" v-model="secretType">Base64密码</radio>
 | 
			
		||||
                </div>
 | 
			
		||||
                <textarea name="secret" maxlength="256" v-model="secret" rows="3"></textarea>
 | 
			
		||||
                <p class="comment" v-if="secretType == 'clear'">客户端需要将明文转换为BASE64使用。</p>
 | 
			
		||||
                <div style="margin-top: 1em">
 | 
			
		||||
                    <a href="" @click.prevent="generateSecret">[随机生成]</a>
 | 
			
		||||
                </div>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
    </table>
 | 
			
		||||
    <submit-btn></submit-btn>
 | 
			
		||||
</form>
 | 
			
		||||
							
								
								
									
										20
									
								
								web/views/@default/ns/domains/keys/createPopup.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								web/views/@default/ns/domains/keys/createPopup.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
Tea.context(function () {
 | 
			
		||||
	this.secretType = "clear"
 | 
			
		||||
	this.secret = ""
 | 
			
		||||
 | 
			
		||||
	this.$delay(function () {
 | 
			
		||||
		this.$watch("secretType", function () {
 | 
			
		||||
			this.secret = ""
 | 
			
		||||
		})
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	this.generateSecret = function () {
 | 
			
		||||
		this.$post(".generateSecret")
 | 
			
		||||
			.params({
 | 
			
		||||
				secretType: this.secretType
 | 
			
		||||
			})
 | 
			
		||||
			.success(function (resp) {
 | 
			
		||||
				this.secret = resp.data.secret
 | 
			
		||||
			})
 | 
			
		||||
	}
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										38
									
								
								web/views/@default/ns/domains/keys/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								web/views/@default/ns/domains/keys/index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
{$layout}
 | 
			
		||||
{$template "../domain_menu"}
 | 
			
		||||
 | 
			
		||||
<second-menu>
 | 
			
		||||
    <menu-item @click.prevent="createKey">[创建密钥]</menu-item>
 | 
			
		||||
</second-menu>
 | 
			
		||||
 | 
			
		||||
<tip-message-box>这里的密钥可以用于TSIG通讯校验。</tip-message-box>
 | 
			
		||||
 | 
			
		||||
<p class="comment" v-if="keys.length == 0">暂时还没有密钥。</p>
 | 
			
		||||
 | 
			
		||||
<table class="ui table celled selectable" v-if="keys.length > 0">
 | 
			
		||||
    <thead>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <th class="two wide">密钥名称</th>
 | 
			
		||||
            <th class="two wide">算法</th>
 | 
			
		||||
            <th>密码</th>
 | 
			
		||||
            <th class="two wide">密码类型</th>
 | 
			
		||||
            <th class="two wide">状态</th>
 | 
			
		||||
            <th class="two op">操作</th>
 | 
			
		||||
        </tr>
 | 
			
		||||
    </thead>
 | 
			
		||||
    <tr v-for="key in keys">
 | 
			
		||||
        <td>{{key.name}}</td>
 | 
			
		||||
        <td>{{key.algoName}}</td>
 | 
			
		||||
        <td>{{key.secret}}</td>
 | 
			
		||||
        <td>{{key.secretTypeName}}</td>
 | 
			
		||||
        <td>
 | 
			
		||||
            <label-on :v-is-on="key.isOn"></label-on>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td>
 | 
			
		||||
            <a href="" @click.prevent="updateKey(key.id)">修改</a>  
 | 
			
		||||
            <a href="" @click.prevent="deleteKey(key.id)">删除</a>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<div class="page" v-html="page"></div>
 | 
			
		||||
							
								
								
									
										31
									
								
								web/views/@default/ns/domains/keys/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								web/views/@default/ns/domains/keys/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
Tea.context(function () {
 | 
			
		||||
	this.createKey = function () {
 | 
			
		||||
		teaweb.popup(Tea.url(".createPopup?domainId=" + this.domain.id), {
 | 
			
		||||
			height: "24em",
 | 
			
		||||
			callback: function () {
 | 
			
		||||
				teaweb.successRefresh("保存成功")
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.updateKey = function (keyId) {
 | 
			
		||||
		teaweb.popup(Tea.url(".updatePopup?keyId=" + keyId), {
 | 
			
		||||
			height: "26em",
 | 
			
		||||
			callback: function () {
 | 
			
		||||
				teaweb.successRefresh("保存成功")
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.deleteKey = function (keyId) {
 | 
			
		||||
		teaweb.confirm("确定要删除这个密钥吗?", function () {
 | 
			
		||||
			this.$post(".delete")
 | 
			
		||||
				.params({
 | 
			
		||||
					keyId: keyId
 | 
			
		||||
				})
 | 
			
		||||
				.success(function () {
 | 
			
		||||
					teaweb.successRefresh("删除成功")
 | 
			
		||||
				})
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										46
									
								
								web/views/@default/ns/domains/keys/updatePopup.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								web/views/@default/ns/domains/keys/updatePopup.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
{$layout "layout_popup"}
 | 
			
		||||
 | 
			
		||||
<h3>修改密钥</h3>
 | 
			
		||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
 | 
			
		||||
    <csrf-token></csrf-token>
 | 
			
		||||
    <input type="hidden" name="keyId" :value="key.id"/>
 | 
			
		||||
    <table class="ui table definition selectable">
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td class="title">密钥名称 *</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <input type="text" name="name" ref="focus" v-model="key.name"/>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td>算法 *</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <select class="ui dropdown auto-width" name="algo" v-model="key.algo">
 | 
			
		||||
                    <option value="">[选择算法]</option>
 | 
			
		||||
                    <option v-for="algo in algorithms" :value="algo.code">{{algo.name}}</option>
 | 
			
		||||
                </select>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td>密码 *</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <div style="margin-bottom: 1em">
 | 
			
		||||
                    <radio name="secretType" value="clear" :v-value="'clear'" v-model="secretType">明文密码</radio>
 | 
			
		||||
                       
 | 
			
		||||
                    <radio name="secretType" value="base64" :v-value="'base64'" v-model="secretType">Base64密码</radio>
 | 
			
		||||
                </div>
 | 
			
		||||
                <textarea name="secret" maxlength="256" v-model="secret" rows="3"></textarea>
 | 
			
		||||
                <p class="comment" v-if="secretType == 'clear'">客户端需要将明文转换为BASE64使用。</p>
 | 
			
		||||
                <div style="margin-top: 1em">
 | 
			
		||||
                    <a href="" @click.prevent="generateSecret">[随机生成]</a>
 | 
			
		||||
                </div>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td>是否启用</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <checkbox name="isOn" v-model="key.isOn"></checkbox>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
    </table>
 | 
			
		||||
    <submit-btn></submit-btn>
 | 
			
		||||
</form>
 | 
			
		||||
							
								
								
									
										20
									
								
								web/views/@default/ns/domains/keys/updatePopup.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								web/views/@default/ns/domains/keys/updatePopup.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
Tea.context(function () {
 | 
			
		||||
	this.secretType = this.key.secretType
 | 
			
		||||
	this.secret = this.key.secret
 | 
			
		||||
 | 
			
		||||
	this.$delay(function () {
 | 
			
		||||
		this.$watch("secretType", function () {
 | 
			
		||||
			this.secret = ""
 | 
			
		||||
		})
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	this.generateSecret = function () {
 | 
			
		||||
		this.$post(".generateSecret")
 | 
			
		||||
			.params({
 | 
			
		||||
				secretType: this.secretType
 | 
			
		||||
			})
 | 
			
		||||
			.success(function (resp) {
 | 
			
		||||
				this.secret = resp.data.secret
 | 
			
		||||
			})
 | 
			
		||||
	}
 | 
			
		||||
})
 | 
			
		||||
		Reference in New Issue
	
	Block a user