Initial commit (code only without large binaries)
This commit is contained in:
33
EdgeAPI/internal/db/models/nameservers/ns_domain_dao.go
Normal file
33
EdgeAPI/internal/db/models/nameservers/ns_domain_dao.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
const (
|
||||
NSDomainStateEnabled = 1 // 已启用
|
||||
NSDomainStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type NSDomainDAO dbs.DAO
|
||||
|
||||
func NewNSDomainDAO() *NSDomainDAO {
|
||||
return dbs.NewDAO(&NSDomainDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNSDomains",
|
||||
Model: new(NSDomain),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NSDomainDAO)
|
||||
}
|
||||
|
||||
var SharedNSDomainDAO *NSDomainDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNSDomainDAO = NewNSDomainDAO()
|
||||
})
|
||||
}
|
||||
613
EdgeAPI/internal/db/models/nameservers/ns_domain_dao_plus.go
Normal file
613
EdgeAPI/internal/db/models/nameservers/ns_domain_dao_plus.go
Normal file
@@ -0,0 +1,613 @@
|
||||
//go:build plus
|
||||
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// EnableNSDomain 启用条目
|
||||
func (this *NSDomainDAO) EnableNSDomain(tx *dbs.Tx, domainId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(domainId).
|
||||
Set("state", NSDomainStateEnabled).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, domainId)
|
||||
}
|
||||
|
||||
// DisableNSDomain 禁用条目
|
||||
func (this *NSDomainDAO) DisableNSDomain(tx *dbs.Tx, domainId int64) error {
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Pk(domainId).
|
||||
Set("state", NSDomainStateDisabled).
|
||||
Set("version", version).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, domainId)
|
||||
}
|
||||
|
||||
// FindEnabledNSDomain 查找启用中的条目
|
||||
func (this *NSDomainDAO) FindEnabledNSDomain(tx *dbs.Tx, id int64) (*NSDomain, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", NSDomainStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*NSDomain), err
|
||||
}
|
||||
|
||||
// FindNSDomainName 根据主键查找名称
|
||||
func (this *NSDomainDAO) FindNSDomainName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// CreateDomain 创建域名
|
||||
func (this *NSDomainDAO) CreateDomain(tx *dbs.Tx, clusterId int64, userId int64, groupIds []int64, name string, status dnsconfigs.NSDomainStatus) (int64, error) {
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var op = NewNSDomainOperator()
|
||||
op.ClusterId = clusterId
|
||||
op.UserId = userId
|
||||
|
||||
// group ids
|
||||
if groupIds == nil {
|
||||
groupIds = []int64{}
|
||||
}
|
||||
groupIdsJSON, err := json.Marshal(groupIds)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.GroupIds = groupIdsJSON
|
||||
|
||||
op.Name = strings.ToLower(name)
|
||||
op.Version = version
|
||||
op.IsOn = true
|
||||
if len(status) == 0 {
|
||||
op.Status = dnsconfigs.NSDomainStatusNone
|
||||
} else {
|
||||
op.Status = status
|
||||
}
|
||||
op.State = NSDomainStateEnabled
|
||||
domainId, err := this.SaveInt64(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = this.NotifyUpdate(tx, domainId)
|
||||
if err != nil {
|
||||
return domainId, err
|
||||
}
|
||||
return domainId, nil
|
||||
}
|
||||
|
||||
// UpdateDomain 修改域名
|
||||
// 不能允许用户修改域名名称,因为要重新验证
|
||||
func (this *NSDomainDAO) UpdateDomain(tx *dbs.Tx, domainId int64, clusterId int64, userId int64, groupIds []int64, isOn bool) error {
|
||||
if domainId <= 0 {
|
||||
return errors.New("invalid domainId")
|
||||
}
|
||||
|
||||
oldClusterId, err := this.Query(tx).
|
||||
Pk(domainId).
|
||||
Result("clusterId").
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var op = NewNSDomainOperator()
|
||||
op.Id = domainId
|
||||
|
||||
// 如果集群为0,表示不修改
|
||||
if clusterId > 0 {
|
||||
op.ClusterId = clusterId
|
||||
}
|
||||
|
||||
op.UserId = userId
|
||||
|
||||
// group ids
|
||||
if groupIds == nil {
|
||||
groupIds = []int64{}
|
||||
}
|
||||
groupIdsJSON, err := json.Marshal(groupIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.GroupIds = groupIdsJSON
|
||||
|
||||
op.IsOn = isOn
|
||||
op.Version = version
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 通知更新
|
||||
if clusterId > 0 && oldClusterId > 0 && oldClusterId != clusterId {
|
||||
err = models.SharedNSClusterDAO.NotifyUpdate(tx, oldClusterId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, domainId)
|
||||
}
|
||||
|
||||
// UpdateDomainStatus 修改域名状态
|
||||
func (this *NSDomainDAO) UpdateDomainStatus(tx *dbs.Tx, domainId int64, status dnsconfigs.NSDomainStatus) error {
|
||||
if !dnsconfigs.NSDomainStatusIsValid(status) {
|
||||
return errors.New("invalid status '" + status + "'")
|
||||
}
|
||||
|
||||
if domainId <= 0 {
|
||||
return errors.New("invalid 'domainId'")
|
||||
}
|
||||
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = this.Query(tx).
|
||||
Pk(domainId).
|
||||
Set("version", version).
|
||||
Set("status", status).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, domainId)
|
||||
}
|
||||
|
||||
// CountAllEnabledDomains 计算域名数量
|
||||
func (this *NSDomainDAO) CountAllEnabledDomains(tx *dbs.Tx, clusterId int64, userId int64, groupId int64, status dnsconfigs.NSDomainStatus, keyword string) (int64, error) {
|
||||
query := this.Query(tx)
|
||||
if clusterId > 0 {
|
||||
query.Attr("clusterId", clusterId)
|
||||
} else {
|
||||
query.Where("clusterId IN (SELECT id FROM " + models.SharedNSClusterDAO.Table + " WHERE state=1)")
|
||||
}
|
||||
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
} else {
|
||||
query.Where("(userId=0 OR userId IN (SELECT id FROM " + models.SharedUserDAO.Table + " WHERE state=1))")
|
||||
}
|
||||
|
||||
if groupId > 0 {
|
||||
query.JSONContains("groupIds", types.String(groupId))
|
||||
}
|
||||
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
|
||||
if len(status) > 0 {
|
||||
query.Attr("status", status)
|
||||
}
|
||||
|
||||
return query.
|
||||
State(NSDomainStateEnabled).
|
||||
Count()
|
||||
}
|
||||
|
||||
// ListEnabledDomains 列出单页域名
|
||||
func (this *NSDomainDAO) ListEnabledDomains(tx *dbs.Tx, clusterId int64, userId int64, groupId int64, keyword string, offset int64, size int64) (result []*NSDomain, err error) {
|
||||
query := this.Query(tx)
|
||||
if clusterId > 0 {
|
||||
query.Attr("clusterId", clusterId)
|
||||
} else {
|
||||
query.Where("clusterId IN (SELECT id FROM " + models.SharedNSClusterDAO.Table + " WHERE state=1)")
|
||||
}
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
} else {
|
||||
query.Where("(userId=0 OR userId IN (SELECT id FROM " + models.SharedUserDAO.Table + " WHERE state=1))")
|
||||
}
|
||||
|
||||
if groupId > 0 {
|
||||
query.JSONContains("groupIds", types.String(groupId))
|
||||
}
|
||||
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword)").
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
_, err = query.
|
||||
State(NSDomainStateEnabled).
|
||||
DescPk().
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// IncreaseVersion 增加版本
|
||||
func (this *NSDomainDAO) IncreaseVersion(tx *dbs.Tx) (int64, error) {
|
||||
return models.SharedSysLockerDAO.Increase(tx, "NS_DOMAIN_VERSION", 1)
|
||||
}
|
||||
|
||||
// ListDomainsAfterVersion 列出某个版本后的域名
|
||||
func (this *NSDomainDAO) ListDomainsAfterVersion(tx *dbs.Tx, version int64, size int64) (result []*NSDomain, err error) {
|
||||
if size <= 0 {
|
||||
size = 10000
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Gte("version", version).
|
||||
Limit(size).
|
||||
Asc("version").
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindDomainIdWithName 根据名称查找域名ID
|
||||
func (this *NSDomainDAO) FindDomainIdWithName(tx *dbs.Tx, clusterId int64, userId int64, name string, ignoreUser bool) (int64, error) {
|
||||
if len(name) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
name = strings.ToLower(name)
|
||||
|
||||
var query = this.Query(tx)
|
||||
if clusterId > 0 {
|
||||
query.Attr("clusterId", clusterId)
|
||||
}
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
} else {
|
||||
if !ignoreUser {
|
||||
// 很重要,防止影响其他用户
|
||||
query.Attr("userId", 0)
|
||||
}
|
||||
}
|
||||
return query.
|
||||
Attr("name", name).
|
||||
State(NSDomainStateEnabled).
|
||||
ResultPk().
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// FindDomainWithName 根据名称查找域名
|
||||
func (this *NSDomainDAO) FindDomainWithName(tx *dbs.Tx, userId int64, name string) (*NSDomain, error) {
|
||||
if len(name) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var query = this.Query(tx)
|
||||
one, err := query.
|
||||
Attr("userId", userId).
|
||||
Attr("name", name).
|
||||
State(NSDomainStateEnabled).
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return one.(*NSDomain), nil
|
||||
}
|
||||
|
||||
// FindEnabledDomainTSIG 获取TSIG配置
|
||||
func (this *NSDomainDAO) FindEnabledDomainTSIG(tx *dbs.Tx, domainId int64) ([]byte, error) {
|
||||
tsig, err := this.Query(tx).
|
||||
Pk(domainId).
|
||||
Result("tsig").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(tsig), nil
|
||||
}
|
||||
|
||||
// UpdateDomainTSIG 修改TSIG配置
|
||||
func (this *NSDomainDAO) UpdateDomainTSIG(tx *dbs.Tx, domainId int64, tsigJSON []byte) error {
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = this.Query(tx).
|
||||
Pk(domainId).
|
||||
Set("tsig", tsigJSON).
|
||||
Set("version", version).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, domainId)
|
||||
}
|
||||
|
||||
// FindEnabledDomainClusterId 获取域名的集群ID
|
||||
func (this *NSDomainDAO) FindEnabledDomainClusterId(tx *dbs.Tx, domainId int64) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Pk(domainId).
|
||||
State(NSDomainStateEnabled).
|
||||
Result("clusterId").
|
||||
FindInt64Col(0)
|
||||
}
|
||||
|
||||
// ExistUserDomain 检查域名是否存在
|
||||
func (this *NSDomainDAO) ExistUserDomain(tx *dbs.Tx, userId int64, name string) (bool, error) {
|
||||
name = strings.ToLower(name)
|
||||
return this.Query(tx).
|
||||
Attr("userId", userId).
|
||||
Attr("name", name).
|
||||
State(NSDomainStateEnabled).
|
||||
Exist()
|
||||
}
|
||||
|
||||
// ExistVerifiedDomain 检查是否有验证通过的域名存在
|
||||
func (this *NSDomainDAO) ExistVerifiedDomain(tx *dbs.Tx, name string) (bool, error) {
|
||||
name = strings.ToLower(name)
|
||||
return this.Query(tx).
|
||||
Attr("name", name).
|
||||
State(NSDomainStateEnabled).
|
||||
Attr("status", dnsconfigs.NSDomainStatusVerified).
|
||||
Exist()
|
||||
}
|
||||
|
||||
// CheckUserDomain 检查用户域名
|
||||
func (this *NSDomainDAO) CheckUserDomain(tx *dbs.Tx, userId int64, domainId int64) error {
|
||||
if userId <= 0 || domainId <= 0 {
|
||||
return models.ErrNotFound
|
||||
}
|
||||
|
||||
b, err := this.Query(tx).
|
||||
Pk(domainId).
|
||||
Attr("userId", userId).
|
||||
State(NSDomainStateEnabled).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !b {
|
||||
return models.ErrNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DisableDomainWithName 使用名称删除域名
|
||||
func (this *NSDomainDAO) DisableDomainWithName(tx *dbs.Tx, name string) error {
|
||||
if len(name) == 0 {
|
||||
return nil
|
||||
}
|
||||
domainId, err := this.Query(tx).
|
||||
ResultPk().
|
||||
State(NSDomainStateEnabled).
|
||||
Attr("userId", 0). // 不要删除用户的域名
|
||||
Attr("name", name).
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if domainId == 0 {
|
||||
return nil
|
||||
}
|
||||
return this.DisableNSDomain(tx, domainId)
|
||||
}
|
||||
|
||||
// DisableUserDomainWithName 使用名称删除某个用户域名
|
||||
func (this *NSDomainDAO) DisableUserDomainWithName(tx *dbs.Tx, userId int64, name string) error {
|
||||
if userId <= 0 || len(name) == 0 {
|
||||
return nil
|
||||
}
|
||||
domainId, err := this.Query(tx).
|
||||
ResultPk().
|
||||
State(NSDomainStateEnabled).
|
||||
Attr("userId", userId).
|
||||
Attr("name", name).
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if domainId == 0 {
|
||||
return nil
|
||||
}
|
||||
return this.DisableNSDomain(tx, domainId)
|
||||
}
|
||||
|
||||
// FindDomainVerifyingInfo 查找域名验证信息
|
||||
func (this *NSDomainDAO) FindDomainVerifyingInfo(tx *dbs.Tx, domainId int64, autoCreate bool) (*NSDomain, error) {
|
||||
one, err := this.Query(tx).
|
||||
Pk(domainId).
|
||||
State(NSDomainStateEnabled).
|
||||
Result("verifyTXT", "verifyExpiresAt", "status").
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var domain = one.(*NSDomain)
|
||||
if autoCreate {
|
||||
if domain.Status == dnsconfigs.NSDomainStatusNone && (len(domain.VerifyTXT) == 0 || int64(domain.VerifyExpiresAt) < time.Now().Unix()) {
|
||||
// 生成一个
|
||||
var txt = rands.HexString(32)
|
||||
var expiresAt = time.Now().Unix() + 7200
|
||||
err = this.Query(tx).
|
||||
Pk(domainId).
|
||||
Set("verifyTXT", txt).
|
||||
Set("verifyExpiresAt", expiresAt).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
domain.VerifyTXT = txt
|
||||
domain.VerifyExpiresAt = uint64(expiresAt)
|
||||
}
|
||||
}
|
||||
|
||||
return domain, nil
|
||||
}
|
||||
|
||||
// FindVerifiedDomainWithName 查询验证过的域名
|
||||
func (this *NSDomainDAO) FindVerifiedDomainWithName(tx *dbs.Tx, name string) (*NSDomain, error) {
|
||||
one, err := this.Query(tx).
|
||||
State(NSDomainStateEnabled).
|
||||
Attr("name", name).
|
||||
Attr("status", dnsconfigs.NSDomainStatusVerified).
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
}
|
||||
return one.(*NSDomain), nil
|
||||
}
|
||||
|
||||
// FindVerifiedDomainWithNameOnCluster 查询某个集群上验证过的域名
|
||||
func (this *NSDomainDAO) FindVerifiedDomainWithNameOnCluster(tx *dbs.Tx, clusterId int64, name string) (*NSDomain, error) {
|
||||
one, err := this.Query(tx).
|
||||
State(NSDomainStateEnabled).
|
||||
Attr("clusterId", clusterId).
|
||||
Attr("name", name).
|
||||
Attr("status", dnsconfigs.NSDomainStatusVerified).
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
}
|
||||
return one.(*NSDomain), nil
|
||||
}
|
||||
|
||||
// FindRecordsHealthCheckConfig 查找健康检查配置
|
||||
func (this *NSDomainDAO) FindRecordsHealthCheckConfig(tx *dbs.Tx, domainId int64) (*dnsconfigs.NSRecordsHealthCheckConfig, error) {
|
||||
if domainId <= 0 {
|
||||
return nil, errors.New("not valid 'domainId'")
|
||||
}
|
||||
|
||||
recordsHealthCheckConfigJSON, err := this.Query(tx).
|
||||
Pk(domainId).
|
||||
State(NSDomainStateEnabled).
|
||||
Result("recordsHealthCheck").
|
||||
FindJSONCol()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var config = dnsconfigs.NewNSRecordsHealthCheckConfig()
|
||||
if models.IsNull(recordsHealthCheckConfigJSON) {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
err = json.Unmarshal(recordsHealthCheckConfigJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// UpdateRecordsHealthCheckConfig 修改域名健康检查配置
|
||||
func (this *NSDomainDAO) UpdateRecordsHealthCheckConfig(tx *dbs.Tx, domainId int64, healthCheckConfig *dnsconfigs.NSRecordsHealthCheckConfig) error {
|
||||
if domainId <= 0 {
|
||||
return errors.New("not valid 'domainId'")
|
||||
}
|
||||
|
||||
if healthCheckConfig == nil {
|
||||
return errors.New("'healthCheckConfig' should not be nil")
|
||||
}
|
||||
|
||||
healthCheckConfigJSON, err := json.Marshal(healthCheckConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = this.Query(tx).
|
||||
Pk(domainId).
|
||||
Set("recordsHealthCheck", healthCheckConfigJSON).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 恢复离线记录
|
||||
if !healthCheckConfig.IsOn {
|
||||
err = SharedNSRecordDAO.UpdateDomainRecordsUp(tx, domainId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindDomainsWithHealthCheckOn 查找开启健康检查的域名
|
||||
// TODO 如果域名非常多的情况下,需要优化性能
|
||||
func (this *NSDomainDAO) FindDomainsWithHealthCheckOn(tx *dbs.Tx, queryPlanIds []int64) (result []*NSDomain, err error) {
|
||||
var query = this.Query(tx).
|
||||
Result("id", "userId", "recordsHealthCheck", "name").
|
||||
State(NSDomainStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Where(`JSON_CONTAINS(recordsHealthCheck, '{"isOn": true}')`)
|
||||
if len(queryPlanIds) > 0 {
|
||||
// 排序以便于让SQL尽可能得到重用
|
||||
sort.Slice(queryPlanIds, func(i, j int) bool {
|
||||
return queryPlanIds[i] < queryPlanIds[j]
|
||||
})
|
||||
|
||||
var queryPlanStringIds = []string{}
|
||||
for _, planId := range queryPlanIds {
|
||||
queryPlanStringIds = append(queryPlanStringIds, types.String(planId))
|
||||
}
|
||||
query.Where("userId IN (SELECT userId FROM " + SharedNSUserPlanDAO.Table + " WHERE state=1 AND dayTo>=:dayTo AND planId IN (" + strings.Join(queryPlanStringIds, ",") + "))")
|
||||
query.Param("dayTo", timeutil.Format("Ymd"))
|
||||
}
|
||||
_, err = query.
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更改
|
||||
func (this *NSDomainDAO) NotifyUpdate(tx *dbs.Tx, domainId int64) error {
|
||||
clusterId, err := this.Query(tx).
|
||||
Result("clusterId").
|
||||
Pk(domainId).
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if clusterId > 0 {
|
||||
return models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, 0, models.NSNodeTaskTypeDomainChanged)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
@@ -0,0 +1,6 @@
|
||||
package nameservers_test
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
@@ -0,0 +1,149 @@
|
||||
//go:build plus
|
||||
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
const (
|
||||
NSDomainGroupStateEnabled = 1 // 已启用
|
||||
NSDomainGroupStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type NSDomainGroupDAO dbs.DAO
|
||||
|
||||
func NewNSDomainGroupDAO() *NSDomainGroupDAO {
|
||||
return dbs.NewDAO(&NSDomainGroupDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNSDomainGroups",
|
||||
Model: new(NSDomainGroup),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NSDomainGroupDAO)
|
||||
}
|
||||
|
||||
var SharedNSDomainGroupDAO *NSDomainGroupDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNSDomainGroupDAO = NewNSDomainGroupDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableNSDomainGroup 启用条目
|
||||
func (this *NSDomainGroupDAO) EnableNSDomainGroup(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSDomainGroupStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableNSDomainGroup 禁用条目
|
||||
func (this *NSDomainGroupDAO) DisableNSDomainGroup(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSDomainGroupStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// FindEnabledNSDomainGroup 查找启用中的条目
|
||||
func (this *NSDomainGroupDAO) FindEnabledNSDomainGroup(tx *dbs.Tx, id int64) (*NSDomainGroup, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", NSDomainGroupStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*NSDomainGroup), err
|
||||
}
|
||||
|
||||
// FindNSDomainGroupName 根据主键查找名称
|
||||
func (this *NSDomainGroupDAO) FindNSDomainGroupName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// CreateGroup 创建分组
|
||||
func (this *NSDomainGroupDAO) CreateGroup(tx *dbs.Tx, userId int64, name string) (int64, error) {
|
||||
var op = NewNSDomainGroupOperator()
|
||||
op.UserId = userId
|
||||
op.Name = name
|
||||
op.State = NSDomainGroupStateEnabled
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// UpdateGroup 修改分组
|
||||
func (this *NSDomainGroupDAO) UpdateGroup(tx *dbs.Tx, groupId int64, name string, isOn bool) error {
|
||||
if groupId <= 0 {
|
||||
return errors.New("invalid groupId")
|
||||
}
|
||||
var op = NewNSDomainGroupOperator()
|
||||
op.Id = groupId
|
||||
op.Name = name
|
||||
op.IsOn = isOn
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// FindAllGroups 查找所有分组
|
||||
func (this *NSDomainGroupDAO) FindAllGroups(tx *dbs.Tx, userId int64) (result []*NSDomainGroup, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Attr("userId", userId).
|
||||
State(NSDomainGroupStateEnabled).
|
||||
Desc("order").
|
||||
AscPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// CountAllAvailableGroups 计算可用分组数量
|
||||
func (this *NSDomainGroupDAO) CountAllAvailableGroups(tx *dbs.Tx, userId int64) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Attr("userId", userId).
|
||||
Attr("isOn", true).
|
||||
State(NSDomainGroupStateEnabled).
|
||||
Count()
|
||||
}
|
||||
|
||||
// FindAllAvailableGroups 查找所有分组
|
||||
func (this *NSDomainGroupDAO) FindAllAvailableGroups(tx *dbs.Tx, userId int64) (result []*NSDomainGroup, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Attr("userId", userId).
|
||||
Attr("isOn", true).
|
||||
State(NSDomainGroupStateEnabled).
|
||||
Desc("order").
|
||||
AscPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// CheckUserGroup 检查用户分组
|
||||
func (this *NSDomainGroupDAO) CheckUserGroup(tx *dbs.Tx, userId int64, groupId int64) error {
|
||||
if groupId <= 0 || userId <= 0 {
|
||||
return models.ErrNotFound
|
||||
}
|
||||
b, err := this.Query(tx).
|
||||
Pk(groupId).
|
||||
State(NSDomainGroupStateEnabled).
|
||||
Attr("userId", userId).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !b {
|
||||
return models.ErrNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package nameservers_test
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
@@ -0,0 +1,24 @@
|
||||
package nameservers
|
||||
|
||||
// NSDomainGroup 域名分组
|
||||
type NSDomainGroup struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
Name string `field:"name"` // 分组名称
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Order uint32 `field:"order"` // 排序
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type NSDomainGroupOperator struct {
|
||||
Id interface{} // ID
|
||||
UserId interface{} // 用户ID
|
||||
Name interface{} // 分组名称
|
||||
IsOn interface{} // 是否启用
|
||||
Order interface{} // 排序
|
||||
State interface{} // 状态
|
||||
}
|
||||
|
||||
func NewNSDomainGroupOperator() *NSDomainGroupOperator {
|
||||
return &NSDomainGroupOperator{}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package nameservers
|
||||
42
EdgeAPI/internal/db/models/nameservers/ns_domain_model.go
Normal file
42
EdgeAPI/internal/db/models/nameservers/ns_domain_model.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package nameservers
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// NSDomain DNS域名
|
||||
type NSDomain struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
UserId uint32 `field:"userId"` // 用户ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 域名
|
||||
GroupIds dbs.JSON `field:"groupIds"` // 分组ID
|
||||
Tsig dbs.JSON `field:"tsig"` // TSIG配置
|
||||
VerifyTXT string `field:"verifyTXT"` // 验证用的TXT
|
||||
VerifyExpiresAt uint64 `field:"verifyExpiresAt"` // 验证TXT过期时间
|
||||
RecordsHealthCheck dbs.JSON `field:"recordsHealthCheck"` // 记录健康检查设置
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Version uint64 `field:"version"` // 版本号
|
||||
Status string `field:"status"` // 状态:none|verified
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type NSDomainOperator struct {
|
||||
Id any // ID
|
||||
ClusterId any // 集群ID
|
||||
UserId any // 用户ID
|
||||
IsOn any // 是否启用
|
||||
Name any // 域名
|
||||
GroupIds any // 分组ID
|
||||
Tsig any // TSIG配置
|
||||
VerifyTXT any // 验证用的TXT
|
||||
VerifyExpiresAt any // 验证TXT过期时间
|
||||
RecordsHealthCheck any // 记录健康检查设置
|
||||
CreatedAt any // 创建时间
|
||||
Version any // 版本号
|
||||
Status any // 状态:none|verified
|
||||
State any // 状态
|
||||
}
|
||||
|
||||
func NewNSDomainOperator() *NSDomainOperator {
|
||||
return &NSDomainOperator{}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
)
|
||||
|
||||
func (this *NSDomain) DecodeGroupIds() []int64 {
|
||||
if models.IsNull(this.GroupIds) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var result = []int64{}
|
||||
err := json.Unmarshal(this.GroupIds, &result)
|
||||
if err != nil {
|
||||
remotelogs.Error("NSDomain", "DecodeGroupIds:"+err.Error())
|
||||
}
|
||||
return result
|
||||
}
|
||||
233
EdgeAPI/internal/db/models/nameservers/ns_key_dao_plus.go
Normal file
233
EdgeAPI/internal/db/models/nameservers/ns_key_dao_plus.go
Normal file
@@ -0,0 +1,233 @@
|
||||
//go:build plus
|
||||
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
const (
|
||||
NSKeyStateEnabled = 1 // 已启用
|
||||
NSKeyStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type NSKeyDAO dbs.DAO
|
||||
|
||||
func NewNSKeyDAO() *NSKeyDAO {
|
||||
return dbs.NewDAO(&NSKeyDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNSKeys",
|
||||
Model: new(NSKey),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NSKeyDAO)
|
||||
}
|
||||
|
||||
var SharedNSKeyDAO *NSKeyDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNSKeyDAO = NewNSKeyDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableNSKey 启用条目
|
||||
func (this *NSKeyDAO) EnableNSKey(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSKeyStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableNSKey 禁用条目
|
||||
func (this *NSKeyDAO) DisableNSKey(tx *dbs.Tx, keyId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(keyId).
|
||||
Set("state", NSKeyStateDisabled).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, keyId)
|
||||
}
|
||||
|
||||
// FindEnabledNSKey 查找启用中的条目
|
||||
func (this *NSKeyDAO) FindEnabledNSKey(tx *dbs.Tx, id int64) (*NSKey, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", NSKeyStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*NSKey), err
|
||||
}
|
||||
|
||||
// FindNSKeyName 根据主键查找名称
|
||||
func (this *NSKeyDAO) FindNSKeyName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// CreateKey 创建Key
|
||||
func (this *NSKeyDAO) CreateKey(tx *dbs.Tx, domainId int64, zoneId int64, name string, algo dnsconfigs.KeyAlgorithmType, secret string, secretType string) (int64, error) {
|
||||
var op = NewNSKeyOperator()
|
||||
op.DomainId = domainId
|
||||
op.ZoneId = zoneId
|
||||
op.Name = name
|
||||
op.Algo = algo
|
||||
op.Secret = secret
|
||||
op.SecretType = secretType
|
||||
op.State = NSKeyStateEnabled
|
||||
keyId, err := this.SaveInt64(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = this.NotifyUpdate(tx, keyId)
|
||||
if err != nil {
|
||||
return keyId, err
|
||||
}
|
||||
|
||||
return keyId, nil
|
||||
}
|
||||
|
||||
// UpdateKey 修改Key
|
||||
func (this *NSKeyDAO) UpdateKey(tx *dbs.Tx, keyId int64, name string, algo dnsconfigs.KeyAlgorithmType, secret string, secretType string, isOn bool) error {
|
||||
if keyId <= 0 {
|
||||
return errors.New("invalid keyId")
|
||||
}
|
||||
var op = NewNSKeyOperator()
|
||||
op.Id = keyId
|
||||
op.Name = name
|
||||
op.Algo = algo
|
||||
op.Secret = secret
|
||||
op.SecretType = secretType
|
||||
op.IsOn = isOn
|
||||
err := this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, keyId)
|
||||
}
|
||||
|
||||
// CountEnabledKeys 计算Key的数量
|
||||
func (this *NSKeyDAO) CountEnabledKeys(tx *dbs.Tx, domainId int64, zoneId int64) (int64, error) {
|
||||
var query = this.Query(tx).
|
||||
State(NSKeyStateEnabled)
|
||||
if domainId > 0 {
|
||||
query.Attr("domainId", domainId)
|
||||
}
|
||||
if zoneId > 0 {
|
||||
query.Attr("zoneId", zoneId)
|
||||
}
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// ListEnabledKeys 列出单页Key
|
||||
func (this *NSKeyDAO) ListEnabledKeys(tx *dbs.Tx, domainId int64, zoneId int64, offset int64, size int64) (result []*NSKey, err error) {
|
||||
var query = this.Query(tx).
|
||||
State(NSKeyStateEnabled)
|
||||
if domainId > 0 {
|
||||
query.Attr("domainId", domainId)
|
||||
}
|
||||
if zoneId > 0 {
|
||||
query.Attr("zoneId", zoneId)
|
||||
}
|
||||
_, err = query.
|
||||
DescPk().
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// IncreaseVersion 增加版本
|
||||
func (this *NSKeyDAO) IncreaseVersion(tx *dbs.Tx) (int64, error) {
|
||||
return models.SharedSysLockerDAO.Increase(tx, "NS_KEY_VERSION", 1)
|
||||
}
|
||||
|
||||
// ListKeysAfterVersion 列出某个版本后的密钥
|
||||
func (this *NSKeyDAO) ListKeysAfterVersion(tx *dbs.Tx, version int64, size int64) (result []*NSKey, err error) {
|
||||
if size <= 0 {
|
||||
size = 10000
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Gte("version", version).
|
||||
Limit(size).
|
||||
Asc("version").
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// CheckUserKey 检查用户权限
|
||||
func (this *NSKeyDAO) CheckUserKey(tx *dbs.Tx, userId int64, keyId int64) error {
|
||||
if userId <= 0 || keyId <= 0 {
|
||||
return models.ErrNotFound
|
||||
}
|
||||
|
||||
domainId, err := this.Query(tx).
|
||||
Result("domainId").
|
||||
Pk(keyId).
|
||||
State(NSKeyStateEnabled).
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if domainId <= 0 {
|
||||
return models.ErrNotFound
|
||||
}
|
||||
|
||||
return SharedNSDomainDAO.CheckUserDomain(tx, userId, domainId)
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *NSKeyDAO) NotifyUpdate(tx *dbs.Tx, keyId int64) error {
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = this.Query(tx).
|
||||
Pk(keyId).
|
||||
Set("version", version).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 通知集群
|
||||
domainId, err := this.Query(tx).
|
||||
Pk(keyId).
|
||||
Result("domainId").
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if domainId > 0 {
|
||||
clusterId, err := SharedNSDomainDAO.FindEnabledDomainClusterId(tx, domainId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if clusterId > 0 {
|
||||
err = models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, 0, models.NSNodeTaskTypeKeyChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
32
EdgeAPI/internal/db/models/nameservers/ns_key_model.go
Normal file
32
EdgeAPI/internal/db/models/nameservers/ns_key_model.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package nameservers
|
||||
|
||||
// NSKey 密钥管理
|
||||
type NSKey struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 状态
|
||||
Name string `field:"name"` // 名称
|
||||
DomainId uint64 `field:"domainId"` // 域名ID
|
||||
ZoneId uint64 `field:"zoneId"` // 子域ID
|
||||
Algo string `field:"algo"` // 算法
|
||||
Secret string `field:"secret"` // 密码
|
||||
SecretType string `field:"secretType"` // 密码类型
|
||||
Version uint64 `field:"version"` // 版本号
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type NSKeyOperator struct {
|
||||
Id interface{} // ID
|
||||
IsOn interface{} // 状态
|
||||
Name interface{} // 名称
|
||||
DomainId interface{} // 域名ID
|
||||
ZoneId interface{} // 子域ID
|
||||
Algo interface{} // 算法
|
||||
Secret interface{} // 密码
|
||||
SecretType interface{} // 密码类型
|
||||
Version interface{} // 版本号
|
||||
State interface{} // 状态
|
||||
}
|
||||
|
||||
func NewNSKeyOperator() *NSKeyOperator {
|
||||
return &NSKeyOperator{}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package nameservers
|
||||
168
EdgeAPI/internal/db/models/nameservers/ns_plan_dao_plus.go
Normal file
168
EdgeAPI/internal/db/models/nameservers/ns_plan_dao_plus.go
Normal file
@@ -0,0 +1,168 @@
|
||||
//go:build plus
|
||||
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
const (
|
||||
NSPlanStateEnabled = 1 // 已启用
|
||||
NSPlanStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type NSPlanDAO dbs.DAO
|
||||
|
||||
func NewNSPlanDAO() *NSPlanDAO {
|
||||
return dbs.NewDAO(&NSPlanDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNSPlans",
|
||||
Model: new(NSPlan),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NSPlanDAO)
|
||||
}
|
||||
|
||||
var SharedNSPlanDAO *NSPlanDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNSPlanDAO = NewNSPlanDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableNSPlan 启用条目
|
||||
func (this *NSPlanDAO) EnableNSPlan(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSPlanStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableNSPlan 禁用条目
|
||||
func (this *NSPlanDAO) DisableNSPlan(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSPlanStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// FindEnabledNSPlan 查找启用中的条目
|
||||
func (this *NSPlanDAO) FindEnabledNSPlan(tx *dbs.Tx, id int64) (*NSPlan, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
State(NSPlanStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*NSPlan), err
|
||||
}
|
||||
|
||||
// FindNSPlanName 根据主键查找名称
|
||||
func (this *NSPlanDAO) FindNSPlanName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// CreatePlan 创建套餐
|
||||
func (this *NSPlanDAO) CreatePlan(tx *dbs.Tx, name string, monthlyPrice float32, yearlyPrice float32, config *dnsconfigs.NSPlanConfig) (int64, error) {
|
||||
var op = NewNSPlanOperator()
|
||||
op.Name = name
|
||||
op.MonthlyPrice = monthlyPrice
|
||||
op.YearlyPrice = yearlyPrice
|
||||
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.Config = configJSON
|
||||
op.IsOn = true
|
||||
op.State = NSPlanStateEnabled
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// UpdatePlan 修改套餐
|
||||
func (this *NSPlanDAO) UpdatePlan(tx *dbs.Tx, planId int64, name string, isOn bool, monthlyPrice float32, yearlyPrice float32, config *dnsconfigs.NSPlanConfig) error {
|
||||
if planId <= 0 {
|
||||
return errors.New("invalid planId")
|
||||
}
|
||||
var op = NewNSPlanOperator()
|
||||
op.Id = planId
|
||||
op.Name = name
|
||||
op.MonthlyPrice = monthlyPrice
|
||||
op.YearlyPrice = yearlyPrice
|
||||
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.Config = configJSON
|
||||
op.IsOn = isOn
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// UpdatePlanOrders 修改套餐排序
|
||||
func (this *NSPlanDAO) UpdatePlanOrders(tx *dbs.Tx, planIds []int64) error {
|
||||
var total = len(planIds)
|
||||
if total == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
total++
|
||||
|
||||
for index, planId := range planIds {
|
||||
err := this.Query(tx).
|
||||
Pk(planId).
|
||||
Set("order", total-index).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindAllPlans 查找所有套餐
|
||||
func (this *NSPlanDAO) FindAllPlans(tx *dbs.Tx) (result []*NSPlan, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(NSPlanStateEnabled).
|
||||
Desc("order").
|
||||
AscPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindAllEnabledPlans 查找所有可用套餐
|
||||
func (this *NSPlanDAO) FindAllEnabledPlans(tx *dbs.Tx) (result []*NSPlan, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(NSPlanStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Desc("order").
|
||||
AscPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// ExistPlan 检查套餐是否存在
|
||||
func (this *NSPlanDAO) ExistPlan(tx *dbs.Tx, planId int64) (bool, error) {
|
||||
if planId <= 0 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Pk(planId).
|
||||
Exist()
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package nameservers_test
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
30
EdgeAPI/internal/db/models/nameservers/ns_plan_model.go
Normal file
30
EdgeAPI/internal/db/models/nameservers/ns_plan_model.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package nameservers
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// NSPlan NS套餐
|
||||
type NSPlan struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
Name string `field:"name"` // 套餐名称
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
MonthlyPrice float64 `field:"monthlyPrice"` // 月价格
|
||||
YearlyPrice float64 `field:"yearlyPrice"` // 年价格
|
||||
Order uint32 `field:"order"` // 排序
|
||||
Config dbs.JSON `field:"config"` // 配置
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type NSPlanOperator struct {
|
||||
Id any // ID
|
||||
Name any // 套餐名称
|
||||
IsOn any // 是否启用
|
||||
MonthlyPrice any // 月价格
|
||||
YearlyPrice any // 年价格
|
||||
Order any // 排序
|
||||
Config any // 配置
|
||||
State any // 状态
|
||||
}
|
||||
|
||||
func NewNSPlanOperator() *NSPlanOperator {
|
||||
return &NSPlanOperator{}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package nameservers
|
||||
@@ -0,0 +1,69 @@
|
||||
//go:build plus
|
||||
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type NSQuestionOptionDAO dbs.DAO
|
||||
|
||||
func NewNSQuestionOptionDAO() *NSQuestionOptionDAO {
|
||||
return dbs.NewDAO(&NSQuestionOptionDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNSQuestionOptions",
|
||||
Model: new(NSQuestionOption),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NSQuestionOptionDAO)
|
||||
}
|
||||
|
||||
var SharedNSQuestionOptionDAO *NSQuestionOptionDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNSQuestionOptionDAO = NewNSQuestionOptionDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// FindNSQuestionOptionName 根据主键查找名称
|
||||
func (this *NSQuestionOptionDAO) FindNSQuestionOptionName(tx *dbs.Tx, id uint64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// CreateOption 创建选项
|
||||
func (this *NSQuestionOptionDAO) CreateOption(tx *dbs.Tx, name string, values maps.Map) (int64, error) {
|
||||
if values == nil {
|
||||
values = maps.Map{}
|
||||
}
|
||||
var op = NewNSQuestionOptionOperator()
|
||||
op.Name = name
|
||||
op.Values = values.AsJSON()
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// FindOption 读取选项
|
||||
func (this *NSQuestionOptionDAO) FindOption(tx *dbs.Tx, optionId int64) (*NSQuestionOption, error) {
|
||||
one, err := this.Query(tx).
|
||||
Pk(optionId).
|
||||
Find()
|
||||
if one == nil {
|
||||
return nil, err
|
||||
}
|
||||
return one.(*NSQuestionOption), nil
|
||||
}
|
||||
|
||||
// DeleteOption 删除选项
|
||||
func (this *NSQuestionOptionDAO) DeleteOption(tx *dbs.Tx, optionId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(optionId).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
@@ -0,0 +1,22 @@
|
||||
package nameservers
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// NSQuestionOption DNS请求选项
|
||||
type NSQuestionOption struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
Name string `field:"name"` // 选项名
|
||||
Values dbs.JSON `field:"values"` // 选项值
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
}
|
||||
|
||||
type NSQuestionOptionOperator struct {
|
||||
Id interface{} // ID
|
||||
Name interface{} // 选项名
|
||||
Values interface{} // 选项值
|
||||
CreatedAt interface{} // 创建时间
|
||||
}
|
||||
|
||||
func NewNSQuestionOptionOperator() *NSQuestionOptionOperator {
|
||||
return &NSQuestionOptionOperator{}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package nameservers
|
||||
73
EdgeAPI/internal/db/models/nameservers/ns_record_dao.go
Normal file
73
EdgeAPI/internal/db/models/nameservers/ns_record_dao.go
Normal file
@@ -0,0 +1,73 @@
|
||||
//go:build !plus
|
||||
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
const (
|
||||
NSRecordStateEnabled = 1 // 已启用
|
||||
NSRecordStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type NSRecordDAO dbs.DAO
|
||||
|
||||
func NewNSRecordDAO() *NSRecordDAO {
|
||||
return dbs.NewDAO(&NSRecordDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNSRecords",
|
||||
Model: new(NSRecord),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NSRecordDAO)
|
||||
}
|
||||
|
||||
var SharedNSRecordDAO *NSRecordDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNSRecordDAO = NewNSRecordDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableNSRecord 启用条目
|
||||
func (this *NSRecordDAO) EnableNSRecord(tx *dbs.Tx, id uint64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSRecordStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableNSRecord 禁用条目
|
||||
func (this *NSRecordDAO) DisableNSRecord(tx *dbs.Tx, id uint64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSRecordStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// FindEnabledNSRecord 查找启用中的条目
|
||||
func (this *NSRecordDAO) FindEnabledNSRecord(tx *dbs.Tx, id uint64) (*NSRecord, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
State(NSRecordStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*NSRecord), err
|
||||
}
|
||||
|
||||
// FindNSRecordName 根据主键查找名称
|
||||
func (this *NSRecordDAO) FindNSRecordName(tx *dbs.Tx, id uint64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
849
EdgeAPI/internal/db/models/nameservers/ns_record_dao_plus.go
Normal file
849
EdgeAPI/internal/db/models/nameservers/ns_record_dao_plus.go
Normal file
@@ -0,0 +1,849 @@
|
||||
//go:build plus
|
||||
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
NSRecordStateEnabled = 1 // 已启用
|
||||
NSRecordStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type NSRecordDAO dbs.DAO
|
||||
|
||||
func NewNSRecordDAO() *NSRecordDAO {
|
||||
return dbs.NewDAO(&NSRecordDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNSRecords",
|
||||
Model: new(NSRecord),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NSRecordDAO)
|
||||
}
|
||||
|
||||
var SharedNSRecordDAO *NSRecordDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNSRecordDAO = NewNSRecordDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableNSRecord 启用条目
|
||||
func (this *NSRecordDAO) EnableNSRecord(tx *dbs.Tx, recordId int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(recordId).
|
||||
Set("state", NSRecordStateEnabled).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, recordId)
|
||||
}
|
||||
|
||||
// DisableNSRecord 禁用条目
|
||||
func (this *NSRecordDAO) DisableNSRecord(tx *dbs.Tx, recordId int64) error {
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Pk(recordId).
|
||||
Set("state", NSRecordStateDisabled).
|
||||
Set("version", version).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx, recordId)
|
||||
}
|
||||
|
||||
// FindEnabledNSRecord 查找启用中的条目
|
||||
func (this *NSRecordDAO) FindEnabledNSRecord(tx *dbs.Tx, id int64) (*NSRecord, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", NSRecordStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*NSRecord), err
|
||||
}
|
||||
|
||||
// FindNSRecordName 根据主键查找名称
|
||||
func (this *NSRecordDAO) FindNSRecordName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// CreateRecord 创建记录
|
||||
func (this *NSRecordDAO) CreateRecord(tx *dbs.Tx, domainId int64, description string, name string, recordType dnsconfigs.RecordType, value string, mxPriority int32, srvPriority int32, srvWeight int32, srvPort int32, caaFlag int32, caaTag string, ttl int32, routeIds []string, weight int32) (int64, error) {
|
||||
// TTL默认值
|
||||
// TODO 根据用户级别设置不同的TTL
|
||||
if ttl <= 0 {
|
||||
ttl = 600
|
||||
}
|
||||
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// 处理各个类型的值
|
||||
recordType = strings.ToUpper(recordType)
|
||||
switch recordType {
|
||||
case dnsconfigs.RecordTypeCNAME:
|
||||
if !strings.HasSuffix(value, ".") {
|
||||
value += "."
|
||||
}
|
||||
}
|
||||
|
||||
var op = NewNSRecordOperator()
|
||||
op.DomainId = domainId
|
||||
op.Description = description
|
||||
op.Name = name
|
||||
op.Type = recordType
|
||||
op.Value = value
|
||||
|
||||
// mx priority
|
||||
if recordType == dnsconfigs.RecordTypeMX {
|
||||
if mxPriority > 0 {
|
||||
op.MxPriority = mxPriority
|
||||
} else {
|
||||
op.MxPriority = 0
|
||||
}
|
||||
}
|
||||
|
||||
// srv
|
||||
if recordType == dnsconfigs.RecordTypeSRV {
|
||||
op.SrvPriority = srvPriority
|
||||
op.SrvWeight = srvWeight
|
||||
op.SrvPort = srvPort
|
||||
}
|
||||
|
||||
// caa
|
||||
if recordType == dnsconfigs.RecordTypeCAA {
|
||||
op.CaaFlag = caaFlag
|
||||
op.CaaTag = caaTag
|
||||
}
|
||||
|
||||
op.Ttl = ttl
|
||||
|
||||
if len(routeIds) == 0 {
|
||||
op.RouteIds = `["default"]`
|
||||
} else {
|
||||
routeIds, err := json.Marshal(routeIds)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
op.RouteIds = routeIds
|
||||
}
|
||||
|
||||
op.Weight = weight
|
||||
|
||||
op.IsOn = true
|
||||
op.IsUp = true
|
||||
op.State = NSRecordStateEnabled
|
||||
op.Version = version
|
||||
recordId, err := this.SaveInt64(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = this.NotifyUpdate(tx, recordId)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return recordId, nil
|
||||
}
|
||||
|
||||
// UpdateRecord 修改记录
|
||||
func (this *NSRecordDAO) UpdateRecord(tx *dbs.Tx, recordId int64, description string, name string, recordType dnsconfigs.RecordType, value string, mxPriority int32, srvPriority int32, srvWeight int32, srvPort int32, caaFlag int32, caaTag string, ttl int32, routeIds []string, weight int32, isOn bool) error {
|
||||
// 以前信息
|
||||
// 不需要增加状态条件
|
||||
oldValue, err := this.Query(tx).
|
||||
Pk(recordId).
|
||||
Result("value").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TTL默认值
|
||||
// TODO 根据用户级别设置不同的TTL
|
||||
if ttl <= 0 {
|
||||
ttl = 600
|
||||
}
|
||||
|
||||
if recordId <= 0 {
|
||||
return errors.New("invalid recordId")
|
||||
}
|
||||
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 处理各个类型的值
|
||||
recordType = strings.ToUpper(recordType)
|
||||
switch recordType {
|
||||
case dnsconfigs.RecordTypeCNAME:
|
||||
if !strings.HasSuffix(value, ".") {
|
||||
value += "."
|
||||
}
|
||||
}
|
||||
|
||||
var op = NewNSRecordOperator()
|
||||
op.Id = recordId
|
||||
op.Description = description
|
||||
op.Name = name
|
||||
op.Type = recordType
|
||||
op.Value = value
|
||||
|
||||
// mx priority
|
||||
if recordType == dnsconfigs.RecordTypeMX {
|
||||
if mxPriority > 0 {
|
||||
op.MxPriority = mxPriority
|
||||
} else {
|
||||
op.MxPriority = 0
|
||||
}
|
||||
}
|
||||
|
||||
// srv
|
||||
if recordType == dnsconfigs.RecordTypeSRV {
|
||||
op.SrvPriority = srvPriority
|
||||
op.SrvWeight = srvWeight
|
||||
op.SrvPort = srvPort
|
||||
}
|
||||
|
||||
// caa
|
||||
if recordType == dnsconfigs.RecordTypeCAA {
|
||||
op.CaaFlag = caaFlag
|
||||
op.CaaTag = caaTag
|
||||
}
|
||||
|
||||
op.Ttl = ttl
|
||||
op.Weight = weight
|
||||
op.IsOn = isOn
|
||||
|
||||
if oldValue != value {
|
||||
op.IsUp = true
|
||||
}
|
||||
|
||||
if len(routeIds) == 0 {
|
||||
op.RouteIds = `["default"]`
|
||||
} else {
|
||||
routeIdsJSON, err := json.Marshal(routeIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
op.RouteIds = routeIdsJSON
|
||||
}
|
||||
|
||||
op.Version = version
|
||||
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, recordId)
|
||||
}
|
||||
|
||||
// CountAllEnabledDomainRecords 计算域名中记录数量
|
||||
func (this *NSRecordDAO) CountAllEnabledDomainRecords(tx *dbs.Tx, domainId int64, dnsType dnsconfigs.RecordType, keyword string, routeCode string) (int64, error) {
|
||||
query := this.Query(tx).
|
||||
Attr("domainId", domainId).
|
||||
State(NSRecordStateEnabled)
|
||||
if len(dnsType) > 0 {
|
||||
query.Attr("type", dnsType)
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
var args = utils.SplitKeywordArgs(keyword)
|
||||
if len(args) > 0 {
|
||||
var realKeyword = ""
|
||||
for _, arg := range args {
|
||||
switch arg.Key {
|
||||
case "name":
|
||||
query.Attr("name", arg.Value)
|
||||
case "value":
|
||||
query.Attr("value", arg.Value)
|
||||
case "type":
|
||||
query.Attr("type", arg.Value)
|
||||
default:
|
||||
if len(realKeyword) > 0 {
|
||||
realKeyword += " " + arg.String()
|
||||
} else {
|
||||
realKeyword += arg.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
keyword = realKeyword
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword OR value LIKE :keyword OR description LIKE :keyword)").
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
}
|
||||
if len(routeCode) > 0 {
|
||||
routeCodeJSON, err := json.Marshal(routeCode)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
query.JSONContains("routeIds", string(routeCodeJSON))
|
||||
}
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// CountAllRecordsWithName 查询域名中相同记录名的数量
|
||||
func (this *NSRecordDAO) CountAllRecordsWithName(tx *dbs.Tx, domainId int64, dnsType dnsconfigs.RecordType, name string) (int64, error) {
|
||||
return this.Query(tx).
|
||||
State(NSRecordStateEnabled).
|
||||
Attr("domainId", domainId).
|
||||
Attr("type", dnsType).
|
||||
Attr("name", name).
|
||||
Count()
|
||||
}
|
||||
|
||||
// CountAllEnabledRecords 计算所有记录数量
|
||||
func (this *NSRecordDAO) CountAllEnabledRecords(tx *dbs.Tx) (int64, error) {
|
||||
return this.Query(tx).
|
||||
Where("domainId IN (SELECT id FROM " + SharedNSDomainDAO.Table + " WHERE state=1)").
|
||||
State(NSRecordStateEnabled).
|
||||
Count()
|
||||
}
|
||||
|
||||
// ListEnabledRecords 列出单页记录
|
||||
func (this *NSRecordDAO) ListEnabledRecords(tx *dbs.Tx,
|
||||
domainId int64,
|
||||
dnsType dnsconfigs.RecordType,
|
||||
keyword string,
|
||||
routeCode string,
|
||||
nameAsc bool,
|
||||
nameDesc bool,
|
||||
typeAsc bool,
|
||||
typeDesc bool,
|
||||
ttlAsc bool,
|
||||
ttlDesc bool,
|
||||
upAsc bool,
|
||||
upDesc bool,
|
||||
offset int64,
|
||||
size int64) (result []*NSRecord, err error) {
|
||||
var query = this.Query(tx).
|
||||
Attr("domainId", domainId).
|
||||
State(NSRecordStateEnabled)
|
||||
if len(dnsType) > 0 {
|
||||
query.Attr("type", dnsType)
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
var args = utils.SplitKeywordArgs(keyword)
|
||||
if len(args) > 0 {
|
||||
var realKeyword = ""
|
||||
for _, arg := range args {
|
||||
switch arg.Key {
|
||||
case "name":
|
||||
query.Attr("name", arg.Value)
|
||||
case "value":
|
||||
query.Attr("value", arg.Value)
|
||||
case "type":
|
||||
query.Attr("type", arg.Value)
|
||||
default:
|
||||
if len(realKeyword) > 0 {
|
||||
realKeyword += " " + arg.String()
|
||||
} else {
|
||||
realKeyword += arg.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
keyword = realKeyword
|
||||
}
|
||||
if len(keyword) > 0 {
|
||||
query.Where("(name LIKE :keyword OR value LIKE :keyword OR description LIKE :keyword)").
|
||||
Param("keyword", dbutils.QuoteLike(keyword))
|
||||
}
|
||||
}
|
||||
if len(routeCode) > 0 {
|
||||
routeCodeJSON, err := json.Marshal(routeCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query.JSONContains("routeIds", string(routeCodeJSON))
|
||||
}
|
||||
|
||||
// 排序
|
||||
if nameAsc {
|
||||
query.Asc("name")
|
||||
} else if nameDesc {
|
||||
query.Desc("name")
|
||||
}
|
||||
|
||||
if typeAsc {
|
||||
query.Asc("type")
|
||||
} else if typeDesc {
|
||||
query.Desc("type")
|
||||
}
|
||||
|
||||
if ttlAsc {
|
||||
query.Asc("ttl")
|
||||
} else if ttlDesc {
|
||||
query.Desc("ttl")
|
||||
}
|
||||
|
||||
if upAsc {
|
||||
query.Asc("IF(JSON_CONTAINS(healthCheck, '{\"isOn\": true}'),isUp,2) ")
|
||||
} else if upDesc {
|
||||
query.Desc("isUp + JSON_CONTAINS(healthCheck, '{\"isOn\": true}')")
|
||||
}
|
||||
|
||||
_, err = query.
|
||||
DescPk().
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// IncreaseVersion 增加版本
|
||||
func (this *NSRecordDAO) IncreaseVersion(tx *dbs.Tx) (int64, error) {
|
||||
return models.SharedSysLockerDAO.Increase(tx, "NS_RECORD_VERSION", 1)
|
||||
}
|
||||
|
||||
// ListRecordsAfterVersion 列出某个版本后的记录
|
||||
func (this *NSRecordDAO) ListRecordsAfterVersion(tx *dbs.Tx, version int64, size int64) (result []*NSRecord, err error) {
|
||||
if size <= 0 {
|
||||
size = 10000
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Gte("version", version).
|
||||
Limit(size).
|
||||
Asc("version").
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindEnabledRecordWithName 查询单条记录
|
||||
func (this *NSRecordDAO) FindEnabledRecordWithName(tx *dbs.Tx, domainId int64, recordName string, recordType dnsconfigs.RecordType) (*NSRecord, error) {
|
||||
record, err := this.Query(tx).
|
||||
State(NSRecordStateEnabled).
|
||||
Attr("domainId", domainId).
|
||||
Attr("name", recordName).
|
||||
Attr("type", recordType).
|
||||
Find()
|
||||
if record == nil {
|
||||
return nil, err
|
||||
}
|
||||
return record.(*NSRecord), nil
|
||||
}
|
||||
|
||||
// FindEnabledRecordsWithName 查询多条记录
|
||||
func (this *NSRecordDAO) FindEnabledRecordsWithName(tx *dbs.Tx, domainId int64, recordName string, recordType dnsconfigs.RecordType) (result []*NSRecord, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(NSRecordStateEnabled).
|
||||
Attr("domainId", domainId).
|
||||
Attr("name", recordName).
|
||||
Attr("type", recordType).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// DisableRecordsInDomain 禁用某个域名中的所有记录
|
||||
func (this *NSRecordDAO) DisableRecordsInDomain(tx *dbs.Tx, domainId int64) error {
|
||||
if domainId <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = this.Query(tx).
|
||||
Attr("domainId", domainId).
|
||||
Set("state", NSRecordStateDisabled).
|
||||
Set("version", version).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return SharedNSDomainDAO.NotifyUpdate(tx, domainId)
|
||||
}
|
||||
|
||||
// DisableRecordsInDomainWithNameAndType 禁用某个域名中的某个名称的记录
|
||||
func (this *NSRecordDAO) DisableRecordsInDomainWithNameAndType(tx *dbs.Tx, domainId int64, name string, recordType string) error {
|
||||
if domainId <= 0 {
|
||||
return nil
|
||||
}
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = this.Query(tx).
|
||||
Attr("domainId", domainId).
|
||||
Attr("name", name).
|
||||
Attr("type", recordType).
|
||||
Set("version", version).
|
||||
Set("state", NSRecordStateDisabled).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return SharedNSDomainDAO.NotifyUpdate(tx, domainId)
|
||||
}
|
||||
|
||||
// UpdateRecordsWithDomainId 批量修改记录
|
||||
func (this *NSRecordDAO) UpdateRecordsWithDomainId(tx *dbs.Tx, domainId int64, searchName string, searchType string, searchValue string, searchRouteCodes []string, newName string, newType string, newValue string, newRouteCodes []string) error {
|
||||
searchType = strings.ToUpper(searchType)
|
||||
newType = strings.ToUpper(newType)
|
||||
|
||||
var query = this.Query(tx)
|
||||
query.Attr("domainId", domainId)
|
||||
if len(searchName) > 0 {
|
||||
query.Attr("name", searchName)
|
||||
}
|
||||
if len(searchType) > 0 {
|
||||
query.Attr("type", searchType)
|
||||
}
|
||||
if len(searchValue) > 0 {
|
||||
if searchType == "CNAME" && !strings.HasSuffix(searchValue, ".") {
|
||||
searchValue += "."
|
||||
}
|
||||
query.Attr("value", searchValue)
|
||||
}
|
||||
if len(searchRouteCodes) > 0 {
|
||||
for _, routeCode := range searchRouteCodes {
|
||||
query.JSONContains("routeIds", strconv.Quote(routeCode))
|
||||
}
|
||||
}
|
||||
|
||||
var shouldChange = false
|
||||
if len(newName) > 0 {
|
||||
query.Set("name", newName)
|
||||
shouldChange = true
|
||||
}
|
||||
if len(newType) > 0 {
|
||||
query.Set("type", newType)
|
||||
shouldChange = true
|
||||
}
|
||||
if len(newValue) > 0 {
|
||||
if newType == "CNAME" && !strings.HasSuffix(newValue, ".") {
|
||||
newValue += "."
|
||||
}
|
||||
query.Set("value", newValue)
|
||||
shouldChange = true
|
||||
}
|
||||
if len(newRouteCodes) > 0 {
|
||||
routeCodesJSON, err := json.Marshal(newRouteCodes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
query.Set("routeIds", routeCodesJSON)
|
||||
shouldChange = true
|
||||
}
|
||||
|
||||
if !shouldChange {
|
||||
return nil
|
||||
}
|
||||
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
query.Set("version", version)
|
||||
|
||||
err = query.UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return SharedNSDomainDAO.NotifyUpdate(tx, domainId)
|
||||
}
|
||||
|
||||
// DisableRecordsWithDomainId 批量删除记录
|
||||
func (this *NSRecordDAO) DisableRecordsWithDomainId(tx *dbs.Tx, domainId int64, searchName string, searchType string, searchValue string, searchRouteCodes []string) error {
|
||||
searchType = strings.ToUpper(searchType)
|
||||
|
||||
var query = this.Query(tx)
|
||||
query.Attr("domainId", domainId)
|
||||
if len(searchName) > 0 {
|
||||
query.Attr("name", searchName)
|
||||
}
|
||||
if len(searchType) > 0 {
|
||||
query.Attr("type", searchType)
|
||||
}
|
||||
if len(searchValue) > 0 {
|
||||
if searchType == "CNAME" && !strings.HasSuffix(searchValue, ".") {
|
||||
searchValue += "."
|
||||
}
|
||||
query.Attr("value", searchValue)
|
||||
}
|
||||
if len(searchRouteCodes) > 0 {
|
||||
for _, routeCode := range searchRouteCodes {
|
||||
query.JSONContains("routeIds", strconv.Quote(routeCode))
|
||||
}
|
||||
}
|
||||
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query.Set("version", version)
|
||||
query.Set("state", NSRecordStateDisabled)
|
||||
|
||||
err = query.UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return SharedNSDomainDAO.NotifyUpdate(tx, domainId)
|
||||
}
|
||||
|
||||
// UpdateRecordsIsOnWithDomainId 批量修改域名中的IsOn状态
|
||||
func (this *NSRecordDAO) UpdateRecordsIsOnWithDomainId(tx *dbs.Tx, domainId int64, searchName string, searchType string, searchValue string, searchRouteCodes []string, isOn bool) error {
|
||||
searchType = strings.ToUpper(searchType)
|
||||
|
||||
var query = this.Query(tx)
|
||||
query.Attr("domainId", domainId)
|
||||
if len(searchName) > 0 {
|
||||
query.Attr("name", searchName)
|
||||
}
|
||||
if len(searchType) > 0 {
|
||||
query.Attr("type", searchType)
|
||||
}
|
||||
if len(searchValue) > 0 {
|
||||
if searchType == "CNAME" && !strings.HasSuffix(searchValue, ".") {
|
||||
searchValue += "."
|
||||
}
|
||||
query.Attr("value", searchValue)
|
||||
}
|
||||
if len(searchRouteCodes) > 0 {
|
||||
for _, routeCode := range searchRouteCodes {
|
||||
query.JSONContains("routeIds", strconv.Quote(routeCode))
|
||||
}
|
||||
}
|
||||
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query.Set("version", version)
|
||||
query.Set("isOn", isOn)
|
||||
|
||||
err = query.UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return SharedNSDomainDAO.NotifyUpdate(tx, domainId)
|
||||
}
|
||||
|
||||
// CheckUserRecord 检查用户记录
|
||||
// 注意这里的userId可能为0
|
||||
func (this *NSRecordDAO) CheckUserRecord(tx *dbs.Tx, userId int64, recordId int64) error {
|
||||
if recordId <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
domainId, err := this.Query(tx).
|
||||
Result("domainId").
|
||||
Pk(recordId).
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if domainId == 0 {
|
||||
return models.ErrNotFound
|
||||
}
|
||||
|
||||
return SharedNSDomainDAO.CheckUserDomain(tx, userId, domainId)
|
||||
}
|
||||
|
||||
// CountAllUserRecords 计算用户的记录数
|
||||
func (this *NSRecordDAO) CountAllUserRecords(tx *dbs.Tx, userId int64) (int64, error) {
|
||||
if userId <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return this.Query(tx).
|
||||
Where("domainId IN (SELECT id FROM "+SharedNSDomainDAO.Table+" WHERE state=1 AND userId=:userId)").
|
||||
Param("userId", userId).
|
||||
Count()
|
||||
}
|
||||
|
||||
// FindRecordHealthCheckConfig 查找健康检查配置
|
||||
func (this *NSRecordDAO) FindRecordHealthCheckConfig(tx *dbs.Tx, recordId int64) (*dnsconfigs.NSRecordHealthCheckConfig, error) {
|
||||
if recordId <= 0 {
|
||||
return nil, errors.New("not valid 'recordId'")
|
||||
}
|
||||
|
||||
recordHealthCheckConfigJSON, err := this.Query(tx).
|
||||
Pk(recordId).
|
||||
State(NSRecordStateEnabled).
|
||||
Result("healthCheck").
|
||||
FindJSONCol()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var config = dnsconfigs.NewNSRecordHealthCheckConfig()
|
||||
if models.IsNull(recordHealthCheckConfigJSON) {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
err = json.Unmarshal(recordHealthCheckConfigJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// UpdateRecordHealthCheckConfig 修改健康检查配置
|
||||
func (this *NSRecordDAO) UpdateRecordHealthCheckConfig(tx *dbs.Tx, recordId int64, healthCheckConfig *dnsconfigs.NSRecordHealthCheckConfig) error {
|
||||
if recordId <= 0 {
|
||||
return errors.New("not valid 'recordId'")
|
||||
}
|
||||
|
||||
if healthCheckConfig == nil {
|
||||
return errors.New("'healthCheckConfig' should not be nil")
|
||||
}
|
||||
|
||||
healthCheckConfigJSON, err := json.Marshal(healthCheckConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var query = this.Query(tx).
|
||||
Pk(recordId).
|
||||
Set("healthCheck", healthCheckConfigJSON)
|
||||
|
||||
// 恢复上线状态
|
||||
if !healthCheckConfig.IsOn {
|
||||
query.Set("isUp", true)
|
||||
}
|
||||
|
||||
return query.UpdateQuickly()
|
||||
}
|
||||
|
||||
// UpdateRecordIsUp 设置记录在线
|
||||
func (this *NSRecordDAO) UpdateRecordIsUp(tx *dbs.Tx, recordId int64, isUp bool, countUp int, countDown int) error {
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rowsAffected, err := this.Query(tx).
|
||||
Pk(recordId).
|
||||
Set("isUp", isUp).
|
||||
Set("countUp", countUp).
|
||||
Set("countDown", countDown).
|
||||
Set("version", version).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if rowsAffected > 0 {
|
||||
return this.NotifyUpdate(tx, recordId)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateDomainRecordsUp 将域名下所有记录设置为在线
|
||||
func (this *NSRecordDAO) UpdateDomainRecordsUp(tx *dbs.Tx, domainId int64) error {
|
||||
records, err := this.Query(tx).
|
||||
Result("id").
|
||||
Attr("domainId", domainId).
|
||||
Attr("isUp", 0).
|
||||
State(NSRecordStateEnabled).
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, record := range records {
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = this.Query(tx).
|
||||
Pk(record.(*NSRecord).Id).
|
||||
Set("isUp", 1).
|
||||
Set("countDown", 0).
|
||||
Set("countUp", 0).
|
||||
Set("version", version).
|
||||
UpdateQuickly()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindAllDomainRecordsWithHealthCheckOn 查找开启健康检查的记录
|
||||
func (this *NSRecordDAO) FindAllDomainRecordsWithHealthCheckOn(tx *dbs.Tx, domainId int64) (result []*NSRecord, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Result("id", "name", "type", "value", "healthCheck", "countUp", "countDown", "isUp").
|
||||
State(NSRecordStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Attr("domainId", domainId).
|
||||
Attr("type", []string{dnsconfigs.RecordTypeA, dnsconfigs.RecordTypeAAAA}).
|
||||
Where(`JSON_CONTAINS(healthCheck, '{"isOn": true}')`).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *NSRecordDAO) NotifyUpdate(tx *dbs.Tx, recordId int64) error {
|
||||
domainId, err := this.Query(tx).
|
||||
Pk(recordId).
|
||||
Result("domainId").
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if domainId == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
clusterId, err := SharedNSDomainDAO.FindEnabledDomainClusterId(tx, domainId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if clusterId > 0 {
|
||||
err = models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, 0, models.NSNodeTaskTypeRecordChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package nameservers_test
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
@@ -0,0 +1,262 @@
|
||||
//go:build plus
|
||||
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/regexputils"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
type NSRecordHourlyStatDAO dbs.DAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
// 清理数据任务
|
||||
var ticker = time.NewTicker(time.Duration(rands.Int(24, 48)) * time.Hour)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
err := SharedNSRecordHourlyStatDAO.Clean(nil, 30) // 只保留N天
|
||||
if err != nil {
|
||||
remotelogs.Error("NodeClusterTrafficDailyStatDAO", "clean expired data failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func NewNSRecordHourlyStatDAO() *NSRecordHourlyStatDAO {
|
||||
return dbs.NewDAO(&NSRecordHourlyStatDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNSRecordHourlyStats",
|
||||
Model: new(NSRecordHourlyStat),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NSRecordHourlyStatDAO)
|
||||
}
|
||||
|
||||
var SharedNSRecordHourlyStatDAO *NSRecordHourlyStatDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNSRecordHourlyStatDAO = NewNSRecordHourlyStatDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// IncreaseHourlyStat 增加统计数据
|
||||
func (this *NSRecordHourlyStatDAO) IncreaseHourlyStat(tx *dbs.Tx, clusterId int64, nodeId int64, hour string, domainId int64, recordId int64, countRequests int64, bytes int64) error {
|
||||
if len(hour) != 10 {
|
||||
return errors.New("invalid hour '" + hour + "'")
|
||||
}
|
||||
return this.Query(tx).
|
||||
Param("countRequests", countRequests).
|
||||
Param("bytes", bytes).
|
||||
InsertOrUpdateQuickly(maps.Map{
|
||||
"clusterId": clusterId,
|
||||
"nodeId": nodeId,
|
||||
"domainId": domainId,
|
||||
"recordId": recordId,
|
||||
"day": hour[:8],
|
||||
"hour": hour,
|
||||
"countRequests": countRequests,
|
||||
"bytes": bytes,
|
||||
}, maps.Map{
|
||||
"countRequests": dbs.SQL("countRequests+:countRequests"),
|
||||
"bytes": dbs.SQL("bytes+:bytes"),
|
||||
})
|
||||
}
|
||||
|
||||
// FindHourlyStats 按小时统计
|
||||
func (this *NSRecordHourlyStatDAO) FindHourlyStats(tx *dbs.Tx, hourFrom string, hourTo string) (result []*NSRecordHourlyStat, err error) {
|
||||
ones, err := this.Query(tx).
|
||||
Result("hour", "SUM(countRequests) AS countRequests", "SUM(bytes) AS bytes").
|
||||
Between("hour", hourFrom, hourTo).
|
||||
Group("hour").
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var m = map[string]*NSRecordHourlyStat{} // hour => *NSRecordHourlyStat
|
||||
for _, one := range ones {
|
||||
m[one.(*NSRecordHourlyStat).Hour] = one.(*NSRecordHourlyStat)
|
||||
}
|
||||
hours, err := utils.RangeHours(hourFrom, hourTo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, hour := range hours {
|
||||
stat, ok := m[hour]
|
||||
if ok {
|
||||
result = append(result, stat)
|
||||
} else {
|
||||
result = append(result, &NSRecordHourlyStat{
|
||||
Hour: hour,
|
||||
})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindHourlyStatsWithRecordId 读取某个记录的按小时统计
|
||||
func (this *NSRecordHourlyStatDAO) FindHourlyStatsWithRecordId(tx *dbs.Tx, recordId int64, hourFrom string, hourTo string) (result []*NSRecordHourlyStat, err error) {
|
||||
ones, err := this.Query(tx).
|
||||
Attr("recordId", recordId).
|
||||
Result("hour", "SUM(countRequests) AS countRequests", "SUM(bytes) AS bytes").
|
||||
Between("hour", hourFrom, hourTo).
|
||||
Group("hour").
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var m = map[string]*NSRecordHourlyStat{} // hour => *NSRecordHourlyStat
|
||||
for _, one := range ones {
|
||||
m[one.(*NSRecordHourlyStat).Hour] = one.(*NSRecordHourlyStat)
|
||||
}
|
||||
hours, err := utils.RangeHours(hourFrom, hourTo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, hour := range hours {
|
||||
stat, ok := m[hour]
|
||||
if ok {
|
||||
result = append(result, stat)
|
||||
} else {
|
||||
result = append(result, &NSRecordHourlyStat{
|
||||
Hour: hour,
|
||||
})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindHourlyStatsWithRecordIdInDay 读取某个记录某天的按小时统计
|
||||
// day YYYYMMDD
|
||||
func (this *NSRecordHourlyStatDAO) FindHourlyStatsWithRecordIdInDay(tx *dbs.Tx, recordId int64, day string) (result []*NSRecordHourlyStat, err error) {
|
||||
if !regexputils.YYYYMMDD.MatchString(day) {
|
||||
return
|
||||
}
|
||||
|
||||
ones, err := this.Query(tx).
|
||||
Attr("recordId", recordId).
|
||||
Result("hour", "SUM(countRequests) AS countRequests", "SUM(bytes) AS bytes").
|
||||
Attr("day", day).
|
||||
Group("hour").
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var m = map[string]*NSRecordHourlyStat{} // hour => *NSRecordHourlyStat
|
||||
for _, one := range ones {
|
||||
m[one.(*NSRecordHourlyStat).Hour] = one.(*NSRecordHourlyStat)
|
||||
}
|
||||
hours, err := utils.RangeHours(day+"00", day+"23")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, hour := range hours {
|
||||
stat, ok := m[hour]
|
||||
if ok {
|
||||
result = append(result, stat)
|
||||
} else {
|
||||
result = append(result, &NSRecordHourlyStat{
|
||||
Hour: hour,
|
||||
})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindHourlyStatWithRecordId 获取某个记录的某个小时的统计
|
||||
func (this *NSRecordHourlyStatDAO) FindHourlyStatWithRecordId(tx *dbs.Tx, recordId int64, hour string) (*NSRecordHourlyStat, error) {
|
||||
one, err := this.Query(tx).
|
||||
Result("hour", "SUM(countRequests) AS countRequests", "SUM(bytes) AS bytes").
|
||||
Attr("recordId", recordId).
|
||||
Attr("hour", hour).
|
||||
Group("hour").
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
}
|
||||
return one.(*NSRecordHourlyStat), nil
|
||||
}
|
||||
|
||||
// FindDailyStats 按天统计
|
||||
func (this *NSRecordHourlyStatDAO) FindDailyStats(tx *dbs.Tx, dayFrom string, dayTo string) (result []*NSRecordHourlyStat, err error) {
|
||||
ones, err := this.Query(tx).
|
||||
Result("day", "SUM(countRequests) AS countRequests", "SUM(bytes) AS bytes").
|
||||
Between("day", dayFrom, dayTo).
|
||||
Group("day").
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var m = map[string]*NSRecordHourlyStat{} // day => *NSRecordHourlyStat
|
||||
for _, one := range ones {
|
||||
m[one.(*NSRecordHourlyStat).Day] = one.(*NSRecordHourlyStat)
|
||||
}
|
||||
days, err := utils.RangeDays(dayFrom, dayTo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, day := range days {
|
||||
stat, ok := m[day]
|
||||
if ok {
|
||||
result = append(result, stat)
|
||||
} else {
|
||||
result = append(result, &NSRecordHourlyStat{
|
||||
Day: day,
|
||||
})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ListTopNodes 节点排行
|
||||
func (this *NSRecordHourlyStatDAO) ListTopNodes(tx *dbs.Tx, hourFrom string, hourTo string, size int64) (result []*NSRecordHourlyStat, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Result("MIN(clusterId) AS clusterId", "nodeId", "SUM(countRequests) AS countRequests", "SUM(bytes) AS bytes").
|
||||
Between("hour", hourFrom, hourTo).
|
||||
Group("nodeId").
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// ListTopDomains 域名排行
|
||||
func (this *NSRecordHourlyStatDAO) ListTopDomains(tx *dbs.Tx, userId int64, hourFrom string, hourTo string, size int64) (result []*NSRecordHourlyStat, err error) {
|
||||
var query = this.Query(tx).
|
||||
Result("domainId", "SUM(countRequests) AS countRequests", "SUM(bytes) AS bytes")
|
||||
|
||||
if userId > 0 {
|
||||
query.Where("domainId IN (SELECT id FROM " + SharedNSDomainDAO.Table + " WHERE state=1 AND userId=:userId)")
|
||||
query.Param("userId", userId)
|
||||
}
|
||||
|
||||
_, err = query.
|
||||
Between("hour", hourFrom, hourTo).
|
||||
Group("domainId").
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// Clean 清理历史数据
|
||||
func (this *NSRecordHourlyStatDAO) Clean(tx *dbs.Tx, days int) error {
|
||||
var hour = timeutil.Format("Ymd00", time.Now().AddDate(0, 0, -days))
|
||||
_, err := this.Query(tx).
|
||||
Lt("hour", hour).
|
||||
Delete()
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
//go:build plus
|
||||
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
@@ -0,0 +1,30 @@
|
||||
package nameservers
|
||||
|
||||
// NSRecordHourlyStat NS记录统计
|
||||
type NSRecordHourlyStat struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
NodeId uint32 `field:"nodeId"` // 节点ID
|
||||
DomainId uint64 `field:"domainId"` // 域名ID
|
||||
RecordId uint64 `field:"recordId"` // 记录ID
|
||||
Day string `field:"day"` // YYYYMMDD
|
||||
Hour string `field:"hour"` // YYYYMMDDHH
|
||||
CountRequests uint64 `field:"countRequests"` // 请求数
|
||||
Bytes uint64 `field:"bytes"` // 流量
|
||||
}
|
||||
|
||||
type NSRecordHourlyStatOperator struct {
|
||||
Id interface{} // ID
|
||||
ClusterId interface{} // 集群ID
|
||||
NodeId interface{} // 节点ID
|
||||
DomainId interface{} // 域名ID
|
||||
RecordId interface{} // 记录ID
|
||||
Day interface{} // YYYYMMDD
|
||||
Hour interface{} // YYYYMMDDHH
|
||||
CountRequests interface{} // 请求数
|
||||
Bytes interface{} // 流量
|
||||
}
|
||||
|
||||
func NewNSRecordHourlyStatOperator() *NSRecordHourlyStatOperator {
|
||||
return &NSRecordHourlyStatOperator{}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package nameservers
|
||||
60
EdgeAPI/internal/db/models/nameservers/ns_record_model.go
Normal file
60
EdgeAPI/internal/db/models/nameservers/ns_record_model.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package nameservers
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// NSRecord DNS记录
|
||||
type NSRecord struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
DomainId uint32 `field:"domainId"` // 域名ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Description string `field:"description"` // 备注
|
||||
Name string `field:"name"` // 记录名
|
||||
Type string `field:"type"` // 类型
|
||||
Value string `field:"value"` // 值
|
||||
MxPriority uint32 `field:"mxPriority"` // MX优先级
|
||||
SrvPriority uint32 `field:"srvPriority"` // SRV优先级
|
||||
SrvWeight uint32 `field:"srvWeight"` // SRV权重
|
||||
SrvPort uint32 `field:"srvPort"` // SRV端口
|
||||
CaaFlag uint8 `field:"caaFlag"` // CAA Flag
|
||||
CaaTag string `field:"caaTag"` // CAA TAG
|
||||
Ttl uint32 `field:"ttl"` // TTL(秒)
|
||||
Weight uint32 `field:"weight"` // 权重
|
||||
RouteIds dbs.JSON `field:"routeIds"` // 线路
|
||||
HealthCheck dbs.JSON `field:"healthCheck"` // 健康检查配置
|
||||
CountUp uint32 `field:"countUp"` // 连续上线次数
|
||||
CountDown uint32 `field:"countDown"` // 连续离线次数
|
||||
IsUp bool `field:"isUp"` // 是否在线
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Version uint64 `field:"version"` // 版本号
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type NSRecordOperator struct {
|
||||
Id any // ID
|
||||
DomainId any // 域名ID
|
||||
IsOn any // 是否启用
|
||||
Description any // 备注
|
||||
Name any // 记录名
|
||||
Type any // 类型
|
||||
Value any // 值
|
||||
MxPriority any // MX优先级
|
||||
SrvPriority any // SRV优先级
|
||||
SrvWeight any // SRV权重
|
||||
SrvPort any // SRV端口
|
||||
CaaFlag any // CAA Flag
|
||||
CaaTag any // CAA TAG
|
||||
Ttl any // TTL(秒)
|
||||
Weight any // 权重
|
||||
RouteIds any // 线路
|
||||
HealthCheck any // 健康检查配置
|
||||
CountUp any // 连续上线次数
|
||||
CountDown any // 连续离线次数
|
||||
IsUp any // 是否在线
|
||||
CreatedAt any // 创建时间
|
||||
Version any // 版本号
|
||||
State any // 状态
|
||||
}
|
||||
|
||||
func NewNSRecordOperator() *NSRecordOperator {
|
||||
return &NSRecordOperator{}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
func (this *NSRecord) DecodeRouteIds() []string {
|
||||
var routeIds = []string{}
|
||||
if len(this.RouteIds) > 0 {
|
||||
err := json.Unmarshal(this.RouteIds, &routeIds)
|
||||
if err != nil {
|
||||
// 检查是否有旧的数据
|
||||
var oldRouteIds = []int64{}
|
||||
err = json.Unmarshal(this.RouteIds, &oldRouteIds)
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
routeIds = []string{}
|
||||
for _, routeId := range oldRouteIds {
|
||||
routeIds = append(routeIds, "id:"+types.String(routeId))
|
||||
}
|
||||
}
|
||||
}
|
||||
return routeIds
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
const (
|
||||
NSRouteCategoryStateEnabled = 1 // 已启用
|
||||
NSRouteCategoryStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type NSRouteCategoryDAO dbs.DAO
|
||||
|
||||
func NewNSRouteCategoryDAO() *NSRouteCategoryDAO {
|
||||
return dbs.NewDAO(&NSRouteCategoryDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNSRouteCategories",
|
||||
Model: new(NSRouteCategory),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NSRouteCategoryDAO)
|
||||
}
|
||||
|
||||
var SharedNSRouteCategoryDAO *NSRouteCategoryDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNSRouteCategoryDAO = NewNSRouteCategoryDAO()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
//go:build plus
|
||||
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
// EnableNSRouteCategory 启用条目
|
||||
func (this *NSRouteCategoryDAO) EnableNSRouteCategory(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSRouteCategoryStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableNSRouteCategory 禁用条目
|
||||
func (this *NSRouteCategoryDAO) DisableNSRouteCategory(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSRouteCategoryStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// FindCategory 查找启用中的条目
|
||||
func (this *NSRouteCategoryDAO) FindCategory(tx *dbs.Tx, id int64) (*NSRouteCategory, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
State(NSRouteCategoryStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*NSRouteCategory), err
|
||||
}
|
||||
|
||||
// FindNSRouteCategoryName 根据主键查找名称
|
||||
func (this *NSRouteCategoryDAO) FindNSRouteCategoryName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// CreateCategory 创建分类
|
||||
func (this *NSRouteCategoryDAO) CreateCategory(tx *dbs.Tx, adminId int64, userId int64, name string) (int64, error) {
|
||||
var op = NewNSRouteCategoryOperator()
|
||||
op.AdminId = adminId
|
||||
op.UserId = userId
|
||||
op.Name = name
|
||||
op.IsOn = true
|
||||
op.State = NSRouteCategoryStateEnabled
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// UpdateCategory 修改分类
|
||||
func (this *NSRouteCategoryDAO) UpdateCategory(tx *dbs.Tx, categoryId int64, name string, isOn bool) error {
|
||||
if categoryId <= 0 {
|
||||
return errors.New("invalid categoryId")
|
||||
}
|
||||
var op = NewNSRouteCategoryOperator()
|
||||
op.Id = categoryId
|
||||
op.Name = name
|
||||
op.IsOn = isOn
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// FindAllCategories 查找所有分类
|
||||
func (this *NSRouteCategoryDAO) FindAllCategories(tx *dbs.Tx, userId int64) (result []*NSRouteCategory, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(NSRouteCategoryStateEnabled).
|
||||
Attr("userId", userId). // 必要条件,即使userId为0
|
||||
Desc("order").
|
||||
AscPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateCategoryOrders 修改分类排序
|
||||
func (this *NSRouteCategoryDAO) UpdateCategoryOrders(tx *dbs.Tx, userId int64, categoryIds []int64) error {
|
||||
var order = len(categoryIds)
|
||||
for _, categoryId := range categoryIds {
|
||||
_, err := this.Query(tx).
|
||||
Pk(categoryId).
|
||||
Attr("userId", userId). // 防止用户突破自己的权限操作
|
||||
Set("order", order).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
order--
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckUserCategory 检查用户分类
|
||||
func (this *NSRouteCategoryDAO) CheckUserCategory(tx *dbs.Tx, userId int64, categoryId int64) error {
|
||||
if userId <= 0 || categoryId <= 0 {
|
||||
return models.ErrNotFound
|
||||
}
|
||||
|
||||
b, err := this.Query(tx).
|
||||
Pk(categoryId).
|
||||
State(NSRouteCategoryStateEnabled).
|
||||
Attr("userId", userId).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !b {
|
||||
return models.ErrNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package nameservers_test
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
@@ -0,0 +1,26 @@
|
||||
package nameservers
|
||||
|
||||
// NSRouteCategory 线路分类
|
||||
type NSRouteCategory struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Name string `field:"name"` // 分类名
|
||||
AdminId uint64 `field:"adminId"` // 管理员ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
Order uint32 `field:"order"` // 排序
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type NSRouteCategoryOperator struct {
|
||||
Id any // ID
|
||||
IsOn any // 是否启用
|
||||
Name any // 分类名
|
||||
AdminId any // 管理员ID
|
||||
UserId any // 用户ID
|
||||
Order any // 排序
|
||||
State any // 状态
|
||||
}
|
||||
|
||||
func NewNSRouteCategoryOperator() *NSRouteCategoryOperator {
|
||||
return &NSRouteCategoryOperator{}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package nameservers
|
||||
73
EdgeAPI/internal/db/models/nameservers/ns_route_dao.go
Normal file
73
EdgeAPI/internal/db/models/nameservers/ns_route_dao.go
Normal file
@@ -0,0 +1,73 @@
|
||||
//go:build !plus
|
||||
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
const (
|
||||
NSRouteStateEnabled = 1 // 已启用
|
||||
NSRouteStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type NSRouteDAO dbs.DAO
|
||||
|
||||
func NewNSRouteDAO() *NSRouteDAO {
|
||||
return dbs.NewDAO(&NSRouteDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNSRoutes",
|
||||
Model: new(NSRoute),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NSRouteDAO)
|
||||
}
|
||||
|
||||
var SharedNSRouteDAO *NSRouteDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNSRouteDAO = NewNSRouteDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableNSRoute 启用条目
|
||||
func (this *NSRouteDAO) EnableNSRoute(tx *dbs.Tx, id uint32) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSRouteStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableNSRoute 禁用条目
|
||||
func (this *NSRouteDAO) DisableNSRoute(tx *dbs.Tx, id uint32) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSRouteStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// FindEnabledNSRoute 查找启用中的条目
|
||||
func (this *NSRouteDAO) FindEnabledNSRoute(tx *dbs.Tx, id uint32) (*NSRoute, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
State(NSRouteStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*NSRoute), err
|
||||
}
|
||||
|
||||
// FindNSRouteName 根据主键查找名称
|
||||
func (this *NSRouteDAO) FindNSRouteName(tx *dbs.Tx, id uint32) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
535
EdgeAPI/internal/db/models/nameservers/ns_route_dao_plus.go
Normal file
535
EdgeAPI/internal/db/models/nameservers/ns_route_dao_plus.go
Normal file
@@ -0,0 +1,535 @@
|
||||
//go:build plus
|
||||
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/clients"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/regions"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
NSRouteStateEnabled = 1 // 已启用
|
||||
NSRouteStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
// 线路的几种表达式
|
||||
var routeCodeReg = regexp.MustCompile(`^id:\d+$`) // 自定义线路
|
||||
var routeAgentReg = regexp.MustCompile(`^agent:\w+$`) // 搜索引擎线路
|
||||
var routeProvinceReg = regexp.MustCompile(`^region:province:\d+$`) // 省份线路
|
||||
|
||||
type NSRouteDAO dbs.DAO
|
||||
|
||||
func NewNSRouteDAO() *NSRouteDAO {
|
||||
return dbs.NewDAO(&NSRouteDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNSRoutes",
|
||||
Model: new(NSRoute),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NSRouteDAO)
|
||||
}
|
||||
|
||||
var SharedNSRouteDAO *NSRouteDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNSRouteDAO = NewNSRouteDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableNSRoute 启用条目
|
||||
func (this *NSRouteDAO) EnableNSRoute(tx *dbs.Tx, routeId int64) error {
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Pk(routeId).
|
||||
Set("state", NSRouteStateEnabled).
|
||||
Set("version", version).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx)
|
||||
}
|
||||
|
||||
// DisableNSRoute 禁用条目
|
||||
func (this *NSRouteDAO) DisableNSRoute(tx *dbs.Tx, routeId int64) error {
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Pk(routeId).
|
||||
Set("state", NSRouteStateDisabled).
|
||||
Set("version", version).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.NotifyUpdate(tx)
|
||||
}
|
||||
|
||||
// FindEnabledNSRoute 查找启用中的条目
|
||||
func (this *NSRouteDAO) FindEnabledNSRoute(tx *dbs.Tx, id int64) (*NSRoute, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", NSRouteStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*NSRoute), err
|
||||
}
|
||||
|
||||
// FindEnabledRouteWithCode 根据代号获取线路信息
|
||||
func (this *NSRouteDAO) FindEnabledRouteWithCode(tx *dbs.Tx, code string) (*NSRoute, error) {
|
||||
// id:xxx
|
||||
if routeCodeReg.MatchString(code) {
|
||||
var routeId = types.Int64(code[strings.Index(code, ":")+1:])
|
||||
route, err := this.FindEnabledNSRoute(tx, routeId)
|
||||
if route == nil || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
route.Code = "id:" + types.String(routeId)
|
||||
return route, nil
|
||||
}
|
||||
|
||||
// agent:xxx
|
||||
if code == "agent" {
|
||||
return &NSRoute{
|
||||
Id: 0,
|
||||
IsOn: true,
|
||||
Name: "搜索引擎",
|
||||
Code: code,
|
||||
State: NSRouteStateEnabled,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if routeAgentReg.MatchString(code) {
|
||||
var agentCode = code[strings.Index(code, ":")+1:]
|
||||
agentName, err := clients.SharedClientAgentDAO.FindAgentNameWithCode(tx, agentCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(agentName) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return &NSRoute{
|
||||
Id: 0,
|
||||
IsOn: true,
|
||||
Name: agentName,
|
||||
Code: code,
|
||||
State: NSRouteStateEnabled,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// province
|
||||
if routeProvinceReg.MatchString(code) {
|
||||
var provinceId = types.Int64(code[strings.LastIndex(code, ":")+1:])
|
||||
provinceName, err := regions.SharedRegionProvinceDAO.FindRegionProvinceName(tx, provinceId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(provinceName) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// country
|
||||
countryId, err := regions.SharedRegionProvinceDAO.FindRegionCountryId(tx, provinceId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if countryId > 0 {
|
||||
countryName, err := regions.SharedRegionCountryDAO.FindRegionCountryName(tx, countryId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(countryName) > 0 {
|
||||
return &NSRoute{
|
||||
Id: 0,
|
||||
IsOn: true,
|
||||
Name: countryName + "-" + provinceName,
|
||||
Code: code,
|
||||
State: NSRouteStateEnabled,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var route = dnsconfigs.FindDefaultRoute(code)
|
||||
if route == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &NSRoute{
|
||||
Id: 0,
|
||||
IsOn: true,
|
||||
Name: route.Name,
|
||||
Code: route.Code,
|
||||
State: NSRouteStateEnabled,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FindNSRouteName 根据主键查找名称
|
||||
func (this *NSRouteDAO) FindNSRouteName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// CreateRoute 创建线路
|
||||
func (this *NSRouteDAO) CreateRoute(tx *dbs.Tx, clusterId int64, domainId int64, userId int64, name string, rangesJSON []byte, categoryId int64, priority int32, isPublic bool) (int64, error) {
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var op = NewNSRouteOperator()
|
||||
op.ClusterId = clusterId
|
||||
op.DomainId = domainId
|
||||
op.UserId = userId
|
||||
op.Name = name
|
||||
if len(rangesJSON) > 0 {
|
||||
op.Ranges = rangesJSON
|
||||
} else {
|
||||
op.Ranges = "[]"
|
||||
}
|
||||
op.IsPublic = isPublic
|
||||
op.CategoryId = categoryId
|
||||
|
||||
if priority < 0 {
|
||||
priority = 0
|
||||
}
|
||||
op.Priority = priority
|
||||
|
||||
op.IsOn = true
|
||||
op.State = NSRouteStateEnabled
|
||||
op.Version = version
|
||||
routeId, err := this.SaveInt64(tx, op)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = this.NotifyUpdate(tx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return routeId, nil
|
||||
}
|
||||
|
||||
// UpdateRoute 修改线路
|
||||
func (this *NSRouteDAO) UpdateRoute(tx *dbs.Tx, routeId int64, name string, rangesJSON []byte, categoryId int64, priority int32, isPublic bool, isOn bool) error {
|
||||
if routeId <= 0 {
|
||||
return errors.New("invalid routeId")
|
||||
}
|
||||
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var op = NewNSRouteOperator()
|
||||
op.Id = routeId
|
||||
op.Name = name
|
||||
if len(rangesJSON) > 0 {
|
||||
op.Ranges = rangesJSON
|
||||
} else {
|
||||
op.Ranges = "[]"
|
||||
}
|
||||
|
||||
op.IsPublic = isPublic
|
||||
op.CategoryId = categoryId
|
||||
op.Version = version
|
||||
op.IsOn = isOn
|
||||
|
||||
if priority < 0 {
|
||||
priority = 0
|
||||
}
|
||||
op.Priority = priority
|
||||
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx)
|
||||
}
|
||||
|
||||
// UpdateRouteOrders 修改线路排序
|
||||
func (this *NSRouteDAO) UpdateRouteOrders(tx *dbs.Tx, routeIds []int64) error {
|
||||
version, err := this.IncreaseVersion(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
order := len(routeIds)
|
||||
for _, routeId := range routeIds {
|
||||
_, err = this.Query(tx).
|
||||
Pk(routeId).
|
||||
Set("order", order).
|
||||
Set("version", version).
|
||||
Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
order--
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx)
|
||||
}
|
||||
|
||||
// FindAllEnabledRoutes 列出所有自定义线路
|
||||
func (this *NSRouteDAO) FindAllEnabledRoutes(tx *dbs.Tx, clusterId int64, domainId int64, userId int64, categoryId int64) (result []*NSRoute, err error) {
|
||||
var query = this.Query(tx).
|
||||
State(NSRouteStateEnabled).
|
||||
Slice(&result).
|
||||
Asc("categoryId").
|
||||
Desc("order").
|
||||
AscPk()
|
||||
|
||||
if clusterId < 0 {
|
||||
clusterId = 0
|
||||
}
|
||||
if domainId < 0 {
|
||||
domainId = 0
|
||||
}
|
||||
if userId < 0 {
|
||||
userId = 0
|
||||
}
|
||||
if categoryId < 0 {
|
||||
categoryId = 0
|
||||
}
|
||||
|
||||
// 必要条件,即使值为0
|
||||
query.Attr("clusterId", clusterId)
|
||||
query.Attr("userId", userId)
|
||||
query.Attr("domainId", domainId)
|
||||
|
||||
// 非必要条件
|
||||
if categoryId > 0 {
|
||||
query.Attr("categoryId", categoryId)
|
||||
}
|
||||
|
||||
_, err = query.FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindAllPublicRoutes 查找公用的自定义线路
|
||||
func (this *NSRouteDAO) FindAllPublicRoutes(tx *dbs.Tx) (result []*NSRoute, err error) {
|
||||
_, err = this.Query(tx).
|
||||
State(NSRouteStateEnabled).
|
||||
Attr("userId", 0). // 只能查询管理员的
|
||||
Attr("isOn", true).
|
||||
Attr("clusterId", 0).
|
||||
Attr("domainId", 0).
|
||||
Attr("isPublic", true).
|
||||
Slice(&result).
|
||||
Desc("order").
|
||||
AscPk().
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// CountAllEnabledRoutes 计算所有线路数量
|
||||
func (this *NSRouteDAO) CountAllEnabledRoutes(tx *dbs.Tx, clusterId int64, domainId int64, userId int64) (int64, error) {
|
||||
var query = this.Query(tx).
|
||||
State(NSRouteStateEnabled)
|
||||
if clusterId > 0 {
|
||||
query.Attr("clusterId", clusterId)
|
||||
} else {
|
||||
// 不查询所有集群的线路
|
||||
query.Attr("clusterId", 0)
|
||||
}
|
||||
if domainId > 0 {
|
||||
query.Attr("domainId", domainId)
|
||||
}
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// IncreaseVersion 增加版本
|
||||
func (this *NSRouteDAO) IncreaseVersion(tx *dbs.Tx) (int64, error) {
|
||||
return models.SharedSysLockerDAO.Increase(tx, "NS_ROUTE_VERSION", 1)
|
||||
}
|
||||
|
||||
// ListRoutesAfterVersion 列出某个版本后的域名
|
||||
func (this *NSRouteDAO) ListRoutesAfterVersion(tx *dbs.Tx, version int64, size int64) (result []*NSRoute, err error) {
|
||||
if size <= 0 {
|
||||
size = 10000
|
||||
}
|
||||
|
||||
_, err = this.Query(tx).
|
||||
Gte("version", version).
|
||||
Limit(size).
|
||||
Asc("version").
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// CheckUserRoute 检查用户权限
|
||||
func (this *NSRouteDAO) CheckUserRoute(tx *dbs.Tx, userId int64, routeId int64) error {
|
||||
if userId <= 0 || routeId <= 0 {
|
||||
return models.ErrNotFound
|
||||
}
|
||||
|
||||
b, err := this.Query(tx).
|
||||
Pk(routeId).
|
||||
State(NSRouteStateEnabled).
|
||||
Attr("userId", userId).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !b {
|
||||
return models.ErrNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckRouteCode 检查用户是否可以使用某个线路代号
|
||||
func (this *NSRouteDAO) CheckRouteCode(tx *dbs.Tx, routeCode string, userId int64) error {
|
||||
if len(routeCode) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 是否为内置线路
|
||||
var routeInfo = dnsconfigs.FindDefaultRoute(routeCode)
|
||||
if routeInfo != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 如果是管理员的话直接可以使用
|
||||
if userId == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// id:xxx
|
||||
if routeCodeReg.MatchString(routeCode) {
|
||||
var colonIndex = strings.LastIndex(routeCode, ":")
|
||||
if colonIndex > 0 {
|
||||
var routeId = types.Int64(routeCode[colonIndex+1:])
|
||||
if routeId > 0 {
|
||||
routeOne, err := this.Query(tx).
|
||||
Pk(routeId).
|
||||
State(NSRouteStateEnabled).
|
||||
Result("userId", "isPublic").
|
||||
Find()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if routeOne != nil {
|
||||
var route = routeOne.(*NSRoute)
|
||||
|
||||
// 检查是否为公用线路 或者 自己的线路
|
||||
if (route.UserId == 0 && route.IsPublic) || (int64(route.UserId) == userId) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// agent:xxx
|
||||
if routeCode == "agent" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if routeAgentReg.MatchString(routeCode) {
|
||||
var colonIndex = strings.Index(routeCode, ":")
|
||||
if colonIndex > 0 {
|
||||
var agentCode = routeCode[colonIndex+1:]
|
||||
if len(agentCode) > 0 {
|
||||
agentId, err := clients.SharedClientAgentDAO.FindAgentIdWithCode(tx, agentCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if agentId > 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// province:xxx
|
||||
if routeProvinceReg.MatchString(routeCode) {
|
||||
var provinceId = types.Int64(routeCode[strings.LastIndex(routeCode, ":")+1:])
|
||||
if provinceId <= 0 {
|
||||
return errors.New("invalid province id in '" + routeCode + "'")
|
||||
}
|
||||
b, err := regions.SharedRegionProvinceDAO.Exist(tx, provinceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !b {
|
||||
return errors.New("province id in '" + routeCode + "' not found")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.New("no route with code '" + routeCode + "' found")
|
||||
}
|
||||
|
||||
// CheckRouteCodes 检查用户是否可以使用一组线路代号
|
||||
func (this *NSRouteDAO) CheckRouteCodes(tx *dbs.Tx, routeCodes []string, userId int64) error {
|
||||
if len(routeCodes) == 0 {
|
||||
return nil
|
||||
}
|
||||
for _, routeCode := range routeCodes {
|
||||
if len(routeCode) == 0 {
|
||||
continue
|
||||
}
|
||||
err := this.CheckRouteCode(tx, routeCode, userId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetRoutesCategory 重置线路分类
|
||||
func (this *NSRouteDAO) ResetRoutesCategory(tx *dbs.Tx, categoryId int64) error {
|
||||
if categoryId <= 0 {
|
||||
return nil
|
||||
}
|
||||
return this.Query(tx).
|
||||
Attr("categoryId", categoryId).
|
||||
Set("categoryId", 0).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// NotifyUpdate 通知更新
|
||||
func (this *NSRouteDAO) NotifyUpdate(tx *dbs.Tx) error {
|
||||
// 线路变更时所有集群都要更新
|
||||
clusterIds, err := models.SharedNSClusterDAO.FindAllEnabledClusterIds(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, clusterId := range clusterIds {
|
||||
err = models.SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleDNS, clusterId, 0, 0, models.NSNodeTaskTypeRouteChanged)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
@@ -0,0 +1,6 @@
|
||||
package nameservers_test
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
44
EdgeAPI/internal/db/models/nameservers/ns_route_model.go
Normal file
44
EdgeAPI/internal/db/models/nameservers/ns_route_model.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package nameservers
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// NSRoute DNS线路
|
||||
type NSRoute struct {
|
||||
Id uint32 `field:"id"` // ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||
CategoryId uint32 `field:"categoryId"` // 分类ID
|
||||
DomainId uint64 `field:"domainId"` // 域名ID
|
||||
AdminId uint64 `field:"adminId"` // 管理员ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
IsPublic bool `field:"isPublic"` // 是否公用(管理员创建的线路)
|
||||
Name string `field:"name"` // 名称
|
||||
Ranges dbs.JSON `field:"ranges"` // 范围
|
||||
Order uint32 `field:"order"` // 排序
|
||||
Version uint64 `field:"version"` // 版本号
|
||||
Priority uint32 `field:"priority"` // 优先级,越高越优先
|
||||
Code string `field:"code"` // 代号
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type NSRouteOperator struct {
|
||||
Id any // ID
|
||||
IsOn any // 是否启用
|
||||
ClusterId any // 集群ID
|
||||
CategoryId any // 分类ID
|
||||
DomainId any // 域名ID
|
||||
AdminId any // 管理员ID
|
||||
UserId any // 用户ID
|
||||
IsPublic any // 是否公用(管理员创建的线路)
|
||||
Name any // 名称
|
||||
Ranges any // 范围
|
||||
Order any // 排序
|
||||
Version any // 版本号
|
||||
Priority any // 优先级,越高越优先
|
||||
Code any // 代号
|
||||
State any // 状态
|
||||
}
|
||||
|
||||
func NewNSRouteOperator() *NSRouteOperator {
|
||||
return &NSRouteOperator{}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package nameservers
|
||||
245
EdgeAPI/internal/db/models/nameservers/ns_user_plan_dao_plus.go
Normal file
245
EdgeAPI/internal/db/models/nameservers/ns_user_plan_dao_plus.go
Normal file
@@ -0,0 +1,245 @@
|
||||
//go:build plus
|
||||
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
NSUserPlanStateEnabled = 1 // 已启用
|
||||
NSUserPlanStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type NSUserPlanPeriodUnit = string
|
||||
|
||||
const (
|
||||
NSUserPlanPeriodUnitMonthly NSUserPlanPeriodUnit = "monthly"
|
||||
NSUserPlanPeriodUnitYearly NSUserPlanPeriodUnit = "yearly"
|
||||
)
|
||||
|
||||
type NSUserPlanDAO dbs.DAO
|
||||
|
||||
func NewNSUserPlanDAO() *NSUserPlanDAO {
|
||||
return dbs.NewDAO(&NSUserPlanDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNSUserPlans",
|
||||
Model: new(NSUserPlan),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NSUserPlanDAO)
|
||||
}
|
||||
|
||||
var SharedNSUserPlanDAO *NSUserPlanDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNSUserPlanDAO = NewNSUserPlanDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableNSUserPlan 启用条目
|
||||
func (this *NSUserPlanDAO) EnableNSUserPlan(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSUserPlanStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableNSUserPlan 禁用条目
|
||||
func (this *NSUserPlanDAO) DisableNSUserPlan(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSUserPlanStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// FindEnabledNSUserPlan 查找启用中的条目
|
||||
func (this *NSUserPlanDAO) FindEnabledNSUserPlan(tx *dbs.Tx, id int64) (*NSUserPlan, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
State(NSUserPlanStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*NSUserPlan), err
|
||||
}
|
||||
|
||||
// CreateUserPlan 创建用户套餐
|
||||
func (this *NSUserPlanDAO) CreateUserPlan(tx *dbs.Tx, userId int64, planId int64, dayFrom string, dayTo string, periodUnit NSUserPlanPeriodUnit) (int64, error) {
|
||||
var op = NewNSUserPlanOperator()
|
||||
op.UserId = userId
|
||||
op.PlanId = planId
|
||||
op.DayFrom = dayFrom
|
||||
op.DayTo = dayTo
|
||||
op.PeriodUnit = periodUnit
|
||||
op.State = NSUserPlanStateEnabled
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// UpdateUserPlan 修改用户套餐
|
||||
func (this *NSUserPlanDAO) UpdateUserPlan(tx *dbs.Tx, userPlanId int64, planId int64, dayFrom string, dayTo string, periodUnit NSUserPlanPeriodUnit) error {
|
||||
if userPlanId <= 0 {
|
||||
return errors.New("invalid userPlanId")
|
||||
}
|
||||
var op = NewNSUserPlanOperator()
|
||||
op.Id = userPlanId
|
||||
op.PlanId = planId
|
||||
op.DayFrom = dayFrom
|
||||
op.DayTo = dayTo
|
||||
op.PeriodUnit = periodUnit
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// CountUserPlans 计算用户套餐数量
|
||||
func (this *NSUserPlanDAO) CountUserPlans(tx *dbs.Tx, userId int64, planId int64, periodUnit string, isExpired bool, expireDays int32) (int64, error) {
|
||||
var query = this.Query(tx).
|
||||
State(NSUserPlanStateEnabled)
|
||||
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
if planId > 0 {
|
||||
query.Attr("planId", planId)
|
||||
}
|
||||
if len(periodUnit) > 0 {
|
||||
query.Attr("periodUnit", periodUnit)
|
||||
}
|
||||
if isExpired {
|
||||
query.Lt("dayTo", timeutil.Format("Ymd"))
|
||||
} else if expireDays == 0 {
|
||||
query.Gte("dayTo", timeutil.Format("Ymd"))
|
||||
} else if expireDays > 0 {
|
||||
query.Gte("dayTo", timeutil.Format("Ymd"))
|
||||
query.Lte("dayTo", timeutil.Format("Ymd", time.Now().AddDate(0, 0, int(expireDays))))
|
||||
}
|
||||
|
||||
query.Where("planId IN (SELECT id FROM " + SharedNSPlanDAO.Table + " WHERE state=1)")
|
||||
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// ListUserPlans 列出单页用户套餐
|
||||
func (this *NSUserPlanDAO) ListUserPlans(tx *dbs.Tx, userId int64, planId int64, periodUnit string, isExpired bool, expireDays int32, offset int64, size int64) (result []*NSUserPlan, err error) {
|
||||
var query = this.Query(tx)
|
||||
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
if planId > 0 {
|
||||
query.Attr("planId", planId)
|
||||
}
|
||||
if len(periodUnit) > 0 {
|
||||
query.Attr("periodUnit", periodUnit)
|
||||
}
|
||||
if isExpired {
|
||||
query.Lt("dayTo", timeutil.Format("Ymd"))
|
||||
} else if expireDays == 0 {
|
||||
query.Gte("dayTo", timeutil.Format("Ymd"))
|
||||
} else if expireDays > 0 {
|
||||
query.Gte("dayTo", timeutil.Format("Ymd"))
|
||||
query.Lte("dayTo", timeutil.Format("Ymd", time.Now().AddDate(0, 0, int(expireDays))))
|
||||
}
|
||||
|
||||
query.Where("planId IN (SELECT id FROM " + SharedNSPlanDAO.Table + " WHERE state=1)")
|
||||
|
||||
_, err = query.
|
||||
State(NSUserPlanStateEnabled).
|
||||
Desc("dayFrom").
|
||||
DescPk().
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindUserPlan 查找用户对应的套餐
|
||||
func (this *NSUserPlanDAO) FindUserPlan(tx *dbs.Tx, userId int64) (*NSUserPlan, error) {
|
||||
if userId <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
one, err := this.Query(tx).
|
||||
State(NSUserPlanStateEnabled).
|
||||
Attr("userId", userId).
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return one.(*NSUserPlan), nil
|
||||
}
|
||||
|
||||
// RenewUserPlan 更新用户套餐
|
||||
func (this *NSUserPlanDAO) RenewUserPlan(tx *dbs.Tx, userId int64, planId int64, dayFrom string, dayTo string, period NSUserPlanPeriodUnit) error {
|
||||
if userId <= 0 {
|
||||
return errors.New("invalid userId")
|
||||
}
|
||||
|
||||
userPlan, err := this.FindUserPlan(tx, userId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if userPlan == nil {
|
||||
_, err = this.CreateUserPlan(tx, userId, planId, dayFrom, dayTo, period)
|
||||
return err
|
||||
}
|
||||
return this.UpdateUserPlan(tx, int64(userPlan.Id), planId, dayFrom, dayTo, period)
|
||||
}
|
||||
|
||||
// FindUserPlanConfig 用户配置
|
||||
// 需要保证非 error 的情况下,一定会返回一个不为空的 NSPlanConfig
|
||||
func (this *NSUserPlanDAO) FindUserPlanConfig(tx *dbs.Tx, userId int64) (*dnsconfigs.NSPlanConfig, error) {
|
||||
// 查找用户套餐
|
||||
userPlan, err := this.FindUserPlan(tx, userId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if userPlan != nil &&
|
||||
len(userPlan.DayTo) > 0 &&
|
||||
userPlan.DayTo >= timeutil.Format("Ymd") /** 在有效期内 **/ {
|
||||
var planId = int64(userPlan.PlanId)
|
||||
if planId > 0 {
|
||||
plan, err := SharedNSPlanDAO.FindEnabledNSPlan(tx, planId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if plan != nil &&
|
||||
len(plan.Config) > 0 &&
|
||||
plan.IsOn {
|
||||
var config = dnsconfigs.DefaultNSUserPlanConfig()
|
||||
err = json.Unmarshal(plan.Config, config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decode plan config failed '%w'", err)
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 从用户全局设置中读取
|
||||
userConfig, err := models.SharedSysSettingDAO.ReadNSUserConfig(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if userConfig != nil && userConfig.DefaultPlanConfig != nil {
|
||||
return userConfig.DefaultPlanConfig, nil
|
||||
}
|
||||
|
||||
return dnsconfigs.DefaultNSUserPlanConfig(), nil
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package nameservers_test
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
28
EdgeAPI/internal/db/models/nameservers/ns_user_plan_model.go
Normal file
28
EdgeAPI/internal/db/models/nameservers/ns_user_plan_model.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package nameservers
|
||||
|
||||
// NSUserPlan 用户套餐
|
||||
type NSUserPlan struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
PlanId uint32 `field:"planId"` // 套餐ID
|
||||
DayFrom string `field:"dayFrom"` // YYYYMMDD
|
||||
DayTo string `field:"dayTo"` // YYYYMMDD
|
||||
PeriodUnit string `field:"periodUnit"` // monthly|yearly
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type NSUserPlanOperator struct {
|
||||
Id any // ID
|
||||
UserId any // 用户ID
|
||||
PlanId any // 套餐ID
|
||||
DayFrom any // YYYYMMDD
|
||||
DayTo any // YYYYMMDD
|
||||
PeriodUnit any // monthly|yearly
|
||||
CreatedAt any // 创建时间
|
||||
State any // 状态
|
||||
}
|
||||
|
||||
func NewNSUserPlanOperator() *NSUserPlanOperator {
|
||||
return &NSUserPlanOperator{}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package nameservers
|
||||
@@ -0,0 +1,13 @@
|
||||
//go:build plus
|
||||
|
||||
package nameservers
|
||||
|
||||
import timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
|
||||
// IsAvailable 判断当前套餐是否有效
|
||||
func (this *NSUserPlan) IsAvailable() bool {
|
||||
if len(this.DayTo) == 0 {
|
||||
return false
|
||||
}
|
||||
return this.DayTo >= timeutil.Format("Ymd")
|
||||
}
|
||||
65
EdgeAPI/internal/db/models/nameservers/ns_zone_dao_plus.go
Normal file
65
EdgeAPI/internal/db/models/nameservers/ns_zone_dao_plus.go
Normal file
@@ -0,0 +1,65 @@
|
||||
//go:build plus
|
||||
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
const (
|
||||
NSZoneStateEnabled = 1 // 已启用
|
||||
NSZoneStateDisabled = 0 // 已禁用
|
||||
)
|
||||
|
||||
type NSZoneDAO dbs.DAO
|
||||
|
||||
func NewNSZoneDAO() *NSZoneDAO {
|
||||
return dbs.NewDAO(&NSZoneDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNSZones",
|
||||
Model: new(NSZone),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NSZoneDAO)
|
||||
}
|
||||
|
||||
var SharedNSZoneDAO *NSZoneDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNSZoneDAO = NewNSZoneDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableNSZone 启用条目
|
||||
func (this *NSZoneDAO) EnableNSZone(tx *dbs.Tx, id uint64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSZoneStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableNSZone 禁用条目
|
||||
func (this *NSZoneDAO) DisableNSZone(tx *dbs.Tx, id uint64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NSZoneStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// FindEnabledNSZone 查找启用中的条目
|
||||
func (this *NSZoneDAO) FindEnabledNSZone(tx *dbs.Tx, id uint64) (*NSZone, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", NSZoneStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*NSZone), err
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package nameservers
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
28
EdgeAPI/internal/db/models/nameservers/ns_zone_model.go
Normal file
28
EdgeAPI/internal/db/models/nameservers/ns_zone_model.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package nameservers
|
||||
|
||||
import "github.com/iwind/TeaGo/dbs"
|
||||
|
||||
// NSZone 域名子域
|
||||
type NSZone struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
DomainId uint64 `field:"domainId"` // 域名ID
|
||||
IsOn bool `field:"isOn"` // 是否启用
|
||||
Order uint32 `field:"order"` // 排序
|
||||
Version uint64 `field:"version"` // 版本
|
||||
Tsig dbs.JSON `field:"tsig"` // TSIG配置
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type NSZoneOperator struct {
|
||||
Id interface{} // ID
|
||||
DomainId interface{} // 域名ID
|
||||
IsOn interface{} // 是否启用
|
||||
Order interface{} // 排序
|
||||
Version interface{} // 版本
|
||||
Tsig interface{} // TSIG配置
|
||||
State interface{} // 状态
|
||||
}
|
||||
|
||||
func NewNSZoneOperator() *NSZoneOperator {
|
||||
return &NSZoneOperator{}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package nameservers
|
||||
Reference in New Issue
Block a user