hook.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. package repo
  2. import (
  3. "net/http"
  4. "slices"
  5. "github.com/cockroachdb/errors"
  6. jsoniter "github.com/json-iterator/go"
  7. api "github.com/gogs/go-gogs-client"
  8. "gogs.io/gogs/internal/context"
  9. "gogs.io/gogs/internal/database"
  10. "gogs.io/gogs/internal/route/api/v1/convert"
  11. )
  12. // https://github.com/gogs/go-gogs-client/wiki/Repositories#list-hooks
  13. func ListHooks(c *context.APIContext) {
  14. hooks, err := database.GetWebhooksByRepoID(c.Repo.Repository.ID)
  15. if err != nil {
  16. c.Errorf(err, "get webhooks by repository ID")
  17. return
  18. }
  19. apiHooks := make([]*api.Hook, len(hooks))
  20. for i := range hooks {
  21. apiHooks[i] = convert.ToHook(c.Repo.RepoLink, hooks[i])
  22. }
  23. c.JSONSuccess(&apiHooks)
  24. }
  25. // https://github.com/gogs/go-gogs-client/wiki/Repositories#create-a-hook
  26. func CreateHook(c *context.APIContext, form api.CreateHookOption) {
  27. if !database.IsValidHookTaskType(form.Type) {
  28. c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Invalid hook type."))
  29. return
  30. }
  31. for _, name := range []string{"url", "content_type"} {
  32. if _, ok := form.Config[name]; !ok {
  33. c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Missing config option: "+name))
  34. return
  35. }
  36. }
  37. if !database.IsValidHookContentType(form.Config["content_type"]) {
  38. c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Invalid content type."))
  39. return
  40. }
  41. if len(form.Events) == 0 {
  42. form.Events = []string{"push"}
  43. }
  44. w := &database.Webhook{
  45. RepoID: c.Repo.Repository.ID,
  46. URL: form.Config["url"],
  47. ContentType: database.ToHookContentType(form.Config["content_type"]),
  48. Secret: form.Config["secret"],
  49. HookEvent: &database.HookEvent{
  50. ChooseEvents: true,
  51. HookEvents: database.HookEvents{
  52. Create: slices.Contains(form.Events, string(database.HookEventTypeCreate)),
  53. Delete: slices.Contains(form.Events, string(database.HookEventTypeDelete)),
  54. Fork: slices.Contains(form.Events, string(database.HookEventTypeFork)),
  55. Push: slices.Contains(form.Events, string(database.HookEventTypePush)),
  56. Issues: slices.Contains(form.Events, string(database.HookEventTypeIssues)),
  57. IssueComment: slices.Contains(form.Events, string(database.HookEventTypeIssueComment)),
  58. PullRequest: slices.Contains(form.Events, string(database.HookEventTypePullRequest)),
  59. Release: slices.Contains(form.Events, string(database.HookEventTypeRelease)),
  60. },
  61. },
  62. IsActive: form.Active,
  63. HookTaskType: database.ToHookTaskType(form.Type),
  64. }
  65. if w.HookTaskType == database.SLACK {
  66. channel, ok := form.Config["channel"]
  67. if !ok {
  68. c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Missing config option: channel"))
  69. return
  70. }
  71. meta, err := jsoniter.Marshal(&database.SlackMeta{
  72. Channel: channel,
  73. Username: form.Config["username"],
  74. IconURL: form.Config["icon_url"],
  75. Color: form.Config["color"],
  76. })
  77. if err != nil {
  78. c.Errorf(err, "marshal JSON")
  79. return
  80. }
  81. w.Meta = string(meta)
  82. }
  83. if err := w.UpdateEvent(); err != nil {
  84. c.Errorf(err, "update event")
  85. return
  86. } else if err := database.CreateWebhook(w); err != nil {
  87. c.Errorf(err, "create webhook")
  88. return
  89. }
  90. c.JSON(http.StatusCreated, convert.ToHook(c.Repo.RepoLink, w))
  91. }
  92. // https://github.com/gogs/go-gogs-client/wiki/Repositories#edit-a-hook
  93. func EditHook(c *context.APIContext, form api.EditHookOption) {
  94. w, err := database.GetWebhookOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
  95. if err != nil {
  96. c.NotFoundOrError(err, "get webhook of repository by ID")
  97. return
  98. }
  99. if form.Config != nil {
  100. if url, ok := form.Config["url"]; ok {
  101. w.URL = url
  102. }
  103. if ct, ok := form.Config["content_type"]; ok {
  104. if !database.IsValidHookContentType(ct) {
  105. c.ErrorStatus(http.StatusUnprocessableEntity, errors.New("Invalid content type."))
  106. return
  107. }
  108. w.ContentType = database.ToHookContentType(ct)
  109. }
  110. if w.HookTaskType == database.SLACK {
  111. if channel, ok := form.Config["channel"]; ok {
  112. meta, err := jsoniter.Marshal(&database.SlackMeta{
  113. Channel: channel,
  114. Username: form.Config["username"],
  115. IconURL: form.Config["icon_url"],
  116. Color: form.Config["color"],
  117. })
  118. if err != nil {
  119. c.Errorf(err, "marshal JSON")
  120. return
  121. }
  122. w.Meta = string(meta)
  123. }
  124. }
  125. }
  126. // Update events
  127. if len(form.Events) == 0 {
  128. form.Events = []string{"push"}
  129. }
  130. w.PushOnly = false
  131. w.SendEverything = false
  132. w.ChooseEvents = true
  133. w.Create = slices.Contains(form.Events, string(database.HookEventTypeCreate))
  134. w.Delete = slices.Contains(form.Events, string(database.HookEventTypeDelete))
  135. w.Fork = slices.Contains(form.Events, string(database.HookEventTypeFork))
  136. w.Push = slices.Contains(form.Events, string(database.HookEventTypePush))
  137. w.Issues = slices.Contains(form.Events, string(database.HookEventTypeIssues))
  138. w.IssueComment = slices.Contains(form.Events, string(database.HookEventTypeIssueComment))
  139. w.PullRequest = slices.Contains(form.Events, string(database.HookEventTypePullRequest))
  140. w.Release = slices.Contains(form.Events, string(database.HookEventTypeRelease))
  141. if err = w.UpdateEvent(); err != nil {
  142. c.Errorf(err, "update event")
  143. return
  144. }
  145. if form.Active != nil {
  146. w.IsActive = *form.Active
  147. }
  148. if err := database.UpdateWebhook(w); err != nil {
  149. c.Errorf(err, "update webhook")
  150. return
  151. }
  152. c.JSONSuccess(convert.ToHook(c.Repo.RepoLink, w))
  153. }
  154. func DeleteHook(c *context.APIContext) {
  155. if err := database.DeleteWebhookOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id")); err != nil {
  156. c.Errorf(err, "delete webhook of repository by ID")
  157. return
  158. }
  159. c.NoContent()
  160. }