Issues (81)

components/AccessControl.php (1 issue)

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;
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