globallimit.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  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. "time"
  13. )
  14. type GlobalLimitService interface {
  15. GetGlobalLimit(ctx context.Context, id int64) (*model.GlobalLimit, error)
  16. AddGlobalLimit(ctx context.Context, req v1.GlobalLimitRequest) error
  17. EditGlobalLimit(ctx context.Context, req v1.GlobalLimitRequest) error
  18. DeleteGlobalLimit(ctx context.Context, req v1.GlobalLimitRequest) error
  19. EditGlobalLimitBySnail(ctx context.Context, req v1.GlobalLimitEditRequest) error
  20. }
  21. func NewGlobalLimitService(
  22. service *Service,
  23. globalLimitRepository repository.GlobalLimitRepository,
  24. duedate DuedateService,
  25. crawler CrawlerService,
  26. conf *viper.Viper,
  27. required RequiredService,
  28. parser ParserService,
  29. host HostService,
  30. tcpLimit TcpLimitService,
  31. udpLimit UdpLimitService,
  32. webLimit WebLimitService,
  33. gateWayGroup GatewayGroupService,
  34. hostRep repository.HostRepository,
  35. gateWayGroupRep repository.GatewayGroupRepository,
  36. ) GlobalLimitService {
  37. return &globalLimitService{
  38. Service: service,
  39. globalLimitRepository: globalLimitRepository,
  40. duedate: duedate,
  41. crawler: crawler,
  42. Url: conf.GetString("crawler.Url"),
  43. required: required,
  44. parser: parser,
  45. host: host,
  46. tcpLimit: tcpLimit,
  47. udpLimit: udpLimit,
  48. webLimit: webLimit,
  49. gateWayGroup: gateWayGroup,
  50. hostRep: hostRep,
  51. gateWayGroupRep: gateWayGroupRep,
  52. }
  53. }
  54. type globalLimitService struct {
  55. *Service
  56. globalLimitRepository repository.GlobalLimitRepository
  57. duedate DuedateService
  58. crawler CrawlerService
  59. Url string
  60. required RequiredService
  61. parser ParserService
  62. host HostService
  63. tcpLimit TcpLimitService
  64. udpLimit UdpLimitService
  65. webLimit WebLimitService
  66. gateWayGroup GatewayGroupService
  67. hostRep repository.HostRepository
  68. gateWayGroupRep repository.GatewayGroupRepository
  69. }
  70. func (s *globalLimitService) GlobalLimitRequire(ctx context.Context, req v1.GlobalLimitRequest) (res v1.GlobalLimitRequireResponse, err error) {
  71. res.ExpiredAt, err = s.duedate.NextDueDate(ctx, req.Uid, req.HostId)
  72. if err != nil {
  73. return v1.GlobalLimitRequireResponse{}, err
  74. }
  75. configCount, err := s.host.GetGlobalLimitConfig(ctx, req.HostId)
  76. if err != nil {
  77. return v1.GlobalLimitRequireResponse{}, fmt.Errorf("获取配置限制失败: %w", err)
  78. }
  79. bpsInt, err := strconv.Atoi(configCount.Bps)
  80. if err != nil {
  81. return v1.GlobalLimitRequireResponse{}, err
  82. }
  83. resultFloat := float64(bpsInt) / 2.0 / 8.0
  84. res.Bps = strconv.FormatFloat( resultFloat, 'f', -1, 64) + "M"
  85. res.MaxBytesMonth = configCount.MaxBytesMonth
  86. res.Operator = configCount.Operator
  87. res.IpCount = configCount.IpCount
  88. domain, err := s.hostRep.GetDomainById(ctx, req.HostId)
  89. if err != nil {
  90. return v1.GlobalLimitRequireResponse{}, err
  91. }
  92. res.GlobalLimitName = strconv.Itoa(req.Uid) + "_" + strconv.Itoa(req.HostId) + "_" + domain
  93. return res, nil
  94. }
  95. func (s *globalLimitService) GetGlobalLimit(ctx context.Context, id int64) (*model.GlobalLimit, error) {
  96. return s.globalLimitRepository.GetGlobalLimit(ctx, id)
  97. }
  98. func (s *globalLimitService) AddGlobalLimit(ctx context.Context, req v1.GlobalLimitRequest) error {
  99. isExist, err := s.globalLimitRepository.IsGlobalLimitExistByHostId(ctx, int64(req.HostId))
  100. if err != nil {
  101. return err
  102. }
  103. if isExist {
  104. return fmt.Errorf("配置限制已存在")
  105. }
  106. require, err := s.GlobalLimitRequire(ctx, req)
  107. if err != nil {
  108. return err
  109. }
  110. gatewayGroupId, err := s.gateWayGroupRep.GetGatewayGroupWhereHostIdNull(ctx, require.Operator, require.IpCount)
  111. if err != nil {
  112. return err
  113. }
  114. formData := map[string]interface{}{
  115. "tag": require.GlobalLimitName,
  116. "bps": require.Bps,
  117. "max_bytes_month": require.MaxBytesMonth,
  118. "expired_at": require.ExpiredAt,
  119. }
  120. respBody, err := s.required.SendForm(ctx, "admin/info/waf_common_limit/new", "admin/new/waf_common_limit", formData)
  121. if err != nil {
  122. return err
  123. }
  124. ruleIdBase, err := s.parser.GetRuleIdByColumnName(ctx, respBody, require.GlobalLimitName)
  125. if err != nil {
  126. return err
  127. }
  128. if ruleIdBase == "" {
  129. res, err := s.parser.ParseAlert(string(respBody))
  130. if err != nil {
  131. return err
  132. }
  133. return fmt.Errorf(res)
  134. }
  135. ruleId, err := cast.ToIntE(ruleIdBase)
  136. if err != nil {
  137. return err
  138. }
  139. var tcpLimitRuleId, udpLimitRuleId, webLimitRuleId int
  140. g, gCtx := errgroup.WithContext(ctx)
  141. // 启动tcpLimit调用 - 使用独立的请求参数副本
  142. g.Go(func() error {
  143. tcpLimitReq := &v1.GeneralLimitRequireRequest{
  144. Tag: require.GlobalLimitName,
  145. HostId: req.HostId,
  146. RuleId: ruleId,
  147. Uid: req.Uid,
  148. }
  149. result, e := s.tcpLimit.AddTcpLimit(gCtx, tcpLimitReq)
  150. if e != nil {
  151. return fmt.Errorf("tcpLimit调用失败: %w", e)
  152. }
  153. if result != 0 {
  154. tcpLimitRuleId = result
  155. return nil
  156. }
  157. return fmt.Errorf("tcpLimit调用失败,Id为 %d", result)
  158. })
  159. // 启动udpLimit调用 - 使用独立的请求参数副本
  160. g.Go(func() error {
  161. udpLimitReq := &v1.GeneralLimitRequireRequest{
  162. Tag: require.GlobalLimitName,
  163. HostId: req.HostId,
  164. RuleId: ruleId,
  165. Uid: req.Uid,
  166. }
  167. result, e := s.udpLimit.AddUdpLimit(gCtx, udpLimitReq)
  168. if e != nil {
  169. return fmt.Errorf("udpLimit调用失败: %w", e)
  170. }
  171. if result != 0 {
  172. udpLimitRuleId = result
  173. return nil
  174. }
  175. return fmt.Errorf("udpLimit调用失败,Id为 %d", result)
  176. })
  177. // 启动webLimit调用 - 使用独立的请求参数副本
  178. g.Go(func() error {
  179. webLimitReq := &v1.GeneralLimitRequireRequest{
  180. Tag: require.GlobalLimitName,
  181. HostId: req.HostId,
  182. RuleId: ruleId,
  183. Uid: req.Uid,
  184. }
  185. result, e := s.webLimit.AddWebLimit(gCtx, webLimitReq)
  186. if e != nil {
  187. return fmt.Errorf("webLimit调用失败: %w", e)
  188. }
  189. if result != 0 {
  190. webLimitRuleId = result
  191. return nil
  192. }
  193. return fmt.Errorf("webLimit调用失败,Id为 %d", result)
  194. })
  195. if err := g.Wait(); err != nil {
  196. return err
  197. }
  198. t, err := time.Parse("2006-01-02 15:04:05", require.ExpiredAt)
  199. if err != nil {
  200. return err
  201. }
  202. expiredAt := t.Unix()
  203. err = s.globalLimitRepository.AddGlobalLimit(ctx, &model.GlobalLimit{
  204. HostId: req.HostId,
  205. RuleId: cast.ToInt(ruleId),
  206. Uid: req.Uid,
  207. GlobalLimitName: require.GlobalLimitName,
  208. Comment: req.Comment,
  209. TcpLimitRuleId: tcpLimitRuleId,
  210. UdpLimitRuleId: udpLimitRuleId,
  211. WebLimitRuleId: webLimitRuleId,
  212. GatewayGroupId: gatewayGroupId,
  213. ExpiredAt: expiredAt,
  214. })
  215. if err != nil {
  216. return err
  217. }
  218. err = s.gateWayGroupRep.EditGatewayGroup(ctx, &model.GatewayGroup{
  219. RuleId: gatewayGroupId,
  220. HostId: req.HostId,
  221. })
  222. return nil
  223. }
  224. func (s *globalLimitService) EditGlobalLimit(ctx context.Context, req v1.GlobalLimitRequest) error {
  225. require, err := s.GlobalLimitRequire(ctx, req)
  226. if err != nil {
  227. return err
  228. }
  229. formData := map[string]interface{}{
  230. "tag": require.GlobalLimitName,
  231. "bps": require.Bps,
  232. "max_bytes_month": require.MaxBytesMonth,
  233. "expired_at": require.ExpiredAt,
  234. }
  235. data, err := s.globalLimitRepository.GetGlobalLimitByHostId(ctx, int64(req.HostId))
  236. if err != nil {
  237. return err
  238. }
  239. respBody, err := s.required.SendForm(ctx, "admin/info/waf_common_limit/edit?&__goadmin_edit_pk="+strconv.Itoa(data.RuleId), "admin/edit/waf_common_limit", formData)
  240. if err != nil {
  241. return err
  242. }
  243. res, err := s.parser.ParseAlert(string(respBody))
  244. if err != nil {
  245. return err
  246. }
  247. if res != "" {
  248. return fmt.Errorf(res)
  249. }
  250. t, err := time.Parse("2006-01-02 15:04:05", require.ExpiredAt)
  251. if err != nil {
  252. return err
  253. }
  254. expiredAt := t.Unix()
  255. if err := s.globalLimitRepository.UpdateGlobalLimitByHostId(ctx, &model.GlobalLimit{
  256. HostId: req.HostId,
  257. Comment: req.Comment,
  258. ExpiredAt: expiredAt,
  259. }); err != nil {
  260. return err
  261. }
  262. return nil
  263. }
  264. func (s *globalLimitService) EditGlobalLimitBySnail(ctx context.Context, req v1.GlobalLimitEditRequest) error {
  265. configCount, err := s.host.GetGlobalLimitConfig(ctx, req.HostId)
  266. if err != nil {
  267. return fmt.Errorf("获取配置限制失败: %w", err)
  268. }
  269. data, err := s.globalLimitRepository.GetGlobalLimitByHostId(ctx, int64(req.HostId))
  270. if err != nil {
  271. return err
  272. }
  273. t := time.Unix(req.ExpiredAt, 0)
  274. expiredAt := t.Format("2006-01-02 15:04:05")
  275. formData := map[string]interface{}{
  276. "tag": data.GlobalLimitName,
  277. "bps": configCount.Bps,
  278. "max_bytes_month": configCount.MaxBytesMonth,
  279. "expired_at": expiredAt,
  280. }
  281. respBody, err := s.required.SendForm(ctx, "admin/info/waf_common_limit/edit?&__goadmin_edit_pk="+strconv.Itoa(req.RuleId), "admin/edit/waf_common_limit", formData)
  282. if err != nil {
  283. return err
  284. }
  285. if respBody == nil {
  286. return nil
  287. }
  288. return nil
  289. }
  290. func (s *globalLimitService) DeleteGlobalLimit(ctx context.Context, req v1.GlobalLimitRequest) error {
  291. if err := s.globalLimitRepository.DeleteGlobalLimitByHostId(ctx, int64(req.HostId)); err != nil {
  292. return err
  293. }
  294. return nil
  295. }