Completed
Pull Request — master (#37)
by Thierry
05:33
created

sealHttpFoundationResponse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace lepiaf\SapientBundle\EventSubscriber;
5
6
use lepiaf\SapientBundle\Exception\SealResponseException;
7
use lepiaf\SapientBundle\Exception\WrongKeyException;
8
use lepiaf\SapientBundle\Service\PublicKeyGetter;
9
use ParagonIE\ConstantTime\Base64UrlSafe;
10
use ParagonIE\Sapient\CryptographyKeys\SealingPublicKey;
11
use ParagonIE\Sapient\Sapient;
12
use Psr\Http\Message\ResponseInterface;
13
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
14
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
15
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
16
use Symfony\Component\HttpFoundation\Request;
17
use Symfony\Component\HttpFoundation\Response;
18
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
19
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
20
use Symfony\Component\HttpKernel\KernelEvents;
21
22
class SealResponseSubscriber implements EventSubscriberInterface
23
{
24
    /**
25
     * @var HttpFoundationFactory
26
     */
27
    private $httpFoundationFactory;
28
29
    /**
30
     * @var PublicKeyGetter
31
     */
32
    private $publicKeyGetter;
33
34
    /**
35
     * @var Sapient
36
     */
37
    private $sapient;
38
39
    /**
40
     * @var DiactorosFactory
41
     */
42
    private $diactorosFactory;
43
44 3
    public function __construct(HttpFoundationFactory $httpFoundationFactory, DiactorosFactory $diactorosFactory, Sapient $sapient, PublicKeyGetter $publicKeyGetter)
45
    {
46 3
        $this->httpFoundationFactory = $httpFoundationFactory;
47 3
        $this->diactorosFactory = $diactorosFactory;
48 3
        $this->sapient = $sapient;
49 3
        $this->publicKeyGetter = $publicKeyGetter;
50 3
    }
51
52 1
    public static function getSubscribedEvents()
53
    {
54
        return [
55 1
            KernelEvents::VIEW => ['sealPsrResponse', -110],
56 1
            KernelEvents::RESPONSE => ['sealHttpFoundationResponse', -110],
57
        ];
58
    }
59
60 1
    public function sealHttpFoundationResponse(FilterResponseEvent $event): void
61
    {
62 1
        $publicKey = $this->getSealingKey($event->getRequest());
63 1
        $psrResponse = $this->diactorosFactory->createResponse($event->getResponse());
64 1
        $event->setResponse($this->sealResponse($psrResponse, $publicKey));
65 1
    }
66
67 2
    public function sealPsrResponse(GetResponseForControllerResultEvent $event): void
68
    {
69 2
        $response = $event->getControllerResult();
70 2
        if (!$response instanceof ResponseInterface) {
71 1
            return;
72
        }
73
74 1
        $publicKey = $this->getSealingKey($event->getRequest());
75 1
        $event->setResponse($this->sealResponse($response, $publicKey));
76 1
    }
77
78 2
    private function sealResponse(ResponseInterface $response, string $publicKey): Response
79
    {
80
        try {
81 2
            $psrResponse = $this->sapient->sealResponse($response, new SealingPublicKey(Base64UrlSafe::decode($publicKey)));
82
        } catch (\RangeException $rangeException) {
83
            throw new WrongKeyException($rangeException->getMessage());
84
        } catch (\SodiumException $sodiumException) {
85
            throw new SealResponseException('Cannot seal response.');
86
        }
87
88 2
        return $this->httpFoundationFactory->createResponse($psrResponse);
89
    }
90
91 2
    private function getSealingKey(Request $request)
92
    {
93 2
        $psrRequest = $this->diactorosFactory->createRequest($request);
94
95 2
        return $this->publicKeyGetter->getSealingKey($psrRequest);
96
    }
97
}
98