globallimit.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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. res, e := s.gateWayGroupRep.GetGatewayGroupWhereHostIdNull(gCtx, require.Operator, require.IpCount)
  150. if e != nil {
  151. return e
  152. }
  153. if res == 0 {
  154. return fmt.Errorf("获取网关组失败")
  155. }
  156. gatewayGroupId = res
  157. return nil
  158. })
  159. g.Go(func() error {
  160. res, e := s.GetCdnUserId(gCtx, int64(req.Uid))
  161. if e != nil {
  162. return e
  163. }
  164. if res == 0 {
  165. return fmt.Errorf("获取cdn用户失败")
  166. }
  167. userId = res
  168. return nil
  169. })
  170. g.Go(func() error {
  171. res, e := s.AddGroupId(gCtx, require.GlobalLimitName)
  172. if e != nil {
  173. return e
  174. }
  175. if res == 0 {
  176. return fmt.Errorf("创建规则分组失败")
  177. }
  178. groupId = res
  179. return nil
  180. })
  181. if err = g.Wait(); err != nil {
  182. return err
  183. }
  184. ruleId, err := s.cdnService.BindPlan(ctx, v1.Plan{
  185. UserId: userId,
  186. })
  187. err = s.globalLimitRepository.AddGlobalLimit(ctx, &model.GlobalLimit{
  188. HostId: req.HostId,
  189. Uid: req.Uid,
  190. RuleId: ,
  191. CdnUid: int(userId),
  192. Comment: req.Comment,
  193. ExpiredAt: require.ExpiredAt,
  194. })
  195. if err != nil {
  196. return err
  197. }
  198. return nil
  199. }
  200. func (s *globalLimitService) EditGlobalLimit(ctx context.Context, req v1.GlobalLimitRequest) error {
  201. require, err := s.GlobalLimitRequire(ctx, req)
  202. if err != nil {
  203. return err
  204. }
  205. formData := map[string]interface{}{
  206. "tag": require.GlobalLimitName,
  207. "bps": require.Bps,
  208. "max_bytes_month": require.MaxBytesMonth,
  209. "expired_at": require.ExpiredAt,
  210. }
  211. data, err := s.globalLimitRepository.GetGlobalLimitByHostId(ctx, int64(req.HostId))
  212. if err != nil {
  213. return err
  214. }
  215. 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)
  216. if err != nil {
  217. return err
  218. }
  219. res, err := s.parser.ParseAlert(string(respBody))
  220. if err != nil {
  221. return err
  222. }
  223. if res != "" {
  224. return fmt.Errorf(res)
  225. }
  226. t, err := time.Parse("2006-01-02 15:04:05", require.ExpiredAt)
  227. if err != nil {
  228. return err
  229. }
  230. expiredAt := t.Unix()
  231. if err := s.globalLimitRepository.UpdateGlobalLimitByHostId(ctx, &model.GlobalLimit{
  232. HostId: req.HostId,
  233. Comment: req.Comment,
  234. ExpiredAt: expiredAt,
  235. }); err != nil {
  236. return err
  237. }
  238. return nil
  239. }
  240. func (s *globalLimitService) EditGlobalLimitBySnail(ctx context.Context, req v1.GlobalLimitEditRequest) error {
  241. configCount, err := s.host.GetGlobalLimitConfig(ctx, req.HostId)
  242. if err != nil {
  243. return fmt.Errorf("获取配置限制失败: %w", err)
  244. }
  245. data, err := s.globalLimitRepository.GetGlobalLimitByHostId(ctx, int64(req.HostId))
  246. if err != nil {
  247. return err
  248. }
  249. t := time.Unix(req.ExpiredAt, 0)
  250. expiredAt := t.Format("2006-01-02 15:04:05")
  251. formData := map[string]interface{}{
  252. "tag": data.GlobalLimitName,
  253. "bps": configCount.Bps,
  254. "max_bytes_month": configCount.MaxBytesMonth,
  255. "expired_at": expiredAt,
  256. }
  257. 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)
  258. if err != nil {
  259. return err
  260. }
  261. if respBody == nil {
  262. return nil
  263. }
  264. return nil
  265. }
  266. func (s *globalLimitService) DeleteGlobalLimit(ctx context.Context, req v1.GlobalLimitRequest) error {
  267. if err := s.globalLimitRepository.DeleteGlobalLimitByHostId(ctx, int64(req.HostId)); err != nil {
  268. return err
  269. }
  270. return nil
  271. }