globallimit.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  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/viper"
  9. "golang.org/x/sync/errgroup"
  10. "strconv"
  11. "time"
  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. EditGlobalLimitBySnail(ctx context.Context, req v1.GlobalLimitEditRequest) error
  19. }
  20. func NewGlobalLimitService(
  21. service *Service,
  22. globalLimitRepository repository.GlobalLimitRepository,
  23. duedate DuedateService,
  24. crawler CrawlerService,
  25. conf *viper.Viper,
  26. required RequiredService,
  27. parser ParserService,
  28. host HostService,
  29. tcpLimit TcpLimitService,
  30. udpLimit UdpLimitService,
  31. webLimit WebLimitService,
  32. gateWayGroup GatewayGroupService,
  33. hostRep repository.HostRepository,
  34. gateWayGroupRep repository.GatewayGroupRepository,
  35. cdnService CdnService,
  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. cdnService: cdnService,
  53. }
  54. }
  55. type globalLimitService struct {
  56. *Service
  57. globalLimitRepository repository.GlobalLimitRepository
  58. duedate DuedateService
  59. crawler CrawlerService
  60. Url string
  61. required RequiredService
  62. parser ParserService
  63. host HostService
  64. tcpLimit TcpLimitService
  65. udpLimit UdpLimitService
  66. webLimit WebLimitService
  67. gateWayGroup GatewayGroupService
  68. hostRep repository.HostRepository
  69. gateWayGroupRep repository.GatewayGroupRepository
  70. cdnService CdnService
  71. }
  72. func (s *globalLimitService) GetCdnUserId(ctx context.Context, uid int64) (int64, error) {
  73. data, err := s.globalLimitRepository.GetGlobalLimitFirst(ctx, uid)
  74. if err != nil {
  75. return 0, err
  76. }
  77. if data != nil && data.CdnUid != 0 {
  78. return int64(data.CdnUid), nil
  79. }
  80. userInfo,err := s.globalLimitRepository.GetUserInfo(ctx, uid)
  81. if err != nil {
  82. return 0, err
  83. }
  84. userId, err := s.cdnService.AddUser(ctx, v1.User{
  85. Username: userInfo.Username,
  86. Email: userInfo.Email,
  87. Fullname: userInfo.Username,
  88. Mobile: userInfo.PhoneNumber,
  89. })
  90. if err != nil {
  91. return 0, err
  92. }
  93. return userId, nil
  94. }
  95. func (s *globalLimitService) AddGroupId(ctx context.Context,groupName string) (int64, error) {
  96. groupId, err := s.cdnService.CreateGroup(ctx, v1.Group{
  97. Name: groupName,
  98. })
  99. if err != nil {
  100. return 0, err
  101. }
  102. return groupId, nil
  103. }
  104. func (s *globalLimitService) GlobalLimitRequire(ctx context.Context, req v1.GlobalLimitRequest) (res v1.GlobalLimitRequireResponse, err error) {
  105. res.ExpiredAt, err = s.duedate.NextDueDate(ctx, req.Uid, req.HostId)
  106. if err != nil {
  107. return v1.GlobalLimitRequireResponse{}, err
  108. }
  109. configCount, err := s.host.GetGlobalLimitConfig(ctx, req.HostId)
  110. if err != nil {
  111. return v1.GlobalLimitRequireResponse{}, fmt.Errorf("获取配置限制失败: %w", err)
  112. }
  113. bpsInt, err := strconv.Atoi(configCount.Bps)
  114. if err != nil {
  115. return v1.GlobalLimitRequireResponse{}, err
  116. }
  117. resultFloat := float64(bpsInt) / 2.0 / 8.0
  118. res.Bps = strconv.FormatFloat( resultFloat, 'f', -1, 64) + "M"
  119. res.MaxBytesMonth = configCount.MaxBytesMonth
  120. res.Operator = configCount.Operator
  121. res.IpCount = configCount.IpCount
  122. domain, err := s.hostRep.GetDomainById(ctx, req.HostId)
  123. if err != nil {
  124. return v1.GlobalLimitRequireResponse{}, err
  125. }
  126. res.GlobalLimitName = strconv.Itoa(req.Uid) + "_" + strconv.Itoa(req.HostId) + "_" + domain
  127. return res, nil
  128. }
  129. func (s *globalLimitService) GetGlobalLimit(ctx context.Context, id int64) (*model.GlobalLimit, error) {
  130. return s.globalLimitRepository.GetGlobalLimit(ctx, id)
  131. }
  132. func (s *globalLimitService) AddGlobalLimit(ctx context.Context, req v1.GlobalLimitRequest) error {
  133. isExist, err := s.globalLimitRepository.IsGlobalLimitExistByHostId(ctx, int64(req.HostId))
  134. if err != nil {
  135. return err
  136. }
  137. if isExist {
  138. return fmt.Errorf("配置限制已存在")
  139. }
  140. require, err := s.GlobalLimitRequire(ctx, req)
  141. if err != nil {
  142. return err
  143. }
  144. g, gCtx := errgroup.WithContext(ctx)
  145. var gatewayGroupId int
  146. var userId int64
  147. var groupId int64
  148. g.Go(func() error {
  149. gatewayGroupId, e := s.gateWayGroupRep.GetGatewayGroupWhereHostIdNull(gCtx, require.Operator, require.IpCount)
  150. if e != nil {
  151. return e
  152. }
  153. if gatewayGroupId == 0 {
  154. return fmt.Errorf("获取网关组失败")
  155. }
  156. return nil
  157. })
  158. g.Go(func() error {
  159. res, e := s.GetCdnUserId(gCtx, int64(req.Uid))
  160. if e != nil {
  161. return e
  162. }
  163. if res == 0 {
  164. return fmt.Errorf("获取cdn用户失败")
  165. }
  166. userId = res
  167. return nil
  168. })
  169. g.Go(func() error {
  170. res, e := s.AddGroupId(gCtx, require.GlobalLimitName)
  171. if e != nil {
  172. return e
  173. }
  174. if res == 0 {
  175. return fmt.Errorf("创建规则分组失败")
  176. }
  177. return nil
  178. })
  179. if err = g.Wait(); err != nil {
  180. return err
  181. }
  182. ruleId, err := s.cdnService.BindPlan(ctx, v1.Plan{
  183. })
  184. err = s.globalLimitRepository.AddGlobalLimit(ctx, &model.GlobalLimit{
  185. HostId: req.HostId,
  186. Uid: req.Uid,
  187. RuleId: ,
  188. CdnUid: int(userId),
  189. Comment: req.Comment,
  190. ExpiredAt: require.ExpiredAt,
  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. require, err := s.GlobalLimitRequire(ctx, req)
  199. if err != nil {
  200. return err
  201. }
  202. formData := map[string]interface{}{
  203. "tag": require.GlobalLimitName,
  204. "bps": require.Bps,
  205. "max_bytes_month": require.MaxBytesMonth,
  206. "expired_at": require.ExpiredAt,
  207. }
  208. data, err := s.globalLimitRepository.GetGlobalLimitByHostId(ctx, int64(req.HostId))
  209. if err != nil {
  210. return err
  211. }
  212. 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)
  213. if err != nil {
  214. return err
  215. }
  216. res, err := s.parser.ParseAlert(string(respBody))
  217. if err != nil {
  218. return err
  219. }
  220. if res != "" {
  221. return fmt.Errorf(res)
  222. }
  223. t, err := time.Parse("2006-01-02 15:04:05", require.ExpiredAt)
  224. if err != nil {
  225. return err
  226. }
  227. expiredAt := t.Unix()
  228. if err := s.globalLimitRepository.UpdateGlobalLimitByHostId(ctx, &model.GlobalLimit{
  229. HostId: req.HostId,
  230. Comment: req.Comment,
  231. ExpiredAt: expiredAt,
  232. }); err != nil {
  233. return err
  234. }
  235. return nil
  236. }
  237. func (s *globalLimitService) EditGlobalLimitBySnail(ctx context.Context, req v1.GlobalLimitEditRequest) error {
  238. configCount, err := s.host.GetGlobalLimitConfig(ctx, req.HostId)
  239. if err != nil {
  240. return fmt.Errorf("获取配置限制失败: %w", err)
  241. }
  242. data, err := s.globalLimitRepository.GetGlobalLimitByHostId(ctx, int64(req.HostId))
  243. if err != nil {
  244. return err
  245. }
  246. t := time.Unix(req.ExpiredAt, 0)
  247. expiredAt := t.Format("2006-01-02 15:04:05")
  248. formData := map[string]interface{}{
  249. "tag": data.GlobalLimitName,
  250. "bps": configCount.Bps,
  251. "max_bytes_month": configCount.MaxBytesMonth,
  252. "expired_at": expiredAt,
  253. }
  254. 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)
  255. if err != nil {
  256. return err
  257. }
  258. if respBody == nil {
  259. return nil
  260. }
  261. return nil
  262. }
  263. func (s *globalLimitService) DeleteGlobalLimit(ctx context.Context, req v1.GlobalLimitRequest) error {
  264. if err := s.globalLimitRepository.DeleteGlobalLimitByHostId(ctx, int64(req.HostId)); err != nil {
  265. return err
  266. }
  267. return nil
  268. }