Files
waf-platform/EdgeAPI/internal/rpc/services/httpdns/service_httpdns_app.go

371 lines
11 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

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

package httpdns
import (
"context"
"encoding/json"
"errors"
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
"github.com/iwind/TeaGo/dbs"
"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")
}
// 使用 clusterIdsJSON若为空则从用户关联集群获取
clusterIdsJSON := req.ClusterIdsJSON
if len(clusterIdsJSON) == 0 || string(clusterIdsJSON) == "[]" || string(clusterIdsJSON) == "null" {
// 读取用户关联的 HTTPDNS 集群
if req.UserId > 0 {
user, userErr := models.SharedUserDAO.FindEnabledUser(tx, req.UserId, nil)
if userErr != nil {
return userErr
}
if user != nil && len(user.HttpdnsClusterIds) > 0 {
var userClusterIds []int64
if json.Unmarshal([]byte(user.HttpdnsClusterIds), &userClusterIds) == nil && len(userClusterIds) > 0 {
clusterIdsJSON, _ = json.Marshal(userClusterIds)
}
}
}
}
// 如果仍然没有集群,则不允许创建
if len(clusterIdsJSON) == 0 || string(clusterIdsJSON) == "[]" || string(clusterIdsJSON) == "null" {
return errors.New("用户尚未分配 HTTPDNS 集群,无法创建应用")
}
appDbId, err = models.SharedHTTPDNSAppDAO.CreateApp(tx, appName, appId, clusterIdsJSON, 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
}
// readHTTPDNSDefaultClusterIdList reads default cluster IDs from UserRegisterConfig.
func readHTTPDNSDefaultClusterIdList(tx *dbs.Tx) ([]int64, error) {
// 优先从 UserRegisterConfig 中读取
configJSON, err := models.SharedSysSettingDAO.ReadSetting(tx, systemconfigs.SettingCodeUserRegisterConfig)
if err != nil {
return nil, err
}
if len(configJSON) > 0 {
var config userconfigs.UserRegisterConfig
if err := json.Unmarshal(configJSON, &config); err == nil {
if len(config.HTTPDNSDefaultClusterIds) > 0 {
// 验证集群有效性
var validIds []int64
for _, id := range config.HTTPDNSDefaultClusterIds {
if id <= 0 {
continue
}
cluster, err := models.SharedHTTPDNSClusterDAO.FindEnabledCluster(tx, id)
if err != nil {
return nil, err
}
if cluster != nil && cluster.IsOn {
validIds = append(validIds, id)
}
}
if len(validIds) > 0 {
return validIds, nil
}
}
}
}
return nil, 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
}
err = models.SharedHTTPDNSAppDAO.UpdateApp(tx, req.AppDbId, req.Name, req.ClusterIdsJSON, 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
}