GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( 444a03...8c5a45 )
by Brett
12:38
created

Audit::getEntry()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 7
nc 3
nop 2
dl 0
loc 11
ccs 2
cts 2
cp 1
crap 5
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * This serves as both the Module for the MVC part of the audit and the configuration/entry point for the actual
4
 * audit process.
5
 *
6
 * @author    Steve Guns <[email protected]>
7
 * @package   com.bedezign.yii2.audit
8
 * @copyright 2014-2015 B&E DeZign
9
 */
10
11
namespace bedezign\yii2\audit;
12
13
use bedezign\yii2\audit\components\panels\Panel;
14
use bedezign\yii2\audit\models\AuditEntry;
15
use Yii;
16
use yii\base\ActionEvent;
17
use yii\base\Application;
18
use yii\base\InvalidConfigException;
19
use yii\base\InvalidParamException;
20
use yii\base\Module;
21
use yii\helpers\ArrayHelper;
22
23
/**
24
 * Audit main module.
25
 *
26
 * This module is also responsible for starting the audit process.
27
 * To configure it you need to do 2 things:
28
 * - add a module configuration entry:
29
 *     'modules' => [
30
 *        'audit' => 'bedezign\yii2\audit\Audit',
31
 *     ]
32
 *   or optionally with configuration:
33
 *     'modules' => [
34
 *        'audit' => [
35
 *            'class' => 'bedezign\yii2\audit\Audit',
36
 *            'ignoreActions' => ['debug/*']
37
 *     ]
38
 * - If you want to auto track actions, be sure to add the module to the application bootstrapping:
39
 *    'bootstrap' => ['audit'],
40
 *
41
 * @package bedezign\yii2\audit
42
 * @property AuditEntry $entry
43
 *
44
 * @method void data($type, $data)                                                                      @see ExtraDataPanel::trackData()
45
 * @method \bedezign\yii2\audit\models\AuditError exception(\Exception $exception)                      @see ErrorPanel::log()
46
 * @method \bedezign\yii2\audit\models\AuditError errorMessage($message, $code, $file, $line, $trace)   @see ErrorPanel::logMessage()
47
 */
48
class Audit extends Module
49
{
50
    /**
51
     * @var string|boolean the layout that should be applied for views within this module. This refers to a view name
52
     * relative to [[layoutPath]]. If this is not set, it means the layout value of the [[module|parent module]]
53
     * will be taken. If this is false, layout will be disabled within this module.
54
     */
55
    public $layout = 'main';
56
57
    /**
58
     * @var string name of the component to use for database access
59
     */
60
    public $db = 'db';
61
62
    /**
63
     * @var string[] Action or list of actions to track. '*' is allowed as the first or last character to use as wildcard.
64
     */
65
    public $trackActions = ['*'];
66
67
    /**
68
     * @var string[] Action or list of actions to ignore. '*' is allowed as the first or last character to use as wildcard (eg 'debug/*').
69
     */
70
    public $ignoreActions = [];
71
72
    /**
73
     * @var int Maximum age (in days) of the audit entries before they are truncated
74
     */
75
    public $maxAge = null;
76
77
    /**
78
     * @var string[] IP address or list of IP addresses with access to the viewer, null for everyone (if the IP matches)
79
     * An IP address can contain the wildcard `*` at the end so that it matches IP addresses with the same prefix.
80
     * For example, '192.168.*' matches all IP addresses in the segment '192.168.'.
81
     */
82
    public $accessIps = null;
83
84
    /**
85
     * @var string[] Role or list of roles with access to the viewer, null for everyone (if the user matches)
86
     */
87
    public $accessRoles = ['admin'];
88
89
    /**
90
     * @var int[] User ID or list of user IDs with access to the viewer, null for everyone (if the role matches)
91
     */
92
    public $accessUsers = null;
93
94
    /**
95
     * @var bool Compress extra data generated or just keep in text? For people who don't like binary data in the DB
96
     */
97
    public $compressData = true;
98
99
    /**
100
     * @var string The callback to use to convert a user id into an identifier (username, email, ...). Can also be html.
101
     */
102
    public $userIdentifierCallback = false;
103
104
    /**
105
     * @var string The callback to get a user id.
106
     */
107
    public $userIdCallback = false;
108
109
    /**
110
     * @var string Will be called to translate text in the user filter into a (or more) user id's
111
     */
112
    public $userFilterCallback = false;
113
114
    /**
115
     * @var bool The module does batch saving of the data records by default. You can disable this if you are experiencing
116
     * `max_allowed_packet` errors when logging huge data quantities. Records will be saved per piece instead of all at once
117
     */
118
    public $batchSave = true;
119
120
    /**
121
     * @var array Default log levels to filter and process
122
     */
123
    public $logConfig = ['levels' => ['error', 'warning', 'info', 'profile']];
124
125
126
    /**
127
     * @var array|Panel[] list of panels that should be active/tracking/available during the auditing phase.
128
     * If the value is a simple string, it is the identifier of an internal panel to activate (with default settings)
129
     * If the entry is a '<key>' => '<string>|<array>' it is either a new panel or a panel override (if you specify a core id).
130
     * It is important that the key is unique, as this is the identifier used to store any data associated with the panel.
131
     *
132
     * Please note:
133
     * - If you just want to change the configuration for a core panel, use the `$panelConfiguration`, it will be merged into this one
134
     * - If you add custom panels, please namespace them ("mynamespace/panelname").
135
     */
136
    public $panels = [
137
        'audit/request',
138
        'audit/db',
139
        'audit/log',
140
        'audit/mail',
141
        'audit/profiling',
142
        'audit/trail',
143
        'audit/javascript',
144
        // 'audit/asset',
145
        // 'audit/config',
146
147
        // These provide special functionality and get loaded to activate it
148
        'audit/error',      // Links the extra error reporting functions (`exception()` and `errorMessage()`)
149
        'audit/extra',      // Links the data functions (`data()`)
150
        'audit/curl',       // Links the curl tracking function (`curlBegin()`, `curlEnd()` and `curlExec()`)
151
    ];
152
153
    /**
154
     * Everything you add in here will be merged with the basic panel configuration.
155
     * This gives you an easy way to just add or modify panels/configurations without having to re-specify every panel.
156
     * This only accepts regular definitions ('<key>' => '<array>'), but the core class will be added if needed
157
     * Take a look at the [module configuration](docs/module-configuration.md) for more information.
158
     */
159
    public $panelsMerge = [];
160
161
    /**
162
     * @var LogTarget
163
     */
164
    public $logTarget;
165
166
    /**
167
     * @see \yii\debug\Module::$traceLine
168
     */
169
    public $traceLine = \yii\debug\Module::DEFAULT_IDE_TRACELINE;
170
171
    /**
172
     * @var array
173
     */
174
    private $_corePanels = [
175
        // Tracking/logging panels
176
        'audit/request'    => ['class' => 'bedezign\yii2\audit\panels\RequestPanel'],
177
        'audit/db'         => ['class' => 'bedezign\yii2\audit\panels\DbPanel'],
178
        'audit/log'        => ['class' => 'bedezign\yii2\audit\panels\LogPanel'],
179
        'audit/asset'      => ['class' => 'bedezign\yii2\audit\panels\AssetPanel'],
180
        'audit/config'     => ['class' => 'bedezign\yii2\audit\panels\ConfigPanel'],
181
        'audit/profiling'  => ['class' => 'bedezign\yii2\audit\panels\ProfilingPanel'],
182
183
        // Special other panels
184
        'audit/error'      => ['class' => 'bedezign\yii2\audit\panels\ErrorPanel'],
185
        'audit/javascript' => ['class' => 'bedezign\yii2\audit\panels\JavascriptPanel'],
186
        'audit/trail'      => ['class' => 'bedezign\yii2\audit\panels\TrailPanel'],
187
        'audit/mail'       => ['class' => 'bedezign\yii2\audit\panels\MailPanel'],
188
        'audit/extra'      => ['class' => 'bedezign\yii2\audit\panels\ExtraDataPanel'],
189
        'audit/curl'       => ['class' => 'bedezign\yii2\audit\panels\CurlPanel'],
190
        'audit/soap'       => ['class' => 'bedezign\yii2\audit\panels\SoapPanel'],
191 280
    ];
192
193 114
    /**
194 280
     * @var array
195
     */
196
    private $_panelFunctions = [];
197 114
198
    /**
199 114
     * @var \bedezign\yii2\audit\models\AuditEntry If activated this is the active entry
200
     */
201
    private $_entry = null;
202 114
203
    /**
204
     * @throws InvalidConfigException
205 114
     */
206 114
    public function init()
207 114
    {
208
        parent::init();
209
        $app = Yii::$app;
210
211
        // check if the module has been installed (prevents errors while installing)
212
        if (!$this->getDb()->getTableSchema(AuditEntry::tableName())) {
213 54
            return;
214
        }
215 42
216 9
        // Before action triggers a new audit entry
217
        $app->on(Application::EVENT_BEFORE_ACTION, [$this, 'onBeforeAction']);
218 33
        // After request finalizes the audit entry.
219 42
        $app->on(Application::EVENT_AFTER_REQUEST, [$this, 'onAfterRequest']);
220
221
        // Activate the logging target
222 13
        if (empty($app->getLog()->targets['audit'])) {
223 39
            $this->logTarget = $app->getLog()->targets['audit'] = new LogTarget($this, $this->logConfig);
224
        } else {
225
            $this->logTarget = $app->getLog()->targets['audit'];
226
        }
227
228 50
        // Boot all active panels
229
        $this->normalizePanelConfiguration();
230 50
        $this->panels = $this->loadPanels(array_keys($this->panels));
231 18
    }
232 18
233 50
    /**
234
     * Called to evaluate if the current request should be logged
235
     * @param ActionEvent $event
236
     */
237
    public function onBeforeAction($event)
238
    {
239
        if (!empty($this->trackActions) && !$this->routeMatches($event->action->uniqueId, $this->trackActions)) {
240 114
            return;
241
        }
242 114
        if (!empty($this->ignoreActions) && $this->routeMatches($event->action->uniqueId, $this->ignoreActions)) {
243 114
            return;
244
        }
245 114
        // Still here, start audit
246 114
        $this->getEntry(true);
247
    }
248
249
    /**
250
     *
251
     */
252
    public function onAfterRequest()
253
    {
254
        if ($this->_entry) {
255
            $this->_entry->finalize();
256
        }
257
    }
258
259
    /**
260
     * Allows panels to register functions that can be called directly on the module
261 21
     * @param string    $name
262
     * @param callable  $callback
263 21
     */
264 7
    public function registerFunction($name, $callback)
265
    {
266 7
        if (isset($this->_panelFunctions[$name]))
267
            throw new InvalidParamException("The '$name'-function has already been defined.");
268
269
        $this->_panelFunctions[$name] = $callback;
270
    }
271
272 70
    /**
273
     * @param \yii\debug\Panel $panel
274 70
     */
275
    public function registerPanel(\yii\debug\Panel $panel)
276
    {
277
        $this->panels[$panel->id] = $panel;
278
    }
279
280
    /**
281
     * @param string $name
282 91
     * @param array $params
283
     * @return mixed
284 91
     */
285 39
    public function __call($name, $params)
286 39
    {
287 91
        if (!isset($this->_panelFunctions[$name]))
288 32
            throw new \yii\base\InvalidCallException("Unknown panel function '$name'");
289
290
        return call_user_func_array($this->_panelFunctions[$name], $params);
291
    }
292
293
    /**
294 14
     * @return \yii\db\Connection the database connection.
295
     */
296 14
    public function getDb()
297
    {
298
        return Yii::$app->{$this->db};
299 12
    }
300 1
301
    /**
302 11
     * @param bool $create
303
     * @param bool $new
304
     * @return AuditEntry
305
     */
306
    public function getEntry($create = false, $new = false)
307
    {
308
        $entry = new AuditEntry();
309 1
        $tableSchema = $entry->getDb()->schema->getTableSchema($entry->tableName());
310
        if ($tableSchema) {
311 1
            if ((!$this->_entry && $create) || $new) {
312
                $this->_entry = AuditEntry::create(true);
313
            }
314
        }
315
        return $this->_entry;
316
    }
317
318
    /**
319 280
     * @param $user_id
320
     * @return string
321 280
     */
322 114
    public function getUserIdentifier($user_id)
323 114
    {
324 114
        if (!$user_id) {
325 280
            return Yii::t('audit', 'Guest');
326
        }
327
        if ($this->userIdentifierCallback && is_callable($this->userIdentifierCallback)) {
328
            return call_user_func($this->userIdentifierCallback, $user_id);
329
        }
330
        return $user_id;
331
    }
332
333 142
    /**
334
     * @return int|mixed|null|string
335 114
     */
336 114
    public function getUserId()
337 114
    {
338 1
        if ($this->userIdCallback && is_callable($this->userIdCallback)) {
339 1
            return call_user_func($this->userIdCallback);
340
        }
341 114
        return (Yii::$app instanceof \yii\web\Application && Yii::$app->user) ? Yii::$app->user->id : null;
342 114
    }
343
344 114
    /**
345 114
     * Returns a list of all available panel identifiers
346 114
     * @return string[]
347 114
     */
348
    public function getPanelIdentifiers()
349
    {
350 46
        return array_unique(array_merge(array_keys($this->panels), array_keys($this->_corePanels)));
351
    }
352
353
    /**
354
     * Tries to assemble the configuration for the panels that the user wants for auditing
355
     * @param string[]          Set of panel identifiers that should be loaded
356
     * @return Panel[]
357 280
     */
358
    public function loadPanels($list)
359 280
    {
360 280
        $panels = [];
361 114
        foreach ($list as $panel) {
362
            $panels[$panel] = $this->getPanel($panel);
363 114
        }
364 114
        return $panels;
365 114
    }
366 114
367
    /**
368
     * @param string $identifier
369
     * @return null|Panel
370
     * @throws InvalidConfigException
371 114
     */
372 114
    public function getPanel($identifier)
373
    {
374
        $config = null;
375 114
        if (isset($this->panels[$identifier]))
376 114
            $config = $this->panels[$identifier];
377
        elseif (isset($this->_corePanels[$identifier]))
378
            $config = $this->_corePanels[$identifier];
379
380
        if (!$config)
381
            throw new InvalidConfigException("'$identifier' is not a valid panel identifier");
382 114
383 280
        if (is_array($config)) {
384
            $config['module'] = $this;
385
            $config['id'] = $identifier;
386
            return Yii::createObject($config);
387
        }
388 280
389
        return $config;
390 274
    }
391 278
392 114
    /**
393 114
     * Make sure the configured panels array is a uniform set of <identifier> => <config> entries.
394 114
     * @throws InvalidConfigException
395 280
     */
396 280
    protected function normalizePanelConfiguration()
397 114
    {
398
        $panels = [];
399 165
        foreach ($this->panels as $key => $value) {
400
            if (is_numeric($key)) {
401 114
                // The $value contains the identifier of a core panel
402 114
                if (!isset($this->_corePanels[$value]))
403 278
                    throw new InvalidConfigException("'$value' is not a valid panel identifier");
404 162
                $panels[$value] = $this->_corePanels[$value];
405 6
            }
406
            else {
407
                // The key contains the identifier and the value is either a class name or a full array
408
                $panels[$key] = is_string($value) ? ['class' => $value] : $value;
409
            }
410
        }
411
        $this->panels = ArrayHelper::merge($panels, $this->panelsMerge);
412 27
413
        // We now need one more iteration to add core classes to the panels added via the merge, if needed
414 9
        array_walk($this->panels, function(&$value, $key) {
415 27
           if (!isset($value['class'])) {
416 9
               if (isset($this->_corePanels[$key]))
417 27
                   $value = ArrayHelper::merge($value, $this->_corePanels[$key]);
418
               else
419 9
                   throw new InvalidConfigException("Invalid configuration for '$key'. No 'class' specified.");
420
           }
421
        });
422
    }
423
424
    /**
425
     * @return int|null|string
426
     */
427
    public static function findModuleIdentifier()
428
    {
429
        foreach (Yii::$app->modules as $name => $module) {
430
            $class = null;
431
            if (is_string($module))
432 64
                $class = $module;
433
            elseif (is_array($module)) {
434 28
                if (isset($module['class']))
435 28
                    $class = $module['class'];
436 28
            } else
437 56
                /** @var Module $module */
438 18
                $class = $module::className();
439 18
440 22
            $parts = explode('\\', $class);
441 8
            if ($class && strtolower(end($parts)) == 'audit')
442
                return $name;
443 62
        }
444 6
        return null;
445 6
    }
446 14
447 2
    /**
448
     * @param string $className
449 50
     * @return bool|string
450 26
     */
451 36
    public static function findPanelIdentifier($className)
452 36
    {
453
        $audit = Audit::getInstance();
454
        foreach ($audit->panels as $panel) {
455
            if ($panel->className() == $className) {
456
                return $panel->id;
457
            }
458
        }
459
        return false;
460
    }
461
462
    /**
463
     * Verifies a route against a given list and returns whether it matches or not.
464
     * Entries in the list are allowed to end with a '*', which means that a substring will be used for the match
465
     * instead of a full compare.
466
     *
467
     * @param string $route An application rout
468
     * @param string[] $list List of routes to compare against.
469
     * @return bool
470
     */
471
    protected function routeMatches($route, $list)
472
    {
473
        $list = ArrayHelper::toArray($list);
474
        foreach ($list as $compare) {
475
            $len = strlen($compare);
476
            if ($compare[$len - 1] == '*') {
477
                $compare = rtrim($compare, '*');
478
                if (substr($route, 0, $len - 1) === $compare)
479
                    return true;
480
            }
481
482
            if ($compare[0] == '*') {
483
                $compare = ltrim($compare, '*');
484
                if (substr($route, - ($len - 1)) === $compare)
485
                    return true;
486
            }
487
488
            if ($route === $compare)
489
                return true;
490
        }
491
        return false;
492
    }
493
494
}
495