User roles in Yii2, from DB value

1.6k views Asked by At

This might sound duplicate at the first place but available answers lack clarity and doesnt solve my problem.

i have a database list of users, one tuple would look something like the following.

[
        'id' => '131',
        'username' => 'mat',
        'password' => '9a23b6d49aa244b7b0db52949c0932c365ec8191',
        'authKey' => 'test100key',
        'accessToken' => '100-token',
        'role' => 'editor',
    ]

Now i want to create a type of user called manager, and set access control like this in the controller.

'access' => [
            'class' => AccessControl::className(),
            'rules' => [
                [
                    'actions' => ['create', 'view', 'index'], // Define specific actions
                    'allow' => true, // Has access
                    'roles' => ['editor'], // '@' All logged in users / or your access role e.g. 'admin', 'user'
                ],
                [

I am trying to achieve this with minimum hassle and am not really very familiar with yii/yii2. RBAC actually confuses me and i am finding it difficult to understand the documnetation.

I just need to create three types of user roles. I understand controlling the access to various actions.

User data comes from a table that will be modified realtime by another app.

2

There are 2 answers

0
K3V On BEST ANSWER

Solved it myself. Slight tweak in framework code, i think I will face troubles if I chose to update Yii anyday.

In

vendor/yiisoft/yii2/filters/AccessRule.php edited the matchRole Method as follows

    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;
            } 
        } elseif ($user->can($role)) {
            return true;
        }
        elseif (isset($user->identity->role)){
            if($role == $user->identity->role) {
                return true;
            }
        }
    }

    return false;
}
0
Bizley On

Based on your own answer I see you don't really need RBAC, it's just a matter of checking one property of user. You can do it directly in a controller (and you must not modify core files anyway):

In controller add:

public function behaviors()
{
    return [
        'access' => [
            'class' => \yii\filters\AccessControl::className(),
            'only' => ['create', 'view', 'index'],
            'rules' => [
                [
                    'allow' => true,
                    'matchCallback' => function ($rule, $action) {
                        return !\Yii::$app->user->isGuest 
                            && \Yii::$app->user->identity->role === 'editor';
                    },
                ],
            ],
        ],
    ];
}

matchCallback is the callback that will be called to determine if the rule should be applied. You need to check first if user is not a guest otherwise Yii::$app->user->identity is null.