AccessControl не вызывает bizRule

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
taral14
Сообщения: 236
Зарегистрирован: 2011.02.26, 23:48

AccessControl не вызывает bizRule

Сообщение taral14 »

Настроил права доступа через PhpManager.

Код: Выделить всё

namespace common\components;
use Yii;
class PhpManager extends \yii\rbac\PhpManager
{

    public function getAssignments($userId)
    {
        if(!Yii::$app->user->isGuest){
            $assignment = new \yii\rbac\Assignment;
            $assignment->userId = $userId;
            $assignment->roleName = Yii::$app->user->identity->role;
            return [$assignment->roleName => $assignment];
        }
    }
...
}
 
Прописал роли в файле

Код: Выделить всё

use yii\rbac\Item;

return [
    'items' => [
        'updateOwnProfile' => [
            'type' => Item::TYPE_PERMISSION,
            'description' => 'Редактирование собственного профиля',
            'bizRule' => function(){ exit; },
            'data' => NULL
        ],

        'guest' => [
            'type' => Item::TYPE_ROLE,
            'description' => 'Guest',
            'bizRule' => NULL,
            'data' => NULL
        ],

        'user' => [
            'type' => Item::TYPE_ROLE,
            'description' => 'User',
            'children' => [
                'guest',
                'updateOwnProfile',
            ],
            'bizRule' => 'return !Yii::$app->user->isGuest;',
            'data' => NULL
        ],
    ],
];
 
В контроллере вызываю

Код: Выделить всё

        if(Yii::$app->user->can('updateOwnProfile')) {
            echo 1;
        } else {
            echo 2;
        }
        return '';
 
У меня у пользователя роль user. И если я указываю у этой роли в чилдренах updateOwnProfile то код выводит 1. Иначе 2. Причем не играет роли что я написал в updateOwnProfile:bizRule. Эта функция просто не вызывается.
mickgeek
Сообщения: 957
Зарегистрирован: 2014.05.31, 20:50
Откуда: Санкт-Петербург
Контактная информация:

Re: AccessControl не вызывает bizRule

Сообщение mickgeek »

Во втором Yii нет bizRule.

rbac куда делся biz_rule ?
taral14
Сообщения: 236
Зарегистрирован: 2011.02.26, 23:48

Re: AccessControl не вызывает bizRule

Сообщение taral14 »

Хм. Интересное решение. А как теперь мне в файл с правами добавить правило? Я так понял правила будут в массиве rules. Мне нужно проверять свой ли профиль пытается отредактировать пользователь.
mickgeek
Сообщения: 957
Зарегистрирован: 2014.05.31, 20:50
Откуда: Санкт-Петербург
Контактная информация:

Re: AccessControl не вызывает bizRule

Сообщение mickgeek »

Using Rules

Код: Выделить всё

use yii\rbac\Item;
use app\rbac\rules\OwnProfileRule;

$ownProfileRule = new OwnProfileRule();

return [
    'rules' => [
        $ownProfileRule->name => serialize($ownProfileRule),
    ],
    'items' => [
        'manageOwnProfile' => ['type' => Item::TYPE_PERMISSION, 'ruleName' => $ownProfileRule->name],
        ...
    ],
];
taral14
Сообщения: 236
Зарегистрирован: 2011.02.26, 23:48

Re: AccessControl не вызывает bizRule

Сообщение taral14 »

Спасибо
taral14
Сообщения: 236
Зарегистрирован: 2011.02.26, 23:48

Re: AccessControl не вызывает bizRule

Сообщение taral14 »

Как мне передать дополнительные параметры на права доступа updateOwnProfile? Как сделать это в контроллере понятно. Походу так это не сделать...

Код: Выделить всё

    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'rules' => [
                    [
                        'roles' => ['moderator', 'updateOwnProfile'],
                        'actions' => ['index', 'create', 'update'],
                        'allow' => true,
                    ],
                ],
            ],
        ];
    } 
mickgeek
Сообщения: 957
Зарегистрирован: 2014.05.31, 20:50
Откуда: Санкт-Петербург
Контактная информация:

Re: AccessControl не вызывает bizRule

