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