|
|
@ -1,13 +1,15 @@ |
|
|
|
package webhook |
|
|
|
|
|
|
|
import ( |
|
|
|
"encoding/json" |
|
|
|
"fmt" |
|
|
|
log "github.com/Sirupsen/logrus" |
|
|
|
"github.com/andygrunwald/go-jira" |
|
|
|
"github.com/matrix-org/go-neb/database" |
|
|
|
"github.com/matrix-org/go-neb/errors" |
|
|
|
"github.com/matrix-org/go-neb/matrix" |
|
|
|
"github.com/matrix-org/go-neb/realms/jira" |
|
|
|
"net/http" |
|
|
|
"strings" |
|
|
|
) |
|
|
|
|
|
|
|
type jiraWebhook struct { |
|
|
@ -20,6 +22,14 @@ type jiraWebhook struct { |
|
|
|
Enabled bool `json:"enabled"` |
|
|
|
} |
|
|
|
|
|
|
|
// Event represents an incoming JIRA webhook event
|
|
|
|
type Event struct { |
|
|
|
WebhookEvent string `json:"webhookEvent"` |
|
|
|
Timestamp int64 `json:"timestamp"` |
|
|
|
User jira.User `json:"user"` |
|
|
|
Issue jira.Issue `json:"issue"` |
|
|
|
} |
|
|
|
|
|
|
|
// RegisterHook checks to see if this user is allowed to track the given projects and then tracks them.
|
|
|
|
func RegisterHook(jrealm *realms.JIRARealm, projects []string, userID, webhookEndpointURL string) error { |
|
|
|
// Tracking means that a webhook may need to be created on the remote JIRA installation.
|
|
|
@ -72,8 +82,11 @@ func RegisterHook(jrealm *realms.JIRARealm, projects []string, userID, webhookEn |
|
|
|
// All projects that wish to be tracked are public, but the user cannot create
|
|
|
|
// webhooks. The only way this will work is if we already have a webhook for this
|
|
|
|
// JIRA endpoint.
|
|
|
|
// TODO: Check for an existing webhook for this realm (flag on realm?)
|
|
|
|
return fmt.Errorf("Not supported yet") |
|
|
|
if !jrealm.HasWebhook { |
|
|
|
logger.Print("No webhook exists for this realm.") |
|
|
|
return fmt.Errorf("Not authorised to create webhook: not an admin.") |
|
|
|
} |
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
// The user is probably an admin (can query webhooks endpoint)
|
|
|
@ -85,9 +98,23 @@ func RegisterHook(jrealm *realms.JIRARealm, projects []string, userID, webhookEn |
|
|
|
return createWebhook(jrealm, webhookEndpointURL, userID) |
|
|
|
} |
|
|
|
|
|
|
|
// OnReceiveRequest is called when JIRA hits NEB with an update
|
|
|
|
func OnReceiveRequest(w http.ResponseWriter, req *http.Request, cli *matrix.Client) { |
|
|
|
w.WriteHeader(200) // Do nothing
|
|
|
|
// OnReceiveRequest is called when JIRA hits NEB with an update.
|
|
|
|
// Returns the project key and webhook event, or an error.
|
|
|
|
func OnReceiveRequest(req *http.Request) (string, *Event, *errors.HTTPError) { |
|
|
|
// extract the JIRA webhook event JSON
|
|
|
|
defer req.Body.Close() |
|
|
|
var whe Event |
|
|
|
err := json.NewDecoder(req.Body).Decode(&whe) |
|
|
|
if err != nil { |
|
|
|
return "", nil, &errors.HTTPError{err, "Failed to parse request JSON", 400} |
|
|
|
} |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
return "", nil, &errors.HTTPError{err, "Failed to parse JIRA URL", 400} |
|
|
|
} |
|
|
|
projKey := strings.Split(whe.Issue.Key, "-")[0] |
|
|
|
projKey = strings.ToUpper(projKey) |
|
|
|
return projKey, &whe, nil |
|
|
|
} |
|
|
|
|
|
|
|
func createWebhook(jrealm *realms.JIRARealm, webhookEndpointURL, userID string) error { |
|
|
@ -115,7 +142,11 @@ func createWebhook(jrealm *realms.JIRARealm, webhookEndpointURL, userID string) |
|
|
|
"realm_id": jrealm.ID(), |
|
|
|
"jira_url": jrealm.JIRAEndpoint, |
|
|
|
}).Print("Created webhook") |
|
|
|
return nil |
|
|
|
|
|
|
|
// mark this on the realm and persist it.
|
|
|
|
jrealm.HasWebhook = true |
|
|
|
_, err = database.GetServiceDB().StoreAuthRealm(jrealm) |
|
|
|
return err |
|
|
|
} |
|
|
|
|
|
|
|
func getWebhook(cli *jira.Client, webhookEndpointURL string) (*jiraWebhook, *errors.HTTPError) { |
|
|
|