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.

hook.go 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  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 structs
  6. import (
  7. "encoding/json"
  8. "errors"
  9. "strings"
  10. "time"
  11. )
  12. var (
  13. // ErrInvalidReceiveHook FIXME
  14. ErrInvalidReceiveHook = errors.New("Invalid JSON payload received over webhook")
  15. )
  16. // Hook a hook is a web hook when one repository changed
  17. type Hook struct {
  18. ID int64 `json:"id"`
  19. Type string `json:"type"`
  20. URL string `json:"-"`
  21. Config map[string]string `json:"config"`
  22. Events []string `json:"events"`
  23. Active bool `json:"active"`
  24. // swagger:strfmt date-time
  25. Updated time.Time `json:"updated_at"`
  26. // swagger:strfmt date-time
  27. Created time.Time `json:"created_at"`
  28. }
  29. // HookList represents a list of API hook.
  30. type HookList []*Hook
  31. // CreateHookOptionConfig has all config options in it
  32. // required are "content_type" and "url" Required
  33. type CreateHookOptionConfig map[string]string
  34. // CreateHookOption options when create a hook
  35. type CreateHookOption struct {
  36. // required: true
  37. // enum: dingtalk,discord,gitea,gogs,msteams,slack,telegram,feishu
  38. Type string `json:"type" binding:"Required"`
  39. // required: true
  40. Config CreateHookOptionConfig `json:"config" binding:"Required"`
  41. Events []string `json:"events"`
  42. BranchFilter string `json:"branch_filter" binding:"GlobPattern"`
  43. // default: false
  44. Active bool `json:"active"`
  45. }
  46. // EditHookOption options when modify one hook
  47. type EditHookOption struct {
  48. Config map[string]string `json:"config"`
  49. Events []string `json:"events"`
  50. BranchFilter string `json:"branch_filter" binding:"GlobPattern"`
  51. Active *bool `json:"active"`
  52. }
  53. // Payloader payload is some part of one hook
  54. type Payloader interface {
  55. SetSecret(string)
  56. JSONPayload() ([]byte, error)
  57. }
  58. // PayloadUser represents the author or committer of a commit
  59. type PayloadUser struct {
  60. // Full name of the commit author
  61. Name string `json:"name"`
  62. // swagger:strfmt email
  63. Email string `json:"email"`
  64. UserName string `json:"username"`
  65. }
  66. // FIXME: consider using same format as API when commits API are added.
  67. // applies to PayloadCommit and PayloadCommitVerification
  68. // PayloadCommit represents a commit
  69. type PayloadCommit struct {
  70. // sha1 hash of the commit
  71. ID string `json:"id"`
  72. Message string `json:"message"`
  73. URL string `json:"url"`
  74. Author *PayloadUser `json:"author"`
  75. Committer *PayloadUser `json:"committer"`
  76. Verification *PayloadCommitVerification `json:"verification"`
  77. // swagger:strfmt date-time
  78. Timestamp time.Time `json:"timestamp"`
  79. Added []string `json:"added"`
  80. Removed []string `json:"removed"`
  81. Modified []string `json:"modified"`
  82. }
  83. // PayloadCommitVerification represents the GPG verification of a commit
  84. type PayloadCommitVerification struct {
  85. Verified bool `json:"verified"`
  86. Reason string `json:"reason"`
  87. Signature string `json:"signature"`
  88. Signer *PayloadUser `json:"signer"`
  89. Payload string `json:"payload"`
  90. }
  91. var (
  92. _ Payloader = &CreatePayload{}
  93. _ Payloader = &DeletePayload{}
  94. _ Payloader = &ForkPayload{}
  95. _ Payloader = &PushPayload{}
  96. _ Payloader = &IssuePayload{}
  97. _ Payloader = &IssueCommentPayload{}
  98. _ Payloader = &PullRequestPayload{}
  99. _ Payloader = &RepositoryPayload{}
  100. _ Payloader = &ReleasePayload{}
  101. )
  102. // _________ __
  103. // \_ ___ \_______ ____ _____ _/ |_ ____
  104. // / \ \/\_ __ \_/ __ \\__ \\ __\/ __ \
  105. // \ \____| | \/\ ___/ / __ \| | \ ___/
  106. // \______ /|__| \___ >____ /__| \___ >
  107. // \/ \/ \/ \/
  108. // CreatePayload FIXME
  109. type CreatePayload struct {
  110. Secret string `json:"secret"`
  111. Sha string `json:"sha"`
  112. Ref string `json:"ref"`
  113. RefType string `json:"ref_type"`
  114. Repo *Repository `json:"repository"`
  115. Sender *User `json:"sender"`
  116. }
  117. // SetSecret modifies the secret of the CreatePayload
  118. func (p *CreatePayload) SetSecret(secret string) {
  119. p.Secret = secret
  120. }
  121. // JSONPayload return payload information
  122. func (p *CreatePayload) JSONPayload() ([]byte, error) {
  123. return json.MarshalIndent(p, "", " ")
  124. }
  125. // ParseCreateHook parses create event hook content.
  126. func ParseCreateHook(raw []byte) (*CreatePayload, error) {
  127. hook := new(CreatePayload)
  128. if err := json.Unmarshal(raw, hook); err != nil {
  129. return nil, err
  130. }
  131. // it is possible the JSON was parsed, however,
  132. // was not from Gogs (maybe was from Bitbucket)
  133. // So we'll check to be sure certain key fields
  134. // were populated
  135. switch {
  136. case hook.Repo == nil:
  137. return nil, ErrInvalidReceiveHook
  138. case len(hook.Ref) == 0:
  139. return nil, ErrInvalidReceiveHook
  140. }
  141. return hook, nil
  142. }
  143. // ________ .__ __
  144. // \______ \ ____ | | _____/ |_ ____
  145. // | | \_/ __ \| | _/ __ \ __\/ __ \
  146. // | ` \ ___/| |_\ ___/| | \ ___/
  147. // /_______ /\___ >____/\___ >__| \___ >
  148. // \/ \/ \/ \/
  149. // PusherType define the type to push
  150. type PusherType string
  151. // describe all the PusherTypes
  152. const (
  153. PusherTypeUser PusherType = "user"
  154. )
  155. // DeletePayload represents delete payload
  156. type DeletePayload struct {
  157. Secret string `json:"secret"`
  158. Ref string `json:"ref"`
  159. RefType string `json:"ref_type"`
  160. PusherType PusherType `json:"pusher_type"`
  161. Repo *Repository `json:"repository"`
  162. Sender *User `json:"sender"`
  163. }
  164. // SetSecret modifies the secret of the DeletePayload
  165. func (p *DeletePayload) SetSecret(secret string) {
  166. p.Secret = secret
  167. }
  168. // JSONPayload implements Payload
  169. func (p *DeletePayload) JSONPayload() ([]byte, error) {
  170. return json.MarshalIndent(p, "", " ")
  171. }
  172. // ___________ __
  173. // \_ _____/__________| | __
  174. // | __)/ _ \_ __ \ |/ /
  175. // | \( <_> ) | \/ <
  176. // \___ / \____/|__| |__|_ \
  177. // \/ \/
  178. // ForkPayload represents fork payload
  179. type ForkPayload struct {
  180. Secret string `json:"secret"`
  181. Forkee *Repository `json:"forkee"`
  182. Repo *Repository `json:"repository"`
  183. Sender *User `json:"sender"`
  184. }
  185. // SetSecret modifies the secret of the ForkPayload
  186. func (p *ForkPayload) SetSecret(secret string) {
  187. p.Secret = secret
  188. }
  189. // JSONPayload implements Payload
  190. func (p *ForkPayload) JSONPayload() ([]byte, error) {
  191. return json.MarshalIndent(p, "", " ")
  192. }
  193. // HookIssueCommentAction defines hook issue comment action
  194. type HookIssueCommentAction string
  195. // all issue comment actions
  196. const (
  197. HookIssueCommentCreated HookIssueCommentAction = "created"
  198. HookIssueCommentEdited HookIssueCommentAction = "edited"
  199. HookIssueCommentDeleted HookIssueCommentAction = "deleted"
  200. )
  201. // IssueCommentPayload represents a payload information of issue comment event.
  202. type IssueCommentPayload struct {
  203. Secret string `json:"secret"`
  204. Action HookIssueCommentAction `json:"action"`
  205. Issue *Issue `json:"issue"`
  206. Comment *Comment `json:"comment"`
  207. Changes *ChangesPayload `json:"changes,omitempty"`
  208. Repository *Repository `json:"repository"`
  209. Sender *User `json:"sender"`
  210. IsPull bool `json:"is_pull"`
  211. }
  212. // SetSecret modifies the secret of the IssueCommentPayload
  213. func (p *IssueCommentPayload) SetSecret(secret string) {
  214. p.Secret = secret
  215. }
  216. // JSONPayload implements Payload
  217. func (p *IssueCommentPayload) JSONPayload() ([]byte, error) {
  218. return json.MarshalIndent(p, "", " ")
  219. }
  220. // __________ .__
  221. // \______ \ ____ | | ____ _____ ______ ____
  222. // | _// __ \| | _/ __ \\__ \ / ___// __ \
  223. // | | \ ___/| |_\ ___/ / __ \_\___ \\ ___/
  224. // |____|_ /\___ >____/\___ >____ /____ >\___ >
  225. // \/ \/ \/ \/ \/ \/
  226. // HookReleaseAction defines hook release action type
  227. type HookReleaseAction string
  228. // all release actions
  229. const (
  230. HookReleasePublished HookReleaseAction = "published"
  231. HookReleaseUpdated HookReleaseAction = "updated"
  232. HookReleaseDeleted HookReleaseAction = "deleted"
  233. )
  234. // ReleasePayload represents a payload information of release event.
  235. type ReleasePayload struct {
  236. Secret string `json:"secret"`
  237. Action HookReleaseAction `json:"action"`
  238. Release *Release `json:"release"`
  239. Repository *Repository `json:"repository"`
  240. Sender *User `json:"sender"`
  241. }
  242. // SetSecret modifies the secret of the ReleasePayload
  243. func (p *ReleasePayload) SetSecret(secret string) {
  244. p.Secret = secret
  245. }
  246. // JSONPayload implements Payload
  247. func (p *ReleasePayload) JSONPayload() ([]byte, error) {
  248. return json.MarshalIndent(p, "", " ")
  249. }
  250. // __________ .__
  251. // \______ \__ __ _____| |__
  252. // | ___/ | \/ ___/ | \
  253. // | | | | /\___ \| Y \
  254. // |____| |____//____ >___| /
  255. // \/ \/
  256. // PushPayload represents a payload information of push event.
  257. type PushPayload struct {
  258. Secret string `json:"secret"`
  259. Ref string `json:"ref"`
  260. Before string `json:"before"`
  261. After string `json:"after"`
  262. CompareURL string `json:"compare_url"`
  263. Commits []*PayloadCommit `json:"commits"`
  264. HeadCommit *PayloadCommit `json:"head_commit"`
  265. Repo *Repository `json:"repository"`
  266. Pusher *User `json:"pusher"`
  267. Sender *User `json:"sender"`
  268. }
  269. // SetSecret modifies the secret of the PushPayload
  270. func (p *PushPayload) SetSecret(secret string) {
  271. p.Secret = secret
  272. }
  273. // JSONPayload FIXME
  274. func (p *PushPayload) JSONPayload() ([]byte, error) {
  275. return json.MarshalIndent(p, "", " ")
  276. }
  277. // ParsePushHook parses push event hook content.
  278. func ParsePushHook(raw []byte) (*PushPayload, error) {
  279. hook := new(PushPayload)
  280. if err := json.Unmarshal(raw, hook); err != nil {
  281. return nil, err
  282. }
  283. switch {
  284. case hook.Repo == nil:
  285. return nil, ErrInvalidReceiveHook
  286. case len(hook.Ref) == 0:
  287. return nil, ErrInvalidReceiveHook
  288. }
  289. return hook, nil
  290. }
  291. // Branch returns branch name from a payload
  292. func (p *PushPayload) Branch() string {
  293. return strings.Replace(p.Ref, "refs/heads/", "", -1)
  294. }
  295. // .___
  296. // | | ______ ________ __ ____
  297. // | |/ ___// ___/ | \_/ __ \
  298. // | |\___ \ \___ \| | /\ ___/
  299. // |___/____ >____ >____/ \___ >
  300. // \/ \/ \/
  301. // HookIssueAction FIXME
  302. type HookIssueAction string
  303. const (
  304. // HookIssueOpened opened
  305. HookIssueOpened HookIssueAction = "opened"
  306. // HookIssueClosed closed
  307. HookIssueClosed HookIssueAction = "closed"
  308. // HookIssueReOpened reopened
  309. HookIssueReOpened HookIssueAction = "reopened"
  310. // HookIssueEdited edited
  311. HookIssueEdited HookIssueAction = "edited"
  312. // HookIssueAssigned assigned
  313. HookIssueAssigned HookIssueAction = "assigned"
  314. // HookIssueUnassigned unassigned
  315. HookIssueUnassigned HookIssueAction = "unassigned"
  316. // HookIssueLabelUpdated label_updated
  317. HookIssueLabelUpdated HookIssueAction = "label_updated"
  318. // HookIssueLabelCleared label_cleared
  319. HookIssueLabelCleared HookIssueAction = "label_cleared"
  320. // HookIssueSynchronized synchronized
  321. HookIssueSynchronized HookIssueAction = "synchronized"
  322. // HookIssueMilestoned is an issue action for when a milestone is set on an issue.
  323. HookIssueMilestoned HookIssueAction = "milestoned"
  324. // HookIssueDemilestoned is an issue action for when a milestone is cleared on an issue.
  325. HookIssueDemilestoned HookIssueAction = "demilestoned"
  326. // HookIssueReviewed is an issue action for when a pull request is reviewed
  327. HookIssueReviewed HookIssueAction = "reviewed"
  328. )
  329. // IssuePayload represents the payload information that is sent along with an issue event.
  330. type IssuePayload struct {
  331. Secret string `json:"secret"`
  332. Action HookIssueAction `json:"action"`
  333. Index int64 `json:"number"`
  334. Changes *ChangesPayload `json:"changes,omitempty"`
  335. Issue *Issue `json:"issue"`
  336. Repository *Repository `json:"repository"`
  337. Sender *User `json:"sender"`
  338. }
  339. // SetSecret modifies the secret of the IssuePayload.
  340. func (p *IssuePayload) SetSecret(secret string) {
  341. p.Secret = secret
  342. }
  343. // JSONPayload encodes the IssuePayload to JSON, with an indentation of two spaces.
  344. func (p *IssuePayload) JSONPayload() ([]byte, error) {
  345. return json.MarshalIndent(p, "", " ")
  346. }
  347. // ChangesFromPayload FIXME
  348. type ChangesFromPayload struct {
  349. From string `json:"from"`
  350. }
  351. // ChangesPayload represents the payload information of issue change
  352. type ChangesPayload struct {
  353. Title *ChangesFromPayload `json:"title,omitempty"`
  354. Body *ChangesFromPayload `json:"body,omitempty"`
  355. Ref *ChangesFromPayload `json:"ref,omitempty"`
  356. }
  357. // __________ .__ .__ __________ __
  358. // \______ \__ __| | | | \______ \ ____ ________ __ ____ _______/ |_
  359. // | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\
  360. // | | | | / |_| |__ | | \ ___< <_| | | /\ ___/ \___ \ | |
  361. // |____| |____/|____/____/ |____|_ /\___ >__ |____/ \___ >____ > |__|
  362. // \/ \/ |__| \/ \/
  363. // PullRequestPayload represents a payload information of pull request event.
  364. type PullRequestPayload struct {
  365. Secret string `json:"secret"`
  366. Action HookIssueAction `json:"action"`
  367. Index int64 `json:"number"`
  368. Changes *ChangesPayload `json:"changes,omitempty"`
  369. PullRequest *PullRequest `json:"pull_request"`
  370. Repository *Repository `json:"repository"`
  371. Sender *User `json:"sender"`
  372. Review *ReviewPayload `json:"review"`
  373. }
  374. // SetSecret modifies the secret of the PullRequestPayload.
  375. func (p *PullRequestPayload) SetSecret(secret string) {
  376. p.Secret = secret
  377. }
  378. // JSONPayload FIXME
  379. func (p *PullRequestPayload) JSONPayload() ([]byte, error) {
  380. return json.MarshalIndent(p, "", " ")
  381. }
  382. // ReviewPayload FIXME
  383. type ReviewPayload struct {
  384. Type string `json:"type"`
  385. Content string `json:"content"`
  386. }
  387. //__________ .__ __
  388. //\______ \ ____ ______ ____ _____|__|/ |_ ___________ ___.__.
  389. // | _// __ \\____ \ / _ \/ ___/ \ __\/ _ \_ __ < | |
  390. // | | \ ___/| |_> > <_> )___ \| || | ( <_> ) | \/\___ |
  391. // |____|_ /\___ > __/ \____/____ >__||__| \____/|__| / ____|
  392. // \/ \/|__| \/ \/
  393. // HookRepoAction an action that happens to a repo
  394. type HookRepoAction string
  395. const (
  396. // HookRepoCreated created
  397. HookRepoCreated HookRepoAction = "created"
  398. // HookRepoDeleted deleted
  399. HookRepoDeleted HookRepoAction = "deleted"
  400. )
  401. // RepositoryPayload payload for repository webhooks
  402. type RepositoryPayload struct {
  403. Secret string `json:"secret"`
  404. Action HookRepoAction `json:"action"`
  405. Repository *Repository `json:"repository"`
  406. Organization *User `json:"organization"`
  407. Sender *User `json:"sender"`
  408. }
  409. // SetSecret modifies the secret of the RepositoryPayload
  410. func (p *RepositoryPayload) SetSecret(secret string) {
  411. p.Secret = secret
  412. }
  413. // JSONPayload JSON representation of the payload
  414. func (p *RepositoryPayload) JSONPayload() ([]byte, error) {
  415. return json.MarshalIndent(p, "", " ")
  416. }