Многие разработчики 1С сталкивались с загадочной, на первый взгляд, ситуацией: при выполнении определенного алгоритма или обработчика (например, при создании документа на основании) система выдает фатальную ошибку "У пользователя недостаточно прав на исполнение операции над базой данных". Однако, если взять текст проблемного запроса и выполнить его в консоли запросов под тем же самым пользователем, он благополучно отрабатывает и возвращает данные или пустой результат без каких-либо ругательств.
Рассмотрим подробнее эту ситуацию, проанализируем причины такого расхождения в поведении платформы 1С и выясним причину возникновения ошибки ограничения прав доступа (RLS) на конкретных примерах из конфигураций 1С:ERP, 1С:УТ и 1С:Комплексная автоматизация.
Предположим, у нас возникает ошибка доступа при попытке создания документа поступления на основании заказа. Если пройтись отладчиком с включенной опцией "остановка по ошибке", мы увидим, что проблема кроется в запросе получения расчетного счета контрагента по умолчанию. Пользователь при этом имеет права на чтение справочника расчетных счетов.
Посмотрим на пример типового кода, на котором происходит спотыкание:
Функция ПолучитьБанковскийСчетПоУмолчанию(Получатель, Валюта = Неопределено) Экспорт
Запрос = Новый Запрос(
"ВЫБРАТЬ ПЕРВЫЕ 2
| БанковскиеСчетаКонтрагентов.Ссылка КАК БанковскийСчетПолучателя
|ИЗ
| Справочник.БанковскиеСчетаКонтрагентов КАК БанковскиеСчетаКонтрагентов
|ГДЕ
| НЕ БанковскиеСчетаКонтрагентов.ПометкаУдаления
| И НЕ БанковскиеСчетаКонтрагентов.Закрыт
| И БанковскиеСчетаКонтрагентов.Владелец = &Получатель
| И (БанковскиеСчетаКонтрагентов.ВалютаДенежныхСредств = &Валюта
| ИЛИ &Валюта = Неопределено)
|");
Запрос.УстановитьПараметр("Получатель", Получатель);
Запрос.УстановитьПараметр("Валюта", ?(ЗначениеЗаполнено(Валюта), Валюта, Неопределено));
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Количество() = 1 И Выборка.Следующий() Тогда
БанковскийСчетПолучателя = Выборка.БанковскийСчетПолучателя;
Иначе
БанковскийСчетПолучателя = Справочники.БанковскиеСчетаКонтрагентов.ПустаяСсылка();
КонецЕсли;
Возврат БанковскийСчетПолучателя;
КонецФункции
Падение происходит на строке Запрос.Выполнить().Выбрать(). Разберем по шагам, почему в консоли этого не происходит, а в коде — происходит.
Кажется, что перед нами какая-то магия или "барабашка" в платформе, но этому есть вполне логичные технические объяснения. Выделим несколько основных причин:
&Валюта, который может принимать значение Неопределено. Некоторые консоли принудительно очищают этот параметр или передают его как пустую ссылку, из-за чего условие запроса меняется. Если в "правильной" консоли честно передать Неопределено, запрос также упадет с ошибкой прав, как и в коде.РАЗРЕШЕННЫЕ после слова ВЫБРАТЬ). При использовании этого слова система просто игнорирует записи, на которые у пользователя нет прав, и запрос завершается успешно, просто не выводя скрытые строки. В типовом коде, приведенном выше, слова РАЗРЕШЕННЫЕ нет, поэтому при попытке прочитать недоступную запись платформа генерирует исключение.УстановитьПривилегированныйРежим(Истина)). В этом режиме проверка прав RLS (Record Level Security) полностью отключается, и запрос отрабатывает без ошибок. В фоновом или клиентском коде под пользователем этот режим отключен.Судя по тексту ошибки, права обрезаны механизмом ограничения доступа на уровне записей. В современных решениях, таких как 1С:ERP или 1С:УТ, используется производительный RLS. Доступ к справочнику БанковскиеСчетаКонтрагентов напрямую зависит от прав на владельца — справочники "Контрагенты" или "Партнеры".
Чтобы каждый раз при запросе не вычислять сложные иерархические права, система хранит предрассчитанные доступы в служебных регистрах сведений. Основной из них — регистр ИерархияПартнеров, а также регистр ключей доступа к объектам.
Если в базе произошел сбой (например, зависло фоновое задание по обновлению прав, либо данные были загружены некорректно через обмен), записи в регистре ИерархияПартнеров могут отсутствовать или быть неактуальными. В результате система считает, что у пользователя нет доступа к конкретному контрагенту и его банковскому счету, даже если доступ к самому справочнику разрешен.
Если вы столкнулись с подобной ситуацией, выполните следующие действия для диагностики и исправления:
ИерархияПартнеров.Таким образом, "барабашка" исчезает, когда мы понимаем, как работает производительный RLS в конфигурациях 1С и чем отличается контекст выполнения запроса в модуле от контекста его выполнения в сторонней консоли. Регулярная проверка актуальности служебных регистров прав избавит пользователей от подобных неожиданных ошибок.