Passed
Push — 2.x ( dbec36...335e99 )
by Terry
01:51
created

Report   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 268
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 149
dl 0
loc 268
rs 9.92
c 2
b 0
f 0
wmc 31

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A operationTemplateVarsOfComponents() 0 11 6
C operationTemplateVarsOfStatistics() 0 84 16
A operationTemplateVarsOfFilters() 0 10 1
B actionLog() 0 70 6
A operation() 0 44 1
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
11
declare(strict_types=1);
12
13
namespace Shieldon\Firewall\Panel;
14
15
use Psr\Http\Message\ResponseInterface;
16
use Shieldon\Firewall\Panel\BaseController;
17
use Shieldon\Firewall\Log\ActionLogParsedCache;
18
use function Shieldon\Firewall\__;
19
use function Shieldon\Firewall\get_request;
20
21
use ReflectionObject;
22
use function date;
23
24
/**
25
 * The report controller.
26
 */
27
class Report extends BaseController
28
{
29
    /**
30
     * Constructor
31
     */
32
    public function __construct() 
33
    {
34
        parent::__construct();
35
    }
36
37
    /**
38
     * Operation status.
39
     *
40
     * @return \Psr\Http\Message\ResponseInterface
41
     */
42
    public function operation(): ResponseInterface
43
    {
44
        $data = [];
45
46
        $data = $this->operationTemplateVarsOfComponents($data);
47
        $data = $this->operationTemplateVarsOfFilters($data);
48
        $data = $this->operationTemplateVarsOfStatistics($data);
49
50
        $reasons = [
51
            $this->kernel::REASON_MANUAL_BAN              => __('panel', 'reason_manual_ban', 'Added manually by administrator'),
52
            $this->kernel::REASON_IS_SEARCH_ENGINE        => __('panel', 'reason_is_search_engine', 'Search engine bot'),
53
            $this->kernel::REASON_IS_GOOGLE               => __('panel', 'reason_is_google', 'Google bot'),
54
            $this->kernel::REASON_IS_BING                 => __('panel', 'reason_is_bing', 'Bing bot'),
55
            $this->kernel::REASON_IS_YAHOO                => __('panel', 'reason_is_yahoo', 'Yahoo bot'),
56
            $this->kernel::REASON_TOO_MANY_SESSIONS       => __('panel', 'reason_too_many_sessions', 'Too many sessions'),
57
            $this->kernel::REASON_TOO_MANY_ACCESSES       => __('panel', 'reason_too_many_accesses', 'Too many accesses'),
58
            $this->kernel::REASON_EMPTY_JS_COOKIE         => __('panel', 'reason_empty_js_cookie', 'Cannot create JS cookies'),
59
            $this->kernel::REASON_EMPTY_REFERER           => __('panel', 'reason_empty_referer', 'Empty referrer'),
60
            $this->kernel::REASON_REACHED_LIMIT_DAY       => __('panel', 'reason_reached_limit_day', 'Daily limit reached'),
61
            $this->kernel::REASON_REACHED_LIMIT_HOUR      => __('panel', 'reason_reached_limit_hour', 'Hourly limit reached'),
62
            $this->kernel::REASON_REACHED_LIMIT_MINUTE    => __('panel', 'reason_reached_limit_minute', 'Minutely limit reached'),
63
            $this->kernel::REASON_REACHED_LIMIT_SECOND    => __('panel', 'reason_reached_limit_second', 'Secondly limit reached'),
64
            $this->kernel::REASON_INVALID_IP              => __('panel', 'reason_invalid_ip', 'Invalid IP address.'),
65
            $this->kernel::REASON_DENY_IP                 => __('panel', 'reason_deny_ip', 'Denied by IP component.'),
66
            $this->kernel::REASON_ALLOW_IP                => __('panel', 'reason_allow_ip', 'Allowed by IP component.'),
67
            $this->kernel::REASON_COMPONENT_IP            => __('panel', 'reason_component_ip', 'Denied by IP component.'),
68
            $this->kernel::REASON_COMPONENT_RDNS          => __('panel', 'reason_component_rdns', 'Denied by RDNS component.'),
69
            $this->kernel::REASON_COMPONENT_HEADER        => __('panel', 'reason_component_header', 'Denied by Header component.'),
70
            $this->kernel::REASON_COMPONENT_USERAGENT     => __('panel', 'reason_component_useragent', 'Denied by User-agent component.'),
71
            $this->kernel::REASON_COMPONENT_TRUSTED_ROBOT => __('panel', 'reason_component_trusted_robot', 'Identified as fake search engine.'),
72
        ];
73
74
        $types = [
75
            $this->kernel::ACTION_DENY             => 'DENY',
76
            $this->kernel::ACTION_ALLOW            => 'ALLOW',
77
            $this->kernel::ACTION_TEMPORARILY_DENY => 'CAPTCHA',
78
        ];
79
80
        $data['reason_mapping'] = $reasons;
81
        $data['type_mapping'] = $types;
82
83
        $data['title'] = __('panel', 'title_operation_status', 'Operation Status');
84
85
        return $this->renderPage('panel/operation_status', $data);
86
    }
87
88
    /**
89
     * Action logs
90
     *
91
     * @return \Psr\Http\Message\ResponseInterface
92
     */
93
    public function actionLog(): ResponseInterface
94
    {
95
        $getParams = get_request()->getQueryParams();
96
97
        $tab = $getParams['tab'] ?? 'today';
98
99
        $validTabs = [
100
            'yesterday',
101
            'this_month',
102
            'last_month',
103
            'past_seven_days',
104
            'today',
105
        ];
106
107
        if (!in_array($tab, $validTabs)) {
108
            $type = 'today';
109
        }
110
111
        $data['ip_details'] = [];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.
Loading history...
112
        $data['period_data'] = [];
113
        
114
        $lastCachedTime = '';
115
116
        if (!empty($this->parser)) {
117
118
            $logCacheHandler = new ActionLogParsedCache($this->parser->getDirectory());
119
120
            $ipDetailsCachedData = $logCacheHandler->get($type);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $type does not seem to be defined for all execution paths leading up to this point.
Loading history...
121
122
            // If we have cached data then we don't need to parse them again.
123
            // This will save a lot of time in parsing logs.
124
            if (!empty($ipDetailsCachedData)) {
125
126
                $data['ip_details'] = $ipDetailsCachedData['ip_details'];
127
                $data['period_data'] = $ipDetailsCachedData['period_data'];
128
                $lastCachedTime = date('Y-m-d H:i:s', $ipDetailsCachedData['time']);
129
    
130
                if ('today' === $type ) {
131
                    $ipDetailsCachedData = $logCacheHandler->get('past_seven_hours');
132
                    $data['past_seven_hours'] = $ipDetailsCachedData['period_data'];
133
                }
134
135
            } else {
136
137
                $this->parser->prepare($type);
138
139
                $data['ip_details'] = $this->parser->getIpData();
140
                $data['period_data'] = $this->parser->getParsedPeriodData();
141
142
                $logCacheHandler->save($type, $data);
143
    
144
                if ('today' === $type ) {
145
                    $this->parser->prepare('past_seven_hours');
146
                    $data['past_seven_hours'] = $this->parser->getParsedPeriodData();
147
148
                    $logCacheHandler->save('past_seven_hours', [
149
                        'period_data' => $data['past_seven_hours']
150
                    ]);
151
                }
152
            }
153
        }
154
155
        $data['page_availability'] = $this->pageAvailability['logs'];
156
        $data['last_cached_time'] = $lastCachedTime;
157
158
        $data['page_url'] = $this->url('report/actionLog');
159
160
        $data['title'] = __('panel', 'title_action_logs', 'Action Logs');
161
162
        return $this->renderPage('panel/action_log_' . $type, $data);
163
    }
164
165
    /**
166
     * Template variables of the section Components in page Operation.
167
     *
168
     * @param array $data The template varibles.
169
     *
170
     * @return array
171
     */
172
    private function operationTemplateVarsOfComponents(array $data = []): array
173
    {
174
        $data['components'] = [
175
            'Ip'         => (!empty($this->kernel->component['Ip']))         ? true : false,
176
            'TrustedBot' => (!empty($this->kernel->component['TrustedBot'])) ? true : false,
177
            'Header'     => (!empty($this->kernel->component['Header']))     ? true : false,
178
            'Rdns'       => (!empty($this->kernel->component['Rdns']))       ? true : false,
179
            'UserAgent'  => (!empty($this->kernel->component['UserAgent']))  ? true : false,
180
        ];
181
182
        return $data;
183
    }
184
185
    /**
186
     * Template variables of the section Filters in the page Operation.
187
     *
188
     * @param array $data The template varibles.
189
     *
190
     * @return array
191
     */
192
    private function operationTemplateVarsOfFilters(array $data = []): array
193
    {
194
        $reflection = new ReflectionObject($this->kernel);
195
        $t = $reflection->getProperty('filterStatus');
196
        $t->setAccessible(true);
197
        $filterStatus = $t->getValue($this->kernel);
198
199
        $data['filters'] = $filterStatus;
200
201
        return $data;
202
    }
203
204
    /**
205
     * Template variables of the counters for statistics in the page Operation.
206
     *
207
     * @param array $data The template varibles.
208
     *
209
     * @return array
210
     */
211
    private function operationTemplateVarsOfStatistics(array $data = []): array
212
    {
213
        $ruleList = $this->kernel->driver->getAll('rule');
214
215
        $data['component_ip'] = 0;
216
        $data['component_trustedbot'] = 0;
217
        $data['component_rdns'] = 0;
218
        $data['component_header'] = 0;
219
        $data['component_useragent'] = 0;
220
221
        $data['filter_frequency'] = 0;
222
        $data['filter_referer'] = 0;
223
        $data['filter_cookie'] = 0;
224
        $data['filter_session'] = 0;
225
226
        // Components.
227
        $data['rule_list']['ip'] = [];
228
        $data['rule_list']['trustedbot'] = [];
229
        $data['rule_list']['rdns'] = [];
230
        $data['rule_list']['header'] = [];
231
        $data['rule_list']['useragent'] = [];
232
233
        // Filters.
234
        $data['rule_list']['frequency'] = [];
235
        $data['rule_list']['referer'] = [];
236
        $data['rule_list']['cookie'] = [];
237
        $data['rule_list']['session'] = [];
238
239
        foreach ($ruleList as $ruleInfo) {
240
    
241
            switch ($ruleInfo['reason']) {
242
                case $this->kernel::REASON_DENY_IP:
243
                case $this->kernel::REASON_COMPONENT_IP:
244
                    $data['component_ip']++;
245
                    $data['rule_list']['ip'][] = $ruleInfo;
246
                    break;
247
248
                case $this->kernel::REASON_COMPONENT_RDNS:
249
                    $data['component_rdns']++;
250
                    $data['rule_list']['rdns'][] = $ruleInfo;
251
                    break;
252
                
253
                case $this->kernel::REASON_COMPONENT_HEADER:
254
                    $data['component_header']++;
255
                    $data['rule_list']['header'][] = $ruleInfo;
256
                    break;
257
258
                case $this->kernel::REASON_COMPONENT_USERAGENT:
259
                    $data['component_useragent']++;
260
                    $data['rule_list']['useragent'][] = $ruleInfo;
261
                    break;
262
263
                case $this->kernel::REASON_COMPONENT_TRUSTED_ROBOT:
264
                    $data['component_trustedbot']++;
265
                    $data['rule_list']['trustedbot'][] = $ruleInfo;
266
                    break;
267
268
                case $this->kernel::REASON_TOO_MANY_ACCESSES:
269
                case $this->kernel::REASON_REACHED_LIMIT_DAY:
270
                case $this->kernel::REASON_REACHED_LIMIT_HOUR:
271
                case $this->kernel::REASON_REACHED_LIMIT_MINUTE:
272
                case $this->kernel::REASON_REACHED_LIMIT_SECOND:
273
                    $data['filter_frequency']++;
274
                    $data['rule_list']['frequency'][] = $ruleInfo;
275
                    break;
276
277
                case $this->kernel::REASON_EMPTY_REFERER:
278
                    $data['filter_referer']++;
279
                    $data['rule_list']['referer'][] = $ruleInfo;
280
                    break;
281
282
                case $this->kernel::REASON_EMPTY_JS_COOKIE:
283
                    $data['filter_cookie']++;
284
                    $data['rule_list']['cookie'][] = $ruleInfo;
285
                    break;
286
287
                case $this->kernel::REASON_TOO_MANY_SESSIONS:
288
                    $data['filter_session']++;
289
                    $data['rule_list']['session'][] = $ruleInfo;
290
                    break;
291
            }
292
        }
293
294
        return $data;
295
    }
296
}
297
298