Yii::$app->authManager->checkAccess возвращает разные значения в зависимости от текущего юзера (роли по-умолчанию)

Всё про контроль доступа пользователей: фильтры, RBAC, проверки
Ответить
Matvik
Сообщения: 194
Зарегистрирован: 2013.06.21, 02:32

Yii::$app->authManager->checkAccess возвращает разные значения в зависимости от текущего юзера (роли по-умолчанию)

Сообщение Matvik »

Добрый вечер.
Вкратце:

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

$a = Yii::$app->authManager->checkAccess(100, 'manage_orders');
$b = Yii::$app->authManager->checkAccess(101, 'manage_orders');
$c = Yii::$app->user->can('manage_orders');
Если залогиниться под юзером 100, все три переменные будут false.
Если под 101 - true.
Роли добавляются автоматически через метод ролей по-умолчанию. В правиле UserGroupRule как раз и проверяется текущий пользователь.
Но это дело описано так в документации!
Выходит, если использовать роли по-умолчанию, то нельзя проверять доступ любого другого юзера, кроме текущего?
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Yii::$app->authManager->checkAccess возвращает разные значения в зависимости от текущего юзера (роли по-умолчанию)

Сообщение ElisDN »

Это так криво написано в документации.

Эти 100 и 101 попадают в execute($userId, $item, $params) как раз в $userId. Перепишите UserGroupRule на $user = User::findOne($userId) вместо $user = Yii::$app->user->identity.
Matvik
Сообщения: 194
Зарегистрирован: 2013.06.21, 02:32

Re: Yii::$app->authManager->checkAccess возвращает разные значения в зависимости от текущего юзера (роли по-умолчанию)

Сообщение Matvik »

А, ну да, точно.
Тут еще другой вопрос вылазит тогда: если будет много таких проверок на странице, то каждая будет добавлять запрос в базу, нехорошо.
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Yii::$app->authManager->checkAccess возвращает разные значения в зависимости от текущего юзера (роли по-умолчанию)

Сообщение ElisDN »

Добавьте private static $users = [] и кешируйте:

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

if (!array_key_exists($userId, self::$users)) {
    self::$users[$userId] = User::findOne($userId);
}

$user = self::$users[userId];
Последний раз редактировалось ElisDN 2019.02.25, 01:33, всего редактировалось 3 раза.
Matvik
Сообщения: 194
Зарегистрирован: 2013.06.21, 02:32

Re: Yii::$app->authManager->checkAccess возвращает разные значения в зависимости от текущего юзера (роли по-умолчанию)

Сообщение Matvik »

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

<?php
namespace app\modules\users\components\rbac;

use Yii;
use yii\rbac\Rule;
use app\modules\users\models\User;

class UserGroupRule extends Rule
{
    public $name = 'userGroup';
    
    private static $userRoles = [];

    public function execute($userId, $item, $params)
    {
        if (Yii::$app->user->isGuest || $userId != Yii::$app->user->getId()) {
            if (\array_key_exists($userId, self::$userRoles)) {
                $role = self::$userRoles[$userId];
            } else {
                $user = User::findOne($userId);
                if (!$user) {
                    throw new \yii\web\NotFoundHttpException("User with id $userId not found");
                }
                $role = $user->role;
                self::$userRoles[$userId] = $role;
            }
        } else {
            $role = Yii::$app->user->identity->role;
        }
        
        if ($item->name === User::ROLE_ADMIN) {
            return $role == User::ROLE_ADMIN;
        } elseif ($item->name === User::ROLE_USER) {
            return $role == User::ROLE_ADMIN || $role == User::ROLE_USER;
        }
    }
}
Переписал правило, вроде нормально так? Не пора ли обновить документацию? А то реально не обращаешь внимание на этот нюанс сначала.
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Yii::$app->authManager->checkAccess возвращает разные значения в зависимости от текущего юзера (роли по-умолчанию)

Сообщение ElisDN »

Matvik писал(а): 2019.02.25, 01:50 Переписал правило, вроде нормально так?
Нормально. Можете верх вынести в приватный метод $role = getUserRole($userId).
Matvik писал(а): 2019.02.25, 01:50 Не пора ли обновить документацию?
Пора. Отправляйте Pull Request в docs/guide/xx.
Matvik писал(а): 2019.02.25, 01:50 А то реально не обращаешь внимание на этот нюанс сначала.
Заодно можете и другие косяки подправить, если найдёте.
Matvik
Сообщения: 194
Зарегистрирован: 2013.06.21, 02:32

Re: Yii::$app->authManager->checkAccess возвращает разные значения в зависимости от текущего юзера (роли по-умолчанию)

Сообщение Matvik »

Еще проверку нужно добавить на начало:

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

if ($userId === null) {
            return false;
        }
Довольно громоздко получается, может в доки не влезть)
Ответить