Документация для разработчиков
Темная тема

Общая концепция

С версии 20.0.1200 Главного модуля (main) добавлен API для работы с новыми правами доступа.

Библиотека предназначена для упрощения и стандартизации работы с правами доступа пользователей в модулях.


Терминология

ТерминОписание
ПользовательАвторизованный пользователь системы. Обязательно имеет свой идентификатор (id).
Группа пользователейОбъединение пользователей, предоставляемое главным модулем: администраторы, сотрудники и т.д.
Access codeОбъединение пользователей по какому-либо критерию. Например: пользователи, состоящие в конкретной рабочей группе; сотрудники отдела и т.д. Предоставляется модулем main и хранится в таблице b_user_access.
ДействиеДействие (операция), совершаемое пользователем. Например: сохранение записи.
Разрешение доступаКонкретное право, предоставляемое пользователю. Например: редактирование своих записей или редактирование всех записей.
Правило доступаНабор логики, учитывающий предоставленные пользователю права и другие факторы, и разрешающий или нет выполнение выбранного действия.
РольСвязь между access кодами и выбранными правами доступа.

Общая концепция

В качестве основы для реализации контроля доступа выбрана rule based модель:

  1. Cоставляется список действий, которые может совершить пользователь;
  2. Cоставляется список разрешений, которые могут быть включены для пользователя;
  3. Для каждого действия описывается правило доступа (на основе разрешений или каких-то других факторов);
  4. Контроллер на основе входных данных (действие, пользователь или любая дополнительная информация) находит нужное правило, выполняет его и возвращает результат;
  5. Клиентский код определяет, что делать с результатом.

Система прав доступа предполагается независимой в каждом модуле, со своим набором действий, прав и правил, и со своими таблицами в БД для хранения настроек. Общее API лишь предоставляет единый подход, необходимые классы и методы, но их использование не обязательно.


Работа с БД

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

КлассОписание
Bitrix\Main\Access\Permission\AccessPermissionTableКласс для работы с таблицей для хранения разрешений. Поддерживает иерархию разрешений и содержит необходимые для этого проверки.
Bitrix\Main\Access\Role\AccessRoleTableКласс для работы с таблицей для хранения ролей.
Bitrix\Main\Access\Role\AccessRoleRelationTableКласс для работы с таблицей для хранения связей между ролями и пользователями (access кодами пользователей).

Роли

Роль используется для обеспечения связи между access кодами пользователей и разрешениями. Если какой-то пользователь находится в нескольких ролях, то он получит все права, доступные этим ролям (сумму прав).

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


Разрешения

Для работы со списком разрешений реализован базовый класс справочника Bitrix\Main\Access\Permission\PermissionDictionary, предоставляющий методы для:

  • получения списка всех разрешений;
  • получения названий, подсказок и их переводов;
  • работы с иерархией в разрешениях (см. ниже).

При этом предполагается, что как таковые разрешения будут записаны в словарь в виде констант. Аналогичный пример можно посмотреть в модуле tasks: Bitrix\Tasks\Access\Permission\PermissionDictionary .


Иерархия разрешений

Из коробки поддерживается возможность создания разрешений, зависящих от других разрешений. Для примера возьмем следующий набор прав:

Редактирование записей

  • Редактирование записей в своем отделе;
  • Редактирование всех записей.

Без включения права Редактирование записей не получится включить остальные два. При выключении Редактирования записей будут автоматически выключены и все зависимые.

С технической точки зрения это реализуется с помощью особого формата значений в PermissionDictionary (используется material path нотация), вложенность при этом не ограничена. Пример:

const
  PERMISSION_EDIT = '1',
  PERMISSION_EDIT_DEPARTMENT = '1.1',
  PERMISSION_EDIT_ALL = '1.2';

Отдельно стоит отметить причины по которым используется именно такая запись:

  • константы легко отслеживать по коду с помощью IDE;
  • не требуется дополнительная запись о родительском элементе;
  • в целом компактный формат, удобный для записи словаря и чтения его человеком.

Контроллер

