Passed
Push — 2.x ( fd069b...31976b )
by Terry
02:06
created

Firewall::controlPanel()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 9
rs 10
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
    /**
48
     *   Public methods       | Desctiotion
49
     *  ----------------------|---------------------------------------------
50
     *   setup                | Apply all setup proccesses.
51
     *   configure            | The absolute path of a dictionary for storing data.
52
     *   run                  | Execute the firewall.
53
     *   add                  | Add a PRS-15 middleware used before firewall.
54
     *   controlPanel         | Set the base URL of the control panel.
55
     *  ----------------------|---------------------------------------------
56
     */
57
58
    /**
59
     *   Public methods       | Desctiotion
60
     *  ----------------------|---------------------------------------------
61
     *   getKernel            | Get the Shieldon Kernel instance.
62
     *   getConfiguration     | Get the configuration data.
63
     *   getDirectory         | Get the dictionary where the data is stored.
64
     *   getFileName          | Get the path of the configuration file.
65
     *   getConfig            | Get the value by identification string.
66
     *   setConfig            | Set the value by identification string.
67
     *  ----------------------|---------------------------------------------
68
     */
69
    use FirewallTrait;
70
71
    /**
72
     *   Public methods       | Desctiotion
73
     *  ----------------------|---------------------------------------------
74
     *                        | No public methods.
75
     *  ----------------------|---------------------------------------------
76
     */
77
    use SetupTrait;
1 ignored issue
show
introduced by
The trait Shieldon\Firewall\Firewall\SetupTrait requires some properties which are not provided by Shieldon\Firewall\Firewall: $component, $driver
Loading history...
78
79
    /**
80
     *   Public methods       | Desctiotion
81
     *  ----------------------|---------------------------------------------
82
     *                        | No public methods.
83
     *  ----------------------|---------------------------------------------
84
     */
85
    use XssProtectionTrait;
86
87
    /**
88
     *   Public methods       | Desctiotion
89
     *  ----------------------|---------------------------------------------
90
     *                        | No public methods.
91
     *  ----------------------|---------------------------------------------
92
     */
93
    use MessengerTrait;
94
95
    /**
96
     * Collection of PSR-7 or PSR-15 middlewares.
97
     *
98
     * @var array
99
     */
100
    protected $middlewares = [];
101
102
    /**
103
     * The URI of the control panel.
104
     *
105
     * @var string
106
     */
107
    protected $controlPanelUri = '';
108
109
    /**
110
     * Constructor.
111
     * 
112
     * @param ServerRequestInterface|null $request  A PSR-7 server request.
113
     * @param ResponseInterface|null      $response A PSR-7 server response.
114
     */
115
    public function __construct(?ServerRequestInterface $request = null, ?ResponseInterface $response = null)
116
    {
117
        Container::set('firewall', $this);
118
119
        $this->kernel = new Kernel($request, $response);
120
    }
121
122
    /**
123
     * Set up everything we need.
124
     *
125
     * @return void
126
     */
127
    public function setup(): void
128
    {
129
        $this->status = $this->getOption('daemon');
130
131
        $setupFunctions = [
132
            'Driver',
133
            'Channel',
134
            'Filters',
135
            'Components',
136
            'IpSource',
137
            'Logger',
138
            'LimitSession',
139
            'CronJob',
140
            'ExcludedUrls',
141
            'XssProtection',
142
            'PageAuthentication',
143
            'DialogUserInterface',
144
            'Messengers',
145
            'Captchas',
146
            'MessageEvents',
147
            'DenyTooManyAttempts',
148
            'IptablesBridgeDirectory',
149
        ];
150
151
        foreach ($setupFunctions as $func) {
152
            $function = 'setup' . $func;
153
154
            $this->{$function}();
155
        }
156
    }
157
158
    /**
159
     * Set up the path of the configuration file.
160
     *
161
     * @param string $source The path.
162
     * @param string $type   The type.
163
     * 
164
     * @return void
165
     */
166
    public function configure(string $source, string $type = 'json'): void
167
    {
168
        if ($type === 'json') {
169
            $this->directory = rtrim($source, '\\/');
170
            $configFilePath = $this->directory . '/' . $this->filename;
171
172
            if (file_exists($configFilePath)) {
173
                $jsonString = file_get_contents($configFilePath);
174
175
            } else {
176
                $jsonString = file_get_contents(__DIR__ . '/../../config.json');
177
178
                if (defined('PHP_UNIT_TEST')) {
179
                    $jsonString = file_get_contents(__DIR__ . '/../../tests/config.json');
180
                }
181
            }
182
183
            $this->configuration = json_decode($jsonString, true);
184
            $this->kernel->managedBy('managed');
185
186
        } elseif ($type === 'php') {
187
            $this->configuration = include $source;
188
            $this->kernel->managedBy('config');
189
        }
190
191
        $this->setup();
192
    }
193
194
    /**
195
     * Just, run!
196
     *
197
     * @return ResponseInterface
198
     */
199
    public function run(): ResponseInterface
200
    {
201
        // If settings are ready, let's start monitoring requests.
202
        if ($this->status) {
203
204
            $response = get_request();
205
206
            // PSR-15 request handler.
207
            $requestHandler = new RequestHandler();
208
209
            foreach ($this->middlewares as $middleware) {
210
                $requestHandler->add($middleware);
211
            }
212
213
            $response = $requestHandler->handle($response);
214
215
            // Something is detected by Middlewares, return.
216
            if ($response->getStatusCode() !== $this->kernel::HTTP_STATUS_OK) {
217
                return $response;
218
            }
219
220
            $result = $this->kernel->run();
221
222
            if ($result !== $this->kernel::RESPONSE_ALLOW) {
223
224
                if ($this->kernel->captchaResponse()) {
225
                    $this->kernel->unban();
226
227
                    $response = $response->withHeader('Location', $this->kernel->getCurrentUrl());
228
                    $response = $response->withStatus($this->kernel::HTTP_STATUS_SEE_OTHER);
229
230
                    return $response;
231
                }
232
            }
233
        }
234
235
        return $this->kernel->respond();
236
    }
237
238
    /**
239
     * Add middlewares and use them before going into Shieldon kernal.
240
     *
241
     * @param MiddlewareInterface $middleware A PSR-15 middlewares.
242
     *
243
     * @return void
244
     */
245
    public function add(MiddlewareInterface $middleware): void
246
    {
247
        $this->middlewares[] = $middleware;
248
    }
249
250
    /**
251
     * The base URL for control panel.
252
     *
253
     * @param string $uri The path component of a URI
254
     *
255
     * @return string
256
     */
257
    public function controlPanel(string $uri = ''): string
258
    {
259
        if (!empty($uri)) {
260
            $uri = '/' . trim($uri, '/');
261
            $this->controlPanelUri = $uri;
262
            $this->getKernel()->exclude($this->controlPanelUri);
263
        }
264
265
        return $this->controlPanelUri;
266
    }
267
268
    /**
269
     * Set the channel ID.
270
     *
271
     * @return void
272
     */
273
    protected function setupChannel(): void
274
    {
275
        $channelId = $this->getOption('channel_id');
276
277
        if ($channelId) {
278
            $this->kernel->setChannel($channelId);
279
            $this->channel = $channelId;
280
        }
281
    }
282
}
283