Files
waf-platform/EdgeAPI/internal/rpc/services/nameservers/service_ns_domain.go

1128 lines
29 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build plus
package nameservers
import (
"context"
"encoding/json"
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/db/models/nameservers"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/types"
"strings"
"time"
)
// NSDomainService 域名相关服务
type NSDomainService struct {
services.BaseService
}
// CreateNSDomain 创建域名
func (this *NSDomainService) CreateNSDomain(ctx context.Context, req *pb.CreateNSDomainRequest) (*pb.CreateNSDomainResponse, error) {
// 检查是否为商业用户
if !teaconst.IsPlus {
return nil, errors.New("non commercial user")
}
adminId, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var isAdminRequest = adminId > 0
if userId > 0 {
req.UserId = userId
}
req.Name = strings.ToLower(req.Name)
// 检查 req.NsDomainGroupIds 有效性
var tx = this.NullTx()
if req.UserId > 0 && len(req.NsDomainGroupIds) > 0 {
for _, groupId := range req.NsDomainGroupIds {
err = nameservers.SharedNSDomainGroupDAO.CheckUserGroup(tx, req.UserId, groupId)
if err != nil {
return nil, err
}
}
}
// 检查clusterId
var shouldValidate = false
if req.UserId > 0 && !isAdminRequest {
userConfig, err := models.SharedSysSettingDAO.ReadNSUserConfig(tx)
if err != nil {
return nil, err
}
req.NsClusterId = userConfig.DefaultClusterId
shouldValidate = userConfig.DomainValidation != nil && userConfig.DomainValidation.IsOn
}
if req.NsClusterId <= 0 {
return nil, errors.New("'nsClusterId' required")
}
// 是否已经在当前用户账户里存在
exists, err := nameservers.SharedNSDomainDAO.ExistUserDomain(tx, req.UserId, req.Name)
if err != nil {
return nil, err
}
if exists {
return nil, errors.New("domain '" + req.Name + "' already exists")
}
// 管理员添加时检查是否在别的用户账户里已经存在
// 允许用户添加重复的域名只需要后续进行TXT验证即可
if userId == 0 {
exists, err = nameservers.SharedNSDomainDAO.ExistVerifiedDomain(tx, req.Name)
if err != nil {
return nil, err
}
if exists {
return nil, errors.New("domain '" + req.Name + "' already exists")
}
}
// 状态
var status = dnsconfigs.NSDomainStatusNone
if isAdminRequest || !shouldValidate {
status = dnsconfigs.NSDomainStatusVerified
}
// 创建
domainId, err := nameservers.SharedNSDomainDAO.CreateDomain(tx, req.NsClusterId, req.UserId, req.NsDomainGroupIds, req.Name, status)
if err != nil {
return nil, err
}
return &pb.CreateNSDomainResponse{NsDomainId: domainId}, nil
}
// CreateNSDomains 批量创建域名
func (this *NSDomainService) CreateNSDomains(ctx context.Context, req *pb.CreateNSDomainsRequest) (*pb.CreateNSDomainsResponse, error) {
// 检查是否为商业用户
if !teaconst.IsPlus {
return nil, errors.New("non commercial user")
}
adminId, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var isAdminRequest = adminId > 0
if userId > 0 {
req.UserId = userId
}
// 检查分组有效性
var tx = this.NullTx()
if req.UserId > 0 {
for _, groupId := range req.NsDomainGroupIds {
err = nameservers.SharedNSDomainGroupDAO.CheckUserGroup(tx, req.UserId, groupId)
if err != nil {
return nil, err
}
}
}
// 检查集群
var shouldValidate = false
if req.UserId > 0 && !isAdminRequest {
userConfig, err := models.SharedSysSettingDAO.ReadNSUserConfig(tx)
if err != nil {
return nil, err
}
req.NsClusterId = userConfig.DefaultClusterId
shouldValidate = userConfig.DomainValidation != nil && userConfig.DomainValidation.IsOn
}
if req.NsClusterId <= 0 {
return nil, errors.New("'nsClusterId' required")
}
var domainIds = []int64{}
var domainMap = map[string]bool{} // domainName => bool
err = this.RunTx(func(tx *dbs.Tx) error {
for _, name := range req.Names {
name = strings.ToLower(name)
// 检查是否已添加
_, ok := domainMap[name]
if ok {
return nil
}
domainMap[name] = true
// 是否已经存在
exists, err := nameservers.SharedNSDomainDAO.ExistUserDomain(tx, req.UserId, name)
if err != nil {
return err
}
if exists {
return errors.New("domain '" + name + "' already exists")
}
// 管理员添加时验证域名是否已由别的用户添加过
if userId == 0 {
exists, err = nameservers.SharedNSDomainDAO.ExistVerifiedDomain(tx, name)
if err != nil {
return err
}
if exists {
return errors.New("domain '" + name + "' already exists")
}
}
// 状态
var status = dnsconfigs.NSDomainStatusNone
if isAdminRequest || !shouldValidate {
status = dnsconfigs.NSDomainStatusVerified
}
// 创建
domainId, err := nameservers.SharedNSDomainDAO.CreateDomain(tx, req.NsClusterId, req.UserId, req.NsDomainGroupIds, name, status)
if err != nil {
return err
}
domainIds = append(domainIds, domainId)
}
return nil
})
if err != nil {
return nil, err
}
return &pb.CreateNSDomainsResponse{NsDomainIds: domainIds}, nil
}
// UpdateNSDomain 修改域名
func (this *NSDomainService) UpdateNSDomain(ctx context.Context, req *pb.UpdateNSDomainRequest) (*pb.RPCSuccess, error) {
// 检查是否为商业用户
if !teaconst.IsPlus {
return nil, errors.New("non commercial user")
}
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
if userId > 0 {
req.UserId = userId
}
var tx = this.NullTx()
if userId > 0 {
err = nameservers.SharedNSDomainDAO.CheckUserDomain(tx, userId, req.NsDomainId)
if err != nil {
return nil, err
}
}
if req.UserId > 0 {
// 检查分组有效性
for _, groupId := range req.NsDomainGroupIds {
err = nameservers.SharedNSDomainGroupDAO.CheckUserGroup(tx, req.UserId, groupId)
if err != nil {
return nil, err
}
}
}
err = nameservers.SharedNSDomainDAO.UpdateDomain(tx, req.NsDomainId, req.NsClusterId, req.UserId, req.NsDomainGroupIds, req.IsOn)
if err != nil {
return nil, err
}
return this.Success()
}
// UpdateNSDomainStatus 修改域名状态
func (this *NSDomainService) UpdateNSDomainStatus(ctx context.Context, req *pb.UpdateNSDomainStatusRequest) (*pb.RPCSuccess, error) {
// 检查是否为商业用户
if !teaconst.IsPlus {
return nil, errors.New("non commercial user")
}
_, err := this.ValidateAdmin(ctx)
if err != nil {
return nil, err
}
if req.NsDomainId <= 0 {
return nil, errors.New("invalid nsDomainId")
}
if !dnsconfigs.NSDomainStatusIsValid(req.Status) {
return nil, errors.New("invalid status '" + req.Status + "'")
}
var tx = this.NullTx()
err = nameservers.SharedNSDomainDAO.UpdateDomainStatus(tx, req.NsDomainId, req.Status)
if err != nil {
return nil, err
}
return this.Success()
}
// DeleteNSDomain 删除域名
func (this *NSDomainService) DeleteNSDomain(ctx context.Context, req *pb.DeleteNSDomainRequest) (*pb.RPCSuccess, error) {
// 检查是否为商业用户
if !teaconst.IsPlus {
return nil, errors.New("non commercial user")
}
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var tx = this.NullTx()
if userId > 0 {
err = nameservers.SharedNSDomainDAO.CheckUserDomain(tx, userId, req.NsDomainId)
if err != nil {
return nil, err
}
}
err = nameservers.SharedNSDomainDAO.DisableNSDomain(tx, req.NsDomainId)
if err != nil {
return nil, err
}
return this.Success()
}
// DeleteNSDomains 批量删除域名
func (this *NSDomainService) DeleteNSDomains(ctx context.Context, req *pb.DeleteNSDomainsRequest) (*pb.RPCSuccess, error) {
// 检查是否为商业用户
if !teaconst.IsPlus {
return nil, errors.New("non commercial user")
}
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
if userId > 0 {
req.UserId = userId
}
var tx = this.NullTx()
for _, name := range req.Names {
name = strings.ToLower(strings.TrimSpace(name))
if len(name) == 0 {
continue
}
if req.UserId > 0 {
err = nameservers.SharedNSDomainDAO.DisableUserDomainWithName(tx, req.UserId, name)
} else {
err = nameservers.SharedNSDomainDAO.DisableDomainWithName(tx, name)
}
if err != nil {
return nil, err
}
}
return this.Success()
}
// FindNSDomain 查找单个域名
func (this *NSDomainService) FindNSDomain(ctx context.Context, req *pb.FindNSDomainRequest) (*pb.FindNSDomainResponse, error) {
// 检查是否为商业用户
if !teaconst.IsPlus {
return nil, errors.New("non commercial user")
}
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var tx = this.NullTx()
// 检查用户权限
if userId > 0 {
err = nameservers.SharedNSDomainDAO.CheckUserDomain(tx, userId, req.NsDomainId)
if err != nil {
return nil, err
}
}
domain, err := nameservers.SharedNSDomainDAO.FindEnabledNSDomain(tx, req.NsDomainId)
if err != nil {
return nil, err
}
if domain == nil {
return &pb.FindNSDomainResponse{NsDomain: nil}, nil
}
// 集群
cluster, err := models.SharedNSClusterDAO.FindEnabledNSCluster(tx, int64(domain.ClusterId))
if err != nil {
return nil, err
}
if cluster == nil {
return &pb.FindNSDomainResponse{NsDomain: nil}, nil
}
// 用户
var pbUser *pb.User
if domain.UserId > 0 {
user, err := models.SharedUserDAO.FindEnabledUser(tx, int64(domain.UserId), nil)
if err != nil {
return nil, err
}
if user == nil {
return &pb.FindNSDomainResponse{NsDomain: nil}, nil
}
pbUser = &pb.User{
Id: int64(user.Id),
Username: user.Username,
Fullname: user.Fullname,
}
}
// groups
var pbGroups = []*pb.NSDomainGroup{}
var groupIds = domain.DecodeGroupIds()
for _, groupId := range groupIds {
group, err := nameservers.SharedNSDomainGroupDAO.FindEnabledNSDomainGroup(tx, groupId)
if err != nil {
return nil, err
}
if group != nil && group.IsOn {
pbGroups = append(pbGroups, &pb.NSDomainGroup{
Id: int64(group.Id),
Name: group.Name,
IsOn: group.IsOn,
UserId: int64(group.UserId),
})
}
}
return &pb.FindNSDomainResponse{
NsDomain: &pb.NSDomain{
Id: int64(domain.Id),
Name: domain.Name,
IsOn: domain.IsOn,
TsigJSON: domain.Tsig,
RecordsHealthCheckJSON: domain.RecordsHealthCheck,
CreatedAt: int64(domain.CreatedAt),
Status: domain.Status,
NsCluster: &pb.NSCluster{
Id: int64(cluster.Id),
IsOn: cluster.IsOn,
Name: cluster.Name,
},
UserId: int64(domain.UserId),
User: pbUser,
NsDomainGroupIds: groupIds,
NsDomainGroups: pbGroups,
},
}, nil
}
// FindNSDomainWithName 根据域名名称查找域名
func (this *NSDomainService) FindNSDomainWithName(ctx context.Context, req *pb.FindNSDomainWithNameRequest) (*pb.FindNSDomainWithNameResponse, error) {
// 检查是否为商业用户
if !teaconst.IsPlus {
return nil, errors.New("non commercial user")
}
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
if userId == 0 {
userId = req.UserId
}
var isUserRequest = userId > 0
if len(req.Name) == 0 {
return &pb.FindNSDomainWithNameResponse{
NsDomain: nil,
}, nil
}
var tx = this.NullTx()
domain, err := nameservers.SharedNSDomainDAO.FindDomainWithName(tx, userId, req.Name)
if err != nil {
return nil, err
}
if domain == nil {
return &pb.FindNSDomainWithNameResponse{NsDomain: nil}, nil
}
// 集群
var pbCluster *pb.NSCluster
if !isUserRequest {
cluster, err := models.SharedNSClusterDAO.FindEnabledNSCluster(tx, int64(domain.ClusterId))
if err != nil {
return nil, err
}
if cluster == nil {
return &pb.FindNSDomainWithNameResponse{NsDomain: nil}, nil
}
pbCluster = &pb.NSCluster{
Id: int64(cluster.Id),
IsOn: cluster.IsOn,
Name: cluster.Name,
}
}
// 用户
var pbUser *pb.User
if domain.UserId > 0 && !isUserRequest {
user, err := models.SharedUserDAO.FindEnabledUser(tx, int64(domain.UserId), nil)
if err != nil {
return nil, err
}
if user == nil {
return &pb.FindNSDomainWithNameResponse{NsDomain: nil}, nil
}
pbUser = &pb.User{
Id: int64(user.Id),
Username: user.Username,
Fullname: user.Fullname,
}
}
// groups
var pbGroups = []*pb.NSDomainGroup{}
var groupIds = domain.DecodeGroupIds()
for _, groupId := range groupIds {
group, err := nameservers.SharedNSDomainGroupDAO.FindEnabledNSDomainGroup(tx, groupId)
if err != nil {
return nil, err
}
if group != nil && group.IsOn {
pbGroups = append(pbGroups, &pb.NSDomainGroup{
Id: int64(group.Id),
Name: group.Name,
IsOn: group.IsOn,
UserId: int64(group.UserId),
})
}
}
return &pb.FindNSDomainWithNameResponse{
NsDomain: &pb.NSDomain{
Id: int64(domain.Id),
Name: domain.Name,
IsOn: domain.IsOn,
TsigJSON: domain.Tsig,
Status: domain.Status,
CreatedAt: int64(domain.CreatedAt),
NsCluster: pbCluster,
User: pbUser,
NsDomainGroupIds: groupIds,
NsDomainGroups: pbGroups,
},
}, nil
}
// FindVerifiedNSDomainOnCluster 根据域名名称查找集群中的已验证域名
func (this *NSDomainService) FindVerifiedNSDomainOnCluster(ctx context.Context, req *pb.FindVerifiedNSDomainOnClusterRequest) (*pb.FindVerifiedNSDomainOnClusterResponse, error) {
_, err := this.ValidateAdmin(ctx)
if err != nil {
return nil, err
}
var tx = this.NullTx()
domain, err := nameservers.SharedNSDomainDAO.FindVerifiedDomainWithNameOnCluster(tx, req.NsClusterId, req.Name)
if err != nil {
return nil, err
}
if domain == nil {
return &pb.FindVerifiedNSDomainOnClusterResponse{
NsDomain: nil,
}, nil
}
return &pb.FindVerifiedNSDomainOnClusterResponse{
NsDomain: &pb.NSDomain{
Id: int64(domain.Id),
Name: domain.Name,
IsOn: domain.IsOn,
Status: domain.Status,
},
}, nil
}
// CountAllNSDomains 计算域名数量
func (this *NSDomainService) CountAllNSDomains(ctx context.Context, req *pb.CountAllNSDomainsRequest) (*pb.RPCCountResponse, error) {
// 检查是否为商业用户
if !teaconst.IsPlus {
return nil, errors.New("non commercial user")
}
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var tx = this.NullTx()
if userId > 0 {
req.UserId = userId
// 检查分组
if req.NsDomainGroupId > 0 {
err = nameservers.SharedNSDomainGroupDAO.CheckUserGroup(tx, userId, req.NsDomainGroupId)
if err != nil {
return nil, err
}
}
}
count, err := nameservers.SharedNSDomainDAO.CountAllEnabledDomains(tx, req.NsClusterId, req.UserId, req.NsDomainGroupId, req.Status, req.Keyword)
if err != nil {
return nil, err
}
return this.SuccessCount(count)
}
// ListNSDomains 列出单页域名
func (this *NSDomainService) ListNSDomains(ctx context.Context, req *pb.ListNSDomainsRequest) (*pb.ListNSDomainsResponse, error) {
// 检查是否为商业用户
if !teaconst.IsPlus {
return nil, errors.New("non commercial user")
}
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var isUserRequest = userId > 0
var tx = this.NullTx()
if userId > 0 {
req.UserId = userId
// 检查分组
if req.NsDomainGroupId > 0 {
err = nameservers.SharedNSDomainGroupDAO.CheckUserGroup(tx, userId, req.NsDomainGroupId)
if err != nil {
return nil, err
}
}
}
domains, err := nameservers.SharedNSDomainDAO.ListEnabledDomains(tx, req.NsClusterId, req.UserId, req.NsDomainGroupId, req.Keyword, req.Offset, req.Size)
if err != nil {
return nil, err
}
var pbDomains = []*pb.NSDomain{}
var cacheMap = utils.NewCacheMap()
for _, domain := range domains {
// 集群
cluster, err := models.SharedNSClusterDAO.FindEnabledNSCluster(tx, int64(domain.ClusterId))
if err != nil {
return nil, err
}
if cluster == nil {
continue
}
// 用户
var pbUser *pb.User
if domain.UserId > 0 && !isUserRequest {
user, err := models.SharedUserDAO.FindEnabledUser(tx, int64(domain.UserId), cacheMap)
if err != nil {
return nil, err
}
if user == nil {
continue
}
pbUser = &pb.User{
Id: int64(user.Id),
Username: user.Username,
Fullname: user.Fullname,
}
}
// groups
var pbGroups = []*pb.NSDomainGroup{}
var groupIds = domain.DecodeGroupIds()
for _, groupId := range groupIds {
group, err := nameservers.SharedNSDomainGroupDAO.FindEnabledNSDomainGroup(tx, groupId)
if err != nil {
return nil, err
}
if group != nil && group.IsOn {
pbGroups = append(pbGroups, &pb.NSDomainGroup{
Id: int64(group.Id),
Name: group.Name,
IsOn: group.IsOn,
UserId: int64(group.UserId),
})
}
}
var pbCluster *pb.NSCluster
if !isUserRequest {
pbCluster = &pb.NSCluster{
Id: int64(cluster.Id),
IsOn: cluster.IsOn,
Name: cluster.Name,
}
}
pbDomains = append(pbDomains, &pb.NSDomain{
Id: int64(domain.Id),
Name: domain.Name,
Status: domain.Status,
IsOn: domain.IsOn,
CreatedAt: int64(domain.CreatedAt),
TsigJSON: domain.Tsig,
NsCluster: pbCluster,
User: pbUser,
NsDomainGroupIds: groupIds,
NsDomainGroups: pbGroups,
})
}
return &pb.ListNSDomainsResponse{NsDomains: pbDomains}, nil
}
// ListNSDomainsAfterVersion 根据版本列出一组域名
func (this *NSDomainService) ListNSDomainsAfterVersion(ctx context.Context, req *pb.ListNSDomainsAfterVersionRequest) (*pb.ListNSDomainsAfterVersionResponse, error) {
_, _, err := this.ValidateNodeId(ctx, rpcutils.UserTypeDNS)
if err != nil {
return nil, err
}
// 检查是否为商业用户
if !teaconst.IsPlus {
return &pb.ListNSDomainsAfterVersionResponse{
NsDomains: nil,
}, nil
}
// 集群ID
var tx = this.NullTx()
if req.Size <= 0 {
req.Size = 2000
}
domains, err := nameservers.SharedNSDomainDAO.ListDomainsAfterVersion(tx, req.Version, req.Size)
if err != nil {
return nil, err
}
var pbDomains []*pb.NSDomain
for _, domain := range domains {
pbDomains = append(pbDomains, &pb.NSDomain{
Id: int64(domain.Id),
Name: domain.Name,
IsOn: domain.IsOn,
Status: domain.Status,
IsDeleted: domain.State == nameservers.NSDomainStateDisabled || domain.Status != dnsconfigs.NSDomainStatusVerified,
Version: int64(domain.Version),
UserId: types.Int64(domain.UserId),
TsigJSON: domain.Tsig,
NsCluster: &pb.NSCluster{Id: int64(domain.ClusterId)},
User: nil,
})
}
return &pb.ListNSDomainsAfterVersionResponse{NsDomains: pbDomains}, nil
}
// FindNSDomainTSIG 查找TSIG配置
func (this *NSDomainService) FindNSDomainTSIG(ctx context.Context, req *pb.FindNSDomainTSIGRequest) (*pb.FindNSDomainTSIGResponse, error) {
_, err := this.ValidateAdmin(ctx)
if err != nil {
return nil, err
}
var tx = this.NullTx()
tsig, err := nameservers.SharedNSDomainDAO.FindEnabledDomainTSIG(tx, req.NsDomainId)
if err != nil {
return nil, err
}
return &pb.FindNSDomainTSIGResponse{TsigJSON: tsig}, nil
}
// UpdateNSDomainTSIG 修改TSIG配置
func (this *NSDomainService) UpdateNSDomainTSIG(ctx context.Context, req *pb.UpdateNSDomainTSIGRequest) (*pb.RPCSuccess, error) {
_, err := this.ValidateAdmin(ctx)
if err != nil {
return nil, err
}
var tx = this.NullTx()
err = nameservers.SharedNSDomainDAO.UpdateDomainTSIG(tx, req.NsDomainId, req.TsigJSON)
if err != nil {
return nil, err
}
return this.Success()
}
// ExistNSDomains 检查一组域名是否在用户账户中存在
func (this *NSDomainService) ExistNSDomains(ctx context.Context, req *pb.ExistNSDomainsRequest) (*pb.ExistNSDomainsResponse, error) {
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
if userId > 0 {
req.UserId = userId
}
var existingDomains = []string{}
var tx = this.NullTx()
for _, domainName := range req.Names {
domainName = strings.ToLower(domainName)
b, err := nameservers.SharedNSDomainDAO.ExistUserDomain(tx, req.UserId, domainName)
if err != nil {
return nil, err
}
if b {
existingDomains = append(existingDomains, domainName)
}
}
return &pb.ExistNSDomainsResponse{ExistingNames: existingDomains}, nil
}
// ExistVerifiedNSDomains 检查一组域名是否已通过验证
func (this *NSDomainService) ExistVerifiedNSDomains(ctx context.Context, req *pb.ExistVerifiedNSDomainsRequest) (*pb.ExistVerifiedNSDomainsResponse, error) {
_, _, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
var existingDomains = []string{}
var tx = this.NullTx()
for _, domainName := range req.Names {
domainName = strings.ToLower(domainName)
b, err := nameservers.SharedNSDomainDAO.ExistVerifiedDomain(tx, domainName)
if err != nil {
return nil, err
}
if b {
existingDomains = append(existingDomains, domainName)
}
}
return &pb.ExistVerifiedNSDomainsResponse{ExistingNames: existingDomains}, nil
}
// FindNSDomainVerifyingInfo 获取域名验证信息
func (this *NSDomainService) FindNSDomainVerifyingInfo(ctx context.Context, req *pb.FindNSDomainVerifyingInfoRequest) (*pb.FindNSDomainVerifyingInfoResponse, error) {
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
// 检查权限
var tx = this.NullTx()
if userId > 0 {
err = nameservers.SharedNSDomainDAO.CheckUserDomain(tx, userId, req.NsDomainId)
if err != nil {
return nil, err
}
}
// 检查域名是否已被别的用户验证
domainName, err := nameservers.SharedNSDomainDAO.FindNSDomainName(tx, req.NsDomainId)
if err != nil {
return nil, err
}
if len(domainName) == 0 {
return nil, errors.New("could not find domain name with id '" + types.String(req.NsDomainId) + "'")
}
verifiedDomain, err := nameservers.SharedNSDomainDAO.FindVerifiedDomainWithName(tx, domainName)
if err != nil {
return nil, err
}
if verifiedDomain == nil || int64(verifiedDomain.UserId) == userId {
// 如果当前域名没有验证过或者是自己的验证过的域名则直接不需要通过TXT再次验证
return &pb.FindNSDomainVerifyingInfoResponse{
RequireTXT: false,
}, nil
}
// 生成TXT
domain, err := nameservers.SharedNSDomainDAO.FindDomainVerifyingInfo(tx, req.NsDomainId, true)
if err != nil {
return nil, err
}
if domain == nil {
return &pb.FindNSDomainVerifyingInfoResponse{
Txt: "",
ExpiresAt: 0,
Status: "",
}, nil
}
return &pb.FindNSDomainVerifyingInfoResponse{
RequireTXT: true,
Txt: domain.VerifyTXT,
ExpiresAt: int64(domain.VerifyExpiresAt),
Status: domain.Status,
}, nil
}
// VerifyNSDomain 验证域名信息
func (this *NSDomainService) VerifyNSDomain(ctx context.Context, req *pb.VerifyNSDomainRequest) (*pb.VerifyNSDomainResponse, error) {
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
// 检查权限
var tx = this.NullTx()
if userId > 0 {
err = nameservers.SharedNSDomainDAO.CheckUserDomain(tx, userId, req.NsDomainId)
if err != nil {
return nil, err
}
}
// 客户端需要处理的错误代号列表
const (
ErrorCodeDomainNotFound = "DomainNotFound"
ErrorCodeInvalidStatus = "InvalidStatus"
ErrorCodeInvalidDNSHosts = "InvalidDNSHosts"
ErrorCodeInvalidTXT = "InvalidTXT"
ErrorCodeTXTNotFound = "TXTNotFound"
ErrorCodeTXTExpired = "TXTExpired"
)
// 验证状态
domain, err := nameservers.SharedNSDomainDAO.FindEnabledNSDomain(tx, req.NsDomainId)
if err != nil {
return nil, err
}
if domain == nil {
return &pb.VerifyNSDomainResponse{
ErrorCode: ErrorCodeDomainNotFound,
}, nil
}
if domain.Status != dnsconfigs.NSDomainStatusNone {
return &pb.VerifyNSDomainResponse{
ErrorCode: ErrorCodeInvalidStatus,
ErrorMessage: "invalid status '" + domain.Status + "'",
}, nil
}
// 检查是否已被别的用户所验证
var requireTXT = true
var oldDomainId int64
if userId > 0 {
verifiedDomain, err := nameservers.SharedNSDomainDAO.FindVerifiedDomainWithName(tx, domain.Name)
if err != nil {
return nil, err
}
if verifiedDomain == nil || int64(verifiedDomain.UserId) == userId {
requireTXT = false
}
if verifiedDomain != nil {
oldDomainId = int64(verifiedDomain.Id)
}
}
if requireTXT && (len(domain.VerifyTXT) == 0 || int64(domain.VerifyExpiresAt) < time.Now().Unix()) {
return &pb.VerifyNSDomainResponse{
ErrorCode: ErrorCodeTXTExpired,
}, nil
}
// 当前集群的DNS Hosts
userConfig, err := models.SharedSysSettingDAO.ReadNSUserConfig(tx)
if err != nil {
return nil, err
}
if userConfig == nil {
return nil, errors.New("invalid NSUserConfig")
}
// 是否需要验证
var shouldValidate = userConfig.DomainValidation != nil && userConfig.DomainValidation.IsOn
if !shouldValidate {
// 设置为验证通过
err = nameservers.SharedNSDomainDAO.UpdateDomainStatus(tx, req.NsDomainId, dnsconfigs.NSDomainStatusVerified)
if err != nil {
return nil, err
}
return &pb.VerifyNSDomainResponse{
IsOk: true,
}, nil
}
userHosts, err := models.SharedNSClusterDAO.FindClusterHosts(tx, int64(domain.ClusterId))
if err != nil {
return nil, err
}
if len(userHosts) == 0 {
return nil, errors.New("no hosts in the ns cluster")
}
// 验证主机地址
nsHosts, err := utils.LookupNS(domain.Name, userConfig.DomainValidation.Resolvers)
if err != nil {
remotelogs.Error("NSDomainService", "lookup NS '"+domain.Name+"' failed: "+err.Error())
return &pb.VerifyNSDomainResponse{
ErrorCode: ErrorCodeInvalidDNSHosts,
}, nil
}
if len(nsHosts) == 0 {
return &pb.VerifyNSDomainResponse{
ErrorCode: ErrorCodeInvalidDNSHosts,
CurrentNSValues: nsHosts,
}, nil
}
if len(nsHosts) > 0 {
for _, host := range nsHosts {
host = strings.TrimSuffix(host, ".")
if !lists.ContainsString(userHosts, host) {
return &pb.VerifyNSDomainResponse{
ErrorCode: ErrorCodeInvalidDNSHosts,
ErrorMessage: "invalid dns host '" + host + "'",
CurrentNSValues: nsHosts,
}, nil
}
}
}
// 验证TXT
if requireTXT {
txtList, err := utils.LookupTXT("yanzheng."+domain.Name, userConfig.DomainValidation.Resolvers)
if err != nil {
return nil, err
}
if len(txtList) == 0 {
return &pb.VerifyNSDomainResponse{
ErrorCode: ErrorCodeTXTNotFound,
ErrorMessage: "",
}, nil
}
if !lists.ContainsString(txtList, domain.VerifyTXT) {
return &pb.VerifyNSDomainResponse{
ErrorCode: ErrorCodeInvalidTXT,
ErrorMessage: strings.Join(txtList, ", "),
CurrentTXTValues: txtList,
}, nil
}
}
// 取消原有老的验证过的同名域名
if oldDomainId > 0 {
err = nameservers.SharedNSDomainDAO.DisableNSDomain(tx, oldDomainId)
if err != nil {
return nil, err
}
}
// 设置为验证通过
err = nameservers.SharedNSDomainDAO.UpdateDomainStatus(tx, req.NsDomainId, dnsconfigs.NSDomainStatusVerified)
if err != nil {
return nil, err
}
return &pb.VerifyNSDomainResponse{
IsOk: true,
}, nil
}
// FindNSDomainRecordsHealthCheck 查询记录健康检查全局设置
func (this *NSDomainService) FindNSDomainRecordsHealthCheck(ctx context.Context, req *pb.FindNSDomainRecordsHealthCheckRequest) (*pb.FindNSDomainRecordsHealthCheckResponse, error) {
// 检查是否为商业用户
if !teaconst.IsPlus {
return nil, errors.New("non commercial user")
}
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
// 检查权限
var tx = this.NullTx()
if userId > 0 {
err = nameservers.SharedNSDomainDAO.CheckUserDomain(tx, userId, req.NsDomainId)
if err != nil {
return nil, err
}
// TODO 检查套餐
}
config, err := nameservers.SharedNSDomainDAO.FindRecordsHealthCheckConfig(tx, req.NsDomainId)
if err != nil {
return nil, err
}
configJSON, err := json.Marshal(config)
if err != nil {
return nil, err
}
return &pb.FindNSDomainRecordsHealthCheckResponse{NsDomainRecordsHealthCheckJSON: configJSON}, nil
}
// UpdateNSDomainRecordsHealthCheck 修改记录健康检查全局设置
func (this *NSDomainService) UpdateNSDomainRecordsHealthCheck(ctx context.Context, req *pb.UpdateNSDomainRecordsHealthCheckRequest) (*pb.RPCSuccess, error) {
// 检查是否为商业用户
if !teaconst.IsPlus {
return nil, errors.New("non commercial user")
}
_, userId, err := this.ValidateAdminAndUser(ctx, true)
if err != nil {
return nil, err
}
// 检查权限
var tx = this.NullTx()
if userId > 0 {
err = nameservers.SharedNSDomainDAO.CheckUserDomain(tx, userId, req.NsDomainId)
if err != nil {
return nil, err
}
// TODO 检查套餐
}
if len(req.NsDomainRecordsHealthCheckJSON) == 0 {
return nil, errors.New("invalid 'nsDomainRecordsHealthCheckJSON'")
}
var config = dnsconfigs.NewNSRecordsHealthCheckConfig()
err = json.Unmarshal(req.NsDomainRecordsHealthCheckJSON, config)
if err != nil {
return nil, errors.New("decode 'nsDomainRecordsHealthCheckJSON' failed: " + err.Error())
}
err = nameservers.SharedNSDomainDAO.UpdateRecordsHealthCheckConfig(tx, req.NsDomainId, config)
if err != nil {
return nil, err
}
return this.Success()
}