Сообщение mickgeek »

В поведение не передать.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: AccessControl не вызывает bizRule

Сообщение zelenin »

taral14 писал(а):Как мне передать дополнительные параметры на права доступа updateOwnProfile? Как сделать это в контроллере понятно. Походу так это не сделать...

Код: Выделить всё

    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'rules' => [
                    [
                        'actions' => ['update'],
                        'allow' => true,
                        'matchCallback' => function ($rule, $action) {
                                $model = $this->findModel(Yii::$app->getRequest()->get('id'));
                                return Yii::$app->getUser()->can('updateOwnPost', ['model' => $model]);
                            }
                    ],
                ]
            ]
        ];
    }
 
mickgeek
Сообщения: 957
Зарегистрирован: 2014.05.31, 20:50
Откуда: Санкт-Петербург
Контактная информация:

Re: AccessControl не вызывает bizRule

Сообщение mickgeek »

zelenin, супер! Не знал о таком способе, спасибо)
taral14
Сообщения: 236
Зарегистрирован: 2011.02.26, 23:48

Re: AccessControl не вызывает bizRule

Сообщение taral14 »

Да там можно много что передавать. В vendor\yiisoft\yii2\filters\AccessRule.php можно посмотреть весь список. Есть к примеру denyCallback противоположный к matchCallback. Хотя я не уверен на сколько хорошо использовать в них web\User::can. Поскольку мы делаем дополнительный запрос в $this->findModel который без модификации 2 раза запросит с базы информацию.
mickgeek
Сообщения: 957
Зарегистрирован: 2014.05.31, 20:50
Откуда: Санкт-Петербург
Контактная информация:

Re: AccessControl не вызывает bizRule

Сообщение mickgeek »

Я говорил именно о параметрах созданных правил, нельзя напрямую их передать для проверки конкретных экшенов. Понятное дело, есть denyCallback, он и в предыдущем Yii был (deniedCallback).

А два и более запросов можно избежать так:

Код: Выделить всё

use yii\web\NotFoundHttpException;

private $_model = null;

protected function findModel($id)
{
    if ($this->_model === null) {
        $this->_model = Model::findOne($id);
        if ($this->_model === null) {
            throw new NotFoundHttpException(Yii::t('yii', 'Page not found.'));
        }
    }

    return $this->_model;
} 
Это нормальная практика, и данную функцию вполне можно добавлять в каждый контроллер, где нужно производить поиск.
Последний раз редактировалось mickgeek 2014.06.28, 13:00, всего редактировалось 1 раз.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: AccessControl не вызывает bizRule

Сообщение zelenin »

taral14 писал(а):Да там можно много что передавать. В vendor\yiisoft\yii2\filters\AccessRule.php можно посмотреть весь список. Есть к примеру denyCallback противоположный к matchCallback. Хотя я не уверен на сколько хорошо использовать в них web\User::can. Поскольку мы делаем дополнительный запрос в $this->findModel который без модификации 2 раза запросит с базы информацию.
открою страшную тайну - проверка правила, требующего запрос данных, везде приведет к запросу данных, где бы эту проверку не делать.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: AccessControl не вызывает bizRule

Сообщение zelenin »

mickgeek писал(а): private $_model = null;

protected function findModel($id)
{
    if ($this->_model === null) {
        $this->_model = Model::findOne($id);
        if ($this->_model === null) {
            throw new NotFoundHttpException(Yii::t('yii', 'Page not found.'));
        }
    }

    return $this->_model;
} [/code]
как думаете, могу я функцию использовать более одного раза в приложении? Не приведет ли такой способ к неприятным последствиям?
mickgeek
Сообщения: 957
Зарегистрирован: 2014.05.31, 20:50
Откуда: Санкт-Петербург
Контактная информация:

Re: AccessControl не вызывает bizRule

Сообщение mickgeek »

Хм... А именно, в каких случаях?
taral14
Сообщения: 236
Зарегистрирован: 2011.02.26, 23:48

Re: AccessControl не вызывает bizRule

Сообщение taral14 »

