1package mailgun
2
3import (
4	"crypto/hmac"
5	"crypto/sha256"
6	"crypto/subtle"
7	"encoding/hex"
8	"io"
9	"net/http"
10)
11
12// GetWebhooks returns the complete set of webhooks configured for your domain.
13// Note that a zero-length mapping is not an error.
14func (mg *MailgunImpl) GetWebhooks() (map[string]string, error) {
15	r := newHTTPRequest(generateDomainApiUrl(mg, webhooksEndpoint))
16	r.setClient(mg.Client())
17	r.setBasicAuth(basicAuthUser, mg.ApiKey())
18	var envelope struct {
19		Webhooks map[string]interface{} `json:"webhooks"`
20	}
21	err := getResponseFromJSON(r, &envelope)
22	hooks := make(map[string]string, 0)
23	if err != nil {
24		return hooks, err
25	}
26	for k, v := range envelope.Webhooks {
27		object := v.(map[string]interface{})
28		url := object["url"]
29		hooks[k] = url.(string)
30	}
31	return hooks, nil
32}
33
34// CreateWebhook installs a new webhook for your domain.
35func (mg *MailgunImpl) CreateWebhook(t, u string) error {
36	r := newHTTPRequest(generateDomainApiUrl(mg, webhooksEndpoint))
37	r.setClient(mg.Client())
38	r.setBasicAuth(basicAuthUser, mg.ApiKey())
39	p := newUrlEncodedPayload()
40	p.addValue("id", t)
41	p.addValue("url", u)
42	_, err := makePostRequest(r, p)
43	return err
44}
45
46// DeleteWebhook removes the specified webhook from your domain's configuration.
47func (mg *MailgunImpl) DeleteWebhook(t string) error {
48	r := newHTTPRequest(generateDomainApiUrl(mg, webhooksEndpoint) + "/" + t)
49	r.setClient(mg.Client())
50	r.setBasicAuth(basicAuthUser, mg.ApiKey())
51	_, err := makeDeleteRequest(r)
52	return err
53}
54
55// GetWebhookByType retrieves the currently assigned webhook URL associated with the provided type of webhook.
56func (mg *MailgunImpl) GetWebhookByType(t string) (string, error) {
57	r := newHTTPRequest(generateDomainApiUrl(mg, webhooksEndpoint) + "/" + t)
58	r.setClient(mg.Client())
59	r.setBasicAuth(basicAuthUser, mg.ApiKey())
60	var envelope struct {
61		Webhook struct {
62			Url string `json:"url"`
63		} `json:"webhook"`
64	}
65	err := getResponseFromJSON(r, &envelope)
66	return envelope.Webhook.Url, err
67}
68
69// UpdateWebhook replaces one webhook setting for another.
70func (mg *MailgunImpl) UpdateWebhook(t, u string) error {
71	r := newHTTPRequest(generateDomainApiUrl(mg, webhooksEndpoint) + "/" + t)
72	r.setClient(mg.Client())
73	r.setBasicAuth(basicAuthUser, mg.ApiKey())
74	p := newUrlEncodedPayload()
75	p.addValue("url", u)
76	_, err := makePutRequest(r, p)
77	return err
78}
79
80func (mg *MailgunImpl) VerifyWebhookRequest(req *http.Request) (verified bool, err error) {
81	h := hmac.New(sha256.New, []byte(mg.ApiKey()))
82	io.WriteString(h, req.FormValue("timestamp"))
83	io.WriteString(h, req.FormValue("token"))
84
85	calculatedSignature := h.Sum(nil)
86	signature, err := hex.DecodeString(req.FormValue("signature"))
87	if err != nil {
88		return false, err
89	}
90	if len(calculatedSignature) != len(signature) {
91		return false, nil
92	}
93
94	return subtle.ConstantTimeCompare(signature, calculatedSignature) == 1, nil
95}
96