Completed
Push — 2.1 ( 7c8525...0afc41 )
by Alexander
21:05 queued 16:02
created

AccessControl::denyAccess()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 8
ccs 0
cts 5
cp 0
rs 9.4285
cc 3
eloc 5
nc 2
nop 1
crap 12
1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\filters;
9
10
use Yii;
11
use yii\base\Action;
12
use yii\base\ActionFilter;
13
use yii\di\Instance;
14
use yii\web\ForbiddenHttpException;
15
use yii\web\User;
16
17
/**
18
 * AccessControl provides simple access control based on a set of rules.
19
 *
20
 * AccessControl is an action filter. It will check its [[rules]] to find
21
 * the first rule that matches the current context variables (such as user IP address, user role).
22
 * The matching rule will dictate whether to allow or deny the access to the requested controller
23
 * action. If no rule matches, the access will be denied.
24
 *
25
 * To use AccessControl, declare it in the `behaviors()` method of your controller class.
26
 * For example, the following declarations will allow authenticated users to access the "create"
27
 * and "update" actions and deny all other users from accessing these two actions.
28
 *
29
 * ```php
30
 * public function behaviors()
31
 * {
32
 *     return [
33
 *         'access' => [
34
 *             'class' => \yii\filters\AccessControl::class,
35
 *             'only' => ['create', 'update'],
36
 *             'rules' => [
37
 *                 // deny all POST requests
38
 *                 [
39
 *                     'allow' => false,
40
 *                     'verbs' => ['POST']
41
 *                 ],
42
 *                 // allow authenticated users
43
 *                 [
44
 *                     'allow' => true,
45
 *                     'roles' => ['@'],
46
 *                 ],
47
 *                 // everything else is denied
48
 *             ],
49
 *         ],
50
 *     ];
51
 * }
52
 * ```
53
 *
54
 * @author Qiang Xue <[email protected]>
55
 * @since 2.0
56
 */
57
class AccessControl extends ActionFilter
58
{
59
    /**
60
     * @var User|array|string|false the user object representing the authentication status or the ID of the user application component.
61
     * Starting from version 2.0.2, this can also be a configuration array for creating the object.
62
     * Starting from version 2.0.12, you can set it to `false` to explicitly switch this component support off for the filter.
63
     */
64
    public $user = 'user';
65
    /**
66
     * @var callable a callback that will be called if the access should be denied
67
     * to the current user. If not set, [[denyAccess()]] will be called.
68
     *
69
     * The signature of the callback should be as follows:
70
     *
71
     * ```php
72
     * function ($rule, $action)
73
     * ```
74
     *
75
     * where `$rule` is the rule that denies the user, and `$action` is the current [[Action|action]] object.
76
     * `$rule` can be `null` if access is denied because none of the rules matched.
77
     */
78
    public $denyCallback;
79
    /**
80
     * @var array the default configuration of access rules. Individual rule configurations
81
     * specified via [[rules]] will take precedence when the same property of the rule is configured.
82
     */
83
    public $ruleConfig = ['class' => AccessRule::class];
84
    /**
85
     * @var array a list of access rule objects or configuration arrays for creating the rule objects.
86
     * If a rule is specified via a configuration array, it will be merged with [[ruleConfig]] first
87
     * before it is used for creating the rule object.
88
     * @see ruleConfig
89
     */
90
    public $rules = [];
91
92
93
    /**
94
     * Initializes the [[rules]] array by instantiating rule objects from configurations.
95
     */
96 1
    public function init()
97
    {
98 1
        parent::init();
99 1
        if ($this->user !== false) {
100 1
            $this->user = Instance::ensure($this->user, User::class);
101
        }
102 1
        foreach ($this->rules as $i => $rule) {
103
            if (is_array($rule)) {
104
                $this->rules[$i] = Yii::createObject(array_merge($this->ruleConfig, $rule));
105
            }
106
        }
107 1
    }
108
109
    /**
110
     * This method is invoked right before an action is to be executed (after all possible filters.)
111
     * You may override this method to do last-minute preparation for the action.
112
     * @param Action $action the action to be executed.
113
     * @return bool whether the action should continue to be executed.
114
     */
115
    public function beforeAction($action)
116
    {
117
        $user = $this->user;
118
        $request = Yii::$app->getRequest();
119
        /* @var $rule AccessRule */
120
        foreach ($this->rules as $rule) {
121
            if ($allow = $rule->allows($action, $user, $request)) {
122
                return true;
123
            } elseif ($allow === false) {
124
                if (isset($rule->denyCallback)) {
125
                    call_user_func($rule->denyCallback, $rule, $action);
126
                } elseif ($this->denyCallback !== null) {
127
                    call_user_func($this->denyCallback, $rule, $action);
128
                } else {
129
                    $this->denyAccess($user);
130
                }
131
                return false;
132
            }
133
        }
134
        if ($this->denyCallback !== null) {
135
            call_user_func($this->denyCallback, null, $action);
136
        } else {
137
            $this->denyAccess($user);
138
        }
139
        return false;
140
    }
141
142
    /**
143
     * Denies the access of the user.
144
     * The default implementation will redirect the user to the login page if he is a guest;
145
     * if the user is already logged, a 403 HTTP exception will be thrown.
146
     * @param User|false $user the current user or boolean `false` in case of detached User component
147
     * @throws ForbiddenHttpException if the user is already logged in or in case of detached User component.
148
     */
149
    protected function denyAccess($user)
150
    {
151
        if ($user !== false && $user->getIsGuest()) {
152
            $user->loginRequired();
153
        } else {
154
            throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
155
        }
156
    }
157
}
158