Единой точкой входа для проверки прав доступа в рамках модуля выступает контроллер, удовлетворяющий интерфейсу AccessibleController и, в общем случае, являющийся наследником BaseAccessController.

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

protected function loadItem(int $itemId = null): AccessibleItem
{
   //...
}

protected function loadUser(int $userId): AccessibleUser
{
   //...
}

Базовый контроллер предоставляет два способа использования (на примере модуля tasks).

Полный (об используемых моделях описано ниже):

$userModel = UserModel::createFromId($userId);
$item = TaskModel::createFromId($taskId);
$params = [];
$result = (new TaskAccessController($userModel))->check($action, $item, $params);

И упрощенный:

$result = TaskAccessController::can($userId, $action, $itemId, $params);

Кроме этого существует возможность пакетной проверки доступа к набору действий над одной сущностью:

$request = [
  $actionId => $params
];
$result = (new TaskAccessController($userModel))->batchCheck($request, $item);

В ответе такой запрос вернет массив $actionId => $result

В контроллере реализован статический кеш по пользователю, позволяющий сократить количество запросов к БД. Что бы получить уже созданный экземпляр, можно воспользоваться методом getInstance($userId).


Модели

Проверка прав доступа на базовом уровне работает с двумя моделями:

  • AccessibleUser - предоставляет необходимую информацию и методы о пользователе, совершающем действие. Для удобства реализован базовый класс UserModel. UserModel может быть создан из id пользователя или заполнен свойствами вручную.
  • AccessibleItem - модель сущности, над которой выполняются действия.

UserModel из коробки предоставляет методы, удобные для использования в правилах:

  • isAdmin() - проверка, является ли пользователь администратором;
  • getPermission(string $permissionId) - значение указанного разрешения для пользователя;
  • getUserDepartments() - список отделов пользователя;
  • getAccessCodes() - список access кодов пользователя;
  • getSubordinate($userId) - отношения в иерархии компании с указанным пользователем (об этом ниже).

Bitrix\Main\Access\User\UserSubordinate

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

UserSubordinate::getSubordinate($userId) - позволяет определить кем является указанный пользователь по отношению к текущему.

Возможные варианты:

  • UserSubordinate::RELATION_HIMSELF - один и тот же человек;
  • UserSubordinate::RELATION_DEPARTMENT - сотрудники одного отдела;
  • UserSubordinate::RELATION_SUBORDINATE - подчиненный;
  • UserSubordinate::RELATION_DIRECTOR - начальник;
  • UserSubordinate::RELATION_OTHER_DIRECTOR - начальник другого отдела;
  • UserSubordinate::RELATION_OTHER - все прочее (возможно получить, если, к примеру, не установлен модуль intranet).

Перехват управления

Для расширения функционала и перехвата управления реализована работа с событиями:

СобытиеОписание
Bitrix\Main\Access\Event\EventDictionary::EVENT_ON_BEFORE_CHECKВызывается перед проверкой доступа по конкретному правилу.
Bitrix\Main\Access\Event\EventDictionary::EVENT_ON_AFTER_CHECKВызывается после того как отрабатывает проверка по конкретному правилу.

В события передается следующий набор параметров:

[
   'user' // AccessibleUser
   'item' // AccessibleItem
   'action' // string действие, выполняемое пользователем
   'params' // misc любые дополнительные параметры
   'isAccess' // null|bool результат работы правила
]

Каждый обработчик, висящий на каком-либо событии должен вернуть объект Bitrix\Main\Access\Event\EventResult. Любые прочие значения будут проигнорированы.

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



Пользовательские комментарии

Мы будем рады, если разработчики добавят свои комментарии по практическому использованию методов системы.

Для этого нужно всего лишь авторизоваться на сайте

Но помните, что Пользовательские комментарии, несмотря на модерацию, не являются официальной документацией. Ответственность за их использование несет сам пользователь.

Также Пользовательские комментарии не являются местом для обсуждения функционала. По подобным вопросам обращайтесь на форумы.
© «Битрикс», 2001-2021, «1С-Битрикс», 2021
Наверх