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