В процессе разработки и администрирования систем на базе 1С часто возникает ситуация, когда типовые или уже созданные роли предоставляют избыточные права пользователям. Например, у пользователя есть три разные роли, и каждая из них разрешает редактировать определенный реквизит. Если перед нами стоит задача запретить редактирование этого поля для части сотрудников, мы сталкиваемся с архитектурной особенностью 1С: права в системе всегда суммируются по принципу ИЛИ. Если хотя бы одна роль разрешает действие, система его пропустит.
В этой статье мы разберем, как правильно ограничить доступ к реквизиту, выясним, имеет ли программный код приоритет над правами доступа, и рассмотрим несколько эффективных стратегий решения этой задачи.
Проанализируем вопрос о том, что сильнее: код или роль. В системе 1С программный код, исполняемый на стороне сервера или клиента при создании формы, действительно имеет «визуальный приоритет». Если в роли у пользователя стоит галочка «Редактирование», но в коде формы мы пропишем запрет, то пользователь не сможет изменить значение через интерфейс. Рассмотрим простейший пример, который можно разместить в процедуре ПриСозданииНаСервере:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем условие или конкретного пользователя
Если НЕ РольДоступна("ПолныеПрава") Тогда
Элементы.ИмяРеквизита.ТолькоПросмотр = Истина;
КонецЕсли;
КонецПроцедуры
Важно понимать: этот метод ограничивает только интерфейсную возможность. Если злоумышленник или неопытный разработчик воспользуется внешней обработкой, он сможет изменить этот реквизит программно, так как роль по-прежнему разрешает запись в базу данных. Поэтому утверждение «код > роль» верно только для пользовательского интерфейса (UI).
Это самый правильный и «чистый» способ с точки зрения архитектуры 1С. Разберем его по шагам. Если текущие роли (назовем их Роль1, Роль2 и Роль3) все дают право на реквизит, нам нужно исключить это право из базовых ролей.
РедактированиеСпецРеквизита.Таким образом, мы соблюдаем принцип минимальных привилегий. У большинства пользователей будут старые роли (уже без права правки реквизита), а у «избранных» появится дополнительная роль, дающая это право.
Рассмотрим ситуацию, когда нам нужно блокировать реквизит динамически. Вместо того чтобы писать жесткий код управления элементами формы, современные стандарты разработки рекомендуют использовать Условное оформление. Это особенно удобно в управляемых формах.
Проанализируем, как это настроить программно в ПриСозданииНаСервере:
ЭлементОформления = УсловноеОформление.Элементы.Добавить();
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("ИмяРеквизита");
// Условие: например, если пользователь не входит в определенную группу
ЭлементУсловия = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементУсловия.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Статус");
ЭлементУсловия.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементУсловия.ПравоеЗначение = Перечисления.Статусы.Заблокирован;
ЭлементОформления.Установки.УстановитьЗначениеПараметра("ТолькоПросмотр", Истина);
Этот метод хорош тем, что он централизованно управляет визуализацией и доступностью полей, не разбрасывая логику по разным обработчикам событий элементов.
Выясним, как обеспечить максимальную безопасность, если правки могут прийти «извне» (через программный код или обмены). Для этого необходимо использовать обработчик ПередЗаписью в модуле объекта. Это гарантирует, что даже если роль позволяет редактирование, система проверит логику перед фиксацией данных в БД.
Процедура ПередЗаписью(Отказ)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Проверяем, изменился ли конкретный реквизит
Если ЭтоНовый() = Ложь И ЗначениеЗаполнено(Ссылка) Тогда
СтароеЗначение = Ссылка.ИмяРеквизита;
Если ЭтотОбъект.ИмяРеквизита <> СтароеЗначение Тогда
// Проверяем права текущего пользователя
Если НЕ РольДоступна("ПравоНаИзменениеРеквизита") Тогда
Сообщить("У вас недостаточно прав для изменения поля 'Имя реквизита'!");
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Важный момент: использование метода Ссылка.ИмяРеквизита внутри модуля объекта приводит к дополнительному обращению к базе данных. В высоконагруженных системах это следует учитывать, но для целей безопасности это самый надежный метод.
Если ваша конфигурация построена на базе Библиотеки стандартных подсистем (БСП), рекомендуется использовать профили групп доступа. Вместо прямого редактирования ролей в конфигураторе, вы можете:
Подводя итог, проанализируем выбор метода в зависимости от ваших целей:
ТолькоПросмотр = Истина или Условное оформление в форме.ПередЗаписью, чтобы исключить программный обход ограничений.Помните, что в 1С нет понятия «запрещающей роли». Право, данное хотя бы одной ролью, считается разрешенным для всей сессии пользователя. Поэтому единственный путь через роли — это лишение права во всех текущих ролях и создание одной специальной «разрешающей» роли для узкого круга лиц.