123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- <?php
- namespace common\modules\rbac\components;
- use Yii;
- use yii\base\Module;
- use yii\di\Instance;
- use yii\web\ForbiddenHttpException;
- use yii\web\User;
- /**
- * Access Control Filter (ACF) is a simple authorization method that is best used by applications that only need some simple access control.
- * As its name indicates, ACF is an action filter that can be attached to a controller or a module as a behavior.
- * ACF will check a set of access rules to make sure the current user can access the requested action.
- *
- * To use AccessControl, declare it in the application config as behavior.
- * For example.
- *
- * ~~~
- * 'as access' => [
- * 'class' => 'rbac\components\AccessControl',
- * 'allowActions' => ['site/login', 'site/error']
- * ]
- * ~~~
- *
- * @property User $user
- *
- * @author Misbahul D Munir <misbahuldmunir@gmail.com>
- *
- * @since 1.0
- */
- class AccessControl extends \yii\base\ActionFilter
- {
- /**
- * @var User User for check access.
- */
- private $_user = 'user';
- /**
- * @var array List of action that not need to check access.
- */
- public $allowActions = [];
- /**
- * Get user.
- *
- * @return User
- */
- public function getUser()
- {
- if (!$this->_user instanceof User) {
- $this->_user = Instance::ensure($this->_user, User::className());
- }
- return $this->_user;
- }
- /**
- * Set user.
- *
- * @param User|string $user
- */
- public function setUser($user)
- {
- $this->_user = $user;
- }
- /**
- * {@inheritdoc}
- */
- public function beforeAction($action)
- {
- $actionId = $action->getUniqueId();
- $user = $this->getUser();
- if ($user->can('/'.$actionId)) {
- return true;
- }
- $obj = $action->controller;
- do {
- if ($user->can('/'.ltrim($obj->getUniqueId().'/*', '/'))) {
- return true;
- }
- $obj = $obj->module;
- } while ($obj !== null);
- $this->denyAccess($user);
- }
- /**
- * Denies the access of the user.
- * The default implementation will redirect the user to the login page if he is a guest;
- * if the user is already logged, a 403 HTTP exception will be thrown.
- *
- * @param \yii\web\User $user the current user
- *
- * @throws \yii\web\ForbiddenHttpException if the user is already logged in.
- */
- protected function denyAccess($user)
- {
- if ($user->getIsGuest()) {
- $user->loginRequired();
- } else {
- throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
- }
- }
- /**
- * {@inheritdoc}
- */
- protected function isActive($action)
- {
- $uniqueId = $action->getUniqueId();
- if ($uniqueId === Yii::$app->getErrorHandler()->errorAction) {
- return false;
- }
- $user = $this->getUser();
- if ($user->getIsGuest() && is_array($user->loginUrl) && isset($user->loginUrl[0]) && $uniqueId === trim($user->loginUrl[0], '/')) {
- return false;
- }
- if ($this->owner instanceof Module) {
- // convert action uniqueId into an ID relative to the module
- $mid = $this->owner->getUniqueId();
- $id = $uniqueId;
- if ($mid !== '' && strpos($id, $mid.'/') === 0) {
- $id = substr($id, strlen($mid) + 1);
- }
- } else {
- $id = $action->id;
- }
- foreach ($this->allowActions as $route) {
- if (substr($route, -1) === '*') {
- $route = rtrim($route, '*');
- if ($route === '' || strpos($id, $route) === 0) {
- return false;
- }
- } else {
- if ($id === $route) {
- return false;
- }
- }
- }
- if ($action->controller->hasMethod('allowAction') && in_array($action->id, $action->controller->allowAction())) {
- return false;
- }
- return true;
- }
- }
|