You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

webhook.go 26 kB

11 years ago
11 years ago
8 years ago
8 years ago
8 years ago
11 years ago
11 years ago
Better logging (#6038) (#6095) * Panic don't fatal on create new logger Fixes #5854 Signed-off-by: Andrew Thornton <art27@cantab.net> * partial broken * Update the logging infrastrcture Signed-off-by: Andrew Thornton <art27@cantab.net> * Reset the skip levels for Fatal and Error Signed-off-by: Andrew Thornton <art27@cantab.net> * broken ncsa * More log.Error fixes Signed-off-by: Andrew Thornton <art27@cantab.net> * Remove nal * set log-levels to lowercase * Make console_test test all levels * switch to lowercased levels * OK now working * Fix vetting issues * Fix lint * Fix tests * change default logging to match current gitea * Improve log testing Signed-off-by: Andrew Thornton <art27@cantab.net> * reset error skip levels to 0 * Update documentation and access logger configuration * Redirect the router log back to gitea if redirect macaron log but also allow setting the log level - i.e. TRACE * Fix broken level caching * Refactor the router log * Add Router logger * Add colorizing options * Adjust router colors * Only create logger if they will be used * update app.ini.sample * rename Attribute ColorAttribute * Change from white to green for function * Set fatal/error levels * Restore initial trace logger * Fix Trace arguments in modules/auth/auth.go * Properly handle XORMLogger * Improve admin/config page * fix fmt * Add auto-compression of old logs * Update error log levels * Remove the unnecessary skip argument from Error, Fatal and Critical * Add stacktrace support * Fix tests * Remove x/sync from vendors? * Add stderr option to console logger * Use filepath.ToSlash to protect against Windows in tests * Remove prefixed underscores from names in colors.go * Remove not implemented database logger This was removed from Gogs on 4 Mar 2016 but left in the configuration since then. * Ensure that log paths are relative to ROOT_PATH * use path.Join * rename jsonConfig to logConfig * Rename "config" to "jsonConfig" to make it clearer * Requested changes * Requested changes: XormLogger * Try to color the windows terminal If successful default to colorizing the console logs * fixup * Colorize initially too * update vendor * Colorize logs on default and remove if this is not a colorizing logger * Fix documentation * fix test * Use go-isatty to detect if on windows we are on msys or cygwin * Fix spelling mistake * Add missing vendors * More changes * Rationalise the ANSI writer protection * Adjust colors on advice from @0x5c * Make Flags a comma separated list * Move to use the windows constant for ENABLE_VIRTUAL_TERMINAL_PROCESSING * Ensure matching is done on the non-colored message - to simpify EXPRESSION
6 years ago
11 years ago
9 years ago
9 years ago
11 years ago
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
5 years ago
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
5 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
Better logging (#6038) (#6095) * Panic don't fatal on create new logger Fixes #5854 Signed-off-by: Andrew Thornton <art27@cantab.net> * partial broken * Update the logging infrastrcture Signed-off-by: Andrew Thornton <art27@cantab.net> * Reset the skip levels for Fatal and Error Signed-off-by: Andrew Thornton <art27@cantab.net> * broken ncsa * More log.Error fixes Signed-off-by: Andrew Thornton <art27@cantab.net> * Remove nal * set log-levels to lowercase * Make console_test test all levels * switch to lowercased levels * OK now working * Fix vetting issues * Fix lint * Fix tests * change default logging to match current gitea * Improve log testing Signed-off-by: Andrew Thornton <art27@cantab.net> * reset error skip levels to 0 * Update documentation and access logger configuration * Redirect the router log back to gitea if redirect macaron log but also allow setting the log level - i.e. TRACE * Fix broken level caching * Refactor the router log * Add Router logger * Add colorizing options * Adjust router colors * Only create logger if they will be used * update app.ini.sample * rename Attribute ColorAttribute * Change from white to green for function * Set fatal/error levels * Restore initial trace logger * Fix Trace arguments in modules/auth/auth.go * Properly handle XORMLogger * Improve admin/config page * fix fmt * Add auto-compression of old logs * Update error log levels * Remove the unnecessary skip argument from Error, Fatal and Critical * Add stacktrace support * Fix tests * Remove x/sync from vendors? * Add stderr option to console logger * Use filepath.ToSlash to protect against Windows in tests * Remove prefixed underscores from names in colors.go * Remove not implemented database logger This was removed from Gogs on 4 Mar 2016 but left in the configuration since then. * Ensure that log paths are relative to ROOT_PATH * use path.Join * rename jsonConfig to logConfig * Rename "config" to "jsonConfig" to make it clearer * Requested changes * Requested changes: XormLogger * Try to color the windows terminal If successful default to colorizing the console logs * fixup * Colorize initially too * update vendor * Colorize logs on default and remove if this is not a colorizing logger * Fix documentation * fix test * Use go-isatty to detect if on windows we are on msys or cygwin * Fix spelling mistake * Add missing vendors * More changes * Rationalise the ANSI writer protection * Adjust colors on advice from @0x5c * Make Flags a comma separated list * Move to use the windows constant for ENABLE_VIRTUAL_TERMINAL_PROCESSING * Ensure matching is done on the non-colored message - to simpify EXPRESSION
6 years ago
Better logging (#6038) (#6095) * Panic don't fatal on create new logger Fixes #5854 Signed-off-by: Andrew Thornton <art27@cantab.net> * partial broken * Update the logging infrastrcture Signed-off-by: Andrew Thornton <art27@cantab.net> * Reset the skip levels for Fatal and Error Signed-off-by: Andrew Thornton <art27@cantab.net> * broken ncsa * More log.Error fixes Signed-off-by: Andrew Thornton <art27@cantab.net> * Remove nal * set log-levels to lowercase * Make console_test test all levels * switch to lowercased levels * OK now working * Fix vetting issues * Fix lint * Fix tests * change default logging to match current gitea * Improve log testing Signed-off-by: Andrew Thornton <art27@cantab.net> * reset error skip levels to 0 * Update documentation and access logger configuration * Redirect the router log back to gitea if redirect macaron log but also allow setting the log level - i.e. TRACE * Fix broken level caching * Refactor the router log * Add Router logger * Add colorizing options * Adjust router colors * Only create logger if they will be used * update app.ini.sample * rename Attribute ColorAttribute * Change from white to green for function * Set fatal/error levels * Restore initial trace logger * Fix Trace arguments in modules/auth/auth.go * Properly handle XORMLogger * Improve admin/config page * fix fmt * Add auto-compression of old logs * Update error log levels * Remove the unnecessary skip argument from Error, Fatal and Critical * Add stacktrace support * Fix tests * Remove x/sync from vendors? * Add stderr option to console logger * Use filepath.ToSlash to protect against Windows in tests * Remove prefixed underscores from names in colors.go * Remove not implemented database logger This was removed from Gogs on 4 Mar 2016 but left in the configuration since then. * Ensure that log paths are relative to ROOT_PATH * use path.Join * rename jsonConfig to logConfig * Rename "config" to "jsonConfig" to make it clearer * Requested changes * Requested changes: XormLogger * Try to color the windows terminal If successful default to colorizing the console logs * fixup * Colorize initially too * update vendor * Colorize logs on default and remove if this is not a colorizing logger * Fix documentation * fix test * Use go-isatty to detect if on windows we are on msys or cygwin * Fix spelling mistake * Add missing vendors * More changes * Rationalise the ANSI writer protection * Adjust colors on advice from @0x5c * Make Flags a comma separated list * Move to use the windows constant for ENABLE_VIRTUAL_TERMINAL_PROCESSING * Ensure matching is done on the non-colored message - to simpify EXPRESSION
6 years ago
Better logging (#6038) (#6095) * Panic don't fatal on create new logger Fixes #5854 Signed-off-by: Andrew Thornton <art27@cantab.net> * partial broken * Update the logging infrastrcture Signed-off-by: Andrew Thornton <art27@cantab.net> * Reset the skip levels for Fatal and Error Signed-off-by: Andrew Thornton <art27@cantab.net> * broken ncsa * More log.Error fixes Signed-off-by: Andrew Thornton <art27@cantab.net> * Remove nal * set log-levels to lowercase * Make console_test test all levels * switch to lowercased levels * OK now working * Fix vetting issues * Fix lint * Fix tests * change default logging to match current gitea * Improve log testing Signed-off-by: Andrew Thornton <art27@cantab.net> * reset error skip levels to 0 * Update documentation and access logger configuration * Redirect the router log back to gitea if redirect macaron log but also allow setting the log level - i.e. TRACE * Fix broken level caching * Refactor the router log * Add Router logger * Add colorizing options * Adjust router colors * Only create logger if they will be used * update app.ini.sample * rename Attribute ColorAttribute * Change from white to green for function * Set fatal/error levels * Restore initial trace logger * Fix Trace arguments in modules/auth/auth.go * Properly handle XORMLogger * Improve admin/config page * fix fmt * Add auto-compression of old logs * Update error log levels * Remove the unnecessary skip argument from Error, Fatal and Critical * Add stacktrace support * Fix tests * Remove x/sync from vendors? * Add stderr option to console logger * Use filepath.ToSlash to protect against Windows in tests * Remove prefixed underscores from names in colors.go * Remove not implemented database logger This was removed from Gogs on 4 Mar 2016 but left in the configuration since then. * Ensure that log paths are relative to ROOT_PATH * use path.Join * rename jsonConfig to logConfig * Rename "config" to "jsonConfig" to make it clearer * Requested changes * Requested changes: XormLogger * Try to color the windows terminal If successful default to colorizing the console logs * fixup * Colorize initially too * update vendor * Colorize logs on default and remove if this is not a colorizing logger * Fix documentation * fix test * Use go-isatty to detect if on windows we are on msys or cygwin * Fix spelling mistake * Add missing vendors * More changes * Rationalise the ANSI writer protection * Adjust colors on advice from @0x5c * Make Flags a comma separated list * Move to use the windows constant for ENABLE_VIRTUAL_TERMINAL_PROCESSING * Ensure matching is done on the non-colored message - to simpify EXPRESSION
6 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Copyright 2017 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package models
  6. import (
  7. "context"
  8. "encoding/json"
  9. "fmt"
  10. "strings"
  11. "time"
  12. "code.gitea.io/gitea/modules/log"
  13. "code.gitea.io/gitea/modules/setting"
  14. api "code.gitea.io/gitea/modules/structs"
  15. "code.gitea.io/gitea/modules/timeutil"
  16. gouuid "github.com/google/uuid"
  17. )
  18. // HookContentType is the content type of a web hook
  19. type HookContentType int
  20. const (
  21. // ContentTypeJSON is a JSON payload for web hooks
  22. ContentTypeJSON HookContentType = iota + 1
  23. // ContentTypeForm is an url-encoded form payload for web hook
  24. ContentTypeForm
  25. )
  26. var hookContentTypes = map[string]HookContentType{
  27. "json": ContentTypeJSON,
  28. "form": ContentTypeForm,
  29. }
  30. // ToHookContentType returns HookContentType by given name.
  31. func ToHookContentType(name string) HookContentType {
  32. return hookContentTypes[name]
  33. }
  34. // HookTaskCleanupType is the type of cleanup to perform on hook_task
  35. type HookTaskCleanupType int
  36. const (
  37. // OlderThan hook_task rows will be cleaned up by the age of the row
  38. OlderThan HookTaskCleanupType = iota
  39. // PerWebhook hook_task rows will be cleaned up by leaving the most recent deliveries for each webhook
  40. PerWebhook
  41. )
  42. var hookTaskCleanupTypes = map[string]HookTaskCleanupType{
  43. "OlderThan": OlderThan,
  44. "PerWebhook": PerWebhook,
  45. }
  46. // ToHookTaskCleanupType returns HookTaskCleanupType by given name.
  47. func ToHookTaskCleanupType(name string) HookTaskCleanupType {
  48. return hookTaskCleanupTypes[name]
  49. }
  50. // Name returns the name of a given web hook's content type
  51. func (t HookContentType) Name() string {
  52. switch t {
  53. case ContentTypeJSON:
  54. return "json"
  55. case ContentTypeForm:
  56. return "form"
  57. }
  58. return ""
  59. }
  60. // IsValidHookContentType returns true if given name is a valid hook content type.
  61. func IsValidHookContentType(name string) bool {
  62. _, ok := hookContentTypes[name]
  63. return ok
  64. }
  65. // HookEvents is a set of web hook events
  66. type HookEvents struct {
  67. Create bool `json:"create"`
  68. Delete bool `json:"delete"`
  69. Fork bool `json:"fork"`
  70. Issues bool `json:"issues"`
  71. IssueAssign bool `json:"issue_assign"`
  72. IssueLabel bool `json:"issue_label"`
  73. IssueMilestone bool `json:"issue_milestone"`
  74. IssueComment bool `json:"issue_comment"`
  75. Push bool `json:"push"`
  76. PullRequest bool `json:"pull_request"`
  77. PullRequestAssign bool `json:"pull_request_assign"`
  78. PullRequestLabel bool `json:"pull_request_label"`
  79. PullRequestMilestone bool `json:"pull_request_milestone"`
  80. PullRequestComment bool `json:"pull_request_comment"`
  81. PullRequestReview bool `json:"pull_request_review"`
  82. PullRequestSync bool `json:"pull_request_sync"`
  83. Repository bool `json:"repository"`
  84. Release bool `json:"release"`
  85. }
  86. // HookEvent represents events that will delivery hook.
  87. type HookEvent struct {
  88. PushOnly bool `json:"push_only"`
  89. SendEverything bool `json:"send_everything"`
  90. ChooseEvents bool `json:"choose_events"`
  91. BranchFilter string `json:"branch_filter"`
  92. HookEvents `json:"events"`
  93. }
  94. // HookStatus is the status of a web hook
  95. type HookStatus int
  96. // Possible statuses of a web hook
  97. const (
  98. HookStatusNone = iota
  99. HookStatusSucceed
  100. HookStatusFail
  101. )
  102. // Webhook represents a web hook object.
  103. type Webhook struct {
  104. ID int64 `xorm:"pk autoincr"`
  105. RepoID int64 `xorm:"INDEX"` // An ID of 0 indicates either a default or system webhook
  106. OrgID int64 `xorm:"INDEX"`
  107. IsSystemWebhook bool
  108. URL string `xorm:"url TEXT"`
  109. Signature string `xorm:"TEXT"`
  110. HTTPMethod string `xorm:"http_method"`
  111. ContentType HookContentType
  112. Secret string `xorm:"TEXT"`
  113. Events string `xorm:"TEXT"`
  114. *HookEvent `xorm:"-"`
  115. IsSSL bool `xorm:"is_ssl"`
  116. IsActive bool `xorm:"INDEX"`
  117. Type HookTaskType `xorm:"VARCHAR(16) 'type'"`
  118. Meta string `xorm:"TEXT"` // store hook-specific attributes
  119. LastStatus HookStatus // Last delivery status
  120. CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
  121. UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
  122. }
  123. // AfterLoad updates the webhook object upon setting a column
  124. func (w *Webhook) AfterLoad() {
  125. w.HookEvent = &HookEvent{}
  126. if err := json.Unmarshal([]byte(w.Events), w.HookEvent); err != nil {
  127. log.Error("Unmarshal[%d]: %v", w.ID, err)
  128. }
  129. }
  130. // History returns history of webhook by given conditions.
  131. func (w *Webhook) History(page int) ([]*HookTask, error) {
  132. return HookTasks(w.ID, page)
  133. }
  134. // UpdateEvent handles conversion from HookEvent to Events.
  135. func (w *Webhook) UpdateEvent() error {
  136. data, err := json.Marshal(w.HookEvent)
  137. w.Events = string(data)
  138. return err
  139. }
  140. // HasCreateEvent returns true if hook enabled create event.
  141. func (w *Webhook) HasCreateEvent() bool {
  142. return w.SendEverything ||
  143. (w.ChooseEvents && w.HookEvents.Create)
  144. }
  145. // HasDeleteEvent returns true if hook enabled delete event.
  146. func (w *Webhook) HasDeleteEvent() bool {
  147. return w.SendEverything ||
  148. (w.ChooseEvents && w.HookEvents.Delete)
  149. }
  150. // HasForkEvent returns true if hook enabled fork event.
  151. func (w *Webhook) HasForkEvent() bool {
  152. return w.SendEverything ||
  153. (w.ChooseEvents && w.HookEvents.Fork)
  154. }
  155. // HasIssuesEvent returns true if hook enabled issues event.
  156. func (w *Webhook) HasIssuesEvent() bool {
  157. return w.SendEverything ||
  158. (w.ChooseEvents && w.HookEvents.Issues)
  159. }
  160. // HasIssuesAssignEvent returns true if hook enabled issues assign event.
  161. func (w *Webhook) HasIssuesAssignEvent() bool {
  162. return w.SendEverything ||
  163. (w.ChooseEvents && w.HookEvents.IssueAssign)
  164. }
  165. // HasIssuesLabelEvent returns true if hook enabled issues label event.
  166. func (w *Webhook) HasIssuesLabelEvent() bool {
  167. return w.SendEverything ||
  168. (w.ChooseEvents && w.HookEvents.IssueLabel)
  169. }
  170. // HasIssuesMilestoneEvent returns true if hook enabled issues milestone event.
  171. func (w *Webhook) HasIssuesMilestoneEvent() bool {
  172. return w.SendEverything ||
  173. (w.ChooseEvents && w.HookEvents.IssueMilestone)
  174. }
  175. // HasIssueCommentEvent returns true if hook enabled issue_comment event.
  176. func (w *Webhook) HasIssueCommentEvent() bool {
  177. return w.SendEverything ||
  178. (w.ChooseEvents && w.HookEvents.IssueComment)
  179. }
  180. // HasPushEvent returns true if hook enabled push event.
  181. func (w *Webhook) HasPushEvent() bool {
  182. return w.PushOnly || w.SendEverything ||
  183. (w.ChooseEvents && w.HookEvents.Push)
  184. }
  185. // HasPullRequestEvent returns true if hook enabled pull request event.
  186. func (w *Webhook) HasPullRequestEvent() bool {
  187. return w.SendEverything ||
  188. (w.ChooseEvents && w.HookEvents.PullRequest)
  189. }
  190. // HasPullRequestAssignEvent returns true if hook enabled pull request assign event.
  191. func (w *Webhook) HasPullRequestAssignEvent() bool {
  192. return w.SendEverything ||
  193. (w.ChooseEvents && w.HookEvents.PullRequestAssign)
  194. }
  195. // HasPullRequestLabelEvent returns true if hook enabled pull request label event.
  196. func (w *Webhook) HasPullRequestLabelEvent() bool {
  197. return w.SendEverything ||
  198. (w.ChooseEvents && w.HookEvents.PullRequestLabel)
  199. }
  200. // HasPullRequestMilestoneEvent returns true if hook enabled pull request milestone event.
  201. func (w *Webhook) HasPullRequestMilestoneEvent() bool {
  202. return w.SendEverything ||
  203. (w.ChooseEvents && w.HookEvents.PullRequestMilestone)
  204. }
  205. // HasPullRequestCommentEvent returns true if hook enabled pull_request_comment event.
  206. func (w *Webhook) HasPullRequestCommentEvent() bool {
  207. return w.SendEverything ||
  208. (w.ChooseEvents && w.HookEvents.PullRequestComment)
  209. }
  210. // HasPullRequestApprovedEvent returns true if hook enabled pull request review event.
  211. func (w *Webhook) HasPullRequestApprovedEvent() bool {
  212. return w.SendEverything ||
  213. (w.ChooseEvents && w.HookEvents.PullRequestReview)
  214. }
  215. // HasPullRequestRejectedEvent returns true if hook enabled pull request review event.
  216. func (w *Webhook) HasPullRequestRejectedEvent() bool {
  217. return w.SendEverything ||
  218. (w.ChooseEvents && w.HookEvents.PullRequestReview)
  219. }
  220. // HasPullRequestReviewCommentEvent returns true if hook enabled pull request review event.
  221. func (w *Webhook) HasPullRequestReviewCommentEvent() bool {
  222. return w.SendEverything ||
  223. (w.ChooseEvents && w.HookEvents.PullRequestReview)
  224. }
  225. // HasPullRequestSyncEvent returns true if hook enabled pull request sync event.
  226. func (w *Webhook) HasPullRequestSyncEvent() bool {
  227. return w.SendEverything ||
  228. (w.ChooseEvents && w.HookEvents.PullRequestSync)
  229. }
  230. // HasReleaseEvent returns if hook enabled release event.
  231. func (w *Webhook) HasReleaseEvent() bool {
  232. return w.SendEverything ||
  233. (w.ChooseEvents && w.HookEvents.Release)
  234. }
  235. // HasRepositoryEvent returns if hook enabled repository event.
  236. func (w *Webhook) HasRepositoryEvent() bool {
  237. return w.SendEverything ||
  238. (w.ChooseEvents && w.HookEvents.Repository)
  239. }
  240. // EventCheckers returns event checkers
  241. func (w *Webhook) EventCheckers() []struct {
  242. Has func() bool
  243. Type HookEventType
  244. } {
  245. return []struct {
  246. Has func() bool
  247. Type HookEventType
  248. }{
  249. {w.HasCreateEvent, HookEventCreate},
  250. {w.HasDeleteEvent, HookEventDelete},
  251. {w.HasForkEvent, HookEventFork},
  252. {w.HasPushEvent, HookEventPush},
  253. {w.HasIssuesEvent, HookEventIssues},
  254. {w.HasIssuesAssignEvent, HookEventIssueAssign},
  255. {w.HasIssuesLabelEvent, HookEventIssueLabel},
  256. {w.HasIssuesMilestoneEvent, HookEventIssueMilestone},
  257. {w.HasIssueCommentEvent, HookEventIssueComment},
  258. {w.HasPullRequestEvent, HookEventPullRequest},
  259. {w.HasPullRequestAssignEvent, HookEventPullRequestAssign},
  260. {w.HasPullRequestLabelEvent, HookEventPullRequestLabel},
  261. {w.HasPullRequestMilestoneEvent, HookEventPullRequestMilestone},
  262. {w.HasPullRequestCommentEvent, HookEventPullRequestComment},
  263. {w.HasPullRequestApprovedEvent, HookEventPullRequestReviewApproved},
  264. {w.HasPullRequestRejectedEvent, HookEventPullRequestReviewRejected},
  265. {w.HasPullRequestCommentEvent, HookEventPullRequestReviewComment},
  266. {w.HasPullRequestSyncEvent, HookEventPullRequestSync},
  267. {w.HasRepositoryEvent, HookEventRepository},
  268. {w.HasReleaseEvent, HookEventRelease},
  269. }
  270. }
  271. // EventsArray returns an array of hook events
  272. func (w *Webhook) EventsArray() []string {
  273. events := make([]string, 0, 7)
  274. for _, c := range w.EventCheckers() {
  275. if c.Has() {
  276. events = append(events, string(c.Type))
  277. }
  278. }
  279. return events
  280. }
  281. // CreateWebhook creates a new web hook.
  282. func CreateWebhook(w *Webhook) error {
  283. return createWebhook(x, w)
  284. }
  285. func createWebhook(e Engine, w *Webhook) error {
  286. w.Type = strings.TrimSpace(w.Type)
  287. _, err := e.Insert(w)
  288. return err
  289. }
  290. // getWebhook uses argument bean as query condition,
  291. // ID must be specified and do not assign unnecessary fields.
  292. func getWebhook(bean *Webhook) (*Webhook, error) {
  293. has, err := x.Get(bean)
  294. if err != nil {
  295. return nil, err
  296. } else if !has {
  297. return nil, ErrWebhookNotExist{bean.ID}
  298. }
  299. return bean, nil
  300. }
  301. // GetWebhookByID returns webhook of repository by given ID.
  302. func GetWebhookByID(id int64) (*Webhook, error) {
  303. return getWebhook(&Webhook{
  304. ID: id,
  305. })
  306. }
  307. // GetWebhookByRepoID returns webhook of repository by given ID.
  308. func GetWebhookByRepoID(repoID, id int64) (*Webhook, error) {
  309. return getWebhook(&Webhook{
  310. ID: id,
  311. RepoID: repoID,
  312. })
  313. }
  314. // GetWebhookByOrgID returns webhook of organization by given ID.
  315. func GetWebhookByOrgID(orgID, id int64) (*Webhook, error) {
  316. return getWebhook(&Webhook{
  317. ID: id,
  318. OrgID: orgID,
  319. })
  320. }
  321. // GetActiveWebhooksByRepoID returns all active webhooks of repository.
  322. func GetActiveWebhooksByRepoID(repoID int64) ([]*Webhook, error) {
  323. return getActiveWebhooksByRepoID(x, repoID)
  324. }
  325. func getActiveWebhooksByRepoID(e Engine, repoID int64) ([]*Webhook, error) {
  326. webhooks := make([]*Webhook, 0, 5)
  327. return webhooks, e.Where("is_active=?", true).
  328. Find(&webhooks, &Webhook{RepoID: repoID})
  329. }
  330. // GetWebhooksByRepoID returns all webhooks of a repository.
  331. func GetWebhooksByRepoID(repoID int64, listOptions ListOptions) ([]*Webhook, error) {
  332. if listOptions.Page == 0 {
  333. webhooks := make([]*Webhook, 0, 5)
  334. return webhooks, x.Find(&webhooks, &Webhook{RepoID: repoID})
  335. }
  336. sess := listOptions.getPaginatedSession()
  337. webhooks := make([]*Webhook, 0, listOptions.PageSize)
  338. return webhooks, sess.Find(&webhooks, &Webhook{RepoID: repoID})
  339. }
  340. // GetActiveWebhooksByOrgID returns all active webhooks for an organization.
  341. func GetActiveWebhooksByOrgID(orgID int64) (ws []*Webhook, err error) {
  342. return getActiveWebhooksByOrgID(x, orgID)
  343. }
  344. func getActiveWebhooksByOrgID(e Engine, orgID int64) (ws []*Webhook, err error) {
  345. err = e.
  346. Where("org_id=?", orgID).
  347. And("is_active=?", true).
  348. Find(&ws)
  349. return ws, err
  350. }
  351. // GetWebhooksByOrgID returns paginated webhooks for an organization.
  352. func GetWebhooksByOrgID(orgID int64, listOptions ListOptions) ([]*Webhook, error) {
  353. if listOptions.Page == 0 {
  354. ws := make([]*Webhook, 0, 5)
  355. return ws, x.Find(&ws, &Webhook{OrgID: orgID})
  356. }
  357. sess := listOptions.getPaginatedSession()
  358. ws := make([]*Webhook, 0, listOptions.PageSize)
  359. return ws, sess.Find(&ws, &Webhook{OrgID: orgID})
  360. }
  361. // GetDefaultWebhooks returns all admin-default webhooks.
  362. func GetDefaultWebhooks() ([]*Webhook, error) {
  363. return getDefaultWebhooks(x)
  364. }
  365. func getDefaultWebhooks(e Engine) ([]*Webhook, error) {
  366. webhooks := make([]*Webhook, 0, 5)
  367. return webhooks, e.
  368. Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, false).
  369. Find(&webhooks)
  370. }
  371. // GetSystemOrDefaultWebhook returns admin system or default webhook by given ID.
  372. func GetSystemOrDefaultWebhook(id int64) (*Webhook, error) {
  373. webhook := &Webhook{ID: id}
  374. has, err := x.
  375. Where("repo_id=? AND org_id=?", 0, 0).
  376. Get(webhook)
  377. if err != nil {
  378. return nil, err
  379. } else if !has {
  380. return nil, ErrWebhookNotExist{id}
  381. }
  382. return webhook, nil
  383. }
  384. // GetSystemWebhooks returns all admin system webhooks.
  385. func GetSystemWebhooks() ([]*Webhook, error) {
  386. return getSystemWebhooks(x)
  387. }
  388. func getSystemWebhooks(e Engine) ([]*Webhook, error) {
  389. webhooks := make([]*Webhook, 0, 5)
  390. return webhooks, e.
  391. Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, true).
  392. Find(&webhooks)
  393. }
  394. // UpdateWebhook updates information of webhook.
  395. func UpdateWebhook(w *Webhook) error {
  396. _, err := x.ID(w.ID).AllCols().Update(w)
  397. return err
  398. }
  399. // UpdateWebhookLastStatus updates last status of webhook.
  400. func UpdateWebhookLastStatus(w *Webhook) error {
  401. _, err := x.ID(w.ID).Cols("last_status").Update(w)
  402. return err
  403. }
  404. // deleteWebhook uses argument bean as query condition,
  405. // ID must be specified and do not assign unnecessary fields.
  406. func deleteWebhook(bean *Webhook) (err error) {
  407. sess := x.NewSession()
  408. defer sess.Close()
  409. if err = sess.Begin(); err != nil {
  410. return err
  411. }
  412. if count, err := sess.Delete(bean); err != nil {
  413. return err
  414. } else if count == 0 {
  415. return ErrWebhookNotExist{ID: bean.ID}
  416. } else if _, err = sess.Delete(&HookTask{HookID: bean.ID}); err != nil {
  417. return err
  418. }
  419. return sess.Commit()
  420. }
  421. // DeleteWebhookByRepoID deletes webhook of repository by given ID.
  422. func DeleteWebhookByRepoID(repoID, id int64) error {
  423. return deleteWebhook(&Webhook{
  424. ID: id,
  425. RepoID: repoID,
  426. })
  427. }
  428. // DeleteWebhookByOrgID deletes webhook of organization by given ID.
  429. func DeleteWebhookByOrgID(orgID, id int64) error {
  430. return deleteWebhook(&Webhook{
  431. ID: id,
  432. OrgID: orgID,
  433. })
  434. }
  435. // DeleteDefaultSystemWebhook deletes an admin-configured default or system webhook (where Org and Repo ID both 0)
  436. func DeleteDefaultSystemWebhook(id int64) error {
  437. sess := x.NewSession()
  438. defer sess.Close()
  439. if err := sess.Begin(); err != nil {
  440. return err
  441. }
  442. count, err := sess.
  443. Where("repo_id=? AND org_id=?", 0, 0).
  444. Delete(&Webhook{ID: id})
  445. if err != nil {
  446. return err
  447. } else if count == 0 {
  448. return ErrWebhookNotExist{ID: id}
  449. }
  450. if _, err := sess.Delete(&HookTask{HookID: id}); err != nil {
  451. return err
  452. }
  453. return sess.Commit()
  454. }
  455. // copyDefaultWebhooksToRepo creates copies of the default webhooks in a new repo
  456. func copyDefaultWebhooksToRepo(e Engine, repoID int64) error {
  457. ws, err := getDefaultWebhooks(e)
  458. if err != nil {
  459. return fmt.Errorf("GetDefaultWebhooks: %v", err)
  460. }
  461. for _, w := range ws {
  462. w.ID = 0
  463. w.RepoID = repoID
  464. if err := createWebhook(e, w); err != nil {
  465. return fmt.Errorf("CreateWebhook: %v", err)
  466. }
  467. }
  468. return nil
  469. }
  470. // ___ ___ __ ___________ __
  471. // / | \ ____ ____ | | _\__ ___/____ _____| | __
  472. // / ~ \/ _ \ / _ \| |/ / | | \__ \ / ___/ |/ /
  473. // \ Y ( <_> | <_> ) < | | / __ \_\___ \| <
  474. // \___|_ / \____/ \____/|__|_ \ |____| (____ /____ >__|_ \
  475. // \/ \/ \/ \/ \/
  476. // HookTaskType is the type of an hook task
  477. type HookTaskType = string
  478. // Types of hook tasks
  479. const (
  480. GITEA HookTaskType = "gitea"
  481. GOGS HookTaskType = "gogs"
  482. SLACK HookTaskType = "slack"
  483. DISCORD HookTaskType = "discord"
  484. DINGTALK HookTaskType = "dingtalk"
  485. TELEGRAM HookTaskType = "telegram"
  486. MSTEAMS HookTaskType = "msteams"
  487. FEISHU HookTaskType = "feishu"
  488. MATRIX HookTaskType = "matrix"
  489. )
  490. // HookEventType is the type of an hook event
  491. type HookEventType string
  492. // Types of hook events
  493. const (
  494. HookEventCreate HookEventType = "create"
  495. HookEventDelete HookEventType = "delete"
  496. HookEventFork HookEventType = "fork"
  497. HookEventPush HookEventType = "push"
  498. HookEventIssues HookEventType = "issues"
  499. HookEventIssueAssign HookEventType = "issue_assign"
  500. HookEventIssueLabel HookEventType = "issue_label"
  501. HookEventIssueMilestone HookEventType = "issue_milestone"
  502. HookEventIssueComment HookEventType = "issue_comment"
  503. HookEventPullRequest HookEventType = "pull_request"
  504. HookEventPullRequestAssign HookEventType = "pull_request_assign"
  505. HookEventPullRequestLabel HookEventType = "pull_request_label"
  506. HookEventPullRequestMilestone HookEventType = "pull_request_milestone"
  507. HookEventPullRequestComment HookEventType = "pull_request_comment"
  508. HookEventPullRequestReviewApproved HookEventType = "pull_request_review_approved"
  509. HookEventPullRequestReviewRejected HookEventType = "pull_request_review_rejected"
  510. HookEventPullRequestReviewComment HookEventType = "pull_request_review_comment"
  511. HookEventPullRequestSync HookEventType = "pull_request_sync"
  512. HookEventRepository HookEventType = "repository"
  513. HookEventRelease HookEventType = "release"
  514. )
  515. // Event returns the HookEventType as an event string
  516. func (h HookEventType) Event() string {
  517. switch h {
  518. case HookEventCreate:
  519. return "create"
  520. case HookEventDelete:
  521. return "delete"
  522. case HookEventFork:
  523. return "fork"
  524. case HookEventPush:
  525. return "push"
  526. case HookEventIssues, HookEventIssueAssign, HookEventIssueLabel, HookEventIssueMilestone:
  527. return "issues"
  528. case HookEventPullRequest, HookEventPullRequestAssign, HookEventPullRequestLabel, HookEventPullRequestMilestone,
  529. HookEventPullRequestSync:
  530. return "pull_request"
  531. case HookEventIssueComment, HookEventPullRequestComment:
  532. return "issue_comment"
  533. case HookEventPullRequestReviewApproved:
  534. return "pull_request_approved"
  535. case HookEventPullRequestReviewRejected:
  536. return "pull_request_rejected"
  537. case HookEventPullRequestReviewComment:
  538. return "pull_request_comment"
  539. case HookEventRepository:
  540. return "repository"
  541. case HookEventRelease:
  542. return "release"
  543. }
  544. return ""
  545. }
  546. // HookRequest represents hook task request information.
  547. type HookRequest struct {
  548. Headers map[string]string `json:"headers"`
  549. }
  550. // HookResponse represents hook task response information.
  551. type HookResponse struct {
  552. Status int `json:"status"`
  553. Headers map[string]string `json:"headers"`
  554. Body string `json:"body"`
  555. }
  556. // HookTask represents a hook task.
  557. type HookTask struct {
  558. ID int64 `xorm:"pk autoincr"`
  559. RepoID int64 `xorm:"INDEX"`
  560. HookID int64
  561. UUID string
  562. Typ HookTaskType `xorm:"VARCHAR(16) index"`
  563. URL string `xorm:"TEXT"`
  564. Signature string `xorm:"TEXT"`
  565. api.Payloader `xorm:"-"`
  566. PayloadContent string `xorm:"TEXT"`
  567. HTTPMethod string `xorm:"http_method"`
  568. ContentType HookContentType
  569. EventType HookEventType
  570. IsSSL bool
  571. IsDelivered bool
  572. Delivered int64
  573. DeliveredString string `xorm:"-"`
  574. // History info.
  575. IsSucceed bool
  576. RequestContent string `xorm:"TEXT"`
  577. RequestInfo *HookRequest `xorm:"-"`
  578. ResponseContent string `xorm:"TEXT"`
  579. ResponseInfo *HookResponse `xorm:"-"`
  580. }
  581. // BeforeUpdate will be invoked by XORM before updating a record
  582. // representing this object
  583. func (t *HookTask) BeforeUpdate() {
  584. if t.RequestInfo != nil {
  585. t.RequestContent = t.simpleMarshalJSON(t.RequestInfo)
  586. }
  587. if t.ResponseInfo != nil {
  588. t.ResponseContent = t.simpleMarshalJSON(t.ResponseInfo)
  589. }
  590. }
  591. // AfterLoad updates the webhook object upon setting a column
  592. func (t *HookTask) AfterLoad() {
  593. t.DeliveredString = time.Unix(0, t.Delivered).Format("2006-01-02 15:04:05 MST")
  594. if len(t.RequestContent) == 0 {
  595. return
  596. }
  597. t.RequestInfo = &HookRequest{}
  598. if err := json.Unmarshal([]byte(t.RequestContent), t.RequestInfo); err != nil {
  599. log.Error("Unmarshal RequestContent[%d]: %v", t.ID, err)
  600. }
  601. if len(t.ResponseContent) > 0 {
  602. t.ResponseInfo = &HookResponse{}
  603. if err := json.Unmarshal([]byte(t.ResponseContent), t.ResponseInfo); err != nil {
  604. log.Error("Unmarshal ResponseContent[%d]: %v", t.ID, err)
  605. }
  606. }
  607. }
  608. func (t *HookTask) simpleMarshalJSON(v interface{}) string {
  609. p, err := json.Marshal(v)
  610. if err != nil {
  611. log.Error("Marshal [%d]: %v", t.ID, err)
  612. }
  613. return string(p)
  614. }
  615. // HookTasks returns a list of hook tasks by given conditions.
  616. func HookTasks(hookID int64, page int) ([]*HookTask, error) {
  617. tasks := make([]*HookTask, 0, setting.Webhook.PagingNum)
  618. return tasks, x.
  619. Limit(setting.Webhook.PagingNum, (page-1)*setting.Webhook.PagingNum).
  620. Where("hook_id=?", hookID).
  621. Desc("id").
  622. Find(&tasks)
  623. }
  624. // CreateHookTask creates a new hook task,
  625. // it handles conversion from Payload to PayloadContent.
  626. func CreateHookTask(t *HookTask) error {
  627. return createHookTask(x, t)
  628. }
  629. func createHookTask(e Engine, t *HookTask) error {
  630. data, err := t.Payloader.JSONPayload()
  631. if err != nil {
  632. return err
  633. }
  634. t.UUID = gouuid.New().String()
  635. t.PayloadContent = string(data)
  636. _, err = e.Insert(t)
  637. return err
  638. }
  639. // UpdateHookTask updates information of hook task.
  640. func UpdateHookTask(t *HookTask) error {
  641. _, err := x.ID(t.ID).AllCols().Update(t)
  642. return err
  643. }
  644. // FindUndeliveredHookTasks represents find the undelivered hook tasks
  645. func FindUndeliveredHookTasks() ([]*HookTask, error) {
  646. tasks := make([]*HookTask, 0, 10)
  647. if err := x.Where("is_delivered=?", false).Find(&tasks); err != nil {
  648. return nil, err
  649. }
  650. return tasks, nil
  651. }
  652. // FindRepoUndeliveredHookTasks represents find the undelivered hook tasks of one repository
  653. func FindRepoUndeliveredHookTasks(repoID int64) ([]*HookTask, error) {
  654. tasks := make([]*HookTask, 0, 5)
  655. if err := x.Where("repo_id=? AND is_delivered=?", repoID, false).Find(&tasks); err != nil {
  656. return nil, err
  657. }
  658. return tasks, nil
  659. }
  660. // CleanupHookTaskTable deletes rows from hook_task as needed.
  661. func CleanupHookTaskTable(ctx context.Context, cleanupType HookTaskCleanupType, olderThan time.Duration, numberToKeep int) error {
  662. log.Trace("Doing: CleanupHookTaskTable")
  663. if cleanupType == OlderThan {
  664. deleteOlderThan := time.Now().Add(-olderThan).UnixNano()
  665. deletes, err := x.
  666. Where("is_delivered = ? and delivered < ?", true, deleteOlderThan).
  667. Delete(new(HookTask))
  668. if err != nil {
  669. return err
  670. }
  671. log.Trace("Deleted %d rows from hook_task", deletes)
  672. } else if cleanupType == PerWebhook {
  673. hookIDs := make([]int64, 0, 10)
  674. err := x.Table("webhook").
  675. Where("id > 0").
  676. Cols("id").
  677. Find(&hookIDs)
  678. if err != nil {
  679. return err
  680. }
  681. for _, hookID := range hookIDs {
  682. select {
  683. case <-ctx.Done():
  684. return ErrCancelledf("Before deleting hook_task records for hook id %d", hookID)
  685. default:
  686. }
  687. if err = deleteDeliveredHookTasksByWebhook(hookID, numberToKeep); err != nil {
  688. return err
  689. }
  690. }
  691. }
  692. log.Trace("Finished: CleanupHookTaskTable")
  693. return nil
  694. }
  695. func deleteDeliveredHookTasksByWebhook(hookID int64, numberDeliveriesToKeep int) error {
  696. log.Trace("Deleting hook_task rows for webhook %d, keeping the most recent %d deliveries", hookID, numberDeliveriesToKeep)
  697. var deliveryDates = make([]int64, 0, 10)
  698. err := x.Table("hook_task").
  699. Where("hook_task.hook_id = ? AND hook_task.is_delivered = ? AND hook_task.delivered is not null", hookID, true).
  700. Cols("hook_task.delivered").
  701. Join("INNER", "webhook", "hook_task.hook_id = webhook.id").
  702. OrderBy("hook_task.delivered desc").
  703. Limit(1, int(numberDeliveriesToKeep)).
  704. Find(&deliveryDates)
  705. if err != nil {
  706. return err
  707. }
  708. if len(deliveryDates) > 0 {
  709. deletes, err := x.
  710. Where("hook_id = ? and is_delivered = ? and delivered <= ?", hookID, true, deliveryDates[0]).
  711. Delete(new(HookTask))
  712. if err != nil {
  713. return err
  714. }
  715. log.Trace("Deleted %d hook_task rows for webhook %d", deletes, hookID)
  716. } else {
  717. log.Trace("No hook_task rows to delete for webhook %d", hookID)
  718. }
  719. return nil
  720. }