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

webhook.go 25KB

10 years ago
10 years ago
7 years ago
7 years ago
7 years ago
10 years ago
Add support for corporate WeChat webhooks (#15910) * 企业微信webhook * 企业微信webhook * 企业微信webhook * Update templates/admin/hook_new.tmpl Co-authored-by: a1012112796 <1012112796@qq.com> * Update services/webhook/wechatwork.go Co-authored-by: a1012112796 <1012112796@qq.com> * 修善wechatwork * 修善wechatwork * fix * Update locale_cs-CZ.ini fix * fix build * fix * fix build * make webhooks.zh-cn.md * delet unnecessary blank line * delet unnecessary blank line * 企业微信webhook * 企业微信webhook * 企业微信webhook * Update templates/admin/hook_new.tmpl Co-authored-by: a1012112796 <1012112796@qq.com> * Update services/webhook/wechatwork.go Co-authored-by: a1012112796 <1012112796@qq.com> * 修善wechatwork * 修善wechatwork * fix * fix build * fix * fix build * make webhooks.zh-cn.md * delet unnecessary blank line * delet unnecessary blank line * 企业微信webhook * 企业微信webhook * 企业微信webhook * 企业微信webhook * 企业微信webhook * fix * fix * 企业微信webhook * 企业微信webhook * 企业微信webhook * fix wechat * fix wechat * fix wechat * fix wechat * Fix invalid params and typo of email templates (#16394) Signed-off-by: Meano <meanocat@gmail.com> * Add LRU mem cache implementation (#16226) The current default memory cache implementation is unbounded in size and number of objects cached. This is hardly ideal. This PR proposes creating a TwoQueue LRU cache as the underlying cache for Gitea. The cache is limited by the number of objects stored in the cache (rather than size) for simplicity. The default number of objects is 50000 - which is perhaps too small as most of our objects cached are going to be much less than 1kB. It may be worth considering using a different LRU implementation that actively limits sizes or avoids GC - however, this is just a beginning implementation. Signed-off-by: Andrew Thornton <art27@cantab.net> * [skip ci] Updated translations via Crowdin * Replace `plugins/docker` with `techknowlogick/drone-docker`in ci (#16407) * plugins/docker -> techknowlogick/drone-docker * It is multi-arch * docs: rewrite email setup (#16404) * Add intro for both the docs page and mailer methods * Fix numbering level in SMTP section * Recommends implicit TLS Signed-off-by: Bagas Sanjaya <bagasdotme@gmail.com> * Validate Issue Index before querying DB (#16406) * Fix external renderer (#16401) * fix external renderer * use GBackground context as fallback * no fallback, return error Co-authored-by: Lauris BH <lauris@nix.lv> * Add checkbox to delete pull branch after successful merge (#16049) * Add checkbox to delete pull branch after successful merge * Omit DeleteBranchAfterMerge field in json * Log a warning instead of error when PR head branch deleted * Add DefaultDeleteBranchAfterMerge to PullRequestConfig * Add support for delete_branch_after_merge via API * Fix for API: the branch should be deleted from the HEAD repo If head and base repo are the same, reuse the already opened ctx.Repo.GitRepo * Don't delegate to CleanupBranch, only reuse branch deletion code CleanupBranch contains too much logic that has already been performed by the Merge * Reuse gitrepo in MergePullRequest Co-authored-by: Andrew Thornton <art27@cantab.net> * [skip ci] Updated translations via Crowdin * Detect encoding changes while parsing diff (#16330) * Detect encoding changes while parsing diff * Let branch/tag name be a valid ref to get CI status (#16400) * fix #16384# * refactor: move shared helper func to utils package * extend Tests * use ctx.Repo.GitRepo if not nil * fix * fix * 企业微信webhook * 企业微信webhook * 企业微信webhook * fix build * fix build * Apply suggestions from code review Co-authored-by: a1012112796 <1012112796@qq.com> Co-authored-by: myheavily <myheavily> Co-authored-by: zhaoxin <gitea@fake.local> Co-authored-by: Meano <Meano@foxmail.com> Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: GiteaBot <teabot@gitea.io> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: Bagas Sanjaya <bagasdotme@gmail.com> Co-authored-by: Norwin <noerw@users.noreply.github.com> Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: Jimmy Praet <jimmy.praet@telenet.be> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
3 years ago
10 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
5 years ago
10 years ago
8 years ago
8 years ago
10 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>
4 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>
4 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>
4 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 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
5 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
5 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
5 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  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. "fmt"
  9. "strings"
  10. "time"
  11. "code.gitea.io/gitea/models/db"
  12. "code.gitea.io/gitea/modules/json"
  13. "code.gitea.io/gitea/modules/log"
  14. "code.gitea.io/gitea/modules/setting"
  15. api "code.gitea.io/gitea/modules/structs"
  16. "code.gitea.io/gitea/modules/timeutil"
  17. "code.gitea.io/gitea/modules/util"
  18. gouuid "github.com/google/uuid"
  19. "xorm.io/builder"
  20. )
  21. // HookContentType is the content type of a web hook
  22. type HookContentType int
  23. const (
  24. // ContentTypeJSON is a JSON payload for web hooks
  25. ContentTypeJSON HookContentType = iota + 1
  26. // ContentTypeForm is an url-encoded form payload for web hook
  27. ContentTypeForm
  28. )
  29. var hookContentTypes = map[string]HookContentType{
  30. "json": ContentTypeJSON,
  31. "form": ContentTypeForm,
  32. }
  33. // ToHookContentType returns HookContentType by given name.
  34. func ToHookContentType(name string) HookContentType {
  35. return hookContentTypes[name]
  36. }
  37. // HookTaskCleanupType is the type of cleanup to perform on hook_task
  38. type HookTaskCleanupType int
  39. const (
  40. // OlderThan hook_task rows will be cleaned up by the age of the row
  41. OlderThan HookTaskCleanupType = iota
  42. // PerWebhook hook_task rows will be cleaned up by leaving the most recent deliveries for each webhook
  43. PerWebhook
  44. )
  45. var hookTaskCleanupTypes = map[string]HookTaskCleanupType{
  46. "OlderThan": OlderThan,
  47. "PerWebhook": PerWebhook,
  48. }
  49. // ToHookTaskCleanupType returns HookTaskCleanupType by given name.
  50. func ToHookTaskCleanupType(name string) HookTaskCleanupType {
  51. return hookTaskCleanupTypes[name]
  52. }
  53. // Name returns the name of a given web hook's content type
  54. func (t HookContentType) Name() string {
  55. switch t {
  56. case ContentTypeJSON:
  57. return "json"
  58. case ContentTypeForm:
  59. return "form"
  60. }
  61. return ""
  62. }
  63. // IsValidHookContentType returns true if given name is a valid hook content type.
  64. func IsValidHookContentType(name string) bool {
  65. _, ok := hookContentTypes[name]
  66. return ok
  67. }
  68. // HookEvents is a set of web hook events
  69. type HookEvents struct {
  70. Create bool `json:"create"`
  71. Delete bool `json:"delete"`
  72. Fork bool `json:"fork"`
  73. Issues bool `json:"issues"`
  74. IssueAssign bool `json:"issue_assign"`
  75. IssueLabel bool `json:"issue_label"`
  76. IssueMilestone bool `json:"issue_milestone"`
  77. IssueComment bool `json:"issue_comment"`
  78. Push bool `json:"push"`
  79. PullRequest bool `json:"pull_request"`
  80. PullRequestAssign bool `json:"pull_request_assign"`
  81. PullRequestLabel bool `json:"pull_request_label"`
  82. PullRequestMilestone bool `json:"pull_request_milestone"`
  83. PullRequestComment bool `json:"pull_request_comment"`
  84. PullRequestReview bool `json:"pull_request_review"`
  85. PullRequestSync bool `json:"pull_request_sync"`
  86. Repository bool `json:"repository"`
  87. Release bool `json:"release"`
  88. }
  89. // HookEvent represents events that will delivery hook.
  90. type HookEvent struct {
  91. PushOnly bool `json:"push_only"`
  92. SendEverything bool `json:"send_everything"`
  93. ChooseEvents bool `json:"choose_events"`
  94. BranchFilter string `json:"branch_filter"`
  95. HookEvents `json:"events"`
  96. }
  97. // HookType is the type of a webhook
  98. type HookType = string
  99. // Types of webhooks
  100. const (
  101. GITEA HookType = "gitea"
  102. GOGS HookType = "gogs"
  103. SLACK HookType = "slack"
  104. DISCORD HookType = "discord"
  105. DINGTALK HookType = "dingtalk"
  106. TELEGRAM HookType = "telegram"
  107. MSTEAMS HookType = "msteams"
  108. FEISHU HookType = "feishu"
  109. MATRIX HookType = "matrix"
  110. WECHATWORK HookType = "wechatwork"
  111. )
  112. // HookStatus is the status of a web hook
  113. type HookStatus int
  114. // Possible statuses of a web hook
  115. const (
  116. HookStatusNone = iota
  117. HookStatusSucceed
  118. HookStatusFail
  119. )
  120. // Webhook represents a web hook object.
  121. type Webhook struct {
  122. ID int64 `xorm:"pk autoincr"`
  123. RepoID int64 `xorm:"INDEX"` // An ID of 0 indicates either a default or system webhook
  124. OrgID int64 `xorm:"INDEX"`
  125. IsSystemWebhook bool
  126. URL string `xorm:"url TEXT"`
  127. HTTPMethod string `xorm:"http_method"`
  128. ContentType HookContentType
  129. Secret string `xorm:"TEXT"`
  130. Events string `xorm:"TEXT"`
  131. *HookEvent `xorm:"-"`
  132. IsActive bool `xorm:"INDEX"`
  133. Type HookType `xorm:"VARCHAR(16) 'type'"`
  134. Meta string `xorm:"TEXT"` // store hook-specific attributes
  135. LastStatus HookStatus // Last delivery status
  136. CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
  137. UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
  138. }
  139. func init() {
  140. db.RegisterModel(new(Webhook))
  141. db.RegisterModel(new(HookTask))
  142. }
  143. // AfterLoad updates the webhook object upon setting a column
  144. func (w *Webhook) AfterLoad() {
  145. w.HookEvent = &HookEvent{}
  146. if err := json.Unmarshal([]byte(w.Events), w.HookEvent); err != nil {
  147. log.Error("Unmarshal[%d]: %v", w.ID, err)
  148. }
  149. }
  150. // History returns history of webhook by given conditions.
  151. func (w *Webhook) History(page int) ([]*HookTask, error) {
  152. return HookTasks(w.ID, page)
  153. }
  154. // UpdateEvent handles conversion from HookEvent to Events.
  155. func (w *Webhook) UpdateEvent() error {
  156. data, err := json.Marshal(w.HookEvent)
  157. w.Events = string(data)
  158. return err
  159. }
  160. // HasCreateEvent returns true if hook enabled create event.
  161. func (w *Webhook) HasCreateEvent() bool {
  162. return w.SendEverything ||
  163. (w.ChooseEvents && w.HookEvents.Create)
  164. }
  165. // HasDeleteEvent returns true if hook enabled delete event.
  166. func (w *Webhook) HasDeleteEvent() bool {
  167. return w.SendEverything ||
  168. (w.ChooseEvents && w.HookEvents.Delete)
  169. }
  170. // HasForkEvent returns true if hook enabled fork event.
  171. func (w *Webhook) HasForkEvent() bool {
  172. return w.SendEverything ||
  173. (w.ChooseEvents && w.HookEvents.Fork)
  174. }
  175. // HasIssuesEvent returns true if hook enabled issues event.
  176. func (w *Webhook) HasIssuesEvent() bool {
  177. return w.SendEverything ||
  178. (w.ChooseEvents && w.HookEvents.Issues)
  179. }
  180. // HasIssuesAssignEvent returns true if hook enabled issues assign event.
  181. func (w *Webhook) HasIssuesAssignEvent() bool {
  182. return w.SendEverything ||
  183. (w.ChooseEvents && w.HookEvents.IssueAssign)
  184. }
  185. // HasIssuesLabelEvent returns true if hook enabled issues label event.
  186. func (w *Webhook) HasIssuesLabelEvent() bool {
  187. return w.SendEverything ||
  188. (w.ChooseEvents && w.HookEvents.IssueLabel)
  189. }
  190. // HasIssuesMilestoneEvent returns true if hook enabled issues milestone event.
  191. func (w *Webhook) HasIssuesMilestoneEvent() bool {
  192. return w.SendEverything ||
  193. (w.ChooseEvents && w.HookEvents.IssueMilestone)
  194. }
  195. // HasIssueCommentEvent returns true if hook enabled issue_comment event.
  196. func (w *Webhook) HasIssueCommentEvent() bool {
  197. return w.SendEverything ||
  198. (w.ChooseEvents && w.HookEvents.IssueComment)
  199. }
  200. // HasPushEvent returns true if hook enabled push event.
  201. func (w *Webhook) HasPushEvent() bool {
  202. return w.PushOnly || w.SendEverything ||
  203. (w.ChooseEvents && w.HookEvents.Push)
  204. }
  205. // HasPullRequestEvent returns true if hook enabled pull request event.
  206. func (w *Webhook) HasPullRequestEvent() bool {
  207. return w.SendEverything ||
  208. (w.ChooseEvents && w.HookEvents.PullRequest)
  209. }
  210. // HasPullRequestAssignEvent returns true if hook enabled pull request assign event.
  211. func (w *Webhook) HasPullRequestAssignEvent() bool {
  212. return w.SendEverything ||
  213. (w.ChooseEvents && w.HookEvents.PullRequestAssign)
  214. }
  215. // HasPullRequestLabelEvent returns true if hook enabled pull request label event.
  216. func (w *Webhook) HasPullRequestLabelEvent() bool {
  217. return w.SendEverything ||
  218. (w.ChooseEvents && w.HookEvents.PullRequestLabel)
  219. }
  220. // HasPullRequestMilestoneEvent returns true if hook enabled pull request milestone event.
  221. func (w *Webhook) HasPullRequestMilestoneEvent() bool {
  222. return w.SendEverything ||
  223. (w.ChooseEvents && w.HookEvents.PullRequestMilestone)
  224. }
  225. // HasPullRequestCommentEvent returns true if hook enabled pull_request_comment event.
  226. func (w *Webhook) HasPullRequestCommentEvent() bool {
  227. return w.SendEverything ||
  228. (w.ChooseEvents && w.HookEvents.PullRequestComment)
  229. }
  230. // HasPullRequestApprovedEvent returns true if hook enabled pull request review event.
  231. func (w *Webhook) HasPullRequestApprovedEvent() bool {
  232. return w.SendEverything ||
  233. (w.ChooseEvents && w.HookEvents.PullRequestReview)
  234. }
  235. // HasPullRequestRejectedEvent returns true if hook enabled pull request review event.
  236. func (w *Webhook) HasPullRequestRejectedEvent() bool {
  237. return w.SendEverything ||
  238. (w.ChooseEvents && w.HookEvents.PullRequestReview)
  239. }
  240. // HasPullRequestReviewCommentEvent returns true if hook enabled pull request review event.
  241. func (w *Webhook) HasPullRequestReviewCommentEvent() bool {
  242. return w.SendEverything ||
  243. (w.ChooseEvents && w.HookEvents.PullRequestReview)
  244. }
  245. // HasPullRequestSyncEvent returns true if hook enabled pull request sync event.
  246. func (w *Webhook) HasPullRequestSyncEvent() bool {
  247. return w.SendEverything ||
  248. (w.ChooseEvents && w.HookEvents.PullRequestSync)
  249. }
  250. // HasReleaseEvent returns if hook enabled release event.
  251. func (w *Webhook) HasReleaseEvent() bool {
  252. return w.SendEverything ||
  253. (w.ChooseEvents && w.HookEvents.Release)
  254. }
  255. // HasRepositoryEvent returns if hook enabled repository event.
  256. func (w *Webhook) HasRepositoryEvent() bool {
  257. return w.SendEverything ||
  258. (w.ChooseEvents && w.HookEvents.Repository)
  259. }
  260. // EventCheckers returns event checkers
  261. func (w *Webhook) EventCheckers() []struct {
  262. Has func() bool
  263. Type HookEventType
  264. } {
  265. return []struct {
  266. Has func() bool
  267. Type HookEventType
  268. }{
  269. {w.HasCreateEvent, HookEventCreate},
  270. {w.HasDeleteEvent, HookEventDelete},
  271. {w.HasForkEvent, HookEventFork},
  272. {w.HasPushEvent, HookEventPush},
  273. {w.HasIssuesEvent, HookEventIssues},
  274. {w.HasIssuesAssignEvent, HookEventIssueAssign},
  275. {w.HasIssuesLabelEvent, HookEventIssueLabel},
  276. {w.HasIssuesMilestoneEvent, HookEventIssueMilestone},
  277. {w.HasIssueCommentEvent, HookEventIssueComment},
  278. {w.HasPullRequestEvent, HookEventPullRequest},
  279. {w.HasPullRequestAssignEvent, HookEventPullRequestAssign},
  280. {w.HasPullRequestLabelEvent, HookEventPullRequestLabel},
  281. {w.HasPullRequestMilestoneEvent, HookEventPullRequestMilestone},
  282. {w.HasPullRequestCommentEvent, HookEventPullRequestComment},
  283. {w.HasPullRequestApprovedEvent, HookEventPullRequestReviewApproved},
  284. {w.HasPullRequestRejectedEvent, HookEventPullRequestReviewRejected},
  285. {w.HasPullRequestCommentEvent, HookEventPullRequestReviewComment},
  286. {w.HasPullRequestSyncEvent, HookEventPullRequestSync},
  287. {w.HasRepositoryEvent, HookEventRepository},
  288. {w.HasReleaseEvent, HookEventRelease},
  289. }
  290. }
  291. // EventsArray returns an array of hook events
  292. func (w *Webhook) EventsArray() []string {
  293. events := make([]string, 0, 7)
  294. for _, c := range w.EventCheckers() {
  295. if c.Has() {
  296. events = append(events, string(c.Type))
  297. }
  298. }
  299. return events
  300. }
  301. // CreateWebhook creates a new web hook.
  302. func CreateWebhook(w *Webhook) error {
  303. return createWebhook(db.GetEngine(db.DefaultContext), w)
  304. }
  305. func createWebhook(e db.Engine, w *Webhook) error {
  306. w.Type = strings.TrimSpace(w.Type)
  307. _, err := e.Insert(w)
  308. return err
  309. }
  310. // getWebhook uses argument bean as query condition,
  311. // ID must be specified and do not assign unnecessary fields.
  312. func getWebhook(bean *Webhook) (*Webhook, error) {
  313. has, err := db.GetEngine(db.DefaultContext).Get(bean)
  314. if err != nil {
  315. return nil, err
  316. } else if !has {
  317. return nil, ErrWebhookNotExist{bean.ID}
  318. }
  319. return bean, nil
  320. }
  321. // GetWebhookByID returns webhook of repository by given ID.
  322. func GetWebhookByID(id int64) (*Webhook, error) {
  323. return getWebhook(&Webhook{
  324. ID: id,
  325. })
  326. }
  327. // GetWebhookByRepoID returns webhook of repository by given ID.
  328. func GetWebhookByRepoID(repoID, id int64) (*Webhook, error) {
  329. return getWebhook(&Webhook{
  330. ID: id,
  331. RepoID: repoID,
  332. })
  333. }
  334. // GetWebhookByOrgID returns webhook of organization by given ID.
  335. func GetWebhookByOrgID(orgID, id int64) (*Webhook, error) {
  336. return getWebhook(&Webhook{
  337. ID: id,
  338. OrgID: orgID,
  339. })
  340. }
  341. // ListWebhookOptions are options to filter webhooks on ListWebhooksByOpts
  342. type ListWebhookOptions struct {
  343. db.ListOptions
  344. RepoID int64
  345. OrgID int64
  346. IsActive util.OptionalBool
  347. }
  348. func (opts *ListWebhookOptions) toCond() builder.Cond {
  349. cond := builder.NewCond()
  350. if opts.RepoID != 0 {
  351. cond = cond.And(builder.Eq{"webhook.repo_id": opts.RepoID})
  352. }
  353. if opts.OrgID != 0 {
  354. cond = cond.And(builder.Eq{"webhook.org_id": opts.OrgID})
  355. }
  356. if !opts.IsActive.IsNone() {
  357. cond = cond.And(builder.Eq{"webhook.is_active": opts.IsActive.IsTrue()})
  358. }
  359. return cond
  360. }
  361. func listWebhooksByOpts(e db.Engine, opts *ListWebhookOptions) ([]*Webhook, error) {
  362. sess := e.Where(opts.toCond())
  363. if opts.Page != 0 {
  364. sess = db.SetSessionPagination(sess, opts)
  365. webhooks := make([]*Webhook, 0, opts.PageSize)
  366. err := sess.Find(&webhooks)
  367. return webhooks, err
  368. }
  369. webhooks := make([]*Webhook, 0, 10)
  370. err := sess.Find(&webhooks)
  371. return webhooks, err
  372. }
  373. // ListWebhooksByOpts return webhooks based on options
  374. func ListWebhooksByOpts(opts *ListWebhookOptions) ([]*Webhook, error) {
  375. return listWebhooksByOpts(db.GetEngine(db.DefaultContext), opts)
  376. }
  377. // CountWebhooksByOpts count webhooks based on options and ignore pagination
  378. func CountWebhooksByOpts(opts *ListWebhookOptions) (int64, error) {
  379. return db.GetEngine(db.DefaultContext).Where(opts.toCond()).Count(&Webhook{})
  380. }
  381. // GetDefaultWebhooks returns all admin-default webhooks.
  382. func GetDefaultWebhooks() ([]*Webhook, error) {
  383. return getDefaultWebhooks(db.GetEngine(db.DefaultContext))
  384. }
  385. func getDefaultWebhooks(e db.Engine) ([]*Webhook, error) {
  386. webhooks := make([]*Webhook, 0, 5)
  387. return webhooks, e.
  388. Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, false).
  389. Find(&webhooks)
  390. }
  391. // GetSystemOrDefaultWebhook returns admin system or default webhook by given ID.
  392. func GetSystemOrDefaultWebhook(id int64) (*Webhook, error) {
  393. webhook := &Webhook{ID: id}
  394. has, err := db.GetEngine(db.DefaultContext).
  395. Where("repo_id=? AND org_id=?", 0, 0).
  396. Get(webhook)
  397. if err != nil {
  398. return nil, err
  399. } else if !has {
  400. return nil, ErrWebhookNotExist{id}
  401. }
  402. return webhook, nil
  403. }
  404. // GetSystemWebhooks returns all admin system webhooks.
  405. func GetSystemWebhooks() ([]*Webhook, error) {
  406. return getSystemWebhooks(db.GetEngine(db.DefaultContext))
  407. }
  408. func getSystemWebhooks(e db.Engine) ([]*Webhook, error) {
  409. webhooks := make([]*Webhook, 0, 5)
  410. return webhooks, e.
  411. Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, true).
  412. Find(&webhooks)
  413. }
  414. // UpdateWebhook updates information of webhook.
  415. func UpdateWebhook(w *Webhook) error {
  416. _, err := db.GetEngine(db.DefaultContext).ID(w.ID).AllCols().Update(w)
  417. return err
  418. }
  419. // UpdateWebhookLastStatus updates last status of webhook.
  420. func UpdateWebhookLastStatus(w *Webhook) error {
  421. _, err := db.GetEngine(db.DefaultContext).ID(w.ID).Cols("last_status").Update(w)
  422. return err
  423. }
  424. // deleteWebhook uses argument bean as query condition,
  425. // ID must be specified and do not assign unnecessary fields.
  426. func deleteWebhook(bean *Webhook) (err error) {
  427. sess := db.NewSession(db.DefaultContext)
  428. defer sess.Close()
  429. if err = sess.Begin(); err != nil {
  430. return err
  431. }
  432. if count, err := sess.Delete(bean); err != nil {
  433. return err
  434. } else if count == 0 {
  435. return ErrWebhookNotExist{ID: bean.ID}
  436. } else if _, err = sess.Delete(&HookTask{HookID: bean.ID}); err != nil {
  437. return err
  438. }
  439. return sess.Commit()
  440. }
  441. // DeleteWebhookByRepoID deletes webhook of repository by given ID.
  442. func DeleteWebhookByRepoID(repoID, id int64) error {
  443. return deleteWebhook(&Webhook{
  444. ID: id,
  445. RepoID: repoID,
  446. })
  447. }
  448. // DeleteWebhookByOrgID deletes webhook of organization by given ID.
  449. func DeleteWebhookByOrgID(orgID, id int64) error {
  450. return deleteWebhook(&Webhook{
  451. ID: id,
  452. OrgID: orgID,
  453. })
  454. }
  455. // DeleteDefaultSystemWebhook deletes an admin-configured default or system webhook (where Org and Repo ID both 0)
  456. func DeleteDefaultSystemWebhook(id int64) error {
  457. sess := db.NewSession(db.DefaultContext)
  458. defer sess.Close()
  459. if err := sess.Begin(); err != nil {
  460. return err
  461. }
  462. count, err := sess.
  463. Where("repo_id=? AND org_id=?", 0, 0).
  464. Delete(&Webhook{ID: id})
  465. if err != nil {
  466. return err
  467. } else if count == 0 {
  468. return ErrWebhookNotExist{ID: id}
  469. }
  470. if _, err := sess.Delete(&HookTask{HookID: id}); err != nil {
  471. return err
  472. }
  473. return sess.Commit()
  474. }
  475. // copyDefaultWebhooksToRepo creates copies of the default webhooks in a new repo
  476. func copyDefaultWebhooksToRepo(e db.Engine, repoID int64) error {
  477. ws, err := getDefaultWebhooks(e)
  478. if err != nil {
  479. return fmt.Errorf("GetDefaultWebhooks: %v", err)
  480. }
  481. for _, w := range ws {
  482. w.ID = 0
  483. w.RepoID = repoID
  484. if err := createWebhook(e, w); err != nil {
  485. return fmt.Errorf("CreateWebhook: %v", err)
  486. }
  487. }
  488. return nil
  489. }
  490. // ___ ___ __ ___________ __
  491. // / | \ ____ ____ | | _\__ ___/____ _____| | __
  492. // / ~ \/ _ \ / _ \| |/ / | | \__ \ / ___/ |/ /
  493. // \ Y ( <_> | <_> ) < | | / __ \_\___ \| <
  494. // \___|_ / \____/ \____/|__|_ \ |____| (____ /____ >__|_ \
  495. // \/ \/ \/ \/ \/
  496. // HookEventType is the type of an hook event
  497. type HookEventType string
  498. // Types of hook events
  499. const (
  500. HookEventCreate HookEventType = "create"
  501. HookEventDelete HookEventType = "delete"
  502. HookEventFork HookEventType = "fork"
  503. HookEventPush HookEventType = "push"
  504. HookEventIssues HookEventType = "issues"
  505. HookEventIssueAssign HookEventType = "issue_assign"
  506. HookEventIssueLabel HookEventType = "issue_label"
  507. HookEventIssueMilestone HookEventType = "issue_milestone"
  508. HookEventIssueComment HookEventType = "issue_comment"
  509. HookEventPullRequest HookEventType = "pull_request"
  510. HookEventPullRequestAssign HookEventType = "pull_request_assign"
  511. HookEventPullRequestLabel HookEventType = "pull_request_label"
  512. HookEventPullRequestMilestone HookEventType = "pull_request_milestone"
  513. HookEventPullRequestComment HookEventType = "pull_request_comment"
  514. HookEventPullRequestReviewApproved HookEventType = "pull_request_review_approved"
  515. HookEventPullRequestReviewRejected HookEventType = "pull_request_review_rejected"
  516. HookEventPullRequestReviewComment HookEventType = "pull_request_review_comment"
  517. HookEventPullRequestSync HookEventType = "pull_request_sync"
  518. HookEventRepository HookEventType = "repository"
  519. HookEventRelease HookEventType = "release"
  520. )
  521. // Event returns the HookEventType as an event string
  522. func (h HookEventType) Event() string {
  523. switch h {
  524. case HookEventCreate:
  525. return "create"
  526. case HookEventDelete:
  527. return "delete"
  528. case HookEventFork:
  529. return "fork"
  530. case HookEventPush:
  531. return "push"
  532. case HookEventIssues, HookEventIssueAssign, HookEventIssueLabel, HookEventIssueMilestone:
  533. return "issues"
  534. case HookEventPullRequest, HookEventPullRequestAssign, HookEventPullRequestLabel, HookEventPullRequestMilestone,
  535. HookEventPullRequestSync:
  536. return "pull_request"
  537. case HookEventIssueComment, HookEventPullRequestComment:
  538. return "issue_comment"
  539. case HookEventPullRequestReviewApproved:
  540. return "pull_request_approved"
  541. case HookEventPullRequestReviewRejected:
  542. return "pull_request_rejected"
  543. case HookEventPullRequestReviewComment:
  544. return "pull_request_comment"
  545. case HookEventRepository:
  546. return "repository"
  547. case HookEventRelease:
  548. return "release"
  549. }
  550. return ""
  551. }
  552. // HookRequest represents hook task request information.
  553. type HookRequest struct {
  554. URL string `json:"url"`
  555. HTTPMethod string `json:"http_method"`
  556. Headers map[string]string `json:"headers"`
  557. }
  558. // HookResponse represents hook task response information.
  559. type HookResponse struct {
  560. Status int `json:"status"`
  561. Headers map[string]string `json:"headers"`
  562. Body string `json:"body"`
  563. }
  564. // HookTask represents a hook task.
  565. type HookTask struct {
  566. ID int64 `xorm:"pk autoincr"`
  567. RepoID int64 `xorm:"INDEX"`
  568. HookID int64
  569. UUID string
  570. api.Payloader `xorm:"-"`
  571. PayloadContent string `xorm:"TEXT"`
  572. EventType HookEventType
  573. IsDelivered bool
  574. Delivered int64
  575. DeliveredString string `xorm:"-"`
  576. // History info.
  577. IsSucceed bool
  578. RequestContent string `xorm:"TEXT"`
  579. RequestInfo *HookRequest `xorm:"-"`
  580. ResponseContent string `xorm:"TEXT"`
  581. ResponseInfo *HookResponse `xorm:"-"`
  582. }
  583. // BeforeUpdate will be invoked by XORM before updating a record
  584. // representing this object
  585. func (t *HookTask) BeforeUpdate() {
  586. if t.RequestInfo != nil {
  587. t.RequestContent = t.simpleMarshalJSON(t.RequestInfo)
  588. }
  589. if t.ResponseInfo != nil {
  590. t.ResponseContent = t.simpleMarshalJSON(t.ResponseInfo)
  591. }
  592. }
  593. // AfterLoad updates the webhook object upon setting a column
  594. func (t *HookTask) AfterLoad() {
  595. t.DeliveredString = time.Unix(0, t.Delivered).Format("2006-01-02 15:04:05 MST")
  596. if len(t.RequestContent) == 0 {
  597. return
  598. }
  599. t.RequestInfo = &HookRequest{}
  600. if err := json.Unmarshal([]byte(t.RequestContent), t.RequestInfo); err != nil {
  601. log.Error("Unmarshal RequestContent[%d]: %v", t.ID, err)
  602. }
  603. if len(t.ResponseContent) > 0 {
  604. t.ResponseInfo = &HookResponse{}
  605. if err := json.Unmarshal([]byte(t.ResponseContent), t.ResponseInfo); err != nil {
  606. log.Error("Unmarshal ResponseContent[%d]: %v", t.ID, err)
  607. }
  608. }
  609. }
  610. func (t *HookTask) simpleMarshalJSON(v interface{}) string {
  611. p, err := json.Marshal(v)
  612. if err != nil {
  613. log.Error("Marshal [%d]: %v", t.ID, err)
  614. }
  615. return string(p)
  616. }
  617. // HookTasks returns a list of hook tasks by given conditions.
  618. func HookTasks(hookID int64, page int) ([]*HookTask, error) {
  619. tasks := make([]*HookTask, 0, setting.Webhook.PagingNum)
  620. return tasks, db.GetEngine(db.DefaultContext).
  621. Limit(setting.Webhook.PagingNum, (page-1)*setting.Webhook.PagingNum).
  622. Where("hook_id=?", hookID).
  623. Desc("id").
  624. Find(&tasks)
  625. }
  626. // CreateHookTask creates a new hook task,
  627. // it handles conversion from Payload to PayloadContent.
  628. func CreateHookTask(t *HookTask) error {
  629. return createHookTask(db.GetEngine(db.DefaultContext), t)
  630. }
  631. func createHookTask(e db.Engine, t *HookTask) error {
  632. data, err := t.Payloader.JSONPayload()
  633. if err != nil {
  634. return err
  635. }
  636. t.UUID = gouuid.New().String()
  637. t.PayloadContent = string(data)
  638. _, err = e.Insert(t)
  639. return err
  640. }
  641. // UpdateHookTask updates information of hook task.
  642. func UpdateHookTask(t *HookTask) error {
  643. _, err := db.GetEngine(db.DefaultContext).ID(t.ID).AllCols().Update(t)
  644. return err
  645. }
  646. // FindUndeliveredHookTasks represents find the undelivered hook tasks
  647. func FindUndeliveredHookTasks() ([]*HookTask, error) {
  648. tasks := make([]*HookTask, 0, 10)
  649. if err := db.GetEngine(db.DefaultContext).Where("is_delivered=?", false).Find(&tasks); err != nil {
  650. return nil, err
  651. }
  652. return tasks, nil
  653. }
  654. // FindRepoUndeliveredHookTasks represents find the undelivered hook tasks of one repository
  655. func FindRepoUndeliveredHookTasks(repoID int64) ([]*HookTask, error) {
  656. tasks := make([]*HookTask, 0, 5)
  657. if err := db.GetEngine(db.DefaultContext).Where("repo_id=? AND is_delivered=?", repoID, false).Find(&tasks); err != nil {
  658. return nil, err
  659. }
  660. return tasks, nil
  661. }
  662. // CleanupHookTaskTable deletes rows from hook_task as needed.
  663. func CleanupHookTaskTable(ctx context.Context, cleanupType HookTaskCleanupType, olderThan time.Duration, numberToKeep int) error {
  664. log.Trace("Doing: CleanupHookTaskTable")
  665. if cleanupType == OlderThan {
  666. deleteOlderThan := time.Now().Add(-olderThan).UnixNano()
  667. deletes, err := db.GetEngine(db.DefaultContext).
  668. Where("is_delivered = ? and delivered < ?", true, deleteOlderThan).
  669. Delete(new(HookTask))
  670. if err != nil {
  671. return err
  672. }
  673. log.Trace("Deleted %d rows from hook_task", deletes)
  674. } else if cleanupType == PerWebhook {
  675. hookIDs := make([]int64, 0, 10)
  676. err := db.GetEngine(db.DefaultContext).Table("webhook").
  677. Where("id > 0").
  678. Cols("id").
  679. Find(&hookIDs)
  680. if err != nil {
  681. return err
  682. }
  683. for _, hookID := range hookIDs {
  684. select {
  685. case <-ctx.Done():
  686. return ErrCancelledf("Before deleting hook_task records for hook id %d", hookID)
  687. default:
  688. }
  689. if err = deleteDeliveredHookTasksByWebhook(hookID, numberToKeep); err != nil {
  690. return err
  691. }
  692. }
  693. }
  694. log.Trace("Finished: CleanupHookTaskTable")
  695. return nil
  696. }
  697. func deleteDeliveredHookTasksByWebhook(hookID int64, numberDeliveriesToKeep int) error {
  698. log.Trace("Deleting hook_task rows for webhook %d, keeping the most recent %d deliveries", hookID, numberDeliveriesToKeep)
  699. deliveryDates := make([]int64, 0, 10)
  700. err := db.GetEngine(db.DefaultContext).Table("hook_task").
  701. Where("hook_task.hook_id = ? AND hook_task.is_delivered = ? AND hook_task.delivered is not null", hookID, true).
  702. Cols("hook_task.delivered").
  703. Join("INNER", "webhook", "hook_task.hook_id = webhook.id").
  704. OrderBy("hook_task.delivered desc").
  705. Limit(1, int(numberDeliveriesToKeep)).
  706. Find(&deliveryDates)
  707. if err != nil {
  708. return err
  709. }
  710. if len(deliveryDates) > 0 {
  711. deletes, err := db.GetEngine(db.DefaultContext).
  712. Where("hook_id = ? and is_delivered = ? and delivered <= ?", hookID, true, deliveryDates[0]).
  713. Delete(new(HookTask))
  714. if err != nil {
  715. return err
  716. }
  717. log.Trace("Deleted %d hook_task rows for webhook %d", deletes, hookID)
  718. } else {
  719. log.Trace("No hook_task rows to delete for webhook %d", hookID)
  720. }
  721. return nil
  722. }