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