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

UserPermissions

Права доступа


Права доступа - всегда довольно сложный раздел бизнес-логики любого приложения.

При проектировании публичного API этого сервиса фокус был сделан на ответах на простые вопросы.

Сам этот сервис практически не работает напрямую с хранением настроек и атрибутов прав доступа, это только фасад с удобным API.

Тем не менее, ниже немного описывается структура таблиц и особенности проверки прав доступа.


Настройки прав доступа

Права доступа в CRM (как во многих других модулях) настраиваются на уровне ролей (таблица b_crm_role).

К каждой роли можно отнести пользователя / группу / подразделение и т.д. (таблица b_crm_role_relation).

На каждую роль настраиваются права доступа (таблица b_crm_role_perms).

Права доступа настраиваются в разрезе "сущности" (колонка ENTITY, это горизонтальная строка в интерфейсе настроек).

Для каждой сущности можно настроить определенный уровень прав (колонка ATTR) для определенного действия (колонка PERM_TYPE).

Хранение атрибутов

Каждый раз при создании / изменении элемента любого типа CRM, его данные, влияющие на права доступа, преобразуются в набор атрибутов и записывается в таблицу b_crm_entity_perms (метод \CCrmPerms::UpdateEntityAttr).

Соответствие между этими данными и получаемыми атрибутами представлено в таблице:


Данные элемента Пример значения атрибута
Поле ОтветственныйU1 1 - идентификатор пользователя
Поле ОтветственныйIU1 1 - идентификатор пользователя как сотрудника
Принадлежность ответственного к подразделениям орг. структурыD2 2 - идентификатор подразделения. Сохраняется как принадлежность к подразделению, так и принадлежность ко всем родительским подразделениям
Поле "Доступна (доступен) для всех"O Если галка в поле установлена, то атрибут есть, а если нет то нет
Является ли компания "моей компанией" (Для компаний)IS_MY_COMPANY Если компания является моей компанией, то атрибут есть и к таким записям доступ на чтение есть всегда, независимо от настроек доступа для остальных компаний
Список наблюдателей (Для лидов и сделок)CU1 1 - идентификатор пользователя. Для каждого наблюдателя добавляется свой атрибут в список
Значение статуса/стадии (Для лидов)STATUS_IDNEW NEW - идентификатор статуса
Значение стадии (Для сделок и коммерческих предложений))STAGE_IDNEW NEW - идентификатор стадии

Далее при проверке прав доступа алгоритм следующий:

  • для пользователя, относительно которого проверяются права доступа, получается список его ролей, из ролей и их разрешений строится карта атрибутов, доступных этому пользователю (метод \CCrmRole::GetUserPerms());
  • карта разрешений сравнивается с текущим набором атрибутов элемента с учетом действия, которое производится (\CCrmPerms::CheckEnityAccess());
  • для списочных запросов строится дополнительное выражение для добавления в WHERE (метод \CCrmPerms::BuildSql()).

В этом сервисе все эти действия спрятаны "под капотом" (по факту вызываются методы старого API).


При написании нового кода рекомендуется использовать именно этот сервис, а не старое API.

Инстанс сервиса следует получать из контейнера, т.к. внутри сервиса данные закешированы.

В методе Service\Container::getUserPermissions() есть аргумент $userId, куда можно передать идентификатор пользователя.

Методы

Метод Описание С версии
public function __construct(int $userId)
  • $userId - идентификатор пользователя, относительно которого будет производиться проверка прав;
Конструктор.

Если $userId = 0, то считается, что действие производится от системного пользователя. Этот пользователь не имеет ни на что доступа.

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

public function getUserId(): int
Вернет идентификатор пользователя.
public function getCrmPermissions(): \CCrmPerms
Вернет объект класса \CCrmPerms, завязанного на текущего пользователя.
public function canWriteConfig(): bool
Вернет true, если пользователь имеет право изменять настройки CRM.
public function canReadConfig(): bool
Вернет true, если пользователь имеет право читать настройки CRM.
public function canReadType(int $entityTypeId, int $categoryId = 0): bool
  • $entityTypeId - идентификатор типа сущности CRM;
  • $categoryId - идентификатор направления.
Вернет true, если пользователь имеет право просматривать элементы типа $entityTypeId хотя бы в одном из направлений типа.
public function canReadTypeInCategory(int $entityTypeId, int $categoryId): bool
  • $entityTypeId - идентификатор типа сущности CRM;
  • $categoryId - идентификатор направления.
