globallimit.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. package service
  2. import (
  3. "context"
  4. "fmt"
  5. v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
  6. "github.com/go-nunu/nunu-layout-advanced/internal/model"
  7. "github.com/go-nunu/nunu-layout-advanced/internal/repository"
  8. "github.com/spf13/cast"
  9. "github.com/spf13/viper"
  10. "golang.org/x/sync/errgroup"
  11. "strconv"
  12. )
  13. type GlobalLimitService interface {
  14. GetGlobalLimit(ctx context.Context, id int64) (*model.GlobalLimit, error)
  15. AddGlobalLimit(ctx context.Context, req v1.GlobalLimitRequest) error
  16. EditGlobalLimit(ctx context.Context, req v1.GlobalLimitRequest) error
  17. DeleteGlobalLimit(ctx context.Context, req v1.GlobalLimitRequest) error
  18. }
  19. func NewGlobalLimitService(
  20. service *Service,
  21. globalLimitRepository repository.GlobalLimitRepository,
  22. duedate DuedateService,
  23. crawler CrawlerService,
  24. conf *viper.Viper,
  25. required RequiredService,
  26. parser ParserService,
  27. host HostService,
  28. tcpLimit TcpLimitService,
  29. udpLimit UdpLimitService,
  30. webLimit WebLimitService,
  31. gateWayGroup GatewayGroupService,
  32. hostRep repository.HostRepository,
  33. ) GlobalLimitService {
  34. return &globalLimitService{
  35. Service: service,
  36. globalLimitRepository: globalLimitRepository,
  37. duedate: duedate,
  38. crawler: crawler,
  39. Url: conf.GetString("crawler.Url"),
  40. required: required,
  41. parser: parser,
  42. host: host,
  43. tcpLimit: tcpLimit,
  44. udpLimit: udpLimit,
  45. webLimit: webLimit,
  46. gateWayGroup: gateWayGroup,
  47. hostRep: hostRep,
  48. }
  49. }
  50. type globalLimitService struct {
  51. *Service
  52. globalLimitRepository repository.GlobalLimitRepository
  53. duedate DuedateService
  54. crawler CrawlerService
  55. Url string
  56. required RequiredService
  57. parser ParserService
  58. host HostService
  59. tcpLimit TcpLimitService
  60. udpLimit UdpLimitService
  61. webLimit WebLimitService
  62. gateWayGroup GatewayGroupService
  63. hostRep repository.HostRepository
  64. }
  65. func (s *globalLimitService) GlobalLimitRequire(ctx context.Context, req v1.GlobalLimitRequest) (res v1.GlobalLimitRequireResponse, err error) {
  66. isExist, err := s.globalLimitRepository.IsGlobalLimitExistByHostId(ctx, int64(req.HostId))
  67. if err != nil {
  68. return v1.GlobalLimitRequireResponse{}, err
  69. }
  70. if isExist {
  71. return v1.GlobalLimitRequireResponse{}, fmt.Errorf("配置限制已存在")
  72. }
  73. res.ExpiredAt, err = s.duedate.NextDueDate(ctx, req.Uid, req.HostId)
  74. if err != nil {
  75. return v1.GlobalLimitRequireResponse{}, err
  76. }
  77. configCount, err := s.host.GetGlobalLimitConfig(ctx, req.HostId)
  78. if err != nil {
  79. return v1.GlobalLimitRequireResponse{}, fmt.Errorf("获取配置限制失败: %w", err)
  80. }
  81. res.Bps = configCount.Bps
  82. res.MaxBytesMonth = configCount.MaxBytesMonth
  83. domain, err := s.hostRep.GetDomainById(ctx, req.HostId)
  84. if err != nil {
  85. return v1.GlobalLimitRequireResponse{}, err
  86. }
  87. res.GlobalLimitName = strconv.Itoa(req.Uid) + "_" + strconv.Itoa(req.HostId) + "_" + domain
  88. return res, nil
  89. }
  90. func (s *globalLimitService) GetGlobalLimit(ctx context.Context, id int64) (*model.GlobalLimit, error) {
  91. return s.globalLimitRepository.GetGlobalLimit(ctx, id)
  92. }
  93. func (s *globalLimitService) AddGlobalLimit(ctx context.Context, req v1.GlobalLimitRequest) error {
  94. require, err := s.GlobalLimitRequire(ctx, req)
  95. if err != nil {
  96. return err
  97. }
  98. formData := map[string]interface{}{
  99. "tag": require.GlobalLimitName,
  100. "bps": require.Bps,
  101. "max_bytes_month": require.MaxBytesMonth,
  102. "expired_at": require.ExpiredAt,
  103. }
  104. respBody, err := s.required.SendForm(ctx, "admin/info/waf_common_limit/new", "admin/new/waf_common_limit", formData)
  105. if err != nil {
  106. return err
  107. }
  108. ruleIdBase, err := s.parser.GetRuleIdByColumnName(ctx, respBody, require.GlobalLimitName)
  109. if err != nil {
  110. return err
  111. }
  112. if ruleIdBase == "" {
  113. res, err := s.parser.ParseAlert(string(respBody))
  114. if err != nil {
  115. return err
  116. }
  117. return fmt.Errorf(res)
  118. }
  119. ruleId, err := cast.ToIntE(ruleIdBase)
  120. if err != nil {
  121. return err
  122. }
  123. var tcpLimitRuleId, udpLimitRuleId, webLimitRuleId int
  124. g, gCtx := errgroup.WithContext(ctx)
  125. // 启动tcpLimit调用 - 使用独立的请求参数副本
  126. g.Go(func() error {
  127. tcpLimitReq := &v1.GeneralLimitRequireRequest{
  128. Tag: require.GlobalLimitName,
  129. HostId: req.HostId,
  130. RuleId: ruleId,
  131. Uid: req.Uid,
  132. }
  133. result, e := s.tcpLimit.AddTcpLimit(gCtx, tcpLimitReq)
  134. if e != nil {
  135. return fmt.Errorf("tcpLimit调用失败: %w", e)
  136. }
  137. if result != 0 {
  138. tcpLimitRuleId = result
  139. return nil
  140. }
  141. return fmt.Errorf("tcpLimit调用失败,Id为 %d", result)
  142. })
  143. // 启动udpLimit调用 - 使用独立的请求参数副本
  144. g.Go(func() error {
  145. udpLimitReq := &v1.GeneralLimitRequireRequest{
  146. Tag: require.GlobalLimitName,
  147. HostId: req.HostId,
  148. RuleId: ruleId,
  149. Uid: req.Uid,
  150. }
  151. result, e := s.udpLimit.AddUdpLimit(gCtx, udpLimitReq)
  152. if e != nil {
  153. return fmt.Errorf("udpLimit调用失败: %w", e)
  154. }
  155. if result != 0 {
  156. udpLimitRuleId = result
  157. return nil
  158. }
  159. return fmt.Errorf("udpLimit调用失败,Id为 %d", result)
  160. })
  161. // 启动webLimit调用 - 使用独立的请求参数副本
  162. g.Go(func() error {
  163. webLimitReq := &v1.GeneralLimitRequireRequest{
  164. Tag: require.GlobalLimitName,
  165. HostId: req.HostId,
  166. RuleId: ruleId,
  167. Uid: req.Uid,
  168. }
  169. result, e := s.webLimit.AddWebLimit(gCtx, webLimitReq)
  170. if e != nil {
  171. return fmt.Errorf("webLimit调用失败: %w", e)
  172. }
  173. if result != 0 {
  174. webLimitRuleId = result
  175. return nil
  176. }
  177. return fmt.Errorf("webLimit调用失败,Id为 %d", result)
  178. })
  179. if err := g.Wait(); err != nil {
  180. return err
  181. }
  182. err = s.globalLimitRepository.AddGlobalLimit(ctx, &model.GlobalLimit{
  183. HostId: req.HostId,
  184. RuleId: cast.ToInt(ruleId),
  185. GlobalLimitName: require.GlobalLimitName,
  186. Comment: req.Comment,
  187. TcpLimitRuleId: tcpLimitRuleId,
  188. UdpLimitRuleId: udpLimitRuleId,
  189. WebLimitRuleId: webLimitRuleId,
  190. GatewayGroupId: 5,// TODO: 临时写死
  191. })
  192. if err != nil {
  193. return err
  194. }
  195. return nil
  196. }
  197. func (s *globalLimitService) EditGlobalLimit(ctx context.Context, req v1.GlobalLimitRequest) error {
  198. if err := s.globalLimitRepository.UpdateGlobalLimitByHostId(ctx, &model.GlobalLimit{
  199. HostId: req.HostId,
  200. Comment: req.Comment,
  201. }); err != nil {
  202. return err
  203. }
  204. return nil
  205. }
  206. func (s *globalLimitService) DeleteGlobalLimit(ctx context.Context, req v1.GlobalLimitRequest) error {
  207. if err := s.globalLimitRepository.DeleteGlobalLimitByHostId(ctx, int64(req.HostId)); err != nil {
  208. return err
  209. }
  210. return nil
  211. }