api_events.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package httpd
  2. import (
  3. "fmt"
  4. "net/http"
  5. "strconv"
  6. "github.com/drakkan/sftpgo/v2/dataprovider"
  7. "github.com/drakkan/sftpgo/v2/sdk/plugin"
  8. "github.com/drakkan/sftpgo/v2/util"
  9. )
  10. type commonEventSearchParams struct {
  11. StartTimestamp int64
  12. EndTimestamp int64
  13. Actions []string
  14. Username string
  15. IP string
  16. InstanceIDs []string
  17. ExcludeIDs []string
  18. Limit int
  19. Order int
  20. }
  21. func (c *commonEventSearchParams) fromRequest(r *http.Request) error {
  22. c.Limit = 100
  23. if _, ok := r.URL.Query()["limit"]; ok {
  24. limit, err := strconv.Atoi(r.URL.Query().Get("limit"))
  25. if err != nil {
  26. return util.NewValidationError(fmt.Sprintf("invalid limit: %v", err))
  27. }
  28. if limit < 1 || limit > 1000 {
  29. return util.NewValidationError(fmt.Sprintf("limit is out of the 1-1000 range: %v", limit))
  30. }
  31. c.Limit = limit
  32. }
  33. if _, ok := r.URL.Query()["order"]; ok {
  34. order := r.URL.Query().Get("order")
  35. if order != dataprovider.OrderASC && order != dataprovider.OrderDESC {
  36. return util.NewValidationError(fmt.Sprintf("invalid order %#v", order))
  37. }
  38. if order == dataprovider.OrderASC {
  39. c.Order = 1
  40. }
  41. }
  42. if _, ok := r.URL.Query()["start_timestamp"]; ok {
  43. ts, err := strconv.ParseInt(r.URL.Query().Get("start_timestamp"), 10, 64)
  44. if err != nil {
  45. return util.NewValidationError(fmt.Sprintf("invalid start_timestamp: %v", err))
  46. }
  47. c.StartTimestamp = ts
  48. }
  49. if _, ok := r.URL.Query()["end_timestamp"]; ok {
  50. ts, err := strconv.ParseInt(r.URL.Query().Get("end_timestamp"), 10, 64)
  51. if err != nil {
  52. return util.NewValidationError(fmt.Sprintf("invalid end_timestamp: %v", err))
  53. }
  54. c.EndTimestamp = ts
  55. }
  56. c.Actions = getCommaSeparatedQueryParam(r, "actions")
  57. c.Username = r.URL.Query().Get("username")
  58. c.IP = r.URL.Query().Get("ip")
  59. c.InstanceIDs = getCommaSeparatedQueryParam(r, "instance_ids")
  60. c.ExcludeIDs = getCommaSeparatedQueryParam(r, "exclude_ids")
  61. return nil
  62. }
  63. type fsEventSearchParams struct {
  64. commonEventSearchParams
  65. SSHCmd string
  66. Protocols []string
  67. Statuses []int32
  68. }
  69. func (s *fsEventSearchParams) fromRequest(r *http.Request) error {
  70. if err := s.commonEventSearchParams.fromRequest(r); err != nil {
  71. return err
  72. }
  73. s.IP = r.URL.Query().Get("ip")
  74. s.SSHCmd = r.URL.Query().Get("ssh_cmd")
  75. s.Protocols = getCommaSeparatedQueryParam(r, "protocols")
  76. statuses := getCommaSeparatedQueryParam(r, "statuses")
  77. for _, status := range statuses {
  78. val, err := strconv.Atoi(status)
  79. if err != nil {
  80. return util.NewValidationError(fmt.Sprintf("invalid status: %v", status))
  81. }
  82. s.Statuses = append(s.Statuses, int32(val))
  83. }
  84. return nil
  85. }
  86. type providerEventSearchParams struct {
  87. commonEventSearchParams
  88. ObjectName string
  89. ObjectTypes []string
  90. }
  91. func (s *providerEventSearchParams) fromRequest(r *http.Request) error {
  92. if err := s.commonEventSearchParams.fromRequest(r); err != nil {
  93. return err
  94. }
  95. s.ObjectName = r.URL.Query().Get("object_name")
  96. s.ObjectTypes = getCommaSeparatedQueryParam(r, "object_types")
  97. return nil
  98. }
  99. func searchFsEvents(w http.ResponseWriter, r *http.Request) {
  100. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  101. params := fsEventSearchParams{}
  102. err := params.fromRequest(r)
  103. if err != nil {
  104. sendAPIResponse(w, r, err, "", getRespStatus(err))
  105. return
  106. }
  107. data, _, _, err := plugin.Handler.SearchFsEvents(params.StartTimestamp, params.EndTimestamp, params.Username,
  108. params.IP, params.SSHCmd, params.Actions, params.Protocols, params.InstanceIDs, params.ExcludeIDs,
  109. params.Statuses, params.Limit, params.Order)
  110. if err != nil {
  111. sendAPIResponse(w, r, err, "", getRespStatus(err))
  112. return
  113. }
  114. w.Header().Set("Content-Type", "application/json; charset=utf-8")
  115. w.Write(data) //nolint:errcheck
  116. }
  117. func searchProviderEvents(w http.ResponseWriter, r *http.Request) {
  118. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  119. params := providerEventSearchParams{}
  120. err := params.fromRequest(r)
  121. if err != nil {
  122. sendAPIResponse(w, r, err, "", getRespStatus(err))
  123. return
  124. }
  125. data, _, _, err := plugin.Handler.SearchProviderEvents(params.StartTimestamp, params.EndTimestamp, params.Username,
  126. params.IP, params.ObjectName, params.Limit, params.Order, params.Actions, params.ObjectTypes, params.InstanceIDs,
  127. params.ExcludeIDs)
  128. if err != nil {
  129. sendAPIResponse(w, r, err, "", getRespStatus(err))
  130. return
  131. }
  132. w.Header().Set("Content-Type", "application/json; charset=utf-8")
  133. w.Write(data) //nolint:errcheck
  134. }