Compare commits

...

7 Commits

Author SHA1 Message Date
restitux a2bdbf1756 Reexport gitea types as local types 2022-12-24 15:11:47 -07:00
restitux 1c899982c1 Add support for Gitea webhooks 2022-12-23 21:54:12 -07:00
Dean Karn 4f72f9c366 Update README.md 2022-04-29 21:59:45 -07:00
Dean Karn edaedd4ce9 Merge pull request #144 from iamsumit/issue-47
Changed date field from int64 to time.Time to fix the parsing error.
2022-04-29 21:53:40 -07:00
Sumit Madan b793bbfed1 Fixed test for integration installation events. 2022-03-08 11:04:06 +05:30
Sumit Madan c4e51bc4db Updated test with new changes. 2022-03-08 10:55:28 +05:30
Sumit Madan f22656b35f Changed date field from int64 to time.Time to fix the parsing error. 2022-03-07 13:14:21 +05:30
10 changed files with 2411 additions and 26 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
Library webhooks
================
<img align="right" src="https://raw.githubusercontent.com/go-playground/webhooks/v6/logo.png">![Project status](https://img.shields.io/badge/version-6.0.0-green.svg)
<img align="right" src="https://raw.githubusercontent.com/go-playground/webhooks/v6/logo.png">![Project status](https://img.shields.io/badge/version-6.0.1-green.svg)
[![Test](https://github.com/go-playground/webhooks/workflows/Test/badge.svg?branch=master)](https://github.com/go-playground/webhooks/actions)
[![Coverage Status](https://coveralls.io/repos/go-playground/webhooks/badge.svg?branch=master&service=github)](https://coveralls.io/github/go-playground/webhooks?branch=master)
[![Go Report Card](https://goreportcard.com/badge/go-playground/webhooks)](https://goreportcard.com/report/go-playground/webhooks)
+210
View File
@@ -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)
}
}
+4 -4
View File
@@ -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
View File
@@ -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"`
+2 -1
View File
@@ -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
)
+2178 -4
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -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
View File
@@ -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": [
+2 -2
View File
@@ -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
View File
@@ -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": [