Вернет true, если пользователь имеет право имеет право просматривать элементы типа $entityTypeId в направлении $categoryId. crm 22.0.0
public function canAddType(): bool
Вернет true, если пользователь имеет право создать новый смарт-процесс.
public function canUpdateType(): bool
Вернет true, если пользователь имеет право изменить настройки смарт-процесса с идентификатором типа CRM $entityTypeId.
public function canAddItem(Item $item): bool
Вернет true, если пользователь имеет право создать элемент $item в его текущем состоянии.
public function checkAddPermissions
(int $entityTypeId, int $categoryId = 0, 
?string $stageId = null): bool
Вернет true, если пользователь имеет право создать элемент типа $entityTypeId в направлении $categoryId на стадии $stageId.
Здесь и ниже, если направление не указано, то проверка будет произведена для направления по умолчанию.
Если стадия не указана, то проверка прав с учетом стадии производиться не будет.
public function checkUpdatePermissions
(int $entityTypeId, int $id, 
int $categoryId = 0): bool
Вернет true, если пользователь имеет право изменить элемент с идентификатором $id в направлении $categoryId.
public function canUpdateItem(Item $item): bool
Вернет true, если пользователь имеет право изменить элемент $item.
public function checkDeletePermissions
(int $entityTypeId, int $id, int $categoryId = 0): bool
Вернет true, если пользователь имеет право удалить элемент типа $entityTypeId с идентификатором $id в направлении $categoryId.
public function canDeleteItem(Item $item): bool
Вернет true, если пользователь имеет право удалить элемент $item.
public function checkReadPermissions
(int $entityTypeId, int $id = 0, int $categoryId = 0): bool
Вернет true, если пользователь может прочитать элемент типа $entityTypeId с идентификатором $id в направлении $categoryId.
public function canReadItem(Item $item): bool
Вернет true, если пользователь имеет право прочитать элемент $item.
public function canViewItemsInCategory
(Category $category): bool
Вернет true, если пользователь имеет право прочитать элементы $item направления $category.
public function canAddCategory
(Category $category): bool
Вернет true, если пользователь имеет право создать новое направление $category.
public function canUpdateCategory
(Category $category): bool
Вернет true, если пользователь имеет право изменить направление $category.
public function canDeleteCategory
(Category $category): bool
Вернет true, если пользователь имеет право удалить направление $category.
public function filterAvailableForReadingCategories
(array $categories): array
Вернет массив направлений из набора $categories, в которых пользователь может просматривать элементы.
public function getPermissionType
(Item $item, string $operationType = self::OPERATION_READ): 
string
Вернет строковый идентификатор уровня доступа (все / свои и своего отдела / свои / только открытые / нет), который есть у пользователя к элементу $item при выполнении операции $operationType.
public function prepareItemPermissionAttributes
(Item $item): array
Вернет набор атрибутов элемента $item перед его сохранением в таблицу b_crm_entity_perms.
public static function getItemPermissionEntityType
(Item $item): string
Вернет строковый идентификатор сущности для таблицы прав элемента $item.
public static function getPermissionEntityType
(int $entityTypeId, int $categoryId = 0): string
Вернет строковый идентификатор сущности для таблицы прав типа сущности $entityTypeId в направлении $categoryId.
public static function getEntityNameByPermissionEntityType
(string $permissionEntityType): ?string
Вернет строковый идентификатор типа сущности CRM по строковому идентификатору сущности $permissionEntityType для таблицы прав.
public function applyAvailableItemsFilter
(?array $filter, array $permissionEntityTypes, 
?string $operation = self::OPERATION_READ, 
?string $primary = 'ID'): array

  • $filter - текущий фильтр для списка элементов;
  • $permissionEntityTypes - массив строковых идентификаторов для таблицы прав;
  • $operation - тип операции;
  • $primary - код первичного ключа, который будет добавлен в фильтр.
Дополнит $filter дополнительными ключами, которые позволят отобрать только те элементы, к которым пользователь имеет доступ. Вернет новую версию фильтра.
public function getStartStageId(int $entityTypeId, 
EO_Status_Collection $stages, int $categoryId = 0, 
string $operation = self::OPERATION_ADD): ?string

  • $entityTypeId - идентификатор типа сущности CRM;
  • $stages - коллекция стадий;
  • $categoryId - идентификатор направления;
  • $operation - тип операции.
Вернет идентификатор первой стадии из коллекции $stages типа $entityTypeId направления $categoryId, к которой имеет доступ пользователь при выполнении операции типа $operation.
Обычно этот метод используется, чтоб определить, в какую стадию надо поместить создаваемый пользователем элемент.

Примеры


use Bitrix\Crm\Service;

$entityTypeId = 150;
$factory = Service\Container::getInstance()->getFactory($entityTypeId);
if (!$factory)
{
	return;
}

$userPermissions = Service\Container::getInstance()->getUserPermissions();

$canWriteConfig = $userPermissions->canWriteConfig();

$category = $factory->getDefaultCategory ();
$canReadType = $userPermissions->canReadType (
	$factory->getEntityTypeId (),
	$category->getId()
);
$canUpdateCategory = $userPermissions->canUpdateCategory($category);

$item = $factory->getItem(12);
$canDeleteItem = $userPermissions->canDeleteItem($item);
$canAddItemToCategory = $userPermissions->checkAddPermissions(
	$factory->getEntityTypeId (),
	$category->getId()
);

$categories = $factory->getCategories();
$availableForReadItemsCategories = $userPermissions->filterAvailableForReadingCategories($categories);

$filter = [
	'=CATEGORY_ID' => $category->getId(),
	'>ID' => 100,
];

$permissionEntityTypes = [$userPermissions::getPermissionEntityType($factory->getEntityTypeId, $category->getId())];

$filterWithPermissions = $userPermissions->applyAvailableItemsFilter($filter, $permissionEntityTypes);
© «Битрикс», 2001-2024, «1С-Битрикс», 2024