Программирование, веб-кодинг, Расширения, виджеты

RBAC в Yii2 с помощью расширения yii2-user

Настраиваем авторизацию и управление правами пользователей с помощью ролей

RBAC в Yii2 с помощью расширения yii2-user

Для начала не помешает ознакомиться с документацией - https://github.com/yiisoft/yii2/blob/master/docs/g...

Хороший видеоурок про RBAC в Yii2 -

Так как за основу сайта я взял yii2 basic, а не advanced? то авторизацию пользователей буду делать через расширение yii2-user.

1. Я использовал расширение yii2-user и yii2-rbac. Установил их по инструкции. Не забыв про применение миграций через командную строку.

2. в конфиге

'modules' => [
    'user' => [
        'class' => 'dektrium\user\Module',
        'admins' => ['adminname'],
    ],
    'rbac' => [
        'class' => 'dektrium\rbac\Module',
        //'admins' => ['adminname'],
    ],
],

3. Теперь, когда всё установлено, надо в видах сделать проверку на показ или скрытие ссылок на определённые действия для разных ролей и разрешений.

<span><?php if(!Yii::$app->user->isGuest) : ?>
    <div class="clearfix recent-blog voffset30 bggra">
    <p class="pull-right">
        <?php if (Yii::$app->user->can('author', ['post' => $model])) { 
        echo Html::a('Редактировать', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']); 
            } ?>
        <?php if(Yii::$app->user->identity->isAdmin) { 
        echo Html::a('Удалить', ['delete', 'id' => $model->id], [
            'class' => 'btn btn-danger',
            'data' => [
            'confirm' => 'Are you sure you want to delete this item?',
            'method' => 'post',
            ],
        ]);
        } ?>
    </p>
    </div>
<?php endif;?></span>

Yii::$app->user->identity->isAdmin здесь показал для примера, на самом деле если не делать проверку гость ли это, как сделано выше, то в случае незалогиненного пользователя эта проверка даст ошибку, лучше сразу проверять через сan(): Yii::$app->user->can('admin'), если уж решили внедрять RBAC.

В админке /user/admin - надо создать свою иерархию ролей-разрешений. А также правил.

Правила в Yii2 это отдельный классы, я создал в корне папку rbac и в ней создаю нужные мне классы правил. Например, AuthorRule.php

<span><?php

namespace app\rbac;

use yii\rbac\Rule;

/**
 * Проверяем authorID на соответствие с пользователем переданным через параметры
 */
class AuthorRule extends Rule
{
    public $name = 'updateOwnPost';

    /**
     * @param string|integer $user the user ID.
     * @param Item $item the role or permission that this rule is associated width
     * @param array $params parameters passed to ManagerInterface::checkAccess().
     * @return boolean a value indicating whether the rule permits the role or permission it is associated with.
     */
    public function execute($user, $item, $params)
    {
        return isset($params['post']) ? $params['post']->author_id == $user : false;
    }
}</span>

При создании разрешения в админке /user/admin там есть поле для правила, туда пишу полный путь - app\rbac\AuthorRule

А там где нужна проверка, является ли пользователь автором поста в блоге, ставлю такое условие

<span><?php if (Yii::$app->user->can('author', ['post' => $model])) { 
    echo Html::a('Редактировать', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']); 
} ?></span>

Так лучше, чем было в Yii 1.

4. Осталось не забыть такие проверки прописать в действиях в ваших контроллерах. Ведь пользователи могут и без ссылок на "ред.", "удаление" угадать их URL (которые обычно стандартные). То есть не забываем помимо видов, ограничить права и в контроллерах. Например, actionCreate() у меня

public function actionCreate()
    {
        if (Yii::$app->user->can('createPost')) {
            $model = new Blog();

            if ($model->load(Yii::$app->request->post())) {
                $file = UploadedFile::getInstance($model, 'file');
                if ($file && $file->tempName) {
                    $model->file = $file;
                    if ($model->validate(['file'])) {
                    
                        switch ($model->material_type) {
                            case 0:
                                $material_type = '';
                                break;
                            case 1:
                                $material_type = 'news/';
                                break;
                            case 2:
                                $material_type = 'persons/';
                                break;
                            case 3:
                                $material_type = 'movies/';
                                break;
                            case 4:
                                $material_type = 'interview/';
                                break;
                        }
                    
                        $dir = Yii::getAlias('images/blog/'.$material_type);
                        $fileName = $model->file->baseName . '.' . $model->file->extension;
                        $model->file->saveAs($dir . $fileName);
                        $model->file = $fileName; // без этого ошибка
                        $model->image = '/'.$dir . $fileName;
                    
                        Yii::$app->controller->createDirectory(Yii::getAlias('images/blog/'.$material_type.'/thumbs')); 
                        Image::thumbnail($dir . $fileName, 150, 70)
                        //Image::resize($dir . $fileName, 150, 150)
                        ->save(Yii::getAlias($dir .'thumbs/'. $fileName), ['quality' => 80]);
                    }
                } 
                if ($model->save()) {
                    return $this->redirect(['view', 'id' => $model->id]);
                }               
            
            
            } else {
                return $this->render('create', [
                    'model' => $model,
                ]);
            }
        } else {
            throw new HttpException(403,'Доступ закрыт');
        }
    }


5. Та проверка, которая была по-умолчанию, а именно, на основе фильтров, перекрывается RBAC, я её не убирал из behaviors.