Bladeren bron

refactor(internal/service/api/waf): 重构 Web 转发服务的编辑和删除功能

-优化了 Web 转发配置的编辑流程,拆分为多个步骤处理
- 重构了 Web转发配置的删除流程,实现批量删除功能
- 提取了通用的辅助函数,提高代码复用性
- 移除了冗余代码,简化了逻辑结构
fusu 5 uur geleden
bovenliggende
commit
5040bdc967
1 gewijzigde bestanden met toevoegingen van 66 en 312 verwijderingen
  1. 66 312
      internal/service/api/waf/webforwarding.go

+ 66 - 312
internal/service/api/waf/webforwarding.go

@@ -2,7 +2,6 @@ package waf
 
 import (
 	"context"
-	"encoding/json"
 	"fmt"
 	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
 	"github.com/go-nunu/nunu-layout-advanced/internal/model"
@@ -11,8 +10,6 @@ import (
 	"github.com/go-nunu/nunu-layout-advanced/internal/service/api/flexCdn"
 	"github.com/go-nunu/nunu-layout-advanced/pkg/rabbitmq"
 	"golang.org/x/sync/errgroup"
-	"maps"
-	"net"
 	"sort"
 )
 
@@ -215,364 +212,121 @@ func (s *webForwardingService) AddWebForwarding(ctx context.Context, req *v1.Web
 }
 
 func (s *webForwardingService) EditWebForwarding(ctx context.Context, req *v1.WebForwardingRequest) error {
-
-
-	err := s.wafformatter.validateWafDomainCount(ctx, v1.GlobalRequire{
-		HostId: req.HostId,
-		Domain: req.WebForwardingData.Domain,
-		Comment: req.WebForwardingData.Comment,
-		Uid: req.Uid,
-	})
-	if err != nil {
-		return err
-	}
-
+	// 1. 获取原始数据
 	oldData, err := s.webForwardingRepository.GetWebForwarding(ctx, int64(req.WebForwardingData.Id))
 	if err != nil {
-		return err
+		return fmt.Errorf("获取原始Web转发数据失败: %w", err)
 	}
+	// 继承旧的证书ID和策略ID,以便后续逻辑处理
 	req.WebForwardingData.SslCertId = int64(oldData.SslCertId)
 	req.WebForwardingData.SslPolicyId = int64(oldData.SslPolicyId)
+
+	// 2. 准备WAF数据和基础验证
 	require, formData, err := s.aidedWeb.PrepareWafData(ctx, req)
 	if err != nil {
 		return err
 	}
-
-	// 验证端口重复
-	protocol := s.aidedWeb.GetProtocolType(req.WebForwardingData.IsHttps)
-	err = s.wafformatter.VerifyPort(ctx, protocol, int64(req.WebForwardingData.Id), req.WebForwardingData.Port, int64(require.HostId), req.WebForwardingData.Domain)
-	if err != nil {
+	if err := s.aidedWeb.ValidateEditRequest(ctx, req, require, oldData); err != nil {
 		return err
 	}
 
-
-
-	//修改网站端口
-	if oldData.Port != req.WebForwardingData.Port || oldData.IsHttps != req.WebForwardingData.IsHttps || oldData.HttpsCert != req.WebForwardingData.HttpsCert || oldData.HttpsKey != req.WebForwardingData.HttpsKey {
-		var apiType string
-		var closeType string
-
-		// 修改证书
-		if oldData.HttpsCert != req.WebForwardingData.HttpsCert || oldData.HttpsKey != req.WebForwardingData.HttpsKey {
-			err = s.sslCert.EditSSLCert(ctx, v1.SSL{
-				Name:        req.WebForwardingData.Domain,
-				CertId:      oldData.SslCertId,
-				CertData:    req.WebForwardingData.HttpsCert,
-				KeyData:     req.WebForwardingData.HttpsKey,
-				CdnUserId:   require.CdnUid,
-				Domain:      req.WebForwardingData.Domain,
-				Description: req.WebForwardingData.Comment,
-			})
-			if err != nil {
-				return err
-			}
-		}
-
-		// 切换协议
-		var typeConfig v1.TypeJSON
-		var closeConfig v1.TypeJSON
-		if s.aidedWeb.IsHttpsProtocol(req.WebForwardingData.IsHttps) {
-			typeConfig = formData.HttpsJSON
-			closeConfig = formData.HttpJSON
-			apiType = s.aidedWeb.GetProtocolType(req.WebForwardingData.IsHttps)
-			closeType = s.aidedWeb.GetProtocolType(0) // HTTP
-		} else {
-			typeConfig = formData.HttpJSON
-			closeConfig = formData.HttpsJSON
-			apiType = s.aidedWeb.GetProtocolType(req.WebForwardingData.IsHttps)
-			closeType = s.aidedWeb.GetProtocolType(1) // HTTPS
-		}
-
-
-
-		typeJson,err := json.Marshal(typeConfig)
-		if err != nil {
-			return err
-		}
-		closeJson,err := json.Marshal(closeConfig)
-		if err != nil {
-			return err
-		}
-		// 切换协议
-		err = s.cdn.EditServerType(ctx, v1.EditWebsite{
-			Id:       int64(oldData.CdnWebId),
-			TypeJSON: typeJson,
-		}, apiType)
-		if err != nil {
-			return err
-		}
-		err = s.cdn.EditServerType(ctx, v1.EditWebsite{
-			Id:       int64(oldData.CdnWebId),
-			TypeJSON: closeJson,
-		}, closeType)
-		if err != nil {
-			return err
-		}
-	}
-
-	//修改网站域名
-	if oldData.Domain != req.WebForwardingData.Domain {
-		type serverName struct {
-			Name string `json:"name" form:"name"`
-			Type string `json:"type" form:"type"`
-		}
-		var serverData []serverName
-		var serverJson []byte
-		serverData = append(serverData, serverName{
-			Name: req.WebForwardingData.Domain,
-			Type: "full",
-		})
-		serverJson, err = json.Marshal(serverData)
-		if err != nil {
-			return err
-		}
-		err = s.cdn.EditServerName(ctx, v1.EditServerNames{
-			ServerId:        int64(oldData.CdnWebId),
-			ServerNamesJSON: serverJson,
-		})
-		if err != nil {
-			return err
-		}
+	// 3. 处理SSL证书更新
+	if err := s.aidedWeb.ProcessSSLCertificateUpdate(ctx, req, oldData, require); err != nil {
+		return err
 	}
 
-	//修改网站名字
-	if oldData.Comment != req.WebForwardingData.Comment {
-		nodeId,err := s.globalLimitRep.GetNodeId(ctx, oldData.CdnWebId)
-		if err != nil {
-			return err
-		}
-		err = s.cdn.EditServerBasic(ctx, int64(oldData.CdnWebId), require.Tag,nodeId)
-		if err != nil {
-			return err
-		}
+	// 4. 更新核心CDN配置(端口、协议、域名、备注等)
+	if err := s.aidedWeb.UpdateCdnConfiguration(ctx, req, oldData, require, formData); err != nil {
+		return err
 	}
 
-	//修改Proxy
+	// 5. 更新Proxy Protocol配置
 	if oldData.Proxy != req.WebForwardingData.Proxy {
-		err = s.proxy.EditProxy(ctx, int64(oldData.CdnWebId), v1.ProxyProtocolJSON{
-			IsOn:    req.WebForwardingData.Proxy,
-			Version: 1,
-		})
-		if err != nil {
+		if err := s.aidedWeb.ConfigureProxyProtocol(ctx, req, int64(oldData.CdnWebId)); err != nil {
 			return err
 		}
 	}
 
-	// 修改CC配置
-	err = s.cc.EditCcConfig(ctx, int64(oldData.CdnWebId), v1.CcConfigRequest{
-		IsOn:            req.WebForwardingData.CcConfig.IsOn,
-		Level:           req.WebForwardingData.CcConfig.Level,
-		Limit5s:         req.WebForwardingData.CcConfig.Limit5s,
-		Limit60s:        req.WebForwardingData.CcConfig.Limit60s,
-		Limit300s:       req.WebForwardingData.CcConfig.Limit300s,
-		ThresholdMethod: req.WebForwardingData.CcConfig.ThresholdMethod,
-	})
-	if err != nil {
+	// 6. 更新CC防护配置
+	if err := s.aidedWeb.ConfigureCCProtection(ctx, req, int64(oldData.CdnWebId)); err != nil {
 		return err
 	}
 
-	// 将域名添加到白名单
-	webData, err := s.webForwardingRepository.GetWebForwarding(ctx, int64(req.WebForwardingData.Id))
-	if err != nil {
+	// 7. 处理域名白名单变更
+	if err := s.aidedWeb.ProcessDomainWhitelistChanges(ctx, req, oldData, require); err != nil {
 		return err
 	}
 
-	// 异步任务:将域名添加到白名单
-	if webData.Domain != req.WebForwardingData.Domain {
-		firstIp, err := s.gatewayIp.GetGatewayipByHostIdFirst(ctx, int64(req.HostId), int64(req.Uid))
-		if err != nil {
-			return err
-		}
-		doMain, err := s.wafformatter.ConvertToWildcardDomain(ctx, req.WebForwardingData.Domain)
-		if err != nil {
-			return err
-		}
-
-		oldDomain, err := s.wafformatter.ConvertToWildcardDomain(ctx, webData.Domain)
-		if err != nil {
-			return err
-		}
-		if len(require.GatewayIps) == 0 {
-			return fmt.Errorf("网关组不存在")
-		}
-
-		// 查找域名数量,如果数量小于2,删除旧域名
-		count, err := s.webForwardingRepository.GetDomainCount(ctx, req.HostId, webData.Domain)
-		if err != nil {
-			return err
-		}
-		if count < 2 {
-			go s.wafformatter.PublishDomainWhitelistTask(oldDomain, firstIp, "del")
-		}
-		go s.wafformatter.PublishDomainWhitelistTask(doMain, firstIp, "add")
-	}
-
-	// IP过白
+	// 8. 获取后端IP规则数据
 	ipData, err := s.webForwardingRepository.GetWebForwardingIpsByID(ctx, req.WebForwardingData.Id)
 	if err != nil {
-		return err
+		return fmt.Errorf("获取Web转发IP规则失败: %w", err)
 	}
-	var oldIps []string
-	var newIps []string
-	for _, v := range ipData.BackendList {
-		ip, _, err := net.SplitHostPort(v.Addr)
-		if err != nil {
-			return err
-		}
-		oldIps = append(oldIps, ip)
+
+	// 9. 处理源站IP白名单变更
+	if err := s.aidedWeb.ProcessIpWhitelistChanges(ctx, req, ipData); err != nil {
+		return err
 	}
-	for _, v := range req.WebForwardingData.BackendList {
-		ip, _, err := net.SplitHostPort(v.Addr)
-		if err != nil {
-			return err
-		}
-		newIps = append(newIps, ip)
+
+	// 10. 更新CDN上的源站服务器
+	if err := s.aidedWeb.UpdateOriginServers(ctx, req, oldData, ipData); err != nil {
+		return err
 	}
-	addedIps, removedIps := s.wafformatter.findIpDifferences(oldIps, newIps)
-	if len(addedIps) > 0 {
-		go s.wafformatter.PublishIpWhitelistTask(addedIps, "add", "", "white")
+
+	// 11. 更新本地数据库记录
+	if err := s.aidedWeb.UpdateDatabaseRecords(ctx, req, oldData, require, ipData); err != nil {
+		return err
 	}
 
-	// IP过白
-	if len(removedIps) > 0 {
-		// 1. 一次性获取所有相关IP的数量
-		ipsToDelist, err := s.wafformatter.WashDelIps(ctx, removedIps)
-		if err != nil {
-			return err
-		}
+	return nil
+}
 
-		// 4. 如果有需要处理的IP,则批量发布一次任务
-		if len(ipsToDelist) > 0 {
-			go s.wafformatter.PublishIpWhitelistTask(ipsToDelist, "del", "0", "white")
+// DeleteWebForwarding 批量删除Web转发配置
+// 该函数遍历ID列表,对每个ID执行完整的、独立的删除流程
+func (s *webForwardingService) DeleteWebForwarding(ctx context.Context, req v1.DeleteWebForwardingRequest) error {
+	for _, id := range req.Ids {
+		if err := s.deleteSingleWebForwarding(ctx, id, req.HostId, req.Uid); err != nil {
+			// 增加错误上下文,方便定位问题
+			return fmt.Errorf("删除Web转发配置失败 ID:%d, %w", id, err)
 		}
 	}
+	return nil
+}
 
-	//修改源站
-	addOrigins, delOrigins := s.aidedWeb.FindDifferenceList(ipData.BackendList, req.WebForwardingData.BackendList)
-	addedIds := make(map[string]int64)
-	for _, v := range addOrigins {
-		apiType := s.aidedWeb.GetProtocolType(v.IsHttps)
-		id, err := s.wafformatter.AddOrigin(ctx, v1.WebJson{
-			ApiType:     apiType,
-			BackendList: v.Addr,
-			Host:        v.CustomHost,
-			Comment:     req.WebForwardingData.Comment,
-		})
-		if err != nil {
-			return err
-		}
-		addedIds[v.Addr] = id
+// deleteSingleWebForwarding 删除单个Web转发配置的完整流程
+func (s *webForwardingService) deleteSingleWebForwarding(ctx context.Context, id int, hostId int, uid int) error {
+	// 1. 获取并验证数据
+	oldData, err := s.webForwardingRepository.GetWebForwarding(ctx, int64(id))
+	if err != nil {
+		return fmt.Errorf("获取Web转发数据失败: %w", err)
 	}
-	for _, v := range addedIds {
-		err = s.cdn.AddServerOrigin(ctx, int64(oldData.CdnWebId), v)
-		if err != nil {
-			return err
-		}
+	if err := s.aidedWeb.ValidateDeletePermission(oldData, hostId); err != nil {
+		return err
 	}
 
-	for k, v := range ipData.CdnOriginIds {
-		for _, ip := range delOrigins {
-			if k == ip.Addr {
-				err = s.cdn.DelServerOrigin(ctx, int64(oldData.CdnWebId), v)
-				if err != nil {
-					return err
-				}
-				delete(ipData.CdnOriginIds, k)
-			}
-		}
+	// 2. 删除CDN服务器
+	if err := s.aidedWeb.DeleteCdnServer(ctx, oldData.CdnWebId); err != nil {
+		return err
 	}
 
-	maps.Copy(ipData.CdnOriginIds, addedIds)
-
-	webModel := s.aidedWeb.BuildWebForwardingModel(&req.WebForwardingData, req.WebForwardingData.CdnWebId, require)
-	webModel.Id = req.WebForwardingData.Id
-	if err = s.webForwardingRepository.EditWebForwarding(ctx, webModel); err != nil {
+	// 3. 处理域名白名单清理
+	if err := s.aidedWeb.ProcessDeleteDomainWhitelist(ctx, oldData, uid); err != nil {
 		return err
 	}
-	webRuleModel := s.aidedWeb.BuildWebRuleModel(&req.WebForwardingData, require, req.WebForwardingData.Id, ipData.CdnOriginIds)
-	if err = s.webForwardingRepository.EditWebForwardingIps(ctx, *webRuleModel); err != nil {
+
+	// 4. 处理IP白名单清理
+	if err := s.aidedWeb.ProcessDeleteIpWhitelist(ctx, id); err != nil {
 		return err
 	}
-	return nil
-}
-
-func (s *webForwardingService) DeleteWebForwarding(ctx context.Context, req v1.DeleteWebForwardingRequest) error {
-	for _, Id := range req.Ids {
-		oldData, err := s.webForwardingRepository.GetWebForwarding(ctx, int64(Id))
-		if err != nil {
-			return err
-		}
-
-		if oldData.HostId != req.HostId {
-			return fmt.Errorf("用户权限不足")
-		}
-
-		err = s.cdn.DelServer(ctx, int64(oldData.CdnWebId))
-		if err != nil {
-			return err
-		}
-
-		// 异步任务:将域名添加到白名单
-		firstIp, err := s.gatewayIp.GetGatewayipByHostIdFirst(ctx, int64(oldData.HostId), int64(req.Uid))
-		if err != nil {
-			return err
-		}
-		if oldData.Domain != "" {
-
-			doMain, err := s.wafformatter.ConvertToWildcardDomain(ctx, oldData.Domain)
-			if err != nil {
-				return err
-			}
-			go s.wafformatter.PublishDomainWhitelistTask(doMain, firstIp, "del")
-		}
-		// IP过白
-		ipData, err := s.webForwardingRepository.GetWebForwardingIpsByID(ctx, Id)
-		if err != nil {
-			return err
-		}
-		var ips []string
-		if ipData != nil && len(ipData.BackendList) > 0 {
-			for _, v := range ipData.BackendList {
-				ip, _, err := net.SplitHostPort(v.Addr)
-				if err != nil {
-					return err
-				}
-				ips = append(ips, ip)
-			}
-		}
-		if len(ips) > 0 {
-			ipsToDelist, err := s.wafformatter.WashDelIps(ctx, ips)
-			if err != nil {
-				return err
-			}
-
-			// 4. 如果有需要处理的IP,则批量发布一次任务
-			if len(ipsToDelist) > 0 {
-				go s.wafformatter.PublishIpWhitelistTask(ipsToDelist, "del", "0", "white")
-			}
-		}
-
-		// 删除ssl
-		if oldData.SslCertId != 0 {
-			err = s.cdn.DelSSLCert(ctx, int64(oldData.SslCertId))
-			if err != nil {
-				return err
-			}
-			err = s.sslCert.EditSslPolicy(ctx, int64(oldData.SslPolicyId), []int64{int64(oldData.SslCertId)}, "del")
-			if err != nil {
-				return err
-			}
-		}
-
-
 
+	// 5. 清理SSL证书
+	if err := s.aidedWeb.CleanupSSLCertificate(ctx, oldData); err != nil {
+		return err
+	}
 
-		if err = s.webForwardingRepository.DeleteWebForwarding(ctx, int64(Id)); err != nil {
-			return err
-		}
-		if err = s.webForwardingRepository.DeleteWebForwardingIpsById(ctx, Id); err != nil {
-			return err
-		}
+	// 6. 清理数据库记录
+	if err := s.aidedWeb.CleanupDatabaseRecords(ctx, id); err != nil {
+		return err
 	}
 
 	return nil