|
@ -8,23 +8,26 @@ import ( |
|
|
"fmt" |
|
|
"fmt" |
|
|
log "github.com/Sirupsen/logrus" |
|
|
log "github.com/Sirupsen/logrus" |
|
|
"github.com/google/go-github/github" |
|
|
"github.com/google/go-github/github" |
|
|
|
|
|
"github.com/matrix-org/go-neb/errors" |
|
|
|
|
|
"github.com/matrix-org/go-neb/matrix" |
|
|
"html" |
|
|
"html" |
|
|
"io/ioutil" |
|
|
"io/ioutil" |
|
|
"net/http" |
|
|
"net/http" |
|
|
"strings" |
|
|
"strings" |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
// OnReceiveRequest processes incoming github webhook requests. The secretToken
|
|
|
|
|
|
// parameter is optional.
|
|
|
|
|
|
func OnReceiveRequest(w http.ResponseWriter, r *http.Request, secretToken string) { |
|
|
|
|
|
|
|
|
// OnReceiveRequest processes incoming github webhook requests and returns a
|
|
|
|
|
|
// matrix message to send, along with parsed repo information.
|
|
|
|
|
|
// The secretToken, if supplied, will be used to verify the request is from
|
|
|
|
|
|
// Github. If it isn't, an error is returned.
|
|
|
|
|
|
func OnReceiveRequest(r *http.Request, secretToken string) (string, *github.Repository, *matrix.HTMLMessage, *errors.HTTPError) { |
|
|
// Verify the HMAC signature if NEB was configured with a secret token
|
|
|
// Verify the HMAC signature if NEB was configured with a secret token
|
|
|
eventType := r.Header.Get("X-GitHub-Event") |
|
|
eventType := r.Header.Get("X-GitHub-Event") |
|
|
signatureSHA1 := r.Header.Get("X-Hub-Signature") |
|
|
signatureSHA1 := r.Header.Get("X-Hub-Signature") |
|
|
content, err := ioutil.ReadAll(r.Body) |
|
|
content, err := ioutil.ReadAll(r.Body) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
log.WithError(err).Print("Failed to read Github webhook body") |
|
|
log.WithError(err).Print("Failed to read Github webhook body") |
|
|
w.WriteHeader(400) |
|
|
|
|
|
return |
|
|
|
|
|
|
|
|
return "", nil, nil, &errors.HTTPError{nil, "Failed to parse body", 400} |
|
|
} |
|
|
} |
|
|
// Verify request if a secret token has been supplied.
|
|
|
// Verify request if a secret token has been supplied.
|
|
|
if secretToken != "" { |
|
|
if secretToken != "" { |
|
@ -34,16 +37,14 @@ func OnReceiveRequest(w http.ResponseWriter, r *http.Request, secretToken string |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
log.WithError(err).WithField("X-Hub-Signature", sigHex).Print( |
|
|
log.WithError(err).WithField("X-Hub-Signature", sigHex).Print( |
|
|
"Failed to decode signature as hex.") |
|
|
"Failed to decode signature as hex.") |
|
|
w.WriteHeader(400) |
|
|
|
|
|
return |
|
|
|
|
|
|
|
|
return "", nil, nil, &errors.HTTPError{nil, "Failed to decode signature", 400} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if !checkMAC([]byte(content), sigBytes, []byte(secretToken)) { |
|
|
if !checkMAC([]byte(content), sigBytes, []byte(secretToken)) { |
|
|
log.WithFields(log.Fields{ |
|
|
log.WithFields(log.Fields{ |
|
|
"X-Hub-Signature": signatureSHA1, |
|
|
"X-Hub-Signature": signatureSHA1, |
|
|
}).Print("Received Github event which failed MAC check.") |
|
|
}).Print("Received Github event which failed MAC check.") |
|
|
w.WriteHeader(403) |
|
|
|
|
|
return |
|
|
|
|
|
|
|
|
return "", nil, nil, &errors.HTTPError{nil, "Bad signature", 403} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -55,16 +56,11 @@ func OnReceiveRequest(w http.ResponseWriter, r *http.Request, secretToken string |
|
|
htmlStr, repo, err := parseGithubEvent(eventType, content) |
|
|
htmlStr, repo, err := parseGithubEvent(eventType, content) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
log.WithError(err).Print("Failed to parse github event") |
|
|
log.WithError(err).Print("Failed to parse github event") |
|
|
w.WriteHeader(500) |
|
|
|
|
|
return |
|
|
|
|
|
|
|
|
return "", nil, nil, &errors.HTTPError{nil, "Failed to parse github event", 500} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if err := handleWebhookEvent(eventType, htmlStr, repo); err != nil { |
|
|
|
|
|
log.WithError(err).Print("Failed to handle Github webhook event") |
|
|
|
|
|
w.WriteHeader(500) |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
w.WriteHeader(200) |
|
|
|
|
|
|
|
|
msg := matrix.GetHTMLMessage("m.notice", htmlStr) |
|
|
|
|
|
return eventType, repo, &msg, nil |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// checkMAC reports whether messageMAC is a valid HMAC tag for message.
|
|
|
// checkMAC reports whether messageMAC is a valid HMAC tag for message.
|
|
@ -122,10 +118,6 @@ func parseGithubEvent(eventType string, data []byte) (string, *github.Repository |
|
|
return "", nil, fmt.Errorf("Unrecognized event type") |
|
|
return "", nil, fmt.Errorf("Unrecognized event type") |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func handleWebhookEvent(eventType string, htmlStr string, repo *github.Repository) error { |
|
|
|
|
|
return nil |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func pullRequestHTMLMessage(p github.PullRequestEvent) string { |
|
|
func pullRequestHTMLMessage(p github.PullRequestEvent) string { |
|
|
var actionTarget string |
|
|
var actionTarget string |
|
|
if p.PullRequest.Assignee != nil && p.PullRequest.Assignee.Login != nil { |
|
|
if p.PullRequest.Assignee != nil && p.PullRequest.Assignee.Login != nil { |
|
|