go-mockid/vendor/github.com/mailgun/mailgun-go/v3/webhooks.go

158 lines
4.5 KiB
Go

package mailgun
import (
"context"
"crypto/hmac"
"crypto/sha256"
"crypto/subtle"
"encoding/hex"
"fmt"
"io"
"net/http"
"github.com/mailgun/mailgun-go/v3/events"
)
type UrlOrUrls struct {
Urls []string `json:"urls"`
Url string `json:"url"`
}
type WebHooksListResponse struct {
Webhooks map[string]UrlOrUrls `json:"webhooks"`
}
type WebHookResponse struct {
Webhook UrlOrUrls `json:"webhook"`
}
// ListWebhooks returns the complete set of webhooks configured for your domain.
// Note that a zero-length mapping is not an error.
func (mg *MailgunImpl) ListWebhooks(ctx context.Context) (map[string][]string, error) {
r := newHTTPRequest(generateDomainApiUrl(mg, webhooksEndpoint))
r.setClient(mg.Client())
r.setBasicAuth(basicAuthUser, mg.APIKey())
var body WebHooksListResponse
err := getResponseFromJSON(ctx, r, &body)
if err != nil {
return nil, err
}
hooks := make(map[string][]string, 0)
for k, v := range body.Webhooks {
if v.Url != "" {
hooks[k] = []string{v.Url}
}
if len(v.Urls) != 0 {
hooks[k] = append(hooks[k], v.Urls...)
}
}
return hooks, nil
}
// CreateWebhook installs a new webhook for your domain.
func (mg *MailgunImpl) CreateWebhook(ctx context.Context, kind string, urls []string) error {
r := newHTTPRequest(generateDomainApiUrl(mg, webhooksEndpoint))
r.setClient(mg.Client())
r.setBasicAuth(basicAuthUser, mg.APIKey())
p := newUrlEncodedPayload()
p.addValue("id", kind)
for _, url := range urls {
p.addValue("url", url)
}
_, err := makePostRequest(ctx, r, p)
return err
}
// DeleteWebhook removes the specified webhook from your domain's configuration.
func (mg *MailgunImpl) DeleteWebhook(ctx context.Context, kind string) error {
r := newHTTPRequest(generateDomainApiUrl(mg, webhooksEndpoint) + "/" + kind)
r.setClient(mg.Client())
r.setBasicAuth(basicAuthUser, mg.APIKey())
_, err := makeDeleteRequest(ctx, r)
return err
}
// GetWebhook retrieves the currently assigned webhook URL associated with the provided type of webhook.
func (mg *MailgunImpl) GetWebhook(ctx context.Context, kind string) ([]string, error) {
r := newHTTPRequest(generateDomainApiUrl(mg, webhooksEndpoint) + "/" + kind)
r.setClient(mg.Client())
r.setBasicAuth(basicAuthUser, mg.APIKey())
var body WebHookResponse
if err := getResponseFromJSON(ctx, r, &body); err != nil {
return nil, err
}
if body.Webhook.Url != "" {
return []string{body.Webhook.Url}, nil
}
if len(body.Webhook.Urls) != 0 {
return body.Webhook.Urls, nil
}
return nil, fmt.Errorf("webhook '%s' returned no urls", kind)
}
// UpdateWebhook replaces one webhook setting for another.
func (mg *MailgunImpl) UpdateWebhook(ctx context.Context, kind string, urls []string) error {
r := newHTTPRequest(generateDomainApiUrl(mg, webhooksEndpoint) + "/" + kind)
r.setClient(mg.Client())
r.setBasicAuth(basicAuthUser, mg.APIKey())
p := newUrlEncodedPayload()
for _, url := range urls {
p.addValue("url", url)
}
_, err := makePutRequest(ctx, r, p)
return err
}
// Represents the signature portion of the webhook POST body
type Signature struct {
TimeStamp string `json:"timestamp"`
Token string `json:"token"`
Signature string `json:"signature"`
}
// Represents the JSON payload provided when a Webhook is called by mailgun
type WebhookPayload struct {
Signature Signature `json:"signature"`
EventData events.RawJSON `json:"event-data"`
}
// Use this method to parse the webhook signature given as JSON in the webhook response
func (mg *MailgunImpl) VerifyWebhookSignature(sig Signature) (verified bool, err error) {
h := hmac.New(sha256.New, []byte(mg.APIKey()))
io.WriteString(h, sig.TimeStamp)
io.WriteString(h, sig.Token)
calculatedSignature := h.Sum(nil)
signature, err := hex.DecodeString(sig.Signature)
if err != nil {
return false, err
}
if len(calculatedSignature) != len(signature) {
return false, nil
}
return subtle.ConstantTimeCompare(signature, calculatedSignature) == 1, nil
}
// Deprecated: Please use the VerifyWebhookSignature() to parse the latest
// version of WebHooks from mailgun
func (mg *MailgunImpl) VerifyWebhookRequest(req *http.Request) (verified bool, err error) {
h := hmac.New(sha256.New, []byte(mg.APIKey()))
io.WriteString(h, req.FormValue("timestamp"))
io.WriteString(h, req.FormValue("token"))
calculatedSignature := h.Sum(nil)
signature, err := hex.DecodeString(req.FormValue("signature"))
if err != nil {
return false, err
}
if len(calculatedSignature) != len(signature) {
return false, nil
}
return subtle.ConstantTimeCompare(signature, calculatedSignature) == 1, nil
}