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 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Copyright 2017 The Gitea Authors. All rights reserved.
  3. // SPDX-License-Identifier: MIT
  4. package structs
  5. import (
  6. "errors"
  7. "strings"
  8. "time"
  9. "code.gitea.io/gitea/modules/json"
  10. )
  11. // ErrInvalidReceiveHook FIXME
  12. var ErrInvalidReceiveHook = errors.New("Invalid JSON payload received over webhook")
  13. // Hook a hook is a web hook when one repository changed
  14. type Hook struct {
  15. ID int64 `json:"id"`
  16. Type string `json:"type"`
  17. BranchFilter string `json:"branch_filter"`
  18. URL string `json:"-"`
  19. Config map[string]string `json:"config"`
  20. Events []string `json:"events"`
  21. AuthorizationHeader string `json:"authorization_header"`
  22. Active bool `json:"active"`
  23. // swagger:strfmt date-time
  24. Updated time.Time `json:"updated_at"`
  25. // swagger:strfmt date-time
  26. Created time.Time `json:"created_at"`
  27. }
  28. // HookList represents a list of API hook.
  29. type HookList []*Hook
  30. // CreateHookOptionConfig has all config options in it
  31. // required are "content_type" and "url" Required
  32. type CreateHookOptionConfig map[string]string
  33. // CreateHookOption options when create a hook
  34. type CreateHookOption struct {
  35. // required: true
  36. // enum: dingtalk,discord,gitea,gogs,msteams,slack,telegram,feishu,wechatwork,packagist
  37. Type string `json:"type" binding:"Required"`
  38. // required: true
  39. Config CreateHookOptionConfig `json:"config" binding:"Required"`
  40. Events []string `json:"events"`
  41. BranchFilter string `json:"branch_filter" binding:"GlobPattern"`
  42. AuthorizationHeader string `json:"authorization_header"`
  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. AuthorizationHeader string `json:"authorization_header"`
  52. Active *bool `json:"active"`
  53. }
  54. // Payloader payload is some part of one hook
  55. type Payloader interface {
  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. _ Payloader = &PackagePayload{}
  102. )
  103. // _________ __
  104. // \_ ___ \_______ ____ _____ _/ |_ ____
  105. // / \ \/\_ __ \_/ __ \\__ \\ __\/ __ \
  106. // \ \____| | \/\ ___/ / __ \| | \ ___/
  107. // \______ /|__| \___ >____ /__| \___ >
  108. // \/ \/ \/ \/
  109. // CreatePayload FIXME
  110. type CreatePayload struct {
  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. // JSONPayload return payload information
  118. func (p *CreatePayload) JSONPayload() ([]byte, error) {
  119. return json.MarshalIndent(p, "", " ")
  120. }
  121. // ParseCreateHook parses create event hook content.
  122. func ParseCreateHook(raw []byte) (*CreatePayload, error) {
  123. hook := new(CreatePayload)
  124. if err := json.Unmarshal(raw, hook); err != nil {
  125. return nil, err
  126. }
  127. // it is possible the JSON was parsed, however,
  128. // was not from Gogs (maybe was from Bitbucket)
  129. // So we'll check to be sure certain key fields
  130. // were populated
  131. switch {
  132. case hook.Repo == nil:
  133. return nil, ErrInvalidReceiveHook
  134. case len(hook.Ref) == 0:
  135. return nil, ErrInvalidReceiveHook
  136. }
  137. return hook, nil
  138. }
  139. // ________ .__ __
  140. // \______ \ ____ | | _____/ |_ ____
  141. // | | \_/ __ \| | _/ __ \ __\/ __ \
  142. // | ` \ ___/| |_\ ___/| | \ ___/
  143. // /_______ /\___ >____/\___ >__| \___ >
  144. // \/ \/ \/ \/
  145. // PusherType define the type to push
  146. type PusherType string
  147. // describe all the PusherTypes
  148. const (
  149. PusherTypeUser PusherType = "user"
  150. )
  151. // DeletePayload represents delete payload
  152. type DeletePayload struct {
  153. Ref string `json:"ref"`
  154. RefType string `json:"ref_type"`
  155. PusherType PusherType `json:"pusher_type"`
  156. Repo *Repository `json:"repository"`
  157. Sender *User `json:"sender"`
  158. }
  159. // JSONPayload implements Payload
  160. func (p *DeletePayload) JSONPayload() ([]byte, error) {
  161. return json.MarshalIndent(p, "", " ")
  162. }
  163. // ___________ __
  164. // \_ _____/__________| | __
  165. // | __)/ _ \_ __ \ |/ /
  166. // | \( <_> ) | \/ <
  167. // \___ / \____/|__| |__|_ \
  168. // \/ \/
  169. // ForkPayload represents fork payload
  170. type ForkPayload struct {
  171. Forkee *Repository `json:"forkee"`
  172. Repo *Repository `json:"repository"`
  173. Sender *User `json:"sender"`
  174. }
  175. // JSONPayload implements Payload
  176. func (p *ForkPayload) JSONPayload() ([]byte, error) {
  177. return json.MarshalIndent(p, "", " ")
  178. }
  179. // HookIssueCommentAction defines hook issue comment action
  180. type HookIssueCommentAction string
  181. // all issue comment actions
  182. const (
  183. HookIssueCommentCreated HookIssueCommentAction = "created"
  184. HookIssueCommentEdited HookIssueCommentAction = "edited"
  185. HookIssueCommentDeleted HookIssueCommentAction = "deleted"
  186. )
  187. // IssueCommentPayload represents a payload information of issue comment event.
  188. type IssueCommentPayload struct {
  189. Action HookIssueCommentAction `json:"action"`
  190. Issue *Issue `json:"issue"`
  191. Comment *Comment `json:"comment"`
  192. Changes *ChangesPayload `json:"changes,omitempty"`
  193. Repository *Repository `json:"repository"`
  194. Sender *User `json:"sender"`
  195. IsPull bool `json:"is_pull"`
  196. }
  197. // JSONPayload implements Payload
  198. func (p *IssueCommentPayload) JSONPayload() ([]byte, error) {
  199. return json.MarshalIndent(p, "", " ")
  200. }
  201. // __________ .__
  202. // \______ \ ____ | | ____ _____ ______ ____
  203. // | _// __ \| | _/ __ \\__ \ / ___// __ \
  204. // | | \ ___/| |_\ ___/ / __ \_\___ \\ ___/
  205. // |____|_ /\___ >____/\___ >____ /____ >\___ >
  206. // \/ \/ \/ \/ \/ \/
  207. // HookReleaseAction defines hook release action type
  208. type HookReleaseAction string
  209. // all release actions
  210. const (
  211. HookReleasePublished HookReleaseAction = "published"
  212. HookReleaseUpdated HookReleaseAction = "updated"
  213. HookReleaseDeleted HookReleaseAction = "deleted"
  214. )
  215. // ReleasePayload represents a payload information of release event.
  216. type ReleasePayload struct {
  217. Action HookReleaseAction `json:"action"`
  218. Release *Release `json:"release"`
  219. Repository *Repository `json:"repository"`
  220. Sender *User `json:"sender"`
  221. }
  222. // JSONPayload implements Payload
  223. func (p *ReleasePayload) JSONPayload() ([]byte, error) {
  224. return json.MarshalIndent(p, "", " ")
  225. }
  226. // __________ .__
  227. // \______ \__ __ _____| |__
  228. // | ___/ | \/ ___/ | \
  229. // | | | | /\___ \| Y \
  230. // |____| |____//____ >___| /
  231. // \/ \/
  232. // PushPayload represents a payload information of push event.
  233. type PushPayload struct {
  234. Ref string `json:"ref"`
  235. Before string `json:"before"`
  236. After string `json:"after"`
  237. CompareURL string `json:"compare_url"`
  238. Commits []*PayloadCommit `json:"commits"`
  239. TotalCommits int `json:"total_commits"`
  240. HeadCommit *PayloadCommit `json:"head_commit"`
  241. Repo *Repository `json:"repository"`
  242. Pusher *User `json:"pusher"`
  243. Sender *User `json:"sender"`
  244. }
  245. // JSONPayload FIXME
  246. func (p *PushPayload) JSONPayload() ([]byte, error) {
  247. return json.MarshalIndent(p, "", " ")
  248. }
  249. // ParsePushHook parses push event hook content.
  250. func ParsePushHook(raw []byte) (*PushPayload, error) {
  251. hook := new(PushPayload)
  252. if err := json.Unmarshal(raw, hook); err != nil {
  253. return nil, err
  254. }
  255. switch {
  256. case hook.Repo == nil:
  257. return nil, ErrInvalidReceiveHook
  258. case len(hook.Ref) == 0:
  259. return nil, ErrInvalidReceiveHook
  260. }
  261. return hook, nil
  262. }
  263. // Branch returns branch name from a payload
  264. func (p *PushPayload) Branch() string {
  265. return strings.ReplaceAll(p.Ref, "refs/heads/", "")
  266. }
  267. // .___
  268. // | | ______ ________ __ ____
  269. // | |/ ___// ___/ | \_/ __ \
  270. // | |\___ \ \___ \| | /\ ___/
  271. // |___/____ >____ >____/ \___ >
  272. // \/ \/ \/
  273. // HookIssueAction FIXME
  274. type HookIssueAction string
  275. const (
  276. // HookIssueOpened opened
  277. HookIssueOpened HookIssueAction = "opened"
  278. // HookIssueClosed closed
  279. HookIssueClosed HookIssueAction = "closed"
  280. // HookIssueReOpened reopened
  281. HookIssueReOpened HookIssueAction = "reopened"
  282. // HookIssueEdited edited
  283. HookIssueEdited HookIssueAction = "edited"
  284. // HookIssueAssigned assigned
  285. HookIssueAssigned HookIssueAction = "assigned"
  286. // HookIssueUnassigned unassigned
  287. HookIssueUnassigned HookIssueAction = "unassigned"
  288. // HookIssueLabelUpdated label_updated
  289. HookIssueLabelUpdated HookIssueAction = "label_updated"
  290. // HookIssueLabelCleared label_cleared
  291. HookIssueLabelCleared HookIssueAction = "label_cleared"
  292. // HookIssueSynchronized synchronized
  293. HookIssueSynchronized HookIssueAction = "synchronized"
  294. // HookIssueMilestoned is an issue action for when a milestone is set on an issue.
  295. HookIssueMilestoned HookIssueAction = "milestoned"
  296. // HookIssueDemilestoned is an issue action for when a milestone is cleared on an issue.
  297. HookIssueDemilestoned HookIssueAction = "demilestoned"
  298. // HookIssueReviewed is an issue action for when a pull request is reviewed
  299. HookIssueReviewed HookIssueAction = "reviewed"
  300. // HookIssueReviewRequested is an issue action for when a reviewer is requested for a pull request.
  301. HookIssueReviewRequested HookIssueAction = "review_requested"
  302. // HookIssueReviewRequestRemoved is an issue action for removing a review request to someone on a pull request.
  303. HookIssueReviewRequestRemoved HookIssueAction = "review_request_removed"
  304. )
  305. // IssuePayload represents the payload information that is sent along with an issue event.
  306. type IssuePayload struct {
  307. Action HookIssueAction `json:"action"`
  308. Index int64 `json:"number"`
  309. Changes *ChangesPayload `json:"changes,omitempty"`
  310. Issue *Issue `json:"issue"`
  311. Repository *Repository `json:"repository"`
  312. Sender *User `json:"sender"`
  313. CommitID string `json:"commit_id"`
  314. }
  315. // JSONPayload encodes the IssuePayload to JSON, with an indentation of two spaces.
  316. func (p *IssuePayload) JSONPayload() ([]byte, error) {
  317. return json.MarshalIndent(p, "", " ")
  318. }
  319. // ChangesFromPayload FIXME
  320. type ChangesFromPayload struct {
  321. From string `json:"from"`
  322. }
  323. // ChangesPayload represents the payload information of issue change
  324. type ChangesPayload struct {
  325. Title *ChangesFromPayload `json:"title,omitempty"`
  326. Body *ChangesFromPayload `json:"body,omitempty"`
  327. Ref *ChangesFromPayload `json:"ref,omitempty"`
  328. }
  329. // __________ .__ .__ __________ __
  330. // \______ \__ __| | | | \______ \ ____ ________ __ ____ _______/ |_
  331. // | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\
  332. // | | | | / |_| |__ | | \ ___< <_| | | /\ ___/ \___ \ | |
  333. // |____| |____/|____/____/ |____|_ /\___ >__ |____/ \___ >____ > |__|
  334. // \/ \/ |__| \/ \/
  335. // PullRequestPayload represents a payload information of pull request event.
  336. type PullRequestPayload struct {
  337. Action HookIssueAction `json:"action"`
  338. Index int64 `json:"number"`
  339. Changes *ChangesPayload `json:"changes,omitempty"`
  340. PullRequest *PullRequest `json:"pull_request"`
  341. RequestedReviewer *User `json:"requested_reviewer"`
  342. Repository *Repository `json:"repository"`
  343. Sender *User `json:"sender"`
  344. CommitID string `json:"commit_id"`
  345. Review *ReviewPayload `json:"review"`
  346. }
  347. // JSONPayload FIXME
  348. func (p *PullRequestPayload) JSONPayload() ([]byte, error) {
  349. return json.MarshalIndent(p, "", " ")
  350. }
  351. // ReviewPayload FIXME
  352. type ReviewPayload struct {
  353. Type string `json:"type"`
  354. Content string `json:"content"`
  355. }
  356. // __ __.__ __ .__
  357. // / \ / \__| | _|__|
  358. // \ \/\/ / | |/ / |
  359. // \ /| | <| |
  360. // \__/\ / |__|__|_ \__|
  361. // \/ \/
  362. // HookWikiAction an action that happens to a wiki page
  363. type HookWikiAction string
  364. const (
  365. // HookWikiCreated created
  366. HookWikiCreated HookWikiAction = "created"
  367. // HookWikiEdited edited
  368. HookWikiEdited HookWikiAction = "edited"
  369. // HookWikiDeleted deleted
  370. HookWikiDeleted HookWikiAction = "deleted"
  371. )
  372. // WikiPayload payload for repository webhooks
  373. type WikiPayload struct {
  374. Action HookWikiAction `json:"action"`
  375. Repository *Repository `json:"repository"`
  376. Sender *User `json:"sender"`
  377. Page string `json:"page"`
  378. Comment string `json:"comment"`
  379. }
  380. // JSONPayload JSON representation of the payload
  381. func (p *WikiPayload) JSONPayload() ([]byte, error) {
  382. return json.MarshalIndent(p, "", " ")
  383. }
  384. //__________ .__ __
  385. //\______ \ ____ ______ ____ _____|__|/ |_ ___________ ___.__.
  386. // | _// __ \\____ \ / _ \/ ___/ \ __\/ _ \_ __ < | |
  387. // | | \ ___/| |_> > <_> )___ \| || | ( <_> ) | \/\___ |
  388. // |____|_ /\___ > __/ \____/____ >__||__| \____/|__| / ____|
  389. // \/ \/|__| \/ \/
  390. // HookRepoAction an action that happens to a repo
  391. type HookRepoAction string
  392. const (
  393. // HookRepoCreated created
  394. HookRepoCreated HookRepoAction = "created"
  395. // HookRepoDeleted deleted
  396. HookRepoDeleted HookRepoAction = "deleted"
  397. )
  398. // RepositoryPayload payload for repository webhooks
  399. type RepositoryPayload struct {
  400. Action HookRepoAction `json:"action"`
  401. Repository *Repository `json:"repository"`
  402. Organization *User `json:"organization"`
  403. Sender *User `json:"sender"`
  404. }
  405. // JSONPayload JSON representation of the payload
  406. func (p *RepositoryPayload) JSONPayload() ([]byte, error) {
  407. return json.MarshalIndent(p, "", " ")
  408. }
  409. // HookPackageAction an action that happens to a package
  410. type HookPackageAction string
  411. const (
  412. // HookPackageCreated created
  413. HookPackageCreated HookPackageAction = "created"
  414. // HookPackageDeleted deleted
  415. HookPackageDeleted HookPackageAction = "deleted"
  416. )
  417. // PackagePayload represents a package payload
  418. type PackagePayload struct {
  419. Action HookPackageAction `json:"action"`
  420. Repository *Repository `json:"repository"`
  421. Package *Package `json:"package"`
  422. Organization *User `json:"organization"`
  423. Sender *User `json:"sender"`
  424. }
  425. // JSONPayload implements Payload
  426. func (p *PackagePayload) JSONPayload() ([]byte, error) {
  427. return json.MarshalIndent(p, "", " ")
  428. }