本站源代码
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

280 líneas
8.5KB

  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package webhook
  5. import (
  6. "code.gitea.io/gitea/models"
  7. "code.gitea.io/gitea/modules/log"
  8. "code.gitea.io/gitea/modules/notification/base"
  9. api "code.gitea.io/gitea/modules/structs"
  10. )
  11. type webhookNotifier struct {
  12. base.NullNotifier
  13. }
  14. var (
  15. _ base.Notifier = &webhookNotifier{}
  16. )
  17. // NewNotifier create a new webhookNotifier notifier
  18. func NewNotifier() base.Notifier {
  19. return &webhookNotifier{}
  20. }
  21. func (m *webhookNotifier) NotifyIssueClearLabels(doer *models.User, issue *models.Issue) {
  22. if err := issue.LoadPoster(); err != nil {
  23. log.Error("loadPoster: %v", err)
  24. return
  25. }
  26. if err := issue.LoadRepo(); err != nil {
  27. log.Error("LoadRepo: %v", err)
  28. return
  29. }
  30. mode, _ := models.AccessLevel(issue.Poster, issue.Repo)
  31. var err error
  32. if issue.IsPull {
  33. if err = issue.LoadPullRequest(); err != nil {
  34. log.Error("LoadPullRequest: %v", err)
  35. return
  36. }
  37. err = models.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{
  38. Action: api.HookIssueLabelCleared,
  39. Index: issue.Index,
  40. PullRequest: issue.PullRequest.APIFormat(),
  41. Repository: issue.Repo.APIFormat(mode),
  42. Sender: doer.APIFormat(),
  43. })
  44. } else {
  45. err = models.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{
  46. Action: api.HookIssueLabelCleared,
  47. Index: issue.Index,
  48. Issue: issue.APIFormat(),
  49. Repository: issue.Repo.APIFormat(mode),
  50. Sender: doer.APIFormat(),
  51. })
  52. }
  53. if err != nil {
  54. log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
  55. } else {
  56. go models.HookQueue.Add(issue.RepoID)
  57. }
  58. }
  59. func (m *webhookNotifier) NotifyForkRepository(doer *models.User, oldRepo, repo *models.Repository) {
  60. oldMode, _ := models.AccessLevel(doer, oldRepo)
  61. mode, _ := models.AccessLevel(doer, repo)
  62. // forked webhook
  63. if err := models.PrepareWebhooks(oldRepo, models.HookEventFork, &api.ForkPayload{
  64. Forkee: oldRepo.APIFormat(oldMode),
  65. Repo: repo.APIFormat(mode),
  66. Sender: doer.APIFormat(),
  67. }); err != nil {
  68. log.Error("PrepareWebhooks [repo_id: %d]: %v", oldRepo.ID, err)
  69. } else {
  70. go models.HookQueue.Add(oldRepo.ID)
  71. }
  72. u := repo.MustOwner()
  73. // Add to hook queue for created repo after session commit.
  74. if u.IsOrganization() {
  75. if err := models.PrepareWebhooks(repo, models.HookEventRepository, &api.RepositoryPayload{
  76. Action: api.HookRepoCreated,
  77. Repository: repo.APIFormat(models.AccessModeOwner),
  78. Organization: u.APIFormat(),
  79. Sender: doer.APIFormat(),
  80. }); err != nil {
  81. log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
  82. } else {
  83. go models.HookQueue.Add(repo.ID)
  84. }
  85. }
  86. }
  87. func (m *webhookNotifier) NotifyCreateRepository(doer *models.User, u *models.User, repo *models.Repository) {
  88. // Add to hook queue for created repo after session commit.
  89. if u.IsOrganization() {
  90. if err := models.PrepareWebhooks(repo, models.HookEventRepository, &api.RepositoryPayload{
  91. Action: api.HookRepoCreated,
  92. Repository: repo.APIFormat(models.AccessModeOwner),
  93. Organization: u.APIFormat(),
  94. Sender: doer.APIFormat(),
  95. }); err != nil {
  96. log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
  97. } else {
  98. go models.HookQueue.Add(repo.ID)
  99. }
  100. }
  101. }
  102. func (m *webhookNotifier) NotifyDeleteRepository(doer *models.User, repo *models.Repository) {
  103. u := repo.MustOwner()
  104. if u.IsOrganization() {
  105. if err := models.PrepareWebhooks(repo, models.HookEventRepository, &api.RepositoryPayload{
  106. Action: api.HookRepoDeleted,
  107. Repository: repo.APIFormat(models.AccessModeOwner),
  108. Organization: u.APIFormat(),
  109. Sender: doer.APIFormat(),
  110. }); err != nil {
  111. log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
  112. }
  113. go models.HookQueue.Add(repo.ID)
  114. }
  115. }
  116. func (m *webhookNotifier) NotifyIssueChangeAssignee(doer *models.User, issue *models.Issue, assignee *models.User, removed bool, comment *models.Comment) {
  117. if issue.IsPull {
  118. mode, _ := models.AccessLevelUnit(doer, issue.Repo, models.UnitTypePullRequests)
  119. if err := issue.LoadPullRequest(); err != nil {
  120. log.Error("LoadPullRequest failed: %v", err)
  121. return
  122. }
  123. issue.PullRequest.Issue = issue
  124. apiPullRequest := &api.PullRequestPayload{
  125. Index: issue.Index,
  126. PullRequest: issue.PullRequest.APIFormat(),
  127. Repository: issue.Repo.APIFormat(mode),
  128. Sender: doer.APIFormat(),
  129. }
  130. if removed {
  131. apiPullRequest.Action = api.HookIssueUnassigned
  132. } else {
  133. apiPullRequest.Action = api.HookIssueAssigned
  134. }
  135. // Assignee comment triggers a webhook
  136. if err := models.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, apiPullRequest); err != nil {
  137. log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err)
  138. return
  139. }
  140. } else {
  141. mode, _ := models.AccessLevelUnit(doer, issue.Repo, models.UnitTypeIssues)
  142. apiIssue := &api.IssuePayload{
  143. Index: issue.Index,
  144. Issue: issue.APIFormat(),
  145. Repository: issue.Repo.APIFormat(mode),
  146. Sender: doer.APIFormat(),
  147. }
  148. if removed {
  149. apiIssue.Action = api.HookIssueUnassigned
  150. } else {
  151. apiIssue.Action = api.HookIssueAssigned
  152. }
  153. // Assignee comment triggers a webhook
  154. if err := models.PrepareWebhooks(issue.Repo, models.HookEventIssues, apiIssue); err != nil {
  155. log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err)
  156. return
  157. }
  158. }
  159. go models.HookQueue.Add(issue.RepoID)
  160. }
  161. func (m *webhookNotifier) NotifyIssueChangeTitle(doer *models.User, issue *models.Issue, oldTitle string) {
  162. mode, _ := models.AccessLevel(issue.Poster, issue.Repo)
  163. var err error
  164. if issue.IsPull {
  165. if err = issue.LoadPullRequest(); err != nil {
  166. log.Error("LoadPullRequest failed: %v", err)
  167. return
  168. }
  169. issue.PullRequest.Issue = issue
  170. err = models.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{
  171. Action: api.HookIssueEdited,
  172. Index: issue.Index,
  173. Changes: &api.ChangesPayload{
  174. Title: &api.ChangesFromPayload{
  175. From: oldTitle,
  176. },
  177. },
  178. PullRequest: issue.PullRequest.APIFormat(),
  179. Repository: issue.Repo.APIFormat(mode),
  180. Sender: doer.APIFormat(),
  181. })
  182. } else {
  183. err = models.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{
  184. Action: api.HookIssueEdited,
  185. Index: issue.Index,
  186. Changes: &api.ChangesPayload{
  187. Title: &api.ChangesFromPayload{
  188. From: oldTitle,
  189. },
  190. },
  191. Issue: issue.APIFormat(),
  192. Repository: issue.Repo.APIFormat(mode),
  193. Sender: issue.Poster.APIFormat(),
  194. })
  195. }
  196. if err != nil {
  197. log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
  198. } else {
  199. go models.HookQueue.Add(issue.RepoID)
  200. }
  201. }
  202. func (m *webhookNotifier) NotifyIssueChangeStatus(doer *models.User, issue *models.Issue, isClosed bool) {
  203. mode, _ := models.AccessLevel(issue.Poster, issue.Repo)
  204. var err error
  205. if issue.IsPull {
  206. if err = issue.LoadPullRequest(); err != nil {
  207. log.Error("LoadPullRequest: %v", err)
  208. return
  209. }
  210. // Merge pull request calls issue.changeStatus so we need to handle separately.
  211. apiPullRequest := &api.PullRequestPayload{
  212. Index: issue.Index,
  213. PullRequest: issue.PullRequest.APIFormat(),
  214. Repository: issue.Repo.APIFormat(mode),
  215. Sender: doer.APIFormat(),
  216. }
  217. if isClosed {
  218. apiPullRequest.Action = api.HookIssueClosed
  219. } else {
  220. apiPullRequest.Action = api.HookIssueReOpened
  221. }
  222. err = models.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, apiPullRequest)
  223. } else {
  224. apiIssue := &api.IssuePayload{
  225. Index: issue.Index,
  226. Issue: issue.APIFormat(),
  227. Repository: issue.Repo.APIFormat(mode),
  228. Sender: doer.APIFormat(),
  229. }
  230. if isClosed {
  231. apiIssue.Action = api.HookIssueClosed
  232. } else {
  233. apiIssue.Action = api.HookIssueReOpened
  234. }
  235. err = models.PrepareWebhooks(issue.Repo, models.HookEventIssues, apiIssue)
  236. }
  237. if err != nil {
  238. log.Error("PrepareWebhooks [is_pull: %v, is_closed: %v]: %v", issue.IsPull, isClosed, err)
  239. } else {
  240. go models.HookQueue.Add(issue.Repo.ID)
  241. }
  242. }
  243. func (m *webhookNotifier) NotifyNewIssue(issue *models.Issue) {
  244. mode, _ := models.AccessLevel(issue.Poster, issue.Repo)
  245. if err := models.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{
  246. Action: api.HookIssueOpened,
  247. Index: issue.Index,
  248. Issue: issue.APIFormat(),
  249. Repository: issue.Repo.APIFormat(mode),
  250. Sender: issue.Poster.APIFormat(),
  251. }); err != nil {
  252. log.Error("PrepareWebhooks: %v", err)
  253. } else {
  254. go models.HookQueue.Add(issue.RepoID)
  255. }
  256. }
上海开阖软件有限公司 沪ICP备12045867号-1