zelenin писал(а):открою страшную тайну - проверка правила, требующего запрос данных, везде приведет к запросу данных, где бы эту проверку не делать.
Спасибо за тайну =) Но при более внимательном прочтении моего сообщения можно заметить слово "повторного". Также можно заметить что повторный запрос будет только если не модифицировать findModel
mickgeek
Сообщения: 957
Зарегистрирован: 2014.05.31, 20:50
Откуда: Санкт-Петербург
Контактная информация:

Re: AccessControl не вызывает bizRule

Сообщение mickgeek »

taral14 писал(а):Также можно заметить что повторный запрос будет только если не модифицировать findModel
Создайте ту функцию изначально такой, какой я её описал, и никакие модификации в будущем не потребуются :)
taral14
Сообщения: 236
Зарегистрирован: 2011.02.26, 23:48

Re: AccessControl не вызывает bizRule

Сообщение taral14 »

mickgeek писал(а):Понятное дело, есть denyCallback, он и в предыдущем Yii был (deniedCallback).
На основе вашего сообщения
mickgeek писал(а):zelenin, супер! Не знал о таком способе, спасибо)
я предположил что вы не знаете про denyCallback поскольку matchCallback вызвал у вас удивление.
По поводу кеширования запроса в переменную при вызове findModel. Если уже и делать так то метод нужно точно назвать по другому. Например getModel. Потому что название findModel означает что мы делаем запрос на поиск модели. И прямо в методе делать такой кеш я считаю плохим решением.
zelenin писал(а):как думаете, могу я функцию использовать более одного раза в приложении? Не приведет ли такой способ к неприятным последствиям?
Да может. К примеру вы берете модель. Вносите в нее изменения. Сохраняете. При сохранении модель производит некоторые операции с базой. Но не все изменения отображаются в данных модели. Дальше вы делаете еще запрос на Controller::findModel и думаете что работаете уже с новой моделью которая правильно инициализировалась с данных из базы. В этом случае могут быть неприятные ошибки. Естественно это просто решается рефрешем страницы после изменений в моделе. Но сама ситуация вполне возможна.
taral14
Сообщения: 236
Зарегистрирован: 2011.02.26, 23:48

Re: AccessControl не вызывает bizRule

Сообщение taral14 »

Кстати если уже и писать функцию, то такую.

Код: Выделить всё

private $_models = [];

protected function getModel($id)
{
    if(!array_key_exists($id, $this->_models))
        $model = Model::findOne($id);
        if ($this->_model === null) {
            throw new NotFoundHttpException(Yii::t('yii', 'Page not found.'));
        }
        $this->_models[$id] = $model;
    }

    return $this->_models[$id];
} 
Потому что в вашем случае при повторном запросе вообще игнорируется $id. Оно то ничего. Потому что обычно таким образом только одна модель запрашивается. Но может быть очень не приятный баг.
А вообще я не считаю необходимым такое усложнение.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: AccessControl не вызывает bizRule

Сообщение zelenin »

taral14 писал(а):
zelenin писал(а):открою страшную тайну - проверка правила, требующего запрос данных, везде приведет к запросу данных, где бы эту проверку не делать.
Спасибо за тайну =) Но при более внимательном прочтении моего сообщения можно заметить слово "повторного". Также можно заметить что повторный запрос будет только если не модифицировать findModel
Вы написали, что вам не нравится, что происходит повторный запрос в случае использования matchCallback, но для проверки этого свойства в независимости от того, где происходит проверка, будет запрос. Как может правило провериться, если в его основе сравнение атрибута модели?
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: AccessControl не вызывает bizRule

Сообщение zelenin »

taral14 писал(а):Да может. К примеру вы берете модель. Вносите в нее изменения. Сохраняете. При сохранении модель производит некоторые операции с базой. Но не все изменения отображаются в данных модели. Дальше вы делаете еще запрос на Controller::findModel и думаете что работаете уже с новой моделью которая правильно инициализировалась с данных из базы. В этом случае могут быть неприятные ошибки. Естественно это просто решается рефрешем страницы после изменений в моделе. Но сама ситуация вполне возможна.
а если эта функция будет использована для получения другой модели (с другим id)?
Ответить