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