Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a2bdbf1756 | |||
| 1c899982c1 | |||
| 4f72f9c366 | |||
| edaedd4ce9 | |||
| b793bbfed1 | |||
| c4e51bc4db | |||
| f22656b35f |
@@ -1,6 +1,6 @@
|
||||
Library webhooks
|
||||
================
|
||||
<img align="right" src="https://raw.githubusercontent.com/go-playground/webhooks/v6/logo.png">
|
||||
<img align="right" src="https://raw.githubusercontent.com/go-playground/webhooks/v6/logo.png">
|
||||
[](https://github.com/go-playground/webhooks/actions)
|
||||
[](https://coveralls.io/github/go-playground/webhooks?branch=master)
|
||||
[](https://goreportcard.com/report/go-playground/webhooks)
|
||||
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
package gitea
|
||||
|
||||
import (
|
||||
structs "code.gitea.io/gitea/modules/structs"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// parse errors
|
||||
var (
|
||||
ErrEventNotSpecifiedToParse = errors.New("no Event specified to parse")
|
||||
ErrInvalidHTTPMethod = errors.New("invalid HTTP Method")
|
||||
ErrMissingGiteaEventHeader = errors.New("missing X-Gitea-Event Header")
|
||||
ErrMissingHubSignatureHeader = errors.New("missing X-Hub-Signature Header")
|
||||
ErrEventNotFound = errors.New("event not defined to be parsed")
|
||||
ErrParsingPayload = errors.New("error parsing payload")
|
||||
ErrHMACVerificationFailed = errors.New("HMAC verification failed")
|
||||
)
|
||||
|
||||
// Event defines a Gitea hook event type
|
||||
type Event string
|
||||
|
||||
// Gitea hook types
|
||||
const (
|
||||
CreateEvent Event = "create"
|
||||
DeleteEvent Event = "delete"
|
||||
ForkEvent Event = "fork"
|
||||
IssuesEvent Event = "issues"
|
||||
IssueAssignEvent Event = "issue_assign"
|
||||
IssueLabelEvent Event = "issue_label"
|
||||
IssueMilestoneEvent Event = "issue_milestone"
|
||||
IssueCommentEvent Event = "issue_comment"
|
||||
PushEvent Event = "push"
|
||||
PullRequestEvent Event = "pull_request"
|
||||
PullRequestAssignEvent Event = "pull_request_assign"
|
||||
PullRequestLabelEvent Event = "pull_request_label"
|
||||
PullRequestMilestoneEvent Event = "pull_request_milestone"
|
||||
PullRequestCommentEvent Event = "pull_request_comment"
|
||||
PullRequestReviewEvent Event = "pull_request_review"
|
||||
PullRequestSyncEvent Event = "pull_request_sync"
|
||||
RepositoryEvent Event = "repository"
|
||||
ReleaseEvent Event = "release"
|
||||
PackageEvent Event = "package"
|
||||
)
|
||||
|
||||
type CreatePayload structs.CreatePayload
|
||||
type DeletePayload structs.DeletePayload
|
||||
type ForkPayload structs.ForkPayload
|
||||
type IssuePayload structs.IssuePayload
|
||||
type IssueCommentPayload structs.IssueCommentPayload
|
||||
type PushPayload structs.PushPayload
|
||||
type PullRequestPayload structs.PullRequestPayload
|
||||
type RepositoryPayload structs.RepositoryPayload
|
||||
type ReleasePayload structs.ReleasePayload
|
||||
type PackagePayload structs.PackagePayload
|
||||
|
||||
// EventSubtype defines a GitHub Hook Event subtype
|
||||
type EventSubtype string
|
||||
|
||||
// Gitea hook event subtypes
|
||||
const (
|
||||
NoSubtype EventSubtype = ""
|
||||
BranchSubtype EventSubtype = "branch"
|
||||
TagSubtype EventSubtype = "tag"
|
||||
PullSubtype EventSubtype = "pull"
|
||||
IssueSubtype EventSubtype = "issues"
|
||||
)
|
||||
|
||||
// Option is a configuration option for the webhook
|
||||
type Option func(*Webhook) error
|
||||
|
||||
// Options is a namespace var for configuration options
|
||||
var Options = WebhookOptions{}
|
||||
|
||||
// WebhookOptions is a namespace for configuration option methods
|
||||
type WebhookOptions struct{}
|
||||
|
||||
// Secret registers the Gitea secret
|
||||
func (WebhookOptions) Secret(secret string) Option {
|
||||
return func(hook *Webhook) error {
|
||||
hook.secret = secret
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Webhook instance contains all methods needed to process events
|
||||
type Webhook struct {
|
||||
secret string
|
||||
}
|
||||
|
||||
// New creates and returns a WebHook instance denoted by the Provider type
|
||||
func New(options ...Option) (*Webhook, error) {
|
||||
hook := new(Webhook)
|
||||
for _, opt := range options {
|
||||
if err := opt(hook); err != nil {
|
||||
return nil, errors.New("Error applying Option")
|
||||
}
|
||||
}
|
||||
return hook, nil
|
||||
}
|
||||
|
||||
// Parse verifies and parses the events specified and returns the payload object or an error
|
||||
func (hook Webhook) Parse(r *http.Request, events ...Event) (interface{}, error) {
|
||||
defer func() {
|
||||
_, _ = io.Copy(ioutil.Discard, r.Body)
|
||||
_ = r.Body.Close()
|
||||
}()
|
||||
|
||||
if len(events) == 0 {
|
||||
return nil, ErrEventNotSpecifiedToParse
|
||||
}
|
||||
if r.Method != http.MethodPost {
|
||||
return nil, ErrInvalidHTTPMethod
|
||||
}
|
||||
|
||||
event := r.Header.Get("X-Gitea-Event")
|
||||
if event == "" {
|
||||
return nil, ErrMissingGiteaEventHeader
|
||||
}
|
||||
giteaEvent := Event(event)
|
||||
|
||||
var found bool
|
||||
for _, evt := range events {
|
||||
if evt == giteaEvent {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
// event not defined to be parsed
|
||||
if !found {
|
||||
return nil, ErrEventNotFound
|
||||
}
|
||||
|
||||
payload, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil || len(payload) == 0 {
|
||||
return nil, ErrParsingPayload
|
||||
}
|
||||
|
||||
// If we have a Secret set, we should check the MAC
|
||||
if len(hook.secret) > 0 {
|
||||
signature := r.Header.Get("X-Hub-Signature")
|
||||
if len(signature) == 0 {
|
||||
return nil, ErrMissingHubSignatureHeader
|
||||
}
|
||||
mac := hmac.New(sha1.New, []byte(hook.secret))
|
||||
_, _ = mac.Write(payload)
|
||||
expectedMAC := hex.EncodeToString(mac.Sum(nil))
|
||||
|
||||
if !hmac.Equal([]byte(signature[5:]), []byte(expectedMAC)) {
|
||||
return nil, ErrHMACVerificationFailed
|
||||
}
|
||||
}
|
||||
|
||||
switch giteaEvent {
|
||||
case CreateEvent:
|
||||
var pl CreatePayload
|
||||
err = json.Unmarshal([]byte(payload), &pl)
|
||||
return pl, err
|
||||
case DeleteEvent:
|
||||
var pl DeletePayload
|
||||
err = json.Unmarshal([]byte(payload), &pl)
|
||||
return pl, err
|
||||
case ForkEvent:
|
||||
var pl ForkPayload
|
||||
err = json.Unmarshal([]byte(payload), &pl)
|
||||
return pl, err
|
||||
case IssuesEvent, IssueAssignEvent, IssueLabelEvent, IssueMilestoneEvent:
|
||||
var pl IssuePayload
|
||||
err = json.Unmarshal([]byte(payload), &pl)
|
||||
return pl, err
|
||||
case IssueCommentEvent, PullRequestCommentEvent:
|
||||
var pl IssueCommentPayload
|
||||
err = json.Unmarshal([]byte(payload), &pl)
|
||||
return pl, err
|
||||
case PushEvent:
|
||||
var pl PushPayload
|
||||
err = json.Unmarshal([]byte(payload), &pl)
|
||||
return pl, err
|
||||
case PullRequestEvent, PullRequestAssignEvent, PullRequestLabelEvent,
|
||||
PullRequestMilestoneEvent, PullRequestSyncEvent:
|
||||
var pl PullRequestPayload
|
||||
err = json.Unmarshal([]byte(payload), &pl)
|
||||
return pl, err
|
||||
case PullRequestReviewEvent:
|
||||
var pl PullRequestPayload
|
||||
err = json.Unmarshal([]byte(payload), &pl)
|
||||
return pl, err
|
||||
case RepositoryEvent:
|
||||
var pl RepositoryPayload
|
||||
err = json.Unmarshal([]byte(payload), &pl)
|
||||
return pl, err
|
||||
case ReleaseEvent:
|
||||
var pl ReleasePayload
|
||||
err = json.Unmarshal([]byte(payload), &pl)
|
||||
return pl, err
|
||||
case PackageEvent:
|
||||
var pl PackagePayload
|
||||
err = json.Unmarshal([]byte(payload), &pl)
|
||||
return pl, err
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown event %s", giteaEvent)
|
||||
}
|
||||
}
|
||||
@@ -240,7 +240,7 @@ func TestWebhooks(t *testing.T) {
|
||||
filename: "../testdata/github/installation.json",
|
||||
headers: http.Header{
|
||||
"X-Github-Event": []string{"installation"},
|
||||
"X-Hub-Signature": []string{"sha1=2058cf6cc28570710afbc638e669f5c67305a2db"},
|
||||
"X-Hub-Signature": []string{"sha1=2bcb4ad96133ce2dd6d140fad7a80a2b14407f7f"},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -250,7 +250,7 @@ func TestWebhooks(t *testing.T) {
|
||||
filename: "../testdata/github/installation-repositories.json",
|
||||
headers: http.Header{
|
||||
"X-Github-Event": []string{"installation_repositories"},
|
||||
"X-Hub-Signature": []string{"sha1=c587fbd9dd169db8ae592b3bcc80b08e2e6f4f45"},
|
||||
"X-Hub-Signature": []string{"sha1=997680ef1e6f4a6b6595f5fa70b82989f505137f"},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -260,7 +260,7 @@ func TestWebhooks(t *testing.T) {
|
||||
filename: "../testdata/github/integration-installation.json",
|
||||
headers: http.Header{
|
||||
"X-Github-Event": []string{"integration_installation"},
|
||||
"X-Hub-Signature": []string{"sha1=bb2769f05f1a11af3a1edf8f9fac11bae7402a1e"},
|
||||
"X-Hub-Signature": []string{"sha1=1172601d35bdebac5f3aa7618c9e58eafb404c6f"},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -270,7 +270,7 @@ func TestWebhooks(t *testing.T) {
|
||||
filename: "../testdata/github/integration-installation-repositories.json",
|
||||
headers: http.Header{
|
||||
"X-Github-Event": []string{"integration_installation_repositories"},
|
||||
"X-Hub-Signature": []string{"sha1=2f00a982574188342c2894eb9d1b1e93434687fb"},
|
||||
"X-Hub-Signature": []string{"sha1=7c38ba703a3c89d00823920a47cd8863df8121d2"},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
+8
-8
@@ -1587,10 +1587,10 @@ type InstallationPayload struct {
|
||||
PullRequests string `json:"pull_requests"`
|
||||
RepositoryProjects string `json:"repository_projects"`
|
||||
} `json:"permissions"`
|
||||
Events []string `json:"events"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
SingleFileName *string `json:"single_file_name"`
|
||||
Events []string `json:"events"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
SingleFileName *string `json:"single_file_name"`
|
||||
} `json:"installation"`
|
||||
Repositories []struct {
|
||||
ID int64 `json:"id"`
|
||||
@@ -1665,10 +1665,10 @@ type InstallationRepositoriesPayload struct {
|
||||
Deployments string `json:"deployments"`
|
||||
Contents string `json:"contents"`
|
||||
} `json:"permissions"`
|
||||
Events []string `json:"events"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
SingleFileName *string `json:"single_file_name"`
|
||||
Events []string `json:"events"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
SingleFileName *string `json:"single_file_name"`
|
||||
} `json:"installation"`
|
||||
RepositoriesAdded []struct {
|
||||
ID int64 `json:"id"`
|
||||
|
||||
@@ -3,6 +3,7 @@ module github.com/go-playground/webhooks/v6
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
code.gitea.io/gitea v1.17.4
|
||||
github.com/gogits/go-gogs-client v0.0.0-20200905025246-8bb8a50cb355
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/stretchr/testify v1.8.0
|
||||
)
|
||||
|
||||
+2
-2
@@ -38,8 +38,8 @@
|
||||
"push",
|
||||
"pull_request"
|
||||
],
|
||||
"created_at": 1525109898,
|
||||
"updated_at": 1525109899,
|
||||
"created_at": "2022-03-02T18:02:51.000Z",
|
||||
"updated_at": "2022-03-02T18:02:51.000Z",
|
||||
"single_file_name": "config.yml"
|
||||
},
|
||||
"repository_selection": "selected",
|
||||
|
||||
Vendored
+2
-2
@@ -38,8 +38,8 @@
|
||||
"push",
|
||||
"pull_request"
|
||||
],
|
||||
"created_at": 1525109898,
|
||||
"updated_at": 1525109899,
|
||||
"created_at": "2022-03-02T18:02:51.000Z",
|
||||
"updated_at": "2022-03-02T18:02:51.000Z",
|
||||
"single_file_name": "config.yml"
|
||||
},
|
||||
"repositories": [
|
||||
|
||||
@@ -38,8 +38,8 @@
|
||||
"push",
|
||||
"pull_request"
|
||||
],
|
||||
"created_at": 1525109898,
|
||||
"updated_at": 1525109899,
|
||||
"created_at": "2022-03-02T18:02:51.000Z",
|
||||
"updated_at": "2022-03-02T18:02:51.000Z",
|
||||
"single_file_name": "config.yml"
|
||||
},
|
||||
"repository_selection": "selected",
|
||||
|
||||
+2
-2
@@ -37,8 +37,8 @@
|
||||
"events": [
|
||||
"pull_request"
|
||||
],
|
||||
"created_at": 1516025475,
|
||||
"updated_at": 1516025475,
|
||||
"created_at": "2022-03-02T18:02:51.000Z",
|
||||
"updated_at": "2022-03-02T18:02:51.000Z",
|
||||
"single_file_name": null
|
||||
},
|
||||
"repositories": [
|
||||
|
||||
Reference in New Issue
Block a user