Issues (81)

components/AccessControl.php (2 issues)

1
<?php
2
3
namespace toir427\admin\components;
4
5
use yii\web\ForbiddenHttpException;
6
use yii\base\Module;
7
use Yii;
8
use yii\web\User;
9
use yii\di\Instance;
10
11
/**
12
 * Access Control Filter (ACF) is a simple authorization method that is best used by applications that only need some simple access control. 
13
 * As its name indicates, ACF is an action filter that can be attached to a controller or a module as a behavior. 
14
 * ACF will check a set of access rules to make sure the current user can access the requested action.
15
 *
16
 * To use AccessControl, declare it in the application config as behavior.
17
 * For example.
18
 *
19
 * ```
20
 * 'as access' => [
21
 *     'class' => 'toir427\admin\components\AccessControl',
22
 *     'allowActions' => ['site/login', 'site/error']
23
 * ]
24
 * ```
25
 *
26
 * @property User $user
27
 * 
28
 * @author Misbahul D Munir <[email protected]>
29
 * @since 1.0
30
 */
31
class AccessControl extends \yii\base\ActionFilter
32
{
33
    /**
34
     * @var User User for check access.
35
     */
36
    private $_user = 'user';
37
    /**
38
     * @var array List of action that not need to check access.
39
     */
40
    public $allowActions = [];
41
42
    /**
43
     * Get user
44
     * @return User
45
     */
46
    public function getUser()
47
    {
48
        if (!$this->_user instanceof User) {
0 ignored issues
show
$this->_user is always a sub-type of yii\web\User.
Loading history...
49
            $this->_user = Instance::ensure($this->_user, User::className());
50
        }
51
        return $this->_user;
52
    }
53
54
    /**
55
     * Set user
56
     * @param User|string $user
57
     */
58
    public function setUser($user)
59
    {
60
        $this->_user = $user;
0 ignored issues
show
Documentation Bug introduced by
It seems like $user can also be of type string. However, the property $_user is declared as type yii\web\User. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
61
    }
62
63
    /**
64
     * @inheritdoc
65
     */
66
    public function beforeAction($action)
67
    {
68
        $actionId = $action->getUniqueId();
69
        $user = $this->getUser();
70
        if (Helper::checkRoute('/' . $actionId, Yii::$app->getRequest()->get(), $user)) {
71
            return true;
72
        }
73
        $this->denyAccess($user);
74
    }
75
76
    /**
77
     * Denies the access of the user.
78
     * The default implementation will redirect the user to the login page if he is a guest;
79
     * if the user is already logged, a 403 HTTP exception will be thrown.
80
     * @param  User $user the current user
81
     * @throws ForbiddenHttpException if the user is already logged in.
82
     */
83
    protected function denyAccess($user)
84
    {
85
        if ($user->getIsGuest()) {
86
            $user->loginRequired();
87
        } else {
88
            throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
89
        }
90
    }
91
92
    /**
93
     * @inheritdoc
94
     */
95
    protected function isActive($action)
96
    {
97
        $uniqueId = $action->getUniqueId();
98
        if ($uniqueId === Yii::$app->getErrorHandler()->errorAction) {
99
            return false;
100
        }
101
102
        $user = $this->getUser();
103
        if($user->getIsGuest())
104
        {
105
            $loginUrl = null;
106
            if(is_array($user->loginUrl) && isset($user->loginUrl[0])){
107
                $loginUrl = $user->loginUrl[0];
108
                }else if(is_string($user->loginUrl)){
109
                    $loginUrl = $user->loginUrl;
110
                }
111
                if(!is_null($loginUrl) && trim($loginUrl,'/') === $uniqueId)
112
                {
113
                    return false;
114
                }
115
        }
116
117
        if ($this->owner instanceof Module) {
118
            // convert action uniqueId into an ID relative to the module
119
            $mid = $this->owner->getUniqueId();
120
            $id = $uniqueId;
121
            if ($mid !== '' && strpos($id, $mid . '/') === 0) {
122
                $id = substr($id, strlen($mid) + 1);
123
            }
124
        } else {
125
            $id = $action->id;
126
        }
127
128
        foreach ($this->allowActions as $route) {
129
            if (substr($route, -1) === '*') {
130
                $route = rtrim($route, "*");
131
                if ($route === '' || strpos($id, $route) === 0) {
132
                    return false;
133
                }
134
            } else {
135
                if ($id === $route) {
136
                    return false;
137
                }
138
            }
139
        }
140
141
        if ($action->controller->hasMethod('allowAction') && in_array($action->id, $action->controller->allowAction())) {
142
            return false;
143
        }
144
145
        return true;
146
    }
147
}
148