Access control of a Module in Yii2

10.5k Views Asked by At

I am having a trouble with login part. I read this topic : http://www.yiiframework.com/wiki/771/rbac-super-simple-with-admin-and-user/ . Then i follow its steps, but in step 6. it only configs for just one Controller. I have a Module called Admin with many controllers in it and i don't know how to apply this access control to the whole module. Can anyone help me ? Sorry for my bad English.

5

There are 5 best solutions below

2
On BEST ANSWER

You can create AdminController class, which will extends yii\web\Controller where you define your access rules in behaviors method and make other module controllers extend your AdminController and override behaviors method like this:

public function behaviors()
{
    return \yii\helpers\ArrayHelper::merge(parent::behaviors(), [
        'verbs' => [
            'class' => VerbFilter::className(),
            'actions' => [
                'delete' => ['post'],
            ],
        ],
    ]);
}

Here parent::behaviors() are behaviors from AdminController which define default access rules, and you merge them with specific behaviors in your child controller. It gives you flexibility to override some access rules if you need.

1
On

Make a custom model AccessRules.php as shown below:

<?php 
namespace app\models;


class AccessRules extends \yii\filters\AccessRule
{

    /**
     * @inheritdoc
     */
    protected function matchRole($user)
    {
        if (empty($this->roles)) {
            return true;
        }
        foreach ($this->roles as $role) {
            if ($role === '?') {

                if ($user->getIsGuest()) {
                    return true;
                }
            } elseif ($role === '@') {
                if (!$user->getIsGuest()) {
                    return true;
                }
            // Check if the user is logged in, and the roles match
            } elseif (!$user->getIsGuest() && (int)$role === $user->identity->user_role) {
               return true;
            }
        }

        return false;
    }
}
?>

Now open your site controller and add the following code in fuction behavior part:

use app\models\AccessRules;
 public function behaviors()
   {
        return [
            'access' => [
                    'class' => AccessControl::className(),
    // We will override the default rule config with the new AccessRule class
    'ruleConfig' => [
        'class' => AccessRules::className(),
    ],
    'only' => ['create', 'update', 'delete','index'],
    'rules' => [
        [
            'actions' => ['create', 'update', 'delete','index'],
            'allow' => true,
            // Allow admin to create
            'roles' => [
                '1' 
            ],
        ]
    ],
            ],
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'logout' => ['post'],
                ],
            ],
        ];
    }
0
On

Just add below code in controller which you want to restrict functionality

        'access' => [
            'class' => AccessControl::className(),

            'rules' => 
            [
                [
                    'actions' => ['index','view'],
                    'allow' => true,
                    'roles' => ['@']
                ],

                [
                    'actions' => ['create','update','delete'],                            
                    'allow' => true,
                    'roles' => ['@'],

                     'matchCallback' => function ($rule, $action) 
                     {
                            return Admin::isUserAdmin(Yii::$app->user->identity->username);
                    }
                ],
             ],

        ],
0
On

According to The Yii2 Guide "ACF is an action filter that can be used in a controller or a module" in the same way.

0
On

I can propose a variation of the method from the article that you mentioned. Make first 2 steps as it was described and then do the following:

1. Add the field role to User model and evaluate it with thevalue of one of the constants from the article's example (User::ROLE_ADMIN or User::ROLE_USER)

2. Override the yii\web\User->can()

public function can($permissionName, $params = [], $allowCaching = true)
{
    /** @var \app\models\User $user */
    $user = $this->identity;
    $access = false;
    do {
        if (\Yii::$app->user->isGuest) {
            break;
        }

        if ($user->role === \common\models\User::ROLE_ADMIN) {
            $access = true;
            break;
        }

        if (is_array($permissionName)) {
            $access = in_array($user->role, $permissionName);
        } else {
            $access = $permissionName === $user->role;
        }
    } while (false);

    return $access;
}

So now you can check user's role like this:

\Yii::$app->user->can(User::ROLE_USER)

3. You say:

i don't know how to apply this access control to the whole module.

Then open your module class and add the following to the behaviors() method:

public function behaviors()
{
    return [
        'access' => [
            'class' => AccessControl::className(),
            'rules' => [
                [
                    'allow' => true,
                    'roles' => [User::ROLE_ADMIN]
                ]
            ]
        ]
    ];
}

In this example we grant access to ROLE_ADMIN to all actions of all controllers of your module. That's it.