Перейти к содержимому

Права на инфоблок и заказы - выдача из интерфейса и кодом

Выдаём группе доступ к инфоблоку и заказам и проверяем права в своём коде так, чтобы проверка пережила появление новых ролей.

Решение

Смотрим, какие права уже выданы на инфоблок:

$rights = CIBlock::GetGroupPermissions($iblockId);
foreach ($rights as $groupId => $level) {
printf("группа %-5s уровень %s\n", $groupId, $level);
}
// D - нет доступа, R - чтение, W - запись, X - полный доступ

Уровни обозначаются буквами и складываются по группам: пользователь получает наибольший из своих уровней. Группе, которой в этом списке нет, доступ не выдан вовсе, и её участники инфоблока не видят.

Выдаём доступ группе:

CIBlock::SetPermission($iblockId, [
5 => 'R', // группа только читает
6 => 'W', // группа читает и пишет
]);
// передаётся весь список целиком: отсутствующие группы теряют доступ

Метод перезаписывает список прав полностью, а не дополняет уже имеющийся. Выдать право одной группе, не перечислив при этом остальные, означает отобрать доступ у всех прочих групп разом.

Включаем права на отдельные элементы:

// расширенное управление правами: настройка самого инфоблока
$iblock = new CIBlock();
$iblock->Update($iblockId, ['RIGHTS_MODE' => 'E']);
// после переключения простые права групп перестают действовать

Расширенный режим заменяет механизм целиком: появляются задачи с наборами операций и права на конкретные элементы и разделы инфоблока. Обратное переключение сбрасывает все выданные права, и восстанавливать их после этого приходится руками.

Настраиваем доступ менеджера к заказам:

use Bitrix\Sale\Internals\RoleTable;
// роли модуля продаж живут отдельно от прав модулей
$roles = RoleTable::getList(['select' => ['ID', 'NAME']])->fetchAll();
foreach ($roles as $role) {
printf("роль %-5s %s\n", $role['ID'], $role['NAME']);
}

Роль назначается группе пользователей и описывает, что она делает с заказами: видеть все заказы, видеть только свои, менять статус, отменять оплату. Общее право на модуль продаж этот список никак не заменяет и без назначенной роли не даёт ничего.

Права кэшируются в сессии пользователя на время его работы. Человек, добавленный в группу прямо сейчас, увидит новые разделы только после повторного входа, и это регулярно принимают за неработающую выдачу прав.

Проверяем право в своём коде:

global $USER;
if (!$USER->CanDoOperation('catalog_read')) {
throw new RuntimeException('недостаточно прав');
}
// проверка по операции переживает появление новых ролей и групп

Проверка на принадлежность к администраторам работает ровно до появления первой промежуточной роли на проекте. После этого её приходится переписывать сразу во всех местах кода, а проверка по названию операции продолжает работать без единой правки.

Типичные проблемы

Выдали право одной группе, остальные потеряли доступ.

Метод установки прав перезаписывает список целиком. Передавать нужно все группы, а не только изменённую.

Права на инфоблок не сохраняются.

У инфоблока включено расширенное управление правами. Простые уровни доступа в этом режиме не действуют, и правят их в другом месте.

Менеджер видит чужие заказы.

У его группы роль с доступом ко всем заказам. Ограничение по владельцу задаётся именно в роли модуля продаж.

Файл инфоблока скачивается без авторизации.

Файлы лежат в открытой папке загрузок. Права инфоблока на прямую ссылку к файлу не распространяются.

После добавления в группу права не изменились.

Права закэшированы в сессии пользователя. Изменения вступают в силу после повторного входа либо сброса кэша.

Частые вопросы

Чем задача отличается от уровня доступа?

Уровень - одна буква из готового набора, задача - именованный набор операций. Задачи появляются в расширенном режиме прав и позволяют собрать свою роль.

Как дать доступ к одному разделу инфоблока?

Только в расширенном режиме прав: там права выдаются на раздел и наследуются его элементами. В простом режиме права действуют на весь инфоблок целиком.

Можно ли запретить группе то, что разрешено другой?

Нет, запрещающих прав в платформе нет. Права складываются, и человек получает максимум из своих групп.

Как закрыть файлы инфоблока от посторонних?

Своим скриптом отдачи файла, который проверяет права и только потом читает файл с диска. Прямые ссылки на папку загрузок при этом закрывают на уровне веб-сервера.

Смежное

Первоисточник