MandrillController::getWebHookKey()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 9
rs 10
1
<?php
2
3
namespace LeKoala\Mandrill;
4
5
use Psr\Log\LoggerInterface;
6
use SilverStripe\Control\Controller;
7
use SilverStripe\Control\HTTPRequest;
8
use SilverStripe\Control\HTTPResponse;
9
use SilverStripe\Core\Environment;
10
11
/**
12
 * Provide extensions points for handling the webhook
13
 *
14
 * @author LeKoala <[email protected]>
15
 */
16
class MandrillController extends Controller
17
{
18
    const EVENT_SEND = 'send';
19
    const EVENT_HARD_BOUNCE = 'hard_bounce';
20
    const EVENT_SOFT_BOUNCE = 'soft_bounce';
21
    const EVENT_OPEN = 'open';
22
    const EVENT_CLICK = 'click';
23
    const EVENT_SPAM = 'spam';
24
    const EVENT_UNSUB = 'unsub';
25
    const EVENT_REJECT = 'reject';
26
    const EVENT_INBOUND = 'inbound';
27
    const EVENT_WHITELIST = 'whitelist';
28
    const EVENT_BLACKLIST = 'blacklist';
29
30
    protected $eventsCount = 0;
31
    protected $skipCount = 0;
32
    private static $allowed_actions = [
0 ignored issues
show
introduced by
The private property $allowed_actions is not used, and could be removed.
Loading history...
33
        'incoming',
34
    ];
35
36
    private static $webhook_auth_enabled = false;
37
38
    /**
39
     * Inject public dependencies into the controller
40
     *
41
     * @var array
42
     */
43
    private static $dependencies = [
0 ignored issues
show
introduced by
The private property $dependencies is not used, and could be removed.
Loading history...
44
        'logger' => '%$Psr\Log\LoggerInterface',
45
    ];
46
47
    /**
48
     * @var LoggerInterface
49
     */
50
    public $logger;
51
52
    /**
53
     * Handle incoming webhook
54
     *
55
     * @link http://help.mandrill.com/entries/21738186-introduction-to-webhooks
56
     * @link http://help.mandrill.com/entries/22092308-What-is-the-format-of-inbound-email-webhooks-
57
     * @param HTTPRequest $req
58
     * @return HTTPResponse
59
     */
60
    public function incoming(HTTPRequest $req)
61
    {
62
        $generatedSignature = $this->generateSignature($req->postVars());
63
        $mandrillSignature = $req->getHeader('X-Mandrill-Signature');
64
        $json = $req->postVar('mandrill_events');
65
66
        // By default, return a valid response
67
        $response = $this->getResponse();
68
        $response->setStatusCode(200);
69
        $response->setBody('');
70
71
        //make sure the generated signature matches the X-Mandrill-Signature header
72
        if (self::config()->webhook_auth_enabled && $generatedSignature !== $mandrillSignature) {
73
            return $response;
74
        }
75
76
        if (!$json) {
77
            return $response;
78
        }
79
80
        $events = json_decode($json);
81
82
        foreach ($events as $ev) {
83
            $this->handleAnyEvent($ev);
84
85
            $event = $ev->event;
86
            switch ($event) {
87
                // Sync type
88
                case self::EVENT_BLACKLIST:
89
                case self::EVENT_WHITELIST:
90
                    $this->handleSyncEvent($ev);
91
                    break;
92
                // Inbound type
93
                case self::EVENT_INBOUND:
94
                    $this->handleInboundEvent($ev);
95
                    break;
96
                // Message type
97
                case self::EVENT_CLICK:
98
                case self::EVENT_HARD_BOUNCE:
99
                case self::EVENT_OPEN:
100
                case self::EVENT_REJECT:
101
                case self::EVENT_SEND:
102
                case self::EVENT_SOFT_BOUNCE:
103
                case self::EVENT_SPAM:
104
                case self::EVENT_UNSUB:
105
                    $this->handleMessageEvent($ev);
106
                    break;
107
            }
108
        }
109
        return $response;
110
    }
111
112
    protected function handleAnyEvent($e)
113
    {
114
        $this->extend('updateHandleAnyEvent', $e);
115
    }
116
117
    protected function handleSyncEvent($e)
118
    {
119
        $this->extend('updateHandleSyncEvent', $e);
120
    }
121
122
    protected function handleInboundEvent($e)
123
    {
124
        $this->extend('updateHandleInboundEvent', $e);
125
    }
126
127
    protected function handleMessageEvent($e)
128
    {
129
        $this->extend('updateHandleMessageEvent', $e);
130
    }
131
132
    /**
133
     * Get logger
134
     *
135
     * @return LoggerInterface
136
     */
137
    public function getLogger()
138
    {
139
        return $this->logger;
140
    }
141
142
    /**
143
     * returns the webhook key
144
     *
145
     * @return string
146
     */
147
    public function getWebHookKey()
148
    {
149
        $key = Environment::getEnv('MANDRILL_WEBHOOK_KEY');
150
151
        if (self::config()->webhook_key) {
152
            $key = self::config()->webhook_key;
153
        }
154
155
        return $key;
156
    }
157
158
    /**
159
     * generates signature to verify request is from mailchimp.
160
     * see https://mailchimp.com/developer/transactional/guides/track-respond-activity-webhooks/#authenticating-webhook-requests
161
     *
162
     * @param Array $postVars
163
     * @return string
164
     */
165
    protected function generateSignature(array $postVars)
166
    {
167
        ksort($postVars);
168
        $data = MandrillAdmin::create()->singleton()->WebhookUrl();
169
        $webHookKey = $this->getWebHookKey();
170
171
        foreach ($postVars as $key => $value) {
172
            $data .= $key;
173
            $data .= $value;
174
        }
175
176
        return base64_encode(hash_hmac('sha1', $data, $webHookKey, true));
177
    }
178
}
179