From b079f4081f8b9de1178e23b1590d0c4042fa6d50 Mon Sep 17 00:00:00 2001 From: Max Stanley Date: Sun, 12 Nov 2023 10:29:07 +0000 Subject: [PATCH] Split hook --- modules/structs/hook.go | 432 -------------------------------- modules/structs/hook_issue.go | 103 ++++++++ modules/structs/hook_package.go | 29 +++ modules/structs/hook_pr.go | 36 +++ modules/structs/hook_release.go | 35 +++ modules/structs/hook_repo.go | 219 ++++++++++++++++ modules/structs/hook_wiki.go | 38 +++ modules/webhook/structs.go | 37 +++ routers/api/v1/utils/hook.go | 58 +---- 9 files changed, 499 insertions(+), 488 deletions(-) create mode 100644 modules/structs/hook_issue.go create mode 100644 modules/structs/hook_package.go create mode 100644 modules/structs/hook_pr.go create mode 100644 modules/structs/hook_release.go create mode 100644 modules/structs/hook_repo.go create mode 100644 modules/structs/hook_wiki.go diff --git a/modules/structs/hook.go b/modules/structs/hook.go index 0babe844101a1..bc866173ecbef 100644 --- a/modules/structs/hook.go +++ b/modules/structs/hook.go @@ -6,10 +6,7 @@ package structs import ( "errors" - "strings" "time" - - "code.gitea.io/gitea/modules/json" ) // ErrInvalidReceiveHook FIXME @@ -65,432 +62,3 @@ type EditHookOption struct { type Payloader interface { JSONPayload() ([]byte, error) } - -// PayloadUser represents the author or committer of a commit -type PayloadUser struct { - // Full name of the commit author - Name string `json:"name"` - // swagger:strfmt email - Email string `json:"email"` - UserName string `json:"username"` -} - -// FIXME: consider using same format as API when commits API are added. -// applies to PayloadCommit and PayloadCommitVerification - -// PayloadCommit represents a commit -type PayloadCommit struct { - // sha1 hash of the commit - ID string `json:"id"` - Message string `json:"message"` - URL string `json:"url"` - Author *PayloadUser `json:"author"` - Committer *PayloadUser `json:"committer"` - Verification *PayloadCommitVerification `json:"verification"` - // swagger:strfmt date-time - Timestamp time.Time `json:"timestamp"` - Added []string `json:"added"` - Removed []string `json:"removed"` - Modified []string `json:"modified"` -} - -// PayloadCommitVerification represents the GPG verification of a commit -type PayloadCommitVerification struct { - Verified bool `json:"verified"` - Reason string `json:"reason"` - Signature string `json:"signature"` - Signer *PayloadUser `json:"signer"` - Payload string `json:"payload"` -} - -var ( - _ Payloader = &CreatePayload{} - _ Payloader = &DeletePayload{} - _ Payloader = &ForkPayload{} - _ Payloader = &PushPayload{} - _ Payloader = &IssuePayload{} - _ Payloader = &IssueCommentPayload{} - _ Payloader = &PullRequestPayload{} - _ Payloader = &RepositoryPayload{} - _ Payloader = &ReleasePayload{} - _ Payloader = &PackagePayload{} -) - -// _________ __ -// \_ ___ \_______ ____ _____ _/ |_ ____ -// / \ \/\_ __ \_/ __ \\__ \\ __\/ __ \ -// \ \____| | \/\ ___/ / __ \| | \ ___/ -// \______ /|__| \___ >____ /__| \___ > -// \/ \/ \/ \/ - -// CreatePayload FIXME -type CreatePayload struct { - Sha string `json:"sha"` - Ref string `json:"ref"` - RefType string `json:"ref_type"` - Repo *Repository `json:"repository"` - Sender *User `json:"sender"` -} - -// JSONPayload return payload information -func (p *CreatePayload) JSONPayload() ([]byte, error) { - return json.MarshalIndent(p, "", " ") -} - -// ParseCreateHook parses create event hook content. -func ParseCreateHook(raw []byte) (*CreatePayload, error) { - hook := new(CreatePayload) - if err := json.Unmarshal(raw, hook); err != nil { - return nil, err - } - - // it is possible the JSON was parsed, however, - // was not from Gogs (maybe was from Bitbucket) - // So we'll check to be sure certain key fields - // were populated - switch { - case hook.Repo == nil: - return nil, ErrInvalidReceiveHook - case len(hook.Ref) == 0: - return nil, ErrInvalidReceiveHook - } - return hook, nil -} - -// ________ .__ __ -// \______ \ ____ | | _____/ |_ ____ -// | | \_/ __ \| | _/ __ \ __\/ __ \ -// | ` \ ___/| |_\ ___/| | \ ___/ -// /_______ /\___ >____/\___ >__| \___ > -// \/ \/ \/ \/ - -// PusherType define the type to push -type PusherType string - -// describe all the PusherTypes -const ( - PusherTypeUser PusherType = "user" -) - -// DeletePayload represents delete payload -type DeletePayload struct { - Ref string `json:"ref"` - RefType string `json:"ref_type"` - PusherType PusherType `json:"pusher_type"` - Repo *Repository `json:"repository"` - Sender *User `json:"sender"` -} - -// JSONPayload implements Payload -func (p *DeletePayload) JSONPayload() ([]byte, error) { - return json.MarshalIndent(p, "", " ") -} - -// ___________ __ -// \_ _____/__________| | __ -// | __)/ _ \_ __ \ |/ / -// | \( <_> ) | \/ < -// \___ / \____/|__| |__|_ \ -// \/ \/ - -// ForkPayload represents fork payload -type ForkPayload struct { - Forkee *Repository `json:"forkee"` - Repo *Repository `json:"repository"` - Sender *User `json:"sender"` -} - -// JSONPayload implements Payload -func (p *ForkPayload) JSONPayload() ([]byte, error) { - return json.MarshalIndent(p, "", " ") -} - -// HookIssueCommentAction defines hook issue comment action -type HookIssueCommentAction string - -// all issue comment actions -const ( - HookIssueCommentCreated HookIssueCommentAction = "created" - HookIssueCommentEdited HookIssueCommentAction = "edited" - HookIssueCommentDeleted HookIssueCommentAction = "deleted" -) - -// IssueCommentPayload represents a payload information of issue comment event. -type IssueCommentPayload struct { - Action HookIssueCommentAction `json:"action"` - Issue *Issue `json:"issue"` - Comment *Comment `json:"comment"` - Changes *ChangesPayload `json:"changes,omitempty"` - Repository *Repository `json:"repository"` - Sender *User `json:"sender"` - IsPull bool `json:"is_pull"` -} - -// JSONPayload implements Payload -func (p *IssueCommentPayload) JSONPayload() ([]byte, error) { - return json.MarshalIndent(p, "", " ") -} - -// __________ .__ -// \______ \ ____ | | ____ _____ ______ ____ -// | _// __ \| | _/ __ \\__ \ / ___// __ \ -// | | \ ___/| |_\ ___/ / __ \_\___ \\ ___/ -// |____|_ /\___ >____/\___ >____ /____ >\___ > -// \/ \/ \/ \/ \/ \/ - -// HookReleaseAction defines hook release action type -type HookReleaseAction string - -// all release actions -const ( - HookReleasePublished HookReleaseAction = "published" - HookReleaseUpdated HookReleaseAction = "updated" - HookReleaseDeleted HookReleaseAction = "deleted" -) - -// ReleasePayload represents a payload information of release event. -type ReleasePayload struct { - Action HookReleaseAction `json:"action"` - Release *Release `json:"release"` - Repository *Repository `json:"repository"` - Sender *User `json:"sender"` -} - -// JSONPayload implements Payload -func (p *ReleasePayload) JSONPayload() ([]byte, error) { - return json.MarshalIndent(p, "", " ") -} - -// __________ .__ -// \______ \__ __ _____| |__ -// | ___/ | \/ ___/ | \ -// | | | | /\___ \| Y \ -// |____| |____//____ >___| / -// \/ \/ - -// PushPayload represents a payload information of push event. -type PushPayload struct { - Ref string `json:"ref"` - Before string `json:"before"` - After string `json:"after"` - CompareURL string `json:"compare_url"` - Commits []*PayloadCommit `json:"commits"` - TotalCommits int `json:"total_commits"` - HeadCommit *PayloadCommit `json:"head_commit"` - Repo *Repository `json:"repository"` - Pusher *User `json:"pusher"` - Sender *User `json:"sender"` -} - -// JSONPayload FIXME -func (p *PushPayload) JSONPayload() ([]byte, error) { - return json.MarshalIndent(p, "", " ") -} - -// ParsePushHook parses push event hook content. -func ParsePushHook(raw []byte) (*PushPayload, error) { - hook := new(PushPayload) - if err := json.Unmarshal(raw, hook); err != nil { - return nil, err - } - - switch { - case hook.Repo == nil: - return nil, ErrInvalidReceiveHook - case len(hook.Ref) == 0: - return nil, ErrInvalidReceiveHook - } - return hook, nil -} - -// Branch returns branch name from a payload -func (p *PushPayload) Branch() string { - return strings.ReplaceAll(p.Ref, "refs/heads/", "") -} - -// .___ -// | | ______ ________ __ ____ -// | |/ ___// ___/ | \_/ __ \ -// | |\___ \ \___ \| | /\ ___/ -// |___/____ >____ >____/ \___ > -// \/ \/ \/ - -// HookIssueAction FIXME -type HookIssueAction string - -const ( - // HookIssueOpened opened - HookIssueOpened HookIssueAction = "opened" - // HookIssueClosed closed - HookIssueClosed HookIssueAction = "closed" - // HookIssueReOpened reopened - HookIssueReOpened HookIssueAction = "reopened" - // HookIssueEdited edited - HookIssueEdited HookIssueAction = "edited" - // HookIssueAssigned assigned - HookIssueAssigned HookIssueAction = "assigned" - // HookIssueUnassigned unassigned - HookIssueUnassigned HookIssueAction = "unassigned" - // HookIssueLabelUpdated label_updated - HookIssueLabelUpdated HookIssueAction = "label_updated" - // HookIssueLabelCleared label_cleared - HookIssueLabelCleared HookIssueAction = "label_cleared" - // HookIssueSynchronized synchronized - HookIssueSynchronized HookIssueAction = "synchronized" - // HookIssueMilestoned is an issue action for when a milestone is set on an issue. - HookIssueMilestoned HookIssueAction = "milestoned" - // HookIssueDemilestoned is an issue action for when a milestone is cleared on an issue. - HookIssueDemilestoned HookIssueAction = "demilestoned" - // HookIssueReviewed is an issue action for when a pull request is reviewed - HookIssueReviewed HookIssueAction = "reviewed" - // HookIssueReviewRequested is an issue action for when a reviewer is requested for a pull request. - HookIssueReviewRequested HookIssueAction = "review_requested" - // HookIssueReviewRequestRemoved is an issue action for removing a review request to someone on a pull request. - HookIssueReviewRequestRemoved HookIssueAction = "review_request_removed" -) - -// IssuePayload represents the payload information that is sent along with an issue event. -type IssuePayload struct { - Action HookIssueAction `json:"action"` - Index int64 `json:"number"` - Changes *ChangesPayload `json:"changes,omitempty"` - Issue *Issue `json:"issue"` - Repository *Repository `json:"repository"` - Sender *User `json:"sender"` - CommitID string `json:"commit_id"` -} - -// JSONPayload encodes the IssuePayload to JSON, with an indentation of two spaces. -func (p *IssuePayload) JSONPayload() ([]byte, error) { - return json.MarshalIndent(p, "", " ") -} - -// ChangesFromPayload FIXME -type ChangesFromPayload struct { - From string `json:"from"` -} - -// ChangesPayload represents the payload information of issue change -type ChangesPayload struct { - Title *ChangesFromPayload `json:"title,omitempty"` - Body *ChangesFromPayload `json:"body,omitempty"` - Ref *ChangesFromPayload `json:"ref,omitempty"` -} - -// __________ .__ .__ __________ __ -// \______ \__ __| | | | \______ \ ____ ________ __ ____ _______/ |_ -// | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\ -// | | | | / |_| |__ | | \ ___< <_| | | /\ ___/ \___ \ | | -// |____| |____/|____/____/ |____|_ /\___ >__ |____/ \___ >____ > |__| -// \/ \/ |__| \/ \/ - -// PullRequestPayload represents a payload information of pull request event. -type PullRequestPayload struct { - Action HookIssueAction `json:"action"` - Index int64 `json:"number"` - Changes *ChangesPayload `json:"changes,omitempty"` - PullRequest *PullRequest `json:"pull_request"` - RequestedReviewer *User `json:"requested_reviewer"` - Repository *Repository `json:"repository"` - Sender *User `json:"sender"` - CommitID string `json:"commit_id"` - Review *ReviewPayload `json:"review"` -} - -// JSONPayload FIXME -func (p *PullRequestPayload) JSONPayload() ([]byte, error) { - return json.MarshalIndent(p, "", " ") -} - -// ReviewPayload FIXME -type ReviewPayload struct { - Type string `json:"type"` - Content string `json:"content"` -} - -// __ __.__ __ .__ -// / \ / \__| | _|__| -// \ \/\/ / | |/ / | -// \ /| | <| | -// \__/\ / |__|__|_ \__| -// \/ \/ - -// HookWikiAction an action that happens to a wiki page -type HookWikiAction string - -const ( - // HookWikiCreated created - HookWikiCreated HookWikiAction = "created" - // HookWikiEdited edited - HookWikiEdited HookWikiAction = "edited" - // HookWikiDeleted deleted - HookWikiDeleted HookWikiAction = "deleted" -) - -// WikiPayload payload for repository webhooks -type WikiPayload struct { - Action HookWikiAction `json:"action"` - Repository *Repository `json:"repository"` - Sender *User `json:"sender"` - Page string `json:"page"` - Comment string `json:"comment"` -} - -// JSONPayload JSON representation of the payload -func (p *WikiPayload) JSONPayload() ([]byte, error) { - return json.MarshalIndent(p, "", " ") -} - -//__________ .__ __ -//\______ \ ____ ______ ____ _____|__|/ |_ ___________ ___.__. -// | _// __ \\____ \ / _ \/ ___/ \ __\/ _ \_ __ < | | -// | | \ ___/| |_> > <_> )___ \| || | ( <_> ) | \/\___ | -// |____|_ /\___ > __/ \____/____ >__||__| \____/|__| / ____| -// \/ \/|__| \/ \/ - -// HookRepoAction an action that happens to a repo -type HookRepoAction string - -const ( - // HookRepoCreated created - HookRepoCreated HookRepoAction = "created" - // HookRepoDeleted deleted - HookRepoDeleted HookRepoAction = "deleted" -) - -// RepositoryPayload payload for repository webhooks -type RepositoryPayload struct { - Action HookRepoAction `json:"action"` - Repository *Repository `json:"repository"` - Organization *User `json:"organization"` - Sender *User `json:"sender"` -} - -// JSONPayload JSON representation of the payload -func (p *RepositoryPayload) JSONPayload() ([]byte, error) { - return json.MarshalIndent(p, "", " ") -} - -// HookPackageAction an action that happens to a package -type HookPackageAction string - -const ( - // HookPackageCreated created - HookPackageCreated HookPackageAction = "created" - // HookPackageDeleted deleted - HookPackageDeleted HookPackageAction = "deleted" -) - -// PackagePayload represents a package payload -type PackagePayload struct { - Action HookPackageAction `json:"action"` - Repository *Repository `json:"repository"` - Package *Package `json:"package"` - Organization *User `json:"organization"` - Sender *User `json:"sender"` -} - -// JSONPayload implements Payload -func (p *PackagePayload) JSONPayload() ([]byte, error) { - return json.MarshalIndent(p, "", " ") -} diff --git a/modules/structs/hook_issue.go b/modules/structs/hook_issue.go new file mode 100644 index 0000000000000..fcdb435a4001d --- /dev/null +++ b/modules/structs/hook_issue.go @@ -0,0 +1,103 @@ +package structs + +import "code.gitea.io/gitea/modules/json" + +var ( + _ Payloader = &IssuePayload{} + _ Payloader = &IssueCommentPayload{} +) + +// .___ +// | | ______ ________ __ ____ +// | |/ ___// ___/ | \_/ __ \ +// | |\___ \ \___ \| | /\ ___/ +// |___/____ >____ >____/ \___ > +// \/ \/ \/ + +// HookIssueAction FIXME +type HookIssueAction string + +const ( + // HookIssueOpened opened + HookIssueOpened HookIssueAction = "opened" + // HookIssueClosed closed + HookIssueClosed HookIssueAction = "closed" + // HookIssueReOpened reopened + HookIssueReOpened HookIssueAction = "reopened" + // HookIssueEdited edited + HookIssueEdited HookIssueAction = "edited" + // HookIssueAssigned assigned + HookIssueAssigned HookIssueAction = "assigned" + // HookIssueUnassigned unassigned + HookIssueUnassigned HookIssueAction = "unassigned" + // HookIssueLabelUpdated label_updated + HookIssueLabelUpdated HookIssueAction = "label_updated" + // HookIssueLabelCleared label_cleared + HookIssueLabelCleared HookIssueAction = "label_cleared" + // HookIssueSynchronized synchronized + HookIssueSynchronized HookIssueAction = "synchronized" + // HookIssueMilestoned is an issue action for when a milestone is set on an issue. + HookIssueMilestoned HookIssueAction = "milestoned" + // HookIssueDemilestoned is an issue action for when a milestone is cleared on an issue. + HookIssueDemilestoned HookIssueAction = "demilestoned" + // HookIssueReviewed is an issue action for when a pull request is reviewed + HookIssueReviewed HookIssueAction = "reviewed" + // HookIssueReviewRequested is an issue action for when a reviewer is requested for a pull request. + HookIssueReviewRequested HookIssueAction = "review_requested" + // HookIssueReviewRequestRemoved is an issue action for removing a review request to someone on a pull request. + HookIssueReviewRequestRemoved HookIssueAction = "review_request_removed" +) + +// IssuePayload represents the payload information that is sent along with an issue event. +type IssuePayload struct { + Action HookIssueAction `json:"action"` + Index int64 `json:"number"` + Changes *ChangesPayload `json:"changes,omitempty"` + Issue *Issue `json:"issue"` + Repository *Repository `json:"repository"` + Sender *User `json:"sender"` + CommitID string `json:"commit_id"` +} + +// JSONPayload encodes the IssuePayload to JSON, with an indentation of two spaces. +func (p *IssuePayload) JSONPayload() ([]byte, error) { + return json.MarshalIndent(p, "", " ") +} + +// HookIssueCommentAction defines hook issue comment action +type HookIssueCommentAction string + +// all issue comment actions +const ( + HookIssueCommentCreated HookIssueCommentAction = "created" + HookIssueCommentEdited HookIssueCommentAction = "edited" + HookIssueCommentDeleted HookIssueCommentAction = "deleted" +) + +// IssueCommentPayload represents a payload information of issue comment event. +type IssueCommentPayload struct { + Action HookIssueCommentAction `json:"action"` + Issue *Issue `json:"issue"` + Comment *Comment `json:"comment"` + Changes *ChangesPayload `json:"changes,omitempty"` + Repository *Repository `json:"repository"` + Sender *User `json:"sender"` + IsPull bool `json:"is_pull"` +} + +// JSONPayload implements Payload +func (p *IssueCommentPayload) JSONPayload() ([]byte, error) { + return json.MarshalIndent(p, "", " ") +} + +// ChangesFromPayload FIXME +type ChangesFromPayload struct { + From string `json:"from"` +} + +// ChangesPayload represents the payload information of issue change +type ChangesPayload struct { + Title *ChangesFromPayload `json:"title,omitempty"` + Body *ChangesFromPayload `json:"body,omitempty"` + Ref *ChangesFromPayload `json:"ref,omitempty"` +} diff --git a/modules/structs/hook_package.go b/modules/structs/hook_package.go new file mode 100644 index 0000000000000..ba18dacd076b7 --- /dev/null +++ b/modules/structs/hook_package.go @@ -0,0 +1,29 @@ +package structs + +import "code.gitea.io/gitea/modules/json" + +var _ Payloader = &PackagePayload{} + +// HookPackageAction an action that happens to a package +type HookPackageAction string + +const ( + // HookPackageCreated created + HookPackageCreated HookPackageAction = "created" + // HookPackageDeleted deleted + HookPackageDeleted HookPackageAction = "deleted" +) + +// PackagePayload represents a package payload +type PackagePayload struct { + Action HookPackageAction `json:"action"` + Repository *Repository `json:"repository"` + Package *Package `json:"package"` + Organization *User `json:"organization"` + Sender *User `json:"sender"` +} + +// JSONPayload implements Payload +func (p *PackagePayload) JSONPayload() ([]byte, error) { + return json.MarshalIndent(p, "", " ") +} diff --git a/modules/structs/hook_pr.go b/modules/structs/hook_pr.go new file mode 100644 index 0000000000000..fd44c6ae197f3 --- /dev/null +++ b/modules/structs/hook_pr.go @@ -0,0 +1,36 @@ +package structs + +import "code.gitea.io/gitea/modules/json" + +var _ Payloader = &PullRequestPayload{} + +// __________ .__ .__ __________ __ +// \______ \__ __| | | | \______ \ ____ ________ __ ____ _______/ |_ +// | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\ +// | | | | / |_| |__ | | \ ___< <_| | | /\ ___/ \___ \ | | +// |____| |____/|____/____/ |____|_ /\___ >__ |____/ \___ >____ > |__| +// \/ \/ |__| \/ \/ + +// PullRequestPayload represents a payload information of pull request event. +type PullRequestPayload struct { + Action HookIssueAction `json:"action"` + Index int64 `json:"number"` + Changes *ChangesPayload `json:"changes,omitempty"` + PullRequest *PullRequest `json:"pull_request"` + RequestedReviewer *User `json:"requested_reviewer"` + Repository *Repository `json:"repository"` + Sender *User `json:"sender"` + CommitID string `json:"commit_id"` + Review *ReviewPayload `json:"review"` +} + +// JSONPayload FIXME +func (p *PullRequestPayload) JSONPayload() ([]byte, error) { + return json.MarshalIndent(p, "", " ") +} + +// ReviewPayload FIXME +type ReviewPayload struct { + Type string `json:"type"` + Content string `json:"content"` +} diff --git a/modules/structs/hook_release.go b/modules/structs/hook_release.go new file mode 100644 index 0000000000000..5886f2548b734 --- /dev/null +++ b/modules/structs/hook_release.go @@ -0,0 +1,35 @@ +package structs + +import "code.gitea.io/gitea/modules/json" + +var _ Payloader = &ReleasePayload{} + +// __________ .__ +// \______ \ ____ | | ____ _____ ______ ____ +// | _// __ \| | _/ __ \\__ \ / ___// __ \ +// | | \ ___/| |_\ ___/ / __ \_\___ \\ ___/ +// |____|_ /\___ >____/\___ >____ /____ >\___ > +// \/ \/ \/ \/ \/ \/ + +// HookReleaseAction defines hook release action type +type HookReleaseAction string + +// all release actions +const ( + HookReleasePublished HookReleaseAction = "published" + HookReleaseUpdated HookReleaseAction = "updated" + HookReleaseDeleted HookReleaseAction = "deleted" +) + +// ReleasePayload represents a payload information of release event. +type ReleasePayload struct { + Action HookReleaseAction `json:"action"` + Release *Release `json:"release"` + Repository *Repository `json:"repository"` + Sender *User `json:"sender"` +} + +// JSONPayload implements Payload +func (p *ReleasePayload) JSONPayload() ([]byte, error) { + return json.MarshalIndent(p, "", " ") +} diff --git a/modules/structs/hook_repo.go b/modules/structs/hook_repo.go new file mode 100644 index 0000000000000..3209ab043ce13 --- /dev/null +++ b/modules/structs/hook_repo.go @@ -0,0 +1,219 @@ +package structs + +import ( + "strings" + "time" + + "code.gitea.io/gitea/modules/json" +) + +var ( + _ Payloader = &CreatePayload{} + _ Payloader = &DeletePayload{} + _ Payloader = &ForkPayload{} + _ Payloader = &PushPayload{} + _ Payloader = &RepositoryPayload{} +) + +// PayloadUser represents the author or committer of a commit +type PayloadUser struct { + // Full name of the commit author + Name string `json:"name"` + // swagger:strfmt email + Email string `json:"email"` + UserName string `json:"username"` +} + +// FIXME: consider using same format as API when commits API are added. +// applies to PayloadCommit and PayloadCommitVerification + +// PayloadCommit represents a commit +type PayloadCommit struct { + // sha1 hash of the commit + ID string `json:"id"` + Message string `json:"message"` + URL string `json:"url"` + Author *PayloadUser `json:"author"` + Committer *PayloadUser `json:"committer"` + Verification *PayloadCommitVerification `json:"verification"` + // swagger:strfmt date-time + Timestamp time.Time `json:"timestamp"` + Added []string `json:"added"` + Removed []string `json:"removed"` + Modified []string `json:"modified"` +} + +// PayloadCommitVerification represents the GPG verification of a commit +type PayloadCommitVerification struct { + Verified bool `json:"verified"` + Reason string `json:"reason"` + Signature string `json:"signature"` + Signer *PayloadUser `json:"signer"` + Payload string `json:"payload"` +} + +// _________ __ +// \_ ___ \_______ ____ _____ _/ |_ ____ +// / \ \/\_ __ \_/ __ \\__ \\ __\/ __ \ +// \ \____| | \/\ ___/ / __ \| | \ ___/ +// \______ /|__| \___ >____ /__| \___ > +// \/ \/ \/ \/ + +// CreatePayload FIXME +type CreatePayload struct { + Sha string `json:"sha"` + Ref string `json:"ref"` + RefType string `json:"ref_type"` + Repo *Repository `json:"repository"` + Sender *User `json:"sender"` +} + +// JSONPayload return payload information +func (p *CreatePayload) JSONPayload() ([]byte, error) { + return json.MarshalIndent(p, "", " ") +} + +// ParseCreateHook parses create event hook content. +func ParseCreateHook(raw []byte) (*CreatePayload, error) { + hook := new(CreatePayload) + if err := json.Unmarshal(raw, hook); err != nil { + return nil, err + } + + // it is possible the JSON was parsed, however, + // was not from Gogs (maybe was from Bitbucket) + // So we'll check to be sure certain key fields + // were populated + switch { + case hook.Repo == nil: + return nil, ErrInvalidReceiveHook + case len(hook.Ref) == 0: + return nil, ErrInvalidReceiveHook + } + return hook, nil +} + +// ________ .__ __ +// \______ \ ____ | | _____/ |_ ____ +// | | \_/ __ \| | _/ __ \ __\/ __ \ +// | ` \ ___/| |_\ ___/| | \ ___/ +// /_______ /\___ >____/\___ >__| \___ > +// \/ \/ \/ \/ + +// PusherType define the type to push +type PusherType string + +// describe all the PusherTypes +const ( + PusherTypeUser PusherType = "user" +) + +// DeletePayload represents delete payload +type DeletePayload struct { + Ref string `json:"ref"` + RefType string `json:"ref_type"` + PusherType PusherType `json:"pusher_type"` + Repo *Repository `json:"repository"` + Sender *User `json:"sender"` +} + +// JSONPayload implements Payload +func (p *DeletePayload) JSONPayload() ([]byte, error) { + return json.MarshalIndent(p, "", " ") +} + +// ___________ __ +// \_ _____/__________| | __ +// | __)/ _ \_ __ \ |/ / +// | \( <_> ) | \/ < +// \___ / \____/|__| |__|_ \ +// \/ \/ + +// ForkPayload represents fork payload +type ForkPayload struct { + Forkee *Repository `json:"forkee"` + Repo *Repository `json:"repository"` + Sender *User `json:"sender"` +} + +// JSONPayload implements Payload +func (p *ForkPayload) JSONPayload() ([]byte, error) { + return json.MarshalIndent(p, "", " ") +} + +// __________ .__ +// \______ \__ __ _____| |__ +// | ___/ | \/ ___/ | \ +// | | | | /\___ \| Y \ +// |____| |____//____ >___| / +// \/ \/ + +// PushPayload represents a payload information of push event. +type PushPayload struct { + Ref string `json:"ref"` + Before string `json:"before"` + After string `json:"after"` + CompareURL string `json:"compare_url"` + Commits []*PayloadCommit `json:"commits"` + TotalCommits int `json:"total_commits"` + HeadCommit *PayloadCommit `json:"head_commit"` + Repo *Repository `json:"repository"` + Pusher *User `json:"pusher"` + Sender *User `json:"sender"` +} + +// JSONPayload FIXME +func (p *PushPayload) JSONPayload() ([]byte, error) { + return json.MarshalIndent(p, "", " ") +} + +// ParsePushHook parses push event hook content. +func ParsePushHook(raw []byte) (*PushPayload, error) { + hook := new(PushPayload) + if err := json.Unmarshal(raw, hook); err != nil { + return nil, err + } + + switch { + case hook.Repo == nil: + return nil, ErrInvalidReceiveHook + case len(hook.Ref) == 0: + return nil, ErrInvalidReceiveHook + } + return hook, nil +} + +// Branch returns branch name from a payload +func (p *PushPayload) Branch() string { + return strings.ReplaceAll(p.Ref, "refs/heads/", "") +} + +//__________ .__ __ +//\______ \ ____ ______ ____ _____|__|/ |_ ___________ ___.__. +// | _// __ \\____ \ / _ \/ ___/ \ __\/ _ \_ __ < | | +// | | \ ___/| |_> > <_> )___ \| || | ( <_> ) | \/\___ | +// |____|_ /\___ > __/ \____/____ >__||__| \____/|__| / ____| +// \/ \/|__| \/ \/ + +// HookRepoAction an action that happens to a repo +type HookRepoAction string + +const ( + // HookRepoCreated created + HookRepoCreated HookRepoAction = "created" + // HookRepoDeleted deleted + HookRepoDeleted HookRepoAction = "deleted" +) + +// RepositoryPayload payload for repository webhooks +type RepositoryPayload struct { + Action HookRepoAction `json:"action"` + Repository *Repository `json:"repository"` + Organization *User `json:"organization"` + Sender *User `json:"sender"` +} + +// JSONPayload JSON representation of the payload +func (p *RepositoryPayload) JSONPayload() ([]byte, error) { + return json.MarshalIndent(p, "", " ") +} diff --git a/modules/structs/hook_wiki.go b/modules/structs/hook_wiki.go new file mode 100644 index 0000000000000..6bbedc0481804 --- /dev/null +++ b/modules/structs/hook_wiki.go @@ -0,0 +1,38 @@ +package structs + +import "code.gitea.io/gitea/modules/json" + +var _ Payloader = &WikiPayload{} + +// __ __.__ __ .__ +// / \ / \__| | _|__| +// \ \/\/ / | |/ / | +// \ /| | <| | +// \__/\ / |__|__|_ \__| +// \/ \/ + +// HookWikiAction an action that happens to a wiki page +type HookWikiAction string + +const ( + // HookWikiCreated created + HookWikiCreated HookWikiAction = "created" + // HookWikiEdited edited + HookWikiEdited HookWikiAction = "edited" + // HookWikiDeleted deleted + HookWikiDeleted HookWikiAction = "deleted" +) + +// WikiPayload payload for repository webhooks +type WikiPayload struct { + Action HookWikiAction `json:"action"` + Repository *Repository `json:"repository"` + Sender *User `json:"sender"` + Page string `json:"page"` + Comment string `json:"comment"` +} + +// JSONPayload JSON representation of the payload +func (p *WikiPayload) JSONPayload() ([]byte, error) { + return json.MarshalIndent(p, "", " ") +} diff --git a/modules/webhook/structs.go b/modules/webhook/structs.go index 927a91a74c545..1e7d6c1a14e3c 100644 --- a/modules/webhook/structs.go +++ b/modules/webhook/structs.go @@ -3,6 +3,8 @@ package webhook +import "code.gitea.io/gitea/modules/util" + // HookEvents is a set of web hook events type HookEvents struct { Create bool `json:"create"` @@ -28,6 +30,41 @@ type HookEvents struct { Package bool `json:"package"` } +// ParseHookEvents converts a list of strings to HookEvents +func ParseHookEvents(eventTypes []string) HookEvents { + caseInsensitive := true + return HookEvents{ + Create: util.SliceContainsString(eventTypes, HookEventCreate.Event(), caseInsensitive), + Delete: util.SliceContainsString(eventTypes, HookEventDelete.Event(), caseInsensitive), + Fork: util.SliceContainsString(eventTypes, HookEventFork.Event(), caseInsensitive), + Issues: issuesHook(eventTypes, "issues_only", caseInsensitive), + IssueAssign: issuesHook(eventTypes, HookEventIssueAssign.Event(), caseInsensitive), + IssueLabel: issuesHook(eventTypes, HookEventIssueLabel.Event(), caseInsensitive), + IssueMilestone: issuesHook(eventTypes, HookEventIssueMilestone.Event(), caseInsensitive), + IssueComment: issuesHook(eventTypes, HookEventIssueComment.Event(), caseInsensitive), + Push: util.SliceContainsString(eventTypes, HookEventPush.Event(), caseInsensitive), + PullRequest: pullHook(eventTypes, "pull_request_only", caseInsensitive), + PullRequestAssign: pullHook(eventTypes, HookEventPullRequestAssign.Event(), caseInsensitive), + PullRequestLabel: pullHook(eventTypes, HookEventPullRequestLabel.Event(), caseInsensitive), + PullRequestMilestone: pullHook(eventTypes, HookEventPullRequestMilestone.Event(), caseInsensitive), + PullRequestComment: pullHook(eventTypes, HookEventPullRequestComment.Event(), caseInsensitive), + PullRequestReview: pullHook(eventTypes, "pull_request_review", caseInsensitive), + PullRequestReviewRequest: pullHook(eventTypes, HookEventPullRequestReviewRequest.Event(), caseInsensitive), + PullRequestSync: pullHook(eventTypes, HookEventPullRequestSync.Event(), caseInsensitive), + Wiki: util.SliceContainsString(eventTypes, HookEventWiki.Event(), caseInsensitive), + Repository: util.SliceContainsString(eventTypes, HookEventRepository.Event(), caseInsensitive), + Release: util.SliceContainsString(eventTypes, HookEventRelease.Event(), caseInsensitive), + } +} + +func issuesHook(events []string, event string, caseInsensitive bool) bool { + return util.SliceContainsString(events, event, caseInsensitive) || util.SliceContainsString(events, HookEventIssues.Event(), caseInsensitive) +} + +func pullHook(events []string, event string, caseInsensitive bool) bool { + return util.SliceContainsString(events, event, caseInsensitive) || util.SliceContainsString(events, HookEventPullRequest.Event(), caseInsensitive) +} + // HookEvent represents events that will delivery hook. type HookEvent struct { PushOnly bool `json:"push_only"` diff --git a/routers/api/v1/utils/hook.go b/routers/api/v1/utils/hook.go index 362f4bfc4d3f4..1dbde0f86c121 100644 --- a/routers/api/v1/utils/hook.go +++ b/routers/api/v1/utils/hook.go @@ -14,7 +14,6 @@ import ( "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/util" webhook_module "code.gitea.io/gitea/modules/webhook" webhook_service "code.gitea.io/gitea/services/webhook" ) @@ -151,14 +150,6 @@ func toAPIHook(ctx *context.APIContext, repoLink string, hook *webhook.Webhook) return apiHook, true } -func issuesHook(events []string, event string) bool { - return util.SliceContainsString(events, event, true) || util.SliceContainsString(events, string(webhook_module.HookEventIssues), true) -} - -func pullHook(events []string, event string) bool { - return util.SliceContainsString(events, event, true) || util.SliceContainsString(events, string(webhook_module.HookEventPullRequest), true) -} - // addHook add the hook specified by `form`, `ownerID` and `repoID`. If there is // an error, write to `ctx` accordingly. Return (webhook, ok) func addHook(ctx *context.APIContext, form *api.CreateHookOption, ownerID, repoID int64) (*webhook.Webhook, bool) { @@ -178,28 +169,7 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, ownerID, repoI HTTPMethod: "POST", HookEvent: &webhook_module.HookEvent{ ChooseEvents: true, - HookEvents: webhook_module.HookEvents{ - Create: util.SliceContainsString(form.Events, string(webhook_module.HookEventCreate), true), - Delete: util.SliceContainsString(form.Events, string(webhook_module.HookEventDelete), true), - Fork: util.SliceContainsString(form.Events, string(webhook_module.HookEventFork), true), - Issues: issuesHook(form.Events, "issues_only"), - IssueAssign: issuesHook(form.Events, string(webhook_module.HookEventIssueAssign)), - IssueLabel: issuesHook(form.Events, string(webhook_module.HookEventIssueLabel)), - IssueMilestone: issuesHook(form.Events, string(webhook_module.HookEventIssueMilestone)), - IssueComment: issuesHook(form.Events, string(webhook_module.HookEventIssueComment)), - Push: util.SliceContainsString(form.Events, string(webhook_module.HookEventPush), true), - PullRequest: pullHook(form.Events, "pull_request_only"), - PullRequestAssign: pullHook(form.Events, string(webhook_module.HookEventPullRequestAssign)), - PullRequestLabel: pullHook(form.Events, string(webhook_module.HookEventPullRequestLabel)), - PullRequestMilestone: pullHook(form.Events, string(webhook_module.HookEventPullRequestMilestone)), - PullRequestComment: pullHook(form.Events, string(webhook_module.HookEventPullRequestComment)), - PullRequestReview: pullHook(form.Events, "pull_request_review"), - PullRequestReviewRequest: pullHook(form.Events, string(webhook_module.HookEventPullRequestReviewRequest)), - PullRequestSync: pullHook(form.Events, string(webhook_module.HookEventPullRequestSync)), - Wiki: util.SliceContainsString(form.Events, string(webhook_module.HookEventWiki), true), - Repository: util.SliceContainsString(form.Events, string(webhook_module.HookEventRepository), true), - Release: util.SliceContainsString(form.Events, string(webhook_module.HookEventRelease), true), - }, + HookEvents: webhook_module.ParseHookEvents(form.Events), BranchFilter: form.BranchFilter, }, IsActive: form.Active, @@ -350,15 +320,8 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *webhook.Webh w.PushOnly = false w.SendEverything = false w.ChooseEvents = true - w.Create = util.SliceContainsString(form.Events, string(webhook_module.HookEventCreate), true) - w.Push = util.SliceContainsString(form.Events, string(webhook_module.HookEventPush), true) - w.Create = util.SliceContainsString(form.Events, string(webhook_module.HookEventCreate), true) - w.Delete = util.SliceContainsString(form.Events, string(webhook_module.HookEventDelete), true) - w.Fork = util.SliceContainsString(form.Events, string(webhook_module.HookEventFork), true) - w.Repository = util.SliceContainsString(form.Events, string(webhook_module.HookEventRepository), true) - w.Wiki = util.SliceContainsString(form.Events, string(webhook_module.HookEventWiki), true) - w.Release = util.SliceContainsString(form.Events, string(webhook_module.HookEventRelease), true) w.BranchFilter = form.BranchFilter + w.HookEvents = webhook_module.ParseHookEvents(form.Events) err := w.SetHeaderAuthorization(form.AuthorizationHeader) if err != nil { @@ -366,23 +329,6 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *webhook.Webh return false } - // Issues - w.Issues = issuesHook(form.Events, "issues_only") - w.IssueAssign = issuesHook(form.Events, string(webhook_module.HookEventIssueAssign)) - w.IssueLabel = issuesHook(form.Events, string(webhook_module.HookEventIssueLabel)) - w.IssueMilestone = issuesHook(form.Events, string(webhook_module.HookEventIssueMilestone)) - w.IssueComment = issuesHook(form.Events, string(webhook_module.HookEventIssueComment)) - - // Pull requests - w.PullRequest = pullHook(form.Events, "pull_request_only") - w.PullRequestAssign = pullHook(form.Events, string(webhook_module.HookEventPullRequestAssign)) - w.PullRequestLabel = pullHook(form.Events, string(webhook_module.HookEventPullRequestLabel)) - w.PullRequestMilestone = pullHook(form.Events, string(webhook_module.HookEventPullRequestMilestone)) - w.PullRequestComment = pullHook(form.Events, string(webhook_module.HookEventPullRequestComment)) - w.PullRequestReview = pullHook(form.Events, "pull_request_review") - w.PullRequestReviewRequest = pullHook(form.Events, string(webhook_module.HookEventPullRequestReviewRequest)) - w.PullRequestSync = pullHook(form.Events, string(webhook_module.HookEventPullRequestSync)) - if err := w.UpdateEvent(); err != nil { ctx.Error(http.StatusInternalServerError, "UpdateEvent", err) return false