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