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 5.2 kB

11 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
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package models
  5. import (
  6. "encoding/json"
  7. "errors"
  8. "time"
  9. "github.com/gogits/gogs/modules/httplib"
  10. "github.com/gogits/gogs/modules/log"
  11. "github.com/gogits/gogs/modules/setting"
  12. )
  13. var (
  14. ErrWebhookNotExist = errors.New("Webhook does not exist")
  15. )
  16. type HookContentType int
  17. const (
  18. JSON HookContentType = iota + 1
  19. FORM
  20. )
  21. // HookEvent represents events that will delivery hook.
  22. type HookEvent struct {
  23. PushOnly bool `json:"push_only"`
  24. }
  25. // Webhook represents a web hook object.
  26. type Webhook struct {
  27. Id int64
  28. RepoId int64
  29. Url string `xorm:"TEXT"`
  30. ContentType HookContentType
  31. Secret string `xorm:"TEXT"`
  32. Events string `xorm:"TEXT"`
  33. *HookEvent `xorm:"-"`
  34. IsSsl bool
  35. IsActive bool
  36. }
  37. func (w *Webhook) GetEvent() {
  38. w.HookEvent = &HookEvent{}
  39. if err := json.Unmarshal([]byte(w.Events), w.HookEvent); err != nil {
  40. log.Error("webhook.GetEvent(%d): %v", w.Id, err)
  41. }
  42. }
  43. func (w *Webhook) UpdateEvent() error {
  44. data, err := json.Marshal(w.HookEvent)
  45. w.Events = string(data)
  46. return err
  47. }
  48. func (w *Webhook) HasPushEvent() bool {
  49. if w.PushOnly {
  50. return true
  51. }
  52. return false
  53. }
  54. // CreateWebhook creates a new web hook.
  55. func CreateWebhook(w *Webhook) error {
  56. _, err := orm.Insert(w)
  57. return err
  58. }
  59. // GetWebhookById returns webhook by given ID.
  60. func GetWebhookById(hookId int64) (*Webhook, error) {
  61. w := &Webhook{Id: hookId}
  62. has, err := orm.Get(w)
  63. if err != nil {
  64. return nil, err
  65. } else if !has {
  66. return nil, ErrWebhookNotExist
  67. }
  68. return w, nil
  69. }
  70. // GetActiveWebhooksByRepoId returns all active webhooks of repository.
  71. func GetActiveWebhooksByRepoId(repoId int64) (ws []*Webhook, err error) {
  72. err = orm.Find(&ws, &Webhook{RepoId: repoId, IsActive: true})
  73. return ws, err
  74. }
  75. // GetWebhooksByRepoId returns all webhooks of repository.
  76. func GetWebhooksByRepoId(repoId int64) (ws []*Webhook, err error) {
  77. err = orm.Find(&ws, &Webhook{RepoId: repoId})
  78. return ws, err
  79. }
  80. // UpdateWebhook updates information of webhook.
  81. func UpdateWebhook(w *Webhook) error {
  82. _, err := orm.AllCols().Update(w)
  83. return err
  84. }
  85. // DeleteWebhook deletes webhook of repository.
  86. func DeleteWebhook(hookId int64) error {
  87. _, err := orm.Delete(&Webhook{Id: hookId})
  88. return err
  89. }
  90. // ___ ___ __ ___________ __
  91. // / | \ ____ ____ | | _\__ ___/____ _____| | __
  92. // / ~ \/ _ \ / _ \| |/ / | | \__ \ / ___/ |/ /
  93. // \ Y ( <_> | <_> ) < | | / __ \_\___ \| <
  94. // \___|_ / \____/ \____/|__|_ \ |____| (____ /____ >__|_ \
  95. // \/ \/ \/ \/ \/
  96. type HookTaskType int
  97. const (
  98. WEBHOOK = iota + 1
  99. SERVICE
  100. )
  101. type PayloadAuthor struct {
  102. Name string `json:"name"`
  103. Email string `json:"email"`
  104. }
  105. type PayloadCommit struct {
  106. Id string `json:"id"`
  107. Message string `json:"message"`
  108. Url string `json:"url"`
  109. Author *PayloadAuthor `json:"author"`
  110. }
  111. type PayloadRepo struct {
  112. Id int64 `json:"id"`
  113. Name string `json:"name"`
  114. Url string `json:"url"`
  115. Description string `json:"description"`
  116. Website string `json:"website"`
  117. Watchers int `json:"watchers"`
  118. Owner *PayloadAuthor `json:"author"`
  119. Private bool `json:"private"`
  120. }
  121. // Payload represents payload information of hook.
  122. type Payload struct {
  123. Secret string `json:"secret"`
  124. Ref string `json:"ref"`
  125. Commits []*PayloadCommit `json:"commits"`
  126. Repo *PayloadRepo `json:"repository"`
  127. Pusher *PayloadAuthor `json:"pusher"`
  128. }
  129. // HookTask represents hook task.
  130. type HookTask struct {
  131. Id int64
  132. Type int
  133. Url string
  134. *Payload `xorm:"-"`
  135. PayloadContent string `xorm:"TEXT"`
  136. ContentType HookContentType
  137. IsSsl bool
  138. IsDeliveried bool
  139. }
  140. // CreateHookTask creates a new hook task,
  141. // it handles conversion from Payload to PayloadContent.
  142. func CreateHookTask(t *HookTask) error {
  143. data, err := json.Marshal(t.Payload)
  144. if err != nil {
  145. return err
  146. }
  147. t.PayloadContent = string(data)
  148. _, err = orm.Insert(t)
  149. return err
  150. }
  151. // UpdateHookTask updates information of hook task.
  152. func UpdateHookTask(t *HookTask) error {
  153. _, err := orm.AllCols().Update(t)
  154. return err
  155. }
  156. // DeliverHooks checks and delivers undelivered hooks.
  157. func DeliverHooks() {
  158. timeout := time.Duration(setting.WebhookDeliverTimeout) * time.Second
  159. orm.Where("is_deliveried=?", false).Iterate(new(HookTask),
  160. func(idx int, bean interface{}) error {
  161. t := bean.(*HookTask)
  162. // Only support JSON now.
  163. if _, err := httplib.Post(t.Url).SetTimeout(timeout, timeout).
  164. Body([]byte(t.PayloadContent)).Response(); err != nil {
  165. log.Error("webhook.DeliverHooks(Delivery): %v", err)
  166. return nil
  167. }
  168. t.IsDeliveried = true
  169. if err := UpdateHookTask(t); err != nil {
  170. log.Error("webhook.DeliverHooks(UpdateHookTask): %v", err)
  171. return nil
  172. }
  173. log.Trace("Hook delivered: %s", t.PayloadContent)
  174. return nil
  175. })
  176. }