Test Failed
Push — master ( 1cd2da...3b4d09 )
by Fran
02:52
created

Security::checkAdmin()   B

Complexity

Conditions 11
Paths 28

Size

Total Lines 42
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 22.1441

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 11
eloc 28
c 2
b 0
f 1
nc 28
nop 3
dl 0
loc 42
ccs 17
cts 31
cp 0.5484
crap 22.1441
rs 7.3166

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace PSFS\base;
4
5
use PSFS\base\types\helpers\AuthHelper;
6
use PSFS\base\types\helpers\Inspector;
7
use PSFS\base\types\helpers\ResponseHelper;
8
use PSFS\base\types\traits\SecureTrait;
9
use PSFS\base\types\traits\Security\FlashesTrait;
10
use PSFS\base\types\traits\Security\ProfileTrait;
11
use PSFS\base\types\traits\SingletonTrait;
12
use PSFS\base\types\traits\TestTrait;
13
14
/**
15
 * Class Security
16
 * @package PSFS
17
 */
18
class Security
19
{
20
    // sha1('FLASHES')
21
    const FLASH_MESSAGE_TOKEN = '4680c68435db1bfbf17c3fcc4f7b39d2c6122504';
22
    const LOGGED_USER_TOKEN = '__U_T_L__';
23
24
    use SecureTrait;
25
    use SingletonTrait;
26
    use TestTrait;
27
    use ProfileTrait;
28
    use FlashesTrait;
29
30
    /**
31
     * @var bool $authorized
32
     */
33
    private $authorized = FALSE;
34
35
    /**
36
     * @var bool $checked
37
     */
38
    private $checked = false;
39
40
    /**
41
     * Constructor por defecto
42
     */
43 2
    public function init()
44
    {
45 2
        $this->initSession();
46 2
        if (NULL === $this->getSessionKey('__FLASH_CLEAR__')) {
47 2
            $this->clearFlashes();
48 2
            $this->setSessionKey('__FLASH_CLEAR__', microtime(TRUE));
49
        }
50 2
        $this->user = $this->hasSessionKey(AuthHelper::USER_ID_TOKEN) ? unserialize($this->getSessionKey(AuthHelper::USER_ID_TOKEN)) : null;
51 2
        $this->admin = $this->hasSessionKey(AuthHelper::ADMIN_ID_TOKEN) ? unserialize($this->getSessionKey(AuthHelper::ADMIN_ID_TOKEN)) : null;
52 2
        if (null === $this->admin) {
53 2
            $this->checkAdmin();
54
        }
55 2
        $this->setLoaded(true);
56
    }
57
58
    /**
59
     * @return array|null
60
     */
61 4
    public function getAdmins()
62
    {
63 4
        return Cache::getInstance()->getDataFromFile(CONFIG_DIR . DIRECTORY_SEPARATOR . 'admins.json', Cache::JSONGZ, true);
64
    }
65
66
    /**
67
     * @param string $user
68
     * @param string $pass
69
     * @param boolean $force
70
     *
71
     * @return bool
72
     */
73 5
    public function checkAdmin($user = NULL, $pass = NULL, $force = false)
74
    {
75 5
        Logger::log('Checking admin session');
76 5
        if ((!$this->authorized && !$this->checked) || $force) {
77 4
            $admins = $this->getAdmins();
78 4
            $token = null;
79 4
            if (null !== $admins) {
80 2
                if(empty($user)) {
81
                    // First try, traditional basic auth
82 2
                    Inspector::stats('[Auth] Checking Basic Auth');
83 2
                    list($user, $token) = AuthHelper::checkBasicAuth($user, $pass, $admins);
84
                }
85 2
                if(empty($user)) {
86
                    // Second try, cookie auth
87 2
                    Inspector::stats('[Auth] Checking Basic Auth PSFS');
88 2
                    list($user, $token) = AuthHelper::checkComplexAuth($admins);
89
                }
90 2
                if (!empty($user) && !empty($admins[$user])) {
91
                    $auth = $admins[$user]['hash'];
92
                    $this->authorized = ($auth === $token);
93
                    if ($this->authorized) {
94
                        $this->updateAdmin($user, $admins[$user]['profile']);
95
                        $encrypted = AuthHelper::encrypt("$user:$pass", AuthHelper::SESSION_TOKEN);
96
                        ResponseHelper::setCookieHeaders([
97
                            [
98
                                'name' => AuthHelper::generateProfileHash(),
99
                                'value' => $encrypted,
100
                                'http' => true,
101
                                'domain' => '',
102
                            ]
103
                        ]);
104
                        $this->setSessionKey(AuthHelper::ADMIN_ID_TOKEN, $encrypted);
105
                    }
106
                } else {
107 2
                    $this->admin = null;
108 2
                    $this->setSessionKey(AuthHelper::ADMIN_ID_TOKEN, null);
109
                }
110 2
                $this->checked = true;
111
            }
112
        }
113
114 5
        return $this->authorized || self::isTest();
115
    }
116
117
    /**
118
     * Método que calcula si se está logado o para acceder a administración
119
     * @return bool
120
     */
121 4
    public function canAccessRestrictedAdmin()
122
    {
123 4
        return (null !== $this->admin && !preg_match('/^\/admin\/login/i', Request::requestUri())) || self::isTest();
0 ignored issues
show
Bug introduced by
It seems like PSFS\base\Request::requestUri() can also be of type null; however, parameter $subject of preg_match() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

123
        return (null !== $this->admin && !preg_match('/^\/admin\/login/i', /** @scrutinizer ignore-type */ Request::requestUri())) || self::isTest();
Loading history...
124
    }
125
126
    /**
127
     * Servicio que devuelve una pantalla de error porque se necesita estar authenticado
128
     *
129
     * @param string|null $route
130
     *
131
     * @return string|null
132
     * @throws exception\GeneratorException
133
     */
134
    public function notAuthorized($route)
135
    {
136
        return Template::getInstance()->render('notauthorized.html.twig', array(
137
            'route' => $route,
138
        ));
139
    }
140
141
    /**
142
     * @return bool
143
     */
144
    public function isSuperAdmin()
145
    {
146
        $users = $this->getAdmins();
147
        $logged = $this->getAdmin();
148
        if (is_array($logged)
149
            && array_key_exists('alias', $logged)
150
            && array_key_exists($logged['alias'], $users)) {
151
            $security = $users[$logged['alias']]['profile'];
152
            return AuthHelper::ADMIN_ID_TOKEN === $security;
153
        }
154
155
        return FALSE;
156
    }
157
158
}
159