api_events.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Copyright (C) 2019-2022 Nicola Murino
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Affero General Public License as published
  5. // by the Free Software Foundation, version 3.
  6. //
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU Affero General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU Affero General Public License
  13. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. package httpd
  15. import (
  16. "fmt"
  17. "net/http"
  18. "strconv"
  19. "github.com/sftpgo/sdk/plugin/eventsearcher"
  20. "github.com/drakkan/sftpgo/v2/internal/dataprovider"
  21. "github.com/drakkan/sftpgo/v2/internal/plugin"
  22. "github.com/drakkan/sftpgo/v2/internal/util"
  23. )
  24. func getCommonSearchParamsFromRequest(r *http.Request) (eventsearcher.CommonSearchParams, error) {
  25. c := eventsearcher.CommonSearchParams{}
  26. c.Limit = 100
  27. if _, ok := r.URL.Query()["limit"]; ok {
  28. limit, err := strconv.Atoi(r.URL.Query().Get("limit"))
  29. if err != nil {
  30. return c, util.NewValidationError(fmt.Sprintf("invalid limit: %v", err))
  31. }
  32. if limit < 1 || limit > 1000 {
  33. return c, util.NewValidationError(fmt.Sprintf("limit is out of the 1-1000 range: %v", limit))
  34. }
  35. c.Limit = limit
  36. }
  37. if _, ok := r.URL.Query()["order"]; ok {
  38. order := r.URL.Query().Get("order")
  39. if order != dataprovider.OrderASC && order != dataprovider.OrderDESC {
  40. return c, util.NewValidationError(fmt.Sprintf("invalid order %#v", order))
  41. }
  42. if order == dataprovider.OrderASC {
  43. c.Order = 1
  44. }
  45. }
  46. if _, ok := r.URL.Query()["start_timestamp"]; ok {
  47. ts, err := strconv.ParseInt(r.URL.Query().Get("start_timestamp"), 10, 64)
  48. if err != nil {
  49. return c, util.NewValidationError(fmt.Sprintf("invalid start_timestamp: %v", err))
  50. }
  51. c.StartTimestamp = ts
  52. }
  53. if _, ok := r.URL.Query()["end_timestamp"]; ok {
  54. ts, err := strconv.ParseInt(r.URL.Query().Get("end_timestamp"), 10, 64)
  55. if err != nil {
  56. return c, util.NewValidationError(fmt.Sprintf("invalid end_timestamp: %v", err))
  57. }
  58. c.EndTimestamp = ts
  59. }
  60. c.Actions = getCommaSeparatedQueryParam(r, "actions")
  61. c.Username = r.URL.Query().Get("username")
  62. c.IP = r.URL.Query().Get("ip")
  63. c.InstanceIDs = getCommaSeparatedQueryParam(r, "instance_ids")
  64. c.ExcludeIDs = getCommaSeparatedQueryParam(r, "exclude_ids")
  65. return c, nil
  66. }
  67. func getFsSearchParamsFromRequest(r *http.Request) (eventsearcher.FsEventSearch, error) {
  68. var err error
  69. s := eventsearcher.FsEventSearch{}
  70. s.CommonSearchParams, err = getCommonSearchParamsFromRequest(r)
  71. if err != nil {
  72. return s, err
  73. }
  74. s.FsProvider = -1
  75. if _, ok := r.URL.Query()["fs_provider"]; ok {
  76. provider := r.URL.Query().Get("fs_provider")
  77. val, err := strconv.Atoi(provider)
  78. if err != nil {
  79. return s, util.NewValidationError(fmt.Sprintf("invalid fs_provider: %v", provider))
  80. }
  81. s.FsProvider = val
  82. }
  83. s.IP = r.URL.Query().Get("ip")
  84. s.SSHCmd = r.URL.Query().Get("ssh_cmd")
  85. s.Bucket = r.URL.Query().Get("bucket")
  86. s.Endpoint = r.URL.Query().Get("endpoint")
  87. s.Protocols = getCommaSeparatedQueryParam(r, "protocols")
  88. statuses := getCommaSeparatedQueryParam(r, "statuses")
  89. for _, status := range statuses {
  90. val, err := strconv.Atoi(status)
  91. if err != nil {
  92. return s, util.NewValidationError(fmt.Sprintf("invalid status: %v", status))
  93. }
  94. s.Statuses = append(s.Statuses, int32(val))
  95. }
  96. return s, nil
  97. }
  98. func getProviderSearchParamsFromRequest(r *http.Request) (eventsearcher.ProviderEventSearch, error) {
  99. var err error
  100. s := eventsearcher.ProviderEventSearch{}
  101. s.CommonSearchParams, err = getCommonSearchParamsFromRequest(r)
  102. if err != nil {
  103. return s, err
  104. }
  105. s.ObjectName = r.URL.Query().Get("object_name")
  106. s.ObjectTypes = getCommaSeparatedQueryParam(r, "object_types")
  107. return s, nil
  108. }
  109. func searchFsEvents(w http.ResponseWriter, r *http.Request) {
  110. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  111. filters, err := getFsSearchParamsFromRequest(r)
  112. if err != nil {
  113. sendAPIResponse(w, r, err, "", getRespStatus(err))
  114. return
  115. }
  116. data, _, _, err := plugin.Handler.SearchFsEvents(&filters)
  117. if err != nil {
  118. sendAPIResponse(w, r, err, "", getRespStatus(err))
  119. return
  120. }
  121. w.Header().Set("Content-Type", "application/json; charset=utf-8")
  122. w.Write(data) //nolint:errcheck
  123. }
  124. func searchProviderEvents(w http.ResponseWriter, r *http.Request) {
  125. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  126. filters, err := getProviderSearchParamsFromRequest(r)
  127. if err != nil {
  128. sendAPIResponse(w, r, err, "", getRespStatus(err))
  129. return
  130. }
  131. data, _, _, err := plugin.Handler.SearchProviderEvents(&filters)
  132. if err != nil {
  133. sendAPIResponse(w, r, err, "", getRespStatus(err))
  134. return
  135. }
  136. w.Header().Set("Content-Type", "application/json; charset=utf-8")
  137. w.Write(data) //nolint:errcheck
  138. }