CRM
Права доступа CRM
Рабочая справка по проверке прав CRM в коробочном Bitrix24 через PHP: UserPermissions, CCrmAuthorizationHelper, CCrmPerms и операции CRM.
Если код работает от администратора или из агента, легко случайно обойти пользовательские ограничения. Поэтому для пользовательских сценариев лучше явно проверять права или запускать операцию в контексте нужного пользователя.
Общее понимание
Права CRM зависят от роли, отдела, ответственного, воронки и конкретной сущности.
Как устроены права CRM
В интерфейсе CRM права задаются ролями. В коде можно проверять доступ к конкретной карточке, к типу сущности или к воронке.
| Что проверить | Пример |
|---|---|
| Доступ к конкретной сделке | Может ли пользователь прочитать сделку с ID 123. |
| Доступ к типу | Может ли пользователь читать хоть какие-то сделки. |
| Доступ к воронке | Может ли пользователь читать сделки в воронке 5. |
| Доступ при операции | Можно ли изменить карточку через операцию CRM. |
Права текущего и другого пользователя
Сервис прав можно получить для текущего пользователя или для конкретного пользователя по ID.
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Service;
Loader::includeModule('crm');
/**
* Получает сервис прав текущего пользователя.
*/
function fetchCurrentUserPermissions()
{
return Service\Container::getInstance()->getUserPermissions();
}
/**
* Получает сервис прав конкретного пользователя.
*/
function fetchUserPermissions(int $user_id)
{
return Service\Container::getInstance()->getUserPermissions($user_id);
}
$current_permissions = fetchCurrentUserPermissions();
$user_permissions = fetchUserPermissions($user_id); Проверки через новое API
В новом API проверки прав доступны через сервис UserPermissions.
Проверить чтение элемента
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Service;
const CRM_DEAL_TYPE_ID = \CCrmOwnerType::Deal;
Loader::includeModule('crm');
/**
* Проверяет право чтения CRM-элемента.
*/
function canUserReadCrmItem(int $user_id, int $entity_type_id, int $entity_id): bool
{
$user_permissions = Service\Container::getInstance()->getUserPermissions($user_id);
return $user_permissions->item()->canRead($entity_type_id, $entity_id);
}
$can_read = canUserReadCrmItem($user_id, CRM_DEAL_TYPE_ID, $deal_id);
var_dump($can_read); Проверить изменение и удаление
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Service;
const CRM_DEAL_TYPE_ID = \CCrmOwnerType::Deal;
Loader::includeModule('crm');
/**
* Проверяет права на изменение и удаление CRM-элемента.
*/
function checkCrmItemWritePermissions(int $user_id, int $entity_type_id, int $entity_id): array
{
$user_permissions = Service\Container::getInstance()->getUserPermissions($user_id);
return [
'can_update' => $user_permissions->item()->canUpdate($entity_type_id, $entity_id),
'can_delete' => $user_permissions->item()->canDelete($entity_type_id, $entity_id),
];
}
$permissions = checkCrmItemWritePermissions($user_id, CRM_DEAL_TYPE_ID, $deal_id);
print_r($permissions); Проверить доступ к типу сущности
Иногда нужно проверить не конкретную карточку, а доступ пользователя к типу CRM в целом или к воронке.
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Service;
const CRM_DEAL_TYPE_ID = \CCrmOwnerType::Deal;
Loader::includeModule('crm');
/**
* Проверяет доступ к сделкам в целом и в конкретной воронке.
*/
function checkDealTypePermissions(int $user_id, int $category_id): array
{
$user_permissions = Service\Container::getInstance()->getUserPermissions($user_id);
return [
'can_read_deals' => $user_permissions->entityType()->canReadItems(CRM_DEAL_TYPE_ID),
'can_read_category_deals' => $user_permissions->entityType()->canReadItemsInCategory(
CRM_DEAL_TYPE_ID,
$category_id
),
];
}
$permissions = checkDealTypePermissions($user_id, $category_id);
print_r($permissions); Старые проверки
В старом CRM-коде часто встречаются CCrmPerms и CCrmAuthorizationHelper.
CCrmPerms
CCrmPerms — старый объект прав CRM. Его часто передают в старые методы
проверки, чтобы не получать права заново в каждом вызове.
<?php
/**
* Получает старый объект прав CRM текущего пользователя.
*/
function fetchCurrentCrmPerms(): \CCrmPerms
{
return \CCrmPerms::GetCurrentUserPermissions();
}
$user_permissions = fetchCurrentCrmPerms(); Операции CRM
Операции фабрики могут сами проверять права, если проверка не отключена.
Проверка прав в операции
По умолчанию операция может проверять доступ. Если в служебном скрипте проверку отключают, это нужно делать осознанно.
$operation = $factory->getUpdateOperation($item);
$operation->enableCheckAccess();
$operation_result = $operation->launch();
if (!$operation_result->isSuccess()) {
print_r($operation_result->getErrorMessages());
} $operation = $factory->getUpdateOperation($item);
// Только для служебных сценариев, где права проверены отдельно.
$operation->disableCheckAccess();
$operation_result = $operation->launch(); Контекст пользователя
Операцию можно запустить в контексте конкретного пользователя. Тогда проверки и связанные действия будут учитывать этого пользователя.
<?php
use Bitrix\Main\Loader;
use Bitrix\Crm\Service;
const CRM_DEAL_TYPE_ID = \CCrmOwnerType::Deal;
Loader::includeModule('crm');
/**
* Изменяет сделку в контексте пользователя.
*/
function updateDealTitleWithUserContext(int $deal_id, string $title, int $user_id): array
{
$factory = Service\Container::getInstance()->getFactory(CRM_DEAL_TYPE_ID);
if ($factory === null) {
return [
'is_success' => false,
'error_messages' => ['Фабрика сделок не найдена'],
];
}
$deal_item = $factory->getItem($deal_id);
if ($deal_item === null) {
return [
'is_success' => false,
'error_messages' => ['Сделка не найдена'],
];
}
$deal_item->setTitle($title);
$context = new Service\Context();
$context->setUserId($user_id);
$operation = $factory->getUpdateOperation($deal_item, $context);
$operation->enableCheckAccess();
$operation_result = $operation->launch();
return [
'is_success' => $operation_result->isSuccess(),
'error_messages' => $operation_result->getErrorMessages(),
];
}
$result = updateDealTitleWithUserContext($deal_id, $title, $user_id);
print_r($result);