Completed
Push — master ( 720ad9...c1559c )
by Andrii
04:58
created

User::getAuthData()   B

Complexity

Conditions 4
Paths 5

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 23
ccs 0
cts 18
cp 0
rs 8.7972
cc 4
eloc 13
nc 5
nop 0
crap 20
1
<?php
2
3
/*
4
 * HiPanel core package
5
 *
6
 * @link      https://hipanel.com/
7
 * @package   hipanel-core
8
 * @license   BSD-3-Clause
9
 * @copyright Copyright (c) 2014-2016, HiQDev (http://hiqdev.com/)
10
 */
11
12
namespace hipanel\components;
13
14
use Yii;
15
use yii\base\InvalidCallException;
16
use yii\base\InvalidConfigException;
17
18
class User extends \yii\web\User
19
{
20
    public $isGuestAllowed = false;
21
22
    /**
23
     * @var string the seller login
24
     */
25
    public $seller;
26
27
    public function init()
28
    {
29
        parent::init();
30
        if (empty($this->seller)) {
31
            throw new InvalidConfigException('User "seller" must be set');
32
        }
33
    }
34
35
    public function not($key)
36
    {
37
        $identity = $this->getIdentity();
38
        if (!$identity) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $identity of type null|boolean is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
39
            throw new InvalidCallException();
40
        }
41
42
        return $identity->not($key);
0 ignored issues
show
Bug introduced by
The method not cannot be called on $identity (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
43
    }
44
45
    public function is($key)
46
    {
47
        $identity = $this->getIdentity();
48
        if (!$identity) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $identity of type null|boolean is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
49
            throw new InvalidCallException();
50
        }
51
52
        return $identity->is($key);
0 ignored issues
show
Bug introduced by
The method is cannot be called on $identity (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
53
    }
54
    /**
55
     * @inheritdoc
56
     * XXX fixes redirect loop when identity is set but the object is empty
57
     * @return bool
58
     */
59
    public function getIsGuest()
60
    {
61
        return empty($this->getIdentity()->id);
62
    }
63
64
    /**
65
     * Prepares authorization data.
66
     * Redirects to authorization if necessary.
67
     * @return array
68
     */
69
    public function getAuthData()
70
    {
71
        if ($this->isGuest) {
72
            if ($this->isGuestAllowed) {
73
                return [];
74
            } else {
75
                Yii::$app->response->redirect('/site/login');
76
                Yii::$app->end();
77
            }
78
        }
79
80
        $token = $this->identity->getAccessToken();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface yii\web\IdentityInterface as the method getAccessToken() does only exist in the following implementations of said interface: hipanel\models\User.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
81
        if (empty($token)) {
82
            /// this is very important line
83
            /// without this line - redirect loop
84
            $this->logout();
85
86
            Yii::$app->response->redirect('/site/login');
87
            Yii::$app->end();
88
        }
89
90
        return ['access_token' => $token];
91
    }
92
}
93