375 lines
11 KiB
Go
375 lines
11 KiB
Go
package httpdns
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
|
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
|
"github.com/iwind/TeaGo/dbs"
|
|
"github.com/iwind/TeaGo/types"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
|
)
|
|
|
|
// HTTPDNSAppService HTTPDNS应用服务
|
|
type HTTPDNSAppService struct {
|
|
services.BaseService
|
|
pb.UnimplementedHTTPDNSAppServiceServer
|
|
}
|
|
|
|
func (this *HTTPDNSAppService) CreateHTTPDNSApp(ctx context.Context, req *pb.CreateHTTPDNSAppRequest) (*pb.CreateHTTPDNSAppResponse, error) {
|
|
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if userId > 0 {
|
|
req.UserId = userId
|
|
}
|
|
appName := strings.TrimSpace(req.Name)
|
|
appId := strings.TrimSpace(req.AppId)
|
|
if len(appName) == 0 || len(appId) == 0 {
|
|
return nil, errors.New("required 'name' and 'appId'")
|
|
}
|
|
var appDbId int64
|
|
now := time.Now().Unix()
|
|
err = this.RunTx(func(tx *dbs.Tx) error {
|
|
// 用户端防重复提交:短时间内同用户同应用名仅创建一次。
|
|
if req.UserId > 0 {
|
|
latest, err := models.SharedHTTPDNSAppDAO.FindLatestEnabledAppWithNameAndUser(tx, appName, req.UserId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if latest != nil && int64(latest.CreatedAt) >= now-5 {
|
|
appDbId = int64(latest.Id)
|
|
secret, err := models.SharedHTTPDNSAppSecretDAO.FindEnabledAppSecret(tx, appDbId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if secret == nil {
|
|
_, _, err = models.SharedHTTPDNSAppSecretDAO.InitAppSecret(tx, appDbId, req.SignEnabled)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
exists, err := models.SharedHTTPDNSAppDAO.FindEnabledAppWithAppId(tx, appId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if exists != nil {
|
|
return errors.New("appId already exists")
|
|
}
|
|
|
|
primaryClusterId := req.PrimaryClusterId
|
|
backupClusterId := req.BackupClusterId
|
|
if primaryClusterId <= 0 || backupClusterId <= 0 {
|
|
defaultPrimaryClusterId, defaultBackupClusterId, err := readHTTPDNSDefaultClusterIds(tx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if primaryClusterId <= 0 {
|
|
primaryClusterId = defaultPrimaryClusterId
|
|
}
|
|
if backupClusterId <= 0 {
|
|
backupClusterId = defaultBackupClusterId
|
|
}
|
|
}
|
|
if primaryClusterId > 0 && backupClusterId == primaryClusterId {
|
|
backupClusterId = 0
|
|
}
|
|
|
|
appDbId, err = models.SharedHTTPDNSAppDAO.CreateApp(tx, appName, appId, primaryClusterId, backupClusterId, req.IsOn, req.UserId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _, err = models.SharedHTTPDNSAppSecretDAO.InitAppSecret(tx, appDbId, req.SignEnabled)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return notifyHTTPDNSAppTasksByAppDbId(tx, appDbId, models.HTTPDNSNodeTaskTypeAppChanged)
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &pb.CreateHTTPDNSAppResponse{AppDbId: appDbId}, nil
|
|
}
|
|
|
|
func readHTTPDNSDefaultClusterIds(tx *dbs.Tx) (primaryClusterId int64, backupClusterId int64, err error) {
|
|
primaryClusterId, err = models.SharedHTTPDNSClusterDAO.FindDefaultPrimaryClusterId(tx)
|
|
if err != nil {
|
|
return 0, 0, err
|
|
}
|
|
|
|
backupClusterId = 0
|
|
backupValueJSON, err := models.SharedSysSettingDAO.ReadSetting(tx, systemconfigs.SettingCodeHTTPDNSDefaultBackupClusterId)
|
|
if err != nil {
|
|
return 0, 0, err
|
|
}
|
|
if len(backupValueJSON) > 0 {
|
|
backupClusterId = types.Int64(string(backupValueJSON))
|
|
}
|
|
if backupClusterId > 0 {
|
|
backupCluster, err := models.SharedHTTPDNSClusterDAO.FindEnabledCluster(tx, backupClusterId)
|
|
if err != nil {
|
|
return 0, 0, err
|
|
}
|
|
if backupCluster == nil || !backupCluster.IsOn {
|
|
backupClusterId = 0
|
|
}
|
|
}
|
|
|
|
if primaryClusterId > 0 {
|
|
primaryCluster, err := models.SharedHTTPDNSClusterDAO.FindEnabledCluster(tx, primaryClusterId)
|
|
if err != nil {
|
|
return 0, 0, err
|
|
}
|
|
if primaryCluster == nil || !primaryCluster.IsOn {
|
|
primaryClusterId = 0
|
|
}
|
|
}
|
|
|
|
if primaryClusterId > 0 && backupClusterId == primaryClusterId {
|
|
backupClusterId = 0
|
|
}
|
|
return primaryClusterId, backupClusterId, nil
|
|
}
|
|
|
|
func (this *HTTPDNSAppService) UpdateHTTPDNSApp(ctx context.Context, req *pb.UpdateHTTPDNSAppRequest) (*pb.RPCSuccess, error) {
|
|
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = this.RunTx(func(tx *dbs.Tx) error {
|
|
oldApp, err := ensureAppAccess(tx, req.AppDbId, userId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if oldApp == nil {
|
|
return errors.New("app not found")
|
|
}
|
|
|
|
targetUserId := req.UserId
|
|
if targetUserId <= 0 {
|
|
targetUserId = oldApp.UserId
|
|
}
|
|
if userId > 0 {
|
|
targetUserId = userId
|
|
}
|
|
primaryClusterId := req.PrimaryClusterId
|
|
backupClusterId := req.BackupClusterId
|
|
if primaryClusterId > 0 && backupClusterId == primaryClusterId {
|
|
backupClusterId = 0
|
|
}
|
|
|
|
err = models.SharedHTTPDNSAppDAO.UpdateApp(tx, req.AppDbId, req.Name, primaryClusterId, backupClusterId, req.IsOn, targetUserId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = notifyHTTPDNSAppTasksByApp(tx, oldApp, models.HTTPDNSNodeTaskTypeAppChanged)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return notifyHTTPDNSAppTasksByAppDbId(tx, req.AppDbId, models.HTTPDNSNodeTaskTypeAppChanged)
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return this.Success()
|
|
}
|
|
|
|
func (this *HTTPDNSAppService) DeleteHTTPDNSApp(ctx context.Context, req *pb.DeleteHTTPDNSAppRequest) (*pb.RPCSuccess, error) {
|
|
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = this.RunTx(func(tx *dbs.Tx) error {
|
|
app, err := ensureAppAccess(tx, req.AppDbId, userId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if app == nil {
|
|
return nil
|
|
}
|
|
|
|
// 1) 先停用规则记录
|
|
rules, err := models.SharedHTTPDNSCustomRuleDAO.ListEnabledRulesWithAppId(tx, req.AppDbId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, rule := range rules {
|
|
err = models.SharedHTTPDNSCustomRuleRecordDAO.DisableRecordsWithRuleId(tx, int64(rule.Id))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// 2) 停用规则、域名、密钥
|
|
err = models.SharedHTTPDNSCustomRuleDAO.DisableRulesWithAppId(tx, req.AppDbId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = models.SharedHTTPDNSDomainDAO.DisableDomainsWithAppId(tx, req.AppDbId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = models.SharedHTTPDNSAppSecretDAO.DisableAppSecret(tx, req.AppDbId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 3) 删除该应用的 MySQL 访问日志,避免残留
|
|
err = models.SharedHTTPDNSAccessLogDAO.DeleteLogsWithAppId(tx, app.AppId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 4) 最后停用应用
|
|
err = models.SharedHTTPDNSAppDAO.DisableApp(tx, req.AppDbId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return notifyHTTPDNSAppTasksByApp(tx, app, models.HTTPDNSNodeTaskTypeAppChanged)
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return this.Success()
|
|
}
|
|
|
|
func (this *HTTPDNSAppService) FindHTTPDNSApp(ctx context.Context, req *pb.FindHTTPDNSAppRequest) (*pb.FindHTTPDNSAppResponse, error) {
|
|
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
app, err := ensureAppAccess(this.NullTx(), req.AppDbId, userId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if app == nil {
|
|
return &pb.FindHTTPDNSAppResponse{}, nil
|
|
}
|
|
secret, err := models.SharedHTTPDNSAppSecretDAO.FindEnabledAppSecret(this.NullTx(), req.AppDbId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &pb.FindHTTPDNSAppResponse{App: toPBApp(app, secret)}, nil
|
|
}
|
|
|
|
func (this *HTTPDNSAppService) ListHTTPDNSApps(ctx context.Context, req *pb.ListHTTPDNSAppsRequest) (*pb.ListHTTPDNSAppsResponse, error) {
|
|
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var apps []*models.HTTPDNSApp
|
|
if userId > 0 {
|
|
apps, err = models.SharedHTTPDNSAppDAO.ListEnabledAppsWithUser(this.NullTx(), userId, req.Offset, req.Size, req.Keyword)
|
|
} else {
|
|
apps, err = models.SharedHTTPDNSAppDAO.ListEnabledApps(this.NullTx(), req.Offset, req.Size, req.Keyword)
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var pbApps []*pb.HTTPDNSApp
|
|
for _, app := range apps {
|
|
secret, err := models.SharedHTTPDNSAppSecretDAO.FindEnabledAppSecret(this.NullTx(), int64(app.Id))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pbApps = append(pbApps, toPBApp(app, secret))
|
|
}
|
|
return &pb.ListHTTPDNSAppsResponse{Apps: pbApps}, nil
|
|
}
|
|
|
|
func (this *HTTPDNSAppService) FindAllHTTPDNSApps(ctx context.Context, req *pb.FindAllHTTPDNSAppsRequest) (*pb.FindAllHTTPDNSAppsResponse, error) {
|
|
_, userId, validateErr := this.ValidateAdminAndUser(ctx, true)
|
|
if validateErr != nil {
|
|
if _, nodeErr := this.ValidateHTTPDNSNode(ctx); nodeErr != nil {
|
|
return nil, validateErr
|
|
}
|
|
}
|
|
var apps []*models.HTTPDNSApp
|
|
var err error
|
|
if validateErr == nil && userId > 0 {
|
|
apps, err = models.SharedHTTPDNSAppDAO.FindAllEnabledAppsWithUser(this.NullTx(), userId)
|
|
} else {
|
|
apps, err = models.SharedHTTPDNSAppDAO.FindAllEnabledApps(this.NullTx())
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var pbApps []*pb.HTTPDNSApp
|
|
for _, app := range apps {
|
|
secret, err := models.SharedHTTPDNSAppSecretDAO.FindEnabledAppSecret(this.NullTx(), int64(app.Id))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pbApps = append(pbApps, toPBApp(app, secret))
|
|
}
|
|
return &pb.FindAllHTTPDNSAppsResponse{Apps: pbApps}, nil
|
|
}
|
|
|
|
func (this *HTTPDNSAppService) UpdateHTTPDNSAppSignEnabled(ctx context.Context, req *pb.UpdateHTTPDNSAppSignEnabledRequest) (*pb.RPCSuccess, error) {
|
|
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = this.RunTx(func(tx *dbs.Tx) error {
|
|
app, err := ensureAppAccess(tx, req.AppDbId, userId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if app == nil {
|
|
return errors.New("app not found")
|
|
}
|
|
|
|
err = models.SharedHTTPDNSAppSecretDAO.UpdateSignEnabled(tx, req.AppDbId, req.SignEnabled)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return notifyHTTPDNSAppTasksByAppDbId(tx, req.AppDbId, models.HTTPDNSNodeTaskTypeAppChanged)
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return this.Success()
|
|
}
|
|
|
|
func (this *HTTPDNSAppService) ResetHTTPDNSAppSignSecret(ctx context.Context, req *pb.ResetHTTPDNSAppSignSecretRequest) (*pb.ResetHTTPDNSAppSignSecretResponse, error) {
|
|
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var signSecret string
|
|
var updatedAt int64
|
|
err = this.RunTx(func(tx *dbs.Tx) error {
|
|
app, err := ensureAppAccess(tx, req.AppDbId, userId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if app == nil {
|
|
return errors.New("app not found")
|
|
}
|
|
|
|
signSecret, updatedAt, err = models.SharedHTTPDNSAppSecretDAO.ResetSignSecret(tx, req.AppDbId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return notifyHTTPDNSAppTasksByAppDbId(tx, req.AppDbId, models.HTTPDNSNodeTaskTypeAppChanged)
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &pb.ResetHTTPDNSAppSignSecretResponse{
|
|
SignSecret: signSecret,
|
|
UpdatedAt: updatedAt,
|
|
}, nil
|
|
}
|