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