webhooks/bitbucket/bitbucket.go

205 lines
6.0 KiB
Go
Raw Permalink Normal View History

2016-01-07 18:31:00 +00:00
package bitbucket
2016-01-07 19:19:13 +00:00
import (
"encoding/json"
"errors"
"fmt"
"io"
2016-01-07 19:19:13 +00:00
"io/ioutil"
"net/http"
)
2016-01-07 19:19:13 +00:00
2018-07-26 15:54:32 +00:00
// parse errors
var (
2018-07-26 15:54:32 +00:00
ErrEventNotSpecifiedToParse = errors.New("no Event specified to parse")
ErrInvalidHTTPMethod = errors.New("invalid HTTP Method")
ErrMissingHookUUIDHeader = errors.New("missing X-Hook-UUID Header")
ErrMissingEventKeyHeader = errors.New("missing X-Event-Key Header")
ErrEventNotFound = errors.New("event not defined to be parsed")
ErrParsingPayload = errors.New("error parsing payload")
ErrUUIDVerificationFailed = errors.New("UUID verification failed")
2016-01-07 19:19:13 +00:00
)
2016-01-07 18:31:00 +00:00
// Webhook instance contains all methods needed to process events
type Webhook struct {
uuid string
2016-01-07 18:31:00 +00:00
}
2016-01-07 19:19:13 +00:00
// Event defines a Bitbucket hook event type
2016-01-07 18:31:00 +00:00
type Event string
2016-01-07 19:19:13 +00:00
// Bitbucket hook types
const (
2017-04-22 02:03:45 +00:00
RepoPushEvent Event = "repo:push"
RepoForkEvent Event = "repo:fork"
RepoUpdatedEvent Event = "repo:updated"
RepoCommitCommentCreatedEvent Event = "repo:commit_comment_created"
RepoCommitStatusCreatedEvent Event = "repo:commit_status_created"
RepoCommitStatusUpdatedEvent Event = "repo:commit_status_updated"
IssueCreatedEvent Event = "issue:created"
IssueUpdatedEvent Event = "issue:updated"
IssueCommentCreatedEvent Event = "issue:comment_created"
PullRequestCreatedEvent Event = "pullrequest:created"
PullRequestUpdatedEvent Event = "pullrequest:updated"
PullRequestApprovedEvent Event = "pullrequest:approved"
PullRequestUnapprovedEvent Event = "pullrequest:unapproved"
PullRequestMergedEvent Event = "pullrequest:fulfilled"
PullRequestDeclinedEvent Event = "pullrequest:rejected"
PullRequestCommentCreatedEvent Event = "pullrequest:comment_created"
PullRequestCommentUpdatedEvent Event = "pullrequest:comment_updated"
2018-03-20 17:20:36 +00:00
PullRequestCommentDeletedEvent Event = "pullrequest:comment_deleted"
2016-01-07 19:19:13 +00:00
)
// 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{}
// UUID registers the BitBucket secret
func (WebhookOptions) UUID(uuid string) Option {
return func(hook *Webhook) error {
hook.uuid = uuid
return nil
2016-01-07 19:19:13 +00:00
}
}
// 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
2016-01-07 19:19:13 +00:00
}
// 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()
}()
2016-01-07 19:19:13 +00:00
if len(events) == 0 {
return nil, ErrEventNotSpecifiedToParse
}
if r.Method != http.MethodPost {
return nil, ErrInvalidHTTPMethod
2016-01-07 19:19:13 +00:00
}
uuid := r.Header.Get("X-Hook-UUID")
if hook.uuid != "" && uuid == "" {
return nil, ErrMissingHookUUIDHeader
2016-01-07 19:19:13 +00:00
}
event := r.Header.Get("X-Event-Key")
if event == "" {
return nil, ErrMissingEventKeyHeader
2016-01-07 19:19:13 +00:00
}
2018-07-26 15:54:32 +00:00
if len(hook.uuid) > 0 && uuid != hook.uuid {
return nil, ErrUUIDVerificationFailed
}
2016-01-07 19:19:13 +00:00
bitbucketEvent := Event(event)
var found bool
for _, evt := range events {
if evt == bitbucketEvent {
found = true
break
}
}
// event not defined to be parsed
if !found {
return nil, ErrEventNotFound
2016-01-07 19:19:13 +00:00
}
payload, err := ioutil.ReadAll(r.Body)
if err != nil || len(payload) == 0 {
return nil, ErrParsingPayload
2016-01-07 19:19:13 +00:00
}
2016-01-07 19:19:13 +00:00
switch bitbucketEvent {
case RepoPushEvent:
var pl RepoPushPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2016-01-07 19:19:13 +00:00
case RepoForkEvent:
var pl RepoForkPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2017-04-22 02:03:45 +00:00
case RepoUpdatedEvent:
var pl RepoUpdatedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2016-01-07 19:19:13 +00:00
case RepoCommitCommentCreatedEvent:
var pl RepoCommitCommentCreatedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2016-01-07 19:19:13 +00:00
case RepoCommitStatusCreatedEvent:
var pl RepoCommitStatusCreatedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2016-01-07 19:19:13 +00:00
case RepoCommitStatusUpdatedEvent:
var pl RepoCommitStatusUpdatedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2016-01-07 19:19:13 +00:00
case IssueCreatedEvent:
var pl IssueCreatedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2016-01-07 19:19:13 +00:00
case IssueUpdatedEvent:
var pl IssueUpdatedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2016-01-07 19:19:13 +00:00
case IssueCommentCreatedEvent:
var pl IssueCommentCreatedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2016-01-07 19:19:13 +00:00
case PullRequestCreatedEvent:
var pl PullRequestCreatedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2016-01-07 19:19:13 +00:00
case PullRequestUpdatedEvent:
var pl PullRequestUpdatedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2016-01-07 19:19:13 +00:00
case PullRequestApprovedEvent:
var pl PullRequestApprovedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2017-04-22 02:03:45 +00:00
case PullRequestUnapprovedEvent:
var pl PullRequestUnapprovedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2016-01-07 19:19:13 +00:00
case PullRequestMergedEvent:
var pl PullRequestMergedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2016-01-07 19:19:13 +00:00
case PullRequestDeclinedEvent:
var pl PullRequestDeclinedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2016-01-07 19:19:13 +00:00
case PullRequestCommentCreatedEvent:
var pl PullRequestCommentCreatedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2016-01-07 19:19:13 +00:00
case PullRequestCommentUpdatedEvent:
var pl PullRequestCommentUpdatedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
2016-01-07 19:19:13 +00:00
case PullRequestCommentDeletedEvent:
var pl PullRequestCommentDeletedPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
default:
return nil, fmt.Errorf("unknown event %s", bitbucketEvent)
2016-01-07 19:19:13 +00:00
}
}