После включения механизма ограничения прав доступа на уровне записей (RLS) разработчики часто сталкиваются с ситуацией, когда типовые и доработанные алгоритмы конфигурации начинают вызывать исключения о нехватке прав при обращении к защищенным таблицам. Стандартной реакцией на такое поведение становится попытка массово пропарсить модули конфигурации и заменить конструкцию ВЫБРАТЬ на ВЫБРАТЬ РАЗРЕШЕННЫЕ. Разберем, почему простая контекстная автозамена приводит к ошибкам, какие синтаксические ограничения накладывает платформа 1С:Предприятие и как решить задачу корректно.
Попытка автоматической замены через выгрузку исходных файлов конфигурации или глобальный поиск сталкивается с жесткими правилами языка запросов 1С. Рассмотрим ключевые правила платформы:
РАЗРЕШЕННЫЕ может быть указано только в первом операторе ВЫБРАТЬ пакета запросов или объединения (ОБЪЕДИНИТЬ / ОБЪЕДИНИТЬ ВСЕ). Если заменить ключевое слово во вложенном подзапросе (например, в условии ГДЕ Поле В (ВЫБРАТЬ ...) или в подзапросе секции ИЗ), платформа выдаст критическую синтаксическую ошибку: «Ключевое слово РАЗРЕШЕННЫЕ доступно только у первого запроса».РАЗРЕШЕННЫЕ. Добавлять его вручную в текст запроса динамического списка не требуется.ВЫБРАТЬ РАЗРЕШЕННЫЕ (получится дублирование ключевого слова) либо используется англоязычный оператор SELECT.Вместо регулярных выражений и текстовой замены разберем надежный программный способ модификации запросов с помощью встроенного объекта СхемаЗапроса. Этот объект строит абстрактное синтаксическое дерево (AST) запроса и гарантирует корректную расстановку ключевых слов без нарушения синтаксиса во вложенных запросах.
Посмотрим на пример обработки исходного текста запроса:
Функция ДобавитьРазрешенныеВЗапрос(Знач ИсходныйТекст)
Схема = Новый СхемаЗапроса;
Попытка
Схема.УстановитьТекстЗапроса(ИсходныйТекст);
Исключение
// Текст содержит ошибки либо является динамически формируемым
Возврат ИсходныйТекст;
КонецПопытки;
Для Каждого ЭлементПакета Из Схема.ПакетЗапросов Цикл
Если ТипЗнч(ЭлементПакета) = Тип("ЗапросВыбораСхемыЗапроса") Тогда
// Устанавливаем признак только для основного запроса выборки
ЭлементПакета.ВыбиратьРазрешенные = Истина;
КонецЕсли;
КонецЦикла;
Возврат Схема.ПолучитьТекстЗапроса();
КонецФункции
Такой подход защищает от ошибок во вложенных запросах, поскольку СхемаЗапроса применяет свойство ВыбиратьРазрешенные исключительно к допустимым корневым узлам пакета.
Массовое внедрение модификатора РАЗРЕШЕННЫЕ во все запросы конфигурации несет серьезные методологические и архитектурные риски. Проанализируем последствия слепого скрытия прав:
РАЗРЕШЕННЫЕ молча скроет недоступные строки. В результате алгоритм рассчитает остатки на неполных данных, что приведет к скрытым учетным ошибкам и появлению отрицательных остатков.Стандартом разработки 1С для служебных алгоритмов, регламентных заданий и проведения документов является использование привилегированного режима. Выясним, как правильно применить этот механизм:
// Включение привилегированного режима для служебных расчетов
УстановитьПривилегированныйРежим(Истина);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура,
| ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК ТоварыНаСкладахОстатки";
Запрос.УстановитьПараметр("Период", ТекущаяДатаСеанса());
РезультатЗапроса = Запрос.Выполнить();
УстановитьПривилегированныйРежим(Ложь);
Альтернативно служебные процедуры и функции можно выносить в общие модули с установленным флажком «Привилегированный». В таком случае отпадает необходимость модифицировать сотни прикладных запросов, исключаются синтаксические ошибки, а СУБД выполняет запросы без лишних накладных расходов RLS.
При настройке RLS рекомендуется следовать четкому алгоритму:
ВЫБРАТЬ РАЗРЕШЕННЫЕ следует добавлять только в те отчеты и интерфейсные выборки, где пользователю действительно необходимо показать исключительно доступную ему часть данных.УстановитьПривилегированныйРежим(Истина) или привилегированные модули.СхемаЗапроса либо инструменты статического анализа кода (например, на базе 1C:Enterprise Development Tools / EDT), избегая механической текстовой автозамены.