Completed
Push — master ( 285b1b...2fc430 )
by
unknown
26:57
created

SignatureParameterHandler::normalize()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 9.6666
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 1
crap 2
1
<?php
2
3
namespace MediaMonks\SonataMediaBundle\Handler;
4
5
use MediaMonks\SonataMediaBundle\Exception\SignatureInvalidException;
6
use MediaMonks\SonataMediaBundle\Model\MediaInterface;
7
use MediaMonks\SonataMediaBundle\ParameterBag\ParameterBagInterface;
8
9
class SignatureParameterHandler implements ParameterHandlerInterface
10
{
11
    const PARAMETER_SIGNATURE = 's';
12
    const PARAMETER_BUST_CACHE = 'bc';
13
14
    /**
15
     * @var string
16
     */
17
    private $key;
18
19
    /**
20
     * @var string
21
     */
22
    private $hashAlgorithm;
23
24
    /**
25
     * @param string $key
26
     * @param string $hashAlgorithm
27
     */
28 18
    public function __construct($key, $hashAlgorithm = 'sha256')
29
    {
30 18
        $this->key = $key;
31 18
        $this->hashAlgorithm = $hashAlgorithm;
32 18
    }
33
34
    /**
35
     * @param MediaInterface $media
36
     * @param ParameterBagInterface $parameterBag
37
     * @return array
38
     */
39 8
    public function getRouteParameters(MediaInterface $media, ParameterBagInterface $parameterBag)
40
    {
41 8
        $parameters = $parameterBag->toArray($media);
42 8
        $parameters[self::PARAMETER_SIGNATURE] = $this->calculateSignature($parameters);
43
44 8
        return $parameters;
45
    }
46
47
    /**
48
     * @param MediaInterface $media
49
     * @param ParameterBagInterface $parameterBag
50
     * @return ImageParameterBag|ParameterBagInterface
51
     * @throws SignatureInvalidException
52
     */
53 9
    public function validateParameterBag(MediaInterface $media, ParameterBagInterface $parameterBag)
54
    {
55 9
        $data = $parameterBag->toArray($media);
56
57 9
        if (!isset($data[self::PARAMETER_SIGNATURE])) {
58 1
            throw new SignatureInvalidException();
59
        }
60
61 8
        $signature = $data[self::PARAMETER_SIGNATURE];
62 8
        $parameterBag->removeExtra(self::PARAMETER_SIGNATURE);
63
64 8
        if (!$this->isValid($media, $parameterBag, $signature)) {
65 1
            throw new SignatureInvalidException();
66
        }
67
68 7
        return $parameterBag;
69
    }
70
71
    /**
72
     * @param MediaInterface $media
73
     * @param ParameterBagInterface $parameterBag
74
     * @param $expectedSignature
75
     * @return bool
76
     */
77 8
    private function isValid(MediaInterface $media, ParameterBagInterface $parameterBag, $expectedSignature)
78
    {
79 8
        return hash_equals($this->calculateSignature($parameterBag->toArray($media)), $expectedSignature);
80
    }
81
82
    /**
83
     * @param array $parameters
84
     * @return string
85
     */
86 11
    private function calculateSignature(array $parameters)
87
    {
88 11
        return hash_hmac($this->hashAlgorithm, $this->key, json_encode($this->normalize($parameters)));
89
    }
90
91
    /**
92
     * @param array $parameters
93
     * @return array
94
     */
95 11
    private function normalize(array $parameters)
96
    {
97 11
        if (isset($parameters[self::PARAMETER_BUST_CACHE])) {
98 7
            unset($parameters[self::PARAMETER_BUST_CACHE]);
99
        }
100 11
        ksort($parameters);
101
102 11
        return array_map('strval', $parameters);
103
    }
104
}
105