AbstractSecurity::__construct()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 2
eloc 7
c 4
b 0
f 0
nc 2
nop 1
dl 0
loc 14
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace WebServCo\Api;
6
7
use WebServCo\Framework\Exceptions\NotImplementedException;
8
use WebServCo\Framework\Exceptions\Validation\RequiredArgumentException;
9
use WebServCo\Framework\Interfaces\RequestInterface;
10
11
abstract class AbstractSecurity
12
{
13
    /**
14
     * Allowed methods.
15
     *
16
     * @var array<int,string>
17
     */
18
    protected array $allowedMethods;
19
20
    /**
21
     * Client "Accept" content types.
22
     *
23
     * @var array<string,string>
24
     */
25
    protected array $acceptContentTypes;
26
27
    /**
28
     * Supported content types
29
     *
30
     * @var array<int,string>
31
     */
32
    protected array $supportedContentTypes;
33
34
    protected RequestInterface $request;
35
36
    abstract public function verifyAuthorization(): bool;
37
38
    public function __construct(RequestInterface $request)
39
    {
40
        $this->allowedMethods = [];
41
        $this->supportedContentTypes = [];
42
        $this->request = $request;
43
44
        $this->acceptContentTypes = $this->request->getAcceptContentTypes();
45
46
        if (!\array_key_exists('q=0', $this->acceptContentTypes)) {
47
            return;
48
        }
49
50
        // $q == 0 means that mime-type isn’t supported!
51
        unset($this->acceptContentTypes['q=0']);
52
    }
53
54
    public function verify(): bool
55
    {
56
        $this->verifySsl();
57
        $this->verifyMethod();
58
        $this->verifyContentType();
59
        return true;
60
    }
61
62
    /**
63
    * @return array<string,string>
64
    */
65
    public function getClientContentTypes(): array
66
    {
67
        return $this->acceptContentTypes;
68
    }
69
70
    /**
71
    * @param array<int,string> $allowedMethods
72
    */
73
    public function setAllowedMethods(array $allowedMethods): bool
74
    {
75
        $this->allowedMethods = $allowedMethods;
76
        return true;
77
    }
78
79
    /**
80
    * @param array<int,string> $supportedContentTypes
81
    */
82
    public function setSupportedContentTypes(array $supportedContentTypes): bool
83
    {
84
        $this->supportedContentTypes = $supportedContentTypes;
85
        return true;
86
    }
87
88
    protected function verifyContentType(): bool
89
    {
90
        if (empty($this->supportedContentTypes)) {
91
            throw new RequiredArgumentException('Missing supported content types');
92
        }
93
        if (empty($this->acceptContentTypes)) {
94
            throw new RequiredArgumentException('Missing Accept content type');
95
        }
96
        $intersection = \array_intersect($this->acceptContentTypes, $this->supportedContentTypes);
97
        if (empty($intersection)) {
98
            throw new \WebServCo\Framework\Exceptions\UnsupportedMediaTypeException('Unsupported Accept content type');
99
        }
100
        return true;
101
    }
102
103
    protected function verifyMethod(): bool
104
    {
105
        if (empty($this->allowedMethods)) {
106
            throw new NotImplementedException('Method not implemented');
107
        }
108
        if (!\in_array($this->request->getMethod(), $this->allowedMethods, true)) {
109
            throw new \WebServCo\Framework\Exceptions\MethodNotAllowedException('Unsupported method');
110
        }
111
        return true;
112
    }
113
114
    protected function verifySsl(): bool
115
    {
116
        $schema = $this->request->getSchema();
117
        if ('https' !== $schema) {
118
            throw new \WebServCo\Framework\Exceptions\SslRequiredException('SSL required');
119
        }
120
        return true;
121
    }
122
}
123