Passed
Push — 2.x ( 3181da...fa7f46 )
by Terry
01:56
created

Firewall   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 175
Duplicated Lines 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
eloc 61
dl 0
loc 175
rs 10
c 6
b 0
f 0
wmc 16

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A run() 0 37 6
A configure() 0 26 5
A setup() 0 37 1
A add() 0 3 1
A setupChannel() 0 7 2
1
<?php
2
/**
3
 * This file is part of the Shieldon package.
4
 *
5
 * (c) Terry L. <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * php version 7.1.0
11
 *
12
 * @category  Web-security
13
 * @package   Shieldon
14
 * @author    Terry Lin <[email protected]>
15
 * @copyright 2019 terrylinooo
16
 * @license   https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT
17
 * @link      https://github.com/terrylinooo/shieldon
18
 * @see       https://shieldon.io
19
 */
20
21
declare(strict_types=1);
22
23
namespace Shieldon\Firewall;
24
25
use Psr\Http\Message\ServerRequestInterface;
26
use Psr\Http\Message\ResponseInterface;
27
use Psr\Http\Server\MiddlewareInterface;
28
use Shieldon\Firewall\Kernel;
29
use Shieldon\Firewall\Utils\Container;
30
use Shieldon\Firewall\FirewallTrait;
31
use Shieldon\Firewall\Firewall\SetupTrait;
32
use Shieldon\Firewall\Firewall\Messenger\MessengerTrait;
33
use Shieldon\Firewall\Firewall\XssProtectionTrait;
34
use Shieldon\Psr15\RequestHandler;
35
use function Shieldon\Firewall\get_request;
36
use function defined;
37
use function file_exists;
38
use function file_get_contents;
39
use function json_decode;
40
use function rtrim;
41
42
/**
43
 * Managed Firewall.
44
 */
45
class Firewall
46
{
47
    use FirewallTrait;
48
    use SetupTrait;
0 ignored issues
show
introduced by
The trait Shieldon\Firewall\Firewall\SetupTrait requires some properties which are not provided by Shieldon\Firewall\Firewall: $component, $driver
Loading history...
49
    use XssProtectionTrait;
50
    use MessengerTrait;
51
52
    /**
53
     * Collection of PSR-7 or PSR-15 middlewares.
54
     *
55
     * @var array
56
     */
57
    protected $middlewares = [];
58
59
    /**
60
     * Constructor.
61
     * 
62
     * @param ServerRequestInterface|null $request  A PSR-7 server request.
63
     * @param ResponseInterface|null      $response A PSR-7 server response.
64
     */
65
    public function __construct(?ServerRequestInterface $request = null, ?ResponseInterface $response = null)
66
    {
67
        Container::set('firewall', $this);
68
69
        $this->kernel = new Kernel($request, $response);
70
    }
71
72
    /**
73
     * Setup everything we need.
74
     *
75
     * @return void
76
     */
77
    public function setup(): void
78
    {
79
        $this->status = $this->getOption('daemon');
80
81
        $this->setupDriver();
82
83
        $this->setupChannel();
84
85
        $this->setupFilters();
86
87
        $this->setupComponents();
88
89
        $this->setupIpSource();
90
91
        $this->setupLogger();
92
93
        $this->setupLimitSession();
94
95
        $this->setupCronJob();
96
97
        $this->setupExcludedUrls();
98
99
        $this->setupXssProtection();
0 ignored issues
show
Bug introduced by
The method setupXssProtection() does not exist on Shieldon\Firewall\Firewall. Did you maybe mean setXssProtection()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

99
        $this->/** @scrutinizer ignore-call */ 
100
               setupXssProtection();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
100
101
        $this->setupPageAuthentication();
102
103
        $this->setupDialogUserInterface();
104
105
        $this->setupMessengers();
0 ignored issues
show
Bug introduced by
The method setupMessengers() does not exist on Shieldon\Firewall\Firewall. Did you maybe mean setMessengers()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

105
        $this->/** @scrutinizer ignore-call */ 
106
               setupMessengers();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
106
107
        $this->setupCaptchas();
108
109
        $this->setupMessageEvents();
0 ignored issues
show
Bug introduced by
The method setupMessageEvents() does not exist on Shieldon\Firewall\Firewall. Did you maybe mean setMessageEvents()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

109
        $this->/** @scrutinizer ignore-call */ 
110
               setupMessageEvents();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
110
111
        $this->setupDenyTooManyAttempts();
112
113
        $this->setupIptablesBridgeDirectory();
114
    }
115
116
    /**
117
     * Set up the path of the configuration file.
118
     *
119
     * @param string $source The path.
120
     * @param string $type   The type.
121
     * 
122
     * @return void
123
     */
124
    public function configure(string $source, string $type = 'json'): void
125
    {
126
        if ($type === 'json') {
127
            $this->directory = rtrim($source, '\\/');
128
            $configFilePath = $this->directory . '/' . $this->filename;
129
130
            if (file_exists($configFilePath)) {
131
                $jsonString = file_get_contents($configFilePath);
132
133
            } else {
134
                $jsonString = file_get_contents(__DIR__ . '/../../config.json');
135
136
                if (defined('PHP_UNIT_TEST')) {
137
                    $jsonString = file_get_contents(__DIR__ . '/../../tests/config.json');
138
                }
139
            }
140
141
            $this->configuration = json_decode($jsonString, true);
142
            $this->kernel->managedBy('managed');
143
144
        } elseif ($type === 'php') {
145
            $this->configuration = include $source;
146
            $this->kernel->managedBy('config');
147
        }
148
149
        $this->setup();
150
    }
151
152
    /**
153
     * Just, run!
154
     *
155
     * @return ResponseInterface
156
     */
157
    public function run(): ResponseInterface
158
    {
159
        // If settings are ready, let's start monitoring requests.
160
        if ($this->status) {
161
162
            $response = get_request();
163
164
            // PSR-15 request handler.
165
            $requestHandler = new RequestHandler();
166
167
            foreach ($this->middlewares as $middleware) {
168
                $requestHandler->add($middleware);
169
            }
170
171
            $response = $requestHandler->handle($response);
172
173
            // Something is detected by Middlewares, return.
174
            if ($response->getStatusCode() !== $this->kernel::HTTP_STATUS_OK) {
175
                return $response;
176
            }
177
178
            $result = $this->kernel->run();
179
180
            if ($result !== $this->kernel::RESPONSE_ALLOW) {
181
182
                if ($this->kernel->captchaResponse()) {
183
                    $this->kernel->unban();
184
185
                    $response = $response->withHeader('Location', $this->kernel->getCurrentUrl());
186
                    $response = $response->withStatus($this->kernel::HTTP_STATUS_SEE_OTHER);
187
188
                    return $response;
189
                }
190
            }
191
        }
192
193
        return $this->kernel->respond();
194
    }
195
196
    /**
197
     * Add middlewares and use them before going into Shieldon kernal.
198
     *
199
     * @param MiddlewareInterface $middleware A PSR-15 middlewares.
200
     *
201
     * @return void
202
     */
203
    public function add(MiddlewareInterface $middleware): void
204
    {
205
        $this->middlewares[] = $middleware;
206
    }
207
208
    /**
209
     * Set the channel ID.
210
     *
211
     * @return void
212
     */
213
    protected function setupChannel(): void
214
    {
215
        $channelId = $this->getOption('channel_id');
216
217
        if ($channelId) {
218
            $this->kernel->setChannel($channelId);
219
            $this->channel = $channelId;
220
        }
221
    }
222
}
223