Passed
Push — master ( 8a1c29...aa2240 )
by Fran
06:43
created

Security::checkAdmin()   C

Complexity

Conditions 13
Paths 52

Size

Total Lines 47
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 32
CRAP Score 13.0343

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 13
eloc 31
c 2
b 0
f 1
nc 52
nop 3
dl 0
loc 47
ccs 32
cts 34
cp 0.9412
crap 13.0343
rs 6.6166

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

129
        return (null !== $this->admin && !preg_match('/^\/admin\/login/i', /** @scrutinizer ignore-type */ Request::requestUri())) || self::isTest();
Loading history...
130
    }
131
132
    /**
133
     * Servicio que devuelve una pantalla de error porque se necesita estar authenticado
134
     *
135
     * @param string|null $route
136
     *
137
     * @return string|null
138
     * @throws exception\GeneratorException
139
     */
140 1
    public function notAuthorized($route)
141
    {
142 1
        return Template::getInstance()->render('notauthorized.html.twig', array(
143 1
            'route' => $route,
144 1
        ));
145
    }
146
147 2
    private function checkAdminRole($role = AuthHelper::USER_ID_TOKEN)
148
    {
149 2
        $users = $this->getAdmins();
150 2
        $logged = $this->getAdmin();
151 2
        if (is_array($logged)
152 2
            && array_key_exists('alias', $logged)
153 2
            && array_key_exists($logged['alias'], $users)) {
154 1
            $security = $users[$logged['alias']]['profile'];
155 1
            return $role === $security;
156
        }
157
158 2
        return false;
159
    }
160
161
    /**
162
     * @return bool
163
     */
164 1
    public function isSuperAdmin()
165
    {
166 1
        $users = $this->getAdmins();
167 1
        $logged = $this->getAdmin();
168 1
        if (is_array($logged)
169 1
            && array_key_exists('alias', $logged)
170 1
            && array_key_exists($logged['alias'], $users)) {
171 1
            $security = $users[$logged['alias']]['profile'];
172 1
            return AuthHelper::ADMIN_ID_TOKEN === $security;
173
        }
174
175 1
        return FALSE;
176
    }
177
178
    /**
179
     * @return bool
180
     */
181 1
    public function isManager()
182
    {
183 1
        return $this->checkAdminRole(AuthHelper::MANAGER_ID_TOKEN);
184
    }
185
186
    /**
187
     * @return bool
188
     */
189 2
    public function isUser()
190
    {
191 2
        return $this->checkAdminRole();
192
    }
193
194
195